From 4ea2bcc63e479a6815a13d0b880436031a23c28e Mon Sep 17 00:00:00 2001 From: Joe Fehrman Date: Tue, 23 Jul 2024 09:59:26 -0400 Subject: [PATCH] Pill Variant Large (#3978) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Updating the FormPillGroup component to have size property. * feat: Adding test for new FormPillGroup changes. * chore: Updating storybook story for the FormPillGroup. * chore: Adding changeset information for size variant change. * feat: Updating FormPillGroup components to allow for the font size to be changed dynamically for the FormPills. * feat: Updating the patch to be a minor change rather than a full version number. * fix: Fixing type mistake with fontSize property. * feat: Updating type docs due to failed check. * fix: Fixing formatting problems. * chore: Updating import order. * Revert "feat: Updating type docs due to failed check." This reverts commit e9fe82575bd3fd578d13adc9fdebbd38a021c9fa. * feat: Updating type docs. * fix: Update .changeset/strange-paws-smell.md to include package. Co-authored-by: Nora Krantz <75342690+nkrantz@users.noreply.github.com> * refactor: Replacing "L" variant with "large" variant in FormPillGroup. * refactor: Updating the FormPillGroup component to use a more simple way of retrieving styles. * feat: Updating the changeset. * chore: Adding a JSDoc comment. * chore: Minor update to syntax. * refactor: Refactoring the FormPillGroup styling and props. * feat: Changing the height of the pill for large size variant. * chore: Formatting. * fix: Adding code back that was removed by mistake. * chore: Adding TSDoc. * chore: TSDoc why have you forsaken me?!?! Fixing typedoc. * fix: Removing property that is not used. * chore: small fontSize fix and forgot to add to docs site until now --------- Co-authored-by: Nora Krantz <75342690+nkrantz@users.noreply.github.com> Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> Co-authored-by: “nora --- .changeset/strange-paws-smell.md | 6 ++ .../form-pill-group/src/FormPillButton.tsx | 22 +++++-- .../form-pill-group/src/FormPillGroup.tsx | 63 +++++++++++++------ .../components/form-pill-group/src/index.tsx | 8 ++- .../components/form-pill-group/src/types.ts | 2 + .../form-pill-group/src/useFormPillState.tsx | 16 ++++- .../form-pill-group/stories/index.stories.tsx | 14 ++++- .../components/form-pill-group/type-docs.json | 7 +++ .../src/component-examples/FormPillGroup.tsx | 28 +++++++++ .../components/form-pill-group/index.mdx | 9 +++ 10 files changed, 144 insertions(+), 31 deletions(-) create mode 100644 .changeset/strange-paws-smell.md diff --git a/.changeset/strange-paws-smell.md b/.changeset/strange-paws-smell.md new file mode 100644 index 0000000000..ce17fb9067 --- /dev/null +++ b/.changeset/strange-paws-smell.md @@ -0,0 +1,6 @@ +--- +"@twilio-paste/core": minor +"@twilio-paste/form-pill-group": minor +--- + +[Form Pill Group] Adding size property to the FormPillGroup component. Sizes include default and "large". diff --git a/packages/paste-core/components/form-pill-group/src/FormPillButton.tsx b/packages/paste-core/components/form-pill-group/src/FormPillButton.tsx index 227f7aa763..9242f81854 100644 --- a/packages/paste-core/components/form-pill-group/src/FormPillButton.tsx +++ b/packages/paste-core/components/form-pill-group/src/FormPillButton.tsx @@ -1,11 +1,12 @@ import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; -import type { BoxElementProps } from "@twilio-paste/box"; +import type { BoxElementProps, BoxProps } from "@twilio-paste/box"; import { ErrorIcon } from "@twilio-paste/icons/esm/ErrorIcon"; import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; import * as React from "react"; import { hoverPillStyles, pillStyles } from "./FormPill.styles"; -import type { PillVariant } from "./types"; +import type { FormPillGroupSizeVariant, PillVariant } from "./types"; +import { FormPillGroupContext } from "./useFormPillState"; interface FormPillStylesProps { variant?: PillVariant; @@ -21,6 +22,17 @@ interface FormPillStylesProps { i18nErrorLabel?: string; } +const sizeStyles: Record> = { + default: { + fontSize: "fontSize20", + height: "sizeIcon40", + }, + large: { + fontSize: "fontSize30", + height: "sizeIcon50", + }, +}; + export const FormPillButton = React.forwardRef( ( { @@ -39,6 +51,8 @@ export const FormPillButton = React.forwardRef const hasHoverStyles = isHoverable && !isDisabled; return hasHoverStyles ? { ...pillStyles[variant], ...hoverPillStyles[variant] } : pillStyles[variant]; }, [isHoverable, isDisabled, variant]); + const { size } = React.useContext(FormPillGroupContext); + const { height, fontSize } = sizeStyles[size]; return ( borderRadius="borderRadiusPill" borderStyle="none" cursor="default" - height="sizeIcon40" + height={height} fontFamily="inherit" - fontSize="fontSize20" + fontSize={fontSize} fontWeight="fontWeightMedium" outline="none" paddingLeft="space30" diff --git a/packages/paste-core/components/form-pill-group/src/FormPillGroup.tsx b/packages/paste-core/components/form-pill-group/src/FormPillGroup.tsx index e45a0a9231..7b5bfa21e4 100644 --- a/packages/paste-core/components/form-pill-group/src/FormPillGroup.tsx +++ b/packages/paste-core/components/form-pill-group/src/FormPillGroup.tsx @@ -1,11 +1,14 @@ import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; -import type { BoxElementProps } from "@twilio-paste/box"; +import type { BoxElementProps, BoxProps } from "@twilio-paste/box"; import { Composite } from "@twilio-paste/reakit-library"; import type { CompositeProps } from "@twilio-paste/reakit-library"; import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; import { useUID } from "@twilio-paste/uid-library"; import * as React from "react"; +import type { FormPillGroupSizeVariant } from "./types"; +import { FormPillGroupContext } from "./useFormPillState"; + export interface FormPillGroupProps extends Omit { /** @@ -39,26 +42,50 @@ export interface FormPillGroupProps * @memberof FormPillGroupProps */ display?: "flex" | "inline-flex"; + /** + * Size variant that affects the size and spacing of the pills within the FormPillGroup. 'large' and 'default' are the only supported values. + * + * @default 'default' + * @memberof FormPillGroupProps + */ + size?: FormPillGroupSizeVariant; } +/** + * Contains the style properties for the FormPillGroup component and the FormPill component. + */ +const SizeStyles: Record> = { + default: { + columnGap: "space20", + rowGap: "space20", + }, + large: { + columnGap: "space30", + rowGap: "space30", + }, +}; + const FormPillGroupStyles = React.forwardRef( - ({ element = "FORM_PILL_GROUP", display = "flex", ...props }, ref) => ( - - {props.children} - - ), + ({ element = "FORM_PILL_GROUP", display = "flex", size = "default", ...props }, ref) => { + return ( + + + {props.children} + + + ); + }, ); FormPillGroupStyles.displayName = "StyledFormPillGroup"; diff --git a/packages/paste-core/components/form-pill-group/src/index.tsx b/packages/paste-core/components/form-pill-group/src/index.tsx index 1521bd46c0..d7689789c4 100644 --- a/packages/paste-core/components/form-pill-group/src/index.tsx +++ b/packages/paste-core/components/form-pill-group/src/index.tsx @@ -1,7 +1,9 @@ -import type { FormPillInitialState, FormPillStateReturn } from "./useFormPillState"; +import type { CompositeStateReturn } from "@twilio-paste/reakit-library"; + +import type { FormPillInitialState } from "./useFormPillState"; // for the sake of documenting the types we rename the state hook types to append Props to the name, so we can docuemnt them and not cause a breaking change. -type FormPillStateReturnProps = FormPillStateReturn; +type FormPillStateReturnProps = CompositeStateReturn; type FormPillInitialStateProps = FormPillInitialState; export type { FormPillStateReturnProps, FormPillInitialStateProps }; @@ -10,4 +12,4 @@ export type { FormPillProps } from "./FormPill"; export { FormPillGroup } from "./FormPillGroup"; export type { FormPillGroupProps } from "./FormPillGroup"; export { useFormPillState } from "./useFormPillState"; -export type { FormPillStateReturn, FormPillInitialState }; +export type { CompositeStateReturn as FormPillStateReturn, FormPillInitialState }; diff --git a/packages/paste-core/components/form-pill-group/src/types.ts b/packages/paste-core/components/form-pill-group/src/types.ts index d53e594ca5..5d39660b83 100644 --- a/packages/paste-core/components/form-pill-group/src/types.ts +++ b/packages/paste-core/components/form-pill-group/src/types.ts @@ -2,3 +2,5 @@ import type { BoxStyleProps } from "@twilio-paste/box"; export type PillVariant = "error" | "default"; export type VariantStyles = Record; +/** The size variants for the FormPillGroup component. */ +export type FormPillGroupSizeVariant = "default" | "large"; diff --git a/packages/paste-core/components/form-pill-group/src/useFormPillState.tsx b/packages/paste-core/components/form-pill-group/src/useFormPillState.tsx index 54101b16f9..424dffa8fd 100644 --- a/packages/paste-core/components/form-pill-group/src/useFormPillState.tsx +++ b/packages/paste-core/components/form-pill-group/src/useFormPillState.tsx @@ -1,10 +1,12 @@ import { useCompositeState } from "@twilio-paste/reakit-library"; -import type { CompositeInitialState, CompositeStateReturn as FormPillStateReturn } from "@twilio-paste/reakit-library"; +import type { CompositeInitialState, CompositeStateReturn } from "@twilio-paste/reakit-library"; +import { createContext } from "react"; + +import type { FormPillGroupSizeVariant } from "./types"; -export type { FormPillStateReturn }; export type FormPillInitialState = Omit; -export const useFormPillState = (config: FormPillInitialState = {}): FormPillStateReturn => { +export const useFormPillState = (config: FormPillInitialState = {}): CompositeStateReturn => { return { ...useCompositeState({ ...config, @@ -13,3 +15,11 @@ export const useFormPillState = (config: FormPillInitialState = {}): FormPillSta }), }; }; + +export interface FormPillGroupContextState { + size: FormPillGroupSizeVariant; +} + +export const FormPillGroupContext = createContext({ + size: "default", +}); diff --git a/packages/paste-core/components/form-pill-group/stories/index.stories.tsx b/packages/paste-core/components/form-pill-group/stories/index.stories.tsx index 8a8b984ef2..cde970c838 100644 --- a/packages/paste-core/components/form-pill-group/stories/index.stories.tsx +++ b/packages/paste-core/components/form-pill-group/stories/index.stories.tsx @@ -4,6 +4,7 @@ import { CalendarIcon } from "@twilio-paste/icons/esm/CalendarIcon"; import * as React from "react"; import { FormPill, FormPillGroup, useFormPillState } from "../src"; +import type { FormPillGroupSizeVariant } from "../src/FormPillGroup"; const PILL_NAMES = [ "Default pill", @@ -15,12 +16,18 @@ const PILL_NAMES = [ ]; export const Basic: React.FC< - React.PropsWithChildren<{ selected?: boolean; dismissable?: boolean; disabled?: boolean; ariaLabel?: string }> -> = ({ selected = false, dismissable = false, disabled = false, ariaLabel = "Basic pills:" }) => { + React.PropsWithChildren<{ + selected?: boolean; + dismissable?: boolean; + disabled?: boolean; + ariaLabel?: string; + size?: FormPillGroupSizeVariant; + }> +> = ({ selected = false, dismissable = false, disabled = false, ariaLabel = "Basic pills:", size }) => { const pillState = useFormPillState(); return (
- + {PILL_NAMES.map((pill, index) => ( ; export const Disabled = (): JSX.Element => ; export const Selected = (): JSX.Element => ; export const Dismissable = (): JSX.Element => ; diff --git a/packages/paste-core/components/form-pill-group/type-docs.json b/packages/paste-core/components/form-pill-group/type-docs.json index 7cc274fc36..a072ae0b71 100644 --- a/packages/paste-core/components/form-pill-group/type-docs.json +++ b/packages/paste-core/components/form-pill-group/type-docs.json @@ -2259,6 +2259,13 @@ "required": false, "externalProp": true }, + "size": { + "type": "FormPillGroupSizeVariant", + "defaultValue": "'default'", + "required": false, + "externalProp": false, + "description": "Size variant that affects the size and spacing of the pills within the FormPillGroup. 'large' and 'default' are the only supported values." + }, "slot": { "type": "string", "defaultValue": null, diff --git a/packages/paste-website/src/component-examples/FormPillGroup.tsx b/packages/paste-website/src/component-examples/FormPillGroup.tsx index a6589f510e..ddb3707fbb 100644 --- a/packages/paste-website/src/component-examples/FormPillGroup.tsx +++ b/packages/paste-website/src/component-examples/FormPillGroup.tsx @@ -26,6 +26,34 @@ render( ) `.trim(); +export const largeExample = ` +const BasicFormPillGroup = () => { + const pillState = useFormPillState(); + + return ( + + + + Voice + + + + Video + + + + Verify + + + + ); +}; + +render( + +) +`.trim(); + export const selectableExample = ` const SelectableFormPillGroup = () => { const [pills] = React.useState(['SMS', 'MMS', 'Fax', 'Voice', 'Messaging', 'Chat']); diff --git a/packages/paste-website/src/pages/components/form-pill-group/index.mdx b/packages/paste-website/src/pages/components/form-pill-group/index.mdx index 77fe8baf3b..8ca4889ace 100644 --- a/packages/paste-website/src/pages/components/form-pill-group/index.mdx +++ b/packages/paste-website/src/pages/components/form-pill-group/index.mdx @@ -36,6 +36,7 @@ import {DoDont, Do, Dont} from '../../../components/DoDont'; import {SidebarCategoryRoutes} from '../../../constants'; import { basicExample, + largeExample, selectableExample, dismissableExample, selectableAndDismissableExample, @@ -137,6 +138,14 @@ A Form Pill can have an optional [Avatar](/components/avatar) or [Icon](/compone {basicExample} +### Large + +Use `size="large"` Form Pills only for specific and approved use cases, such as in the filter group pattern (link coming soon!). + + + {largeExample} + + ### Selectable Use a Selectable Form Pill to show an option that a user can select or deselect.