Skip to content

Commit

Permalink
Pill Variant Large (#3978)
Browse files Browse the repository at this point in the history
* 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 e9fe825.

* feat: Updating type docs.

* fix: Update .changeset/strange-paws-smell.md to include package.

Co-authored-by: Nora Krantz <[email protected]>

* 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 <[email protected]>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: “nora <[email protected]>
  • Loading branch information
4 people authored Jul 23, 2024
1 parent fe8825e commit 4ea2bcc
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 31 deletions.
6 changes: 6 additions & 0 deletions .changeset/strange-paws-smell.md
Original file line number Diff line number Diff line change
@@ -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".
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -21,6 +22,17 @@ interface FormPillStylesProps {
i18nErrorLabel?: string;
}

const sizeStyles: Record<FormPillGroupSizeVariant, Pick<BoxProps, "fontSize" | "height">> = {
default: {
fontSize: "fontSize20",
height: "sizeIcon40",
},
large: {
fontSize: "fontSize30",
height: "sizeIcon50",
},
};

export const FormPillButton = React.forwardRef<HTMLElement, FormPillStylesProps>(
(
{
Expand All @@ -39,6 +51,8 @@ export const FormPillButton = React.forwardRef<HTMLElement, FormPillStylesProps>
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 (
<Box
Expand All @@ -55,9 +69,9 @@ export const FormPillButton = React.forwardRef<HTMLElement, FormPillStylesProps>
borderRadius="borderRadiusPill"
borderStyle="none"
cursor="default"
height="sizeIcon40"
height={height}
fontFamily="inherit"
fontSize="fontSize20"
fontSize={fontSize}
fontWeight="fontWeightMedium"
outline="none"
paddingLeft="space30"
Expand Down
Original file line number Diff line number Diff line change
@@ -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<CompositeProps, "unstable_virtual" | "unstable_moves" | "unstable_system" | "wrapElement" | "wrap"> {
/**
Expand Down Expand Up @@ -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<FormPillGroupSizeVariant, Pick<BoxProps, "columnGap" | "rowGap">> = {
default: {
columnGap: "space20",
rowGap: "space20",
},
large: {
columnGap: "space30",
rowGap: "space30",
},
};

const FormPillGroupStyles = React.forwardRef<HTMLUListElement, FormPillGroupProps>(
({ element = "FORM_PILL_GROUP", display = "flex", ...props }, ref) => (
<Box
{...safelySpreadBoxProps(props)}
element={element}
ref={ref}
role="listbox"
lineHeight="lineHeight30"
margin="space0"
padding="space0"
display={display}
flexWrap="wrap"
rowGap="space20"
columnGap="space20"
>
{props.children}
</Box>
),
({ element = "FORM_PILL_GROUP", display = "flex", size = "default", ...props }, ref) => {
return (
<FormPillGroupContext.Provider value={{ size }}>
<Box
{...safelySpreadBoxProps(props)}
element={element}
ref={ref}
role="listbox"
lineHeight="lineHeight30"
margin="space0"
padding="space0"
display={display}
flexWrap="wrap"
{...SizeStyles[size]}
>
{props.children}
</Box>
</FormPillGroupContext.Provider>
);
},
);

FormPillGroupStyles.displayName = "StyledFormPillGroup";
Expand Down
8 changes: 5 additions & 3 deletions packages/paste-core/components/form-pill-group/src/index.tsx
Original file line number Diff line number Diff line change
@@ -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 };
Expand All @@ -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 };
2 changes: 2 additions & 0 deletions packages/paste-core/components/form-pill-group/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ import type { BoxStyleProps } from "@twilio-paste/box";

export type PillVariant = "error" | "default";
export type VariantStyles = Record<PillVariant, BoxStyleProps>;
/** The size variants for the FormPillGroup component. */
export type FormPillGroupSizeVariant = "default" | "large";
Original file line number Diff line number Diff line change
@@ -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<CompositeInitialState, "orientation" | "loop">;

export const useFormPillState = (config: FormPillInitialState = {}): FormPillStateReturn => {
export const useFormPillState = (config: FormPillInitialState = {}): CompositeStateReturn => {
return {
...useCompositeState({
...config,
Expand All @@ -13,3 +15,11 @@ export const useFormPillState = (config: FormPillInitialState = {}): FormPillSta
}),
};
};

export interface FormPillGroupContextState {
size: FormPillGroupSizeVariant;
}

export const FormPillGroupContext = createContext<FormPillGroupContextState>({
size: "default",
});
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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 (
<form>
<FormPillGroup {...pillState} data-testid="form-pill-group" aria-label={ariaLabel}>
<FormPillGroup {...pillState} data-testid="form-pill-group" aria-label={ariaLabel} size={size}>
{PILL_NAMES.map((pill, index) => (
<FormPill
key={pill}
Expand All @@ -41,6 +48,7 @@ export const Basic: React.FC<
);
};

export const Large = (): JSX.Element => <Basic size="large" ariaLabel="Large pill group:" />;
export const Disabled = (): JSX.Element => <Basic disabled ariaLabel="Disabled pills:" />;
export const Selected = (): JSX.Element => <Basic selected ariaLabel="Selected pills:" />;
export const Dismissable = (): JSX.Element => <Basic dismissable ariaLabel="Dismissable pills:" />;
Expand Down
7 changes: 7 additions & 0 deletions packages/paste-core/components/form-pill-group/type-docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
28 changes: 28 additions & 0 deletions packages/paste-website/src/component-examples/FormPillGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,34 @@ render(
)
`.trim();

export const largeExample = `
const BasicFormPillGroup = () => {
const pillState = useFormPillState();
return (
<form>
<FormPillGroup {...pillState} aria-label="Products:" size="large">
<FormPill {...pillState}>
Voice
</FormPill>
<FormPill {...pillState}>
<ProductVideoIcon decorative />
Video
</FormPill>
<FormPill {...pillState}>
<ProductVerifyIcon decorative />
Verify
</FormPill>
</FormPillGroup>
</form>
);
};
render(
<BasicFormPillGroup />
)
`.trim();

export const selectableExample = `
const SelectableFormPillGroup = () => {
const [pills] = React.useState(['SMS', 'MMS', 'Fax', 'Voice', 'Messaging', 'Chat']);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {DoDont, Do, Dont} from '../../../components/DoDont';
import {SidebarCategoryRoutes} from '../../../constants';
import {
basicExample,
largeExample,
selectableExample,
dismissableExample,
selectableAndDismissableExample,
Expand Down Expand Up @@ -137,6 +138,14 @@ A Form Pill can have an optional [Avatar](/components/avatar) or [Icon](/compone
{basicExample}
</LivePreview>

### Large

Use `size="large"` Form Pills only for specific and approved use cases, such as in the filter group pattern (link coming soon!).

<LivePreview scope={{FormPill, FormPillGroup, useFormPillState, ProductVideoIcon, ProductVerifyIcon}} noInline>
{largeExample}
</LivePreview>

### Selectable

Use a Selectable Form Pill to show an option that a user can select or deselect.
Expand Down

0 comments on commit 4ea2bcc

Please sign in to comment.