From f612d1ba651b6c50cec0d87e4546a1d83ce28d57 Mon Sep 17 00:00:00 2001 From: krisantrobus <55083528+krisantrobus@users.noreply.github.com> Date: Tue, 3 Sep 2024 07:48:21 -0500 Subject: [PATCH] fix(form-pill): fix issues where pill text not being truncated (#4047) * fix(form-pill): fix issues where pill textt not being truncated * chore(pr): update lockfile * chore(pr): refactor recursion types * fix(storybook): a11y unique ids * fix(storybook): fix a11y violations * chore(combobox): add ellipse stlying when selected value exceeds length * fix(form-pill): apply ellipse min width box only to elements that have text as the child * Update packages/paste-core/components/combobox/stories/MultiselectCombobox.stories.tsx Co-authored-by: Sarah * Update packages/paste-core/components/form-pill-group/stories/index.stories.tsx Co-authored-by: Nora Krantz <75342690+nkrantz@users.noreply.github.com> * chore(pr): addressing comments * chore(pr): addressing comments --------- Co-authored-by: Sarah Co-authored-by: Nora Krantz <75342690+nkrantz@users.noreply.github.com> Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .changeset/violet-cows-share.md | 6 + .changeset/warm-zoos-kick.md | 6 + .../components/combobox/package.json | 2 + .../combobox/src/singleselect/Combobox.tsx | 1 + .../combobox/stories/Combobox.stories.tsx | 10 ++ .../stories/MultiselectCombobox.stories.tsx | 24 +++ .../components/form-pill-group/package.json | 2 + .../form-pill-group/src/FormPill.tsx | 1 + .../form-pill-group/src/FormPillButton.tsx | 27 +++- .../form-pill-group/src/FormPillGroup.tsx | 1 + .../form-pill-group/stories/index.stories.tsx | 149 ++++++++++++++++++ .../components/popover/package.json | 2 + yarn.lock | 6 + 13 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 .changeset/violet-cows-share.md create mode 100644 .changeset/warm-zoos-kick.md diff --git a/.changeset/violet-cows-share.md b/.changeset/violet-cows-share.md new file mode 100644 index 0000000000..8cdb66f147 --- /dev/null +++ b/.changeset/violet-cows-share.md @@ -0,0 +1,6 @@ +--- +"@twilio-paste/form-pill-group": patch +"@twilio-paste/core": patch +--- + +[FormPillGroup] fixed a bug where long text in a form pill would wrap and break styling. Text within FormPill is now truncated so FormPill(s) will not stretch beyond FormPillGroup width. diff --git a/.changeset/warm-zoos-kick.md b/.changeset/warm-zoos-kick.md new file mode 100644 index 0000000000..92d0302bb4 --- /dev/null +++ b/.changeset/warm-zoos-kick.md @@ -0,0 +1,6 @@ +--- +"@twilio-paste/combobox": patch +"@twilio-paste/core": patch +--- + +[Combobox] added ellipse styling to text that exceeds length of a single select combobox when not active diff --git a/packages/paste-core/components/combobox/package.json b/packages/paste-core/components/combobox/package.json index bbf901363c..0d5e52cd4f 100644 --- a/packages/paste-core/components/combobox/package.json +++ b/packages/paste-core/components/combobox/package.json @@ -55,6 +55,7 @@ "@twilio-paste/styling-library": "^3.0.0", "@twilio-paste/text": "^10.0.0", "@twilio-paste/theme": "^11.0.0", + "@twilio-paste/truncate": "^14.0.0", "@twilio-paste/types": "^6.0.0", "@twilio-paste/uid-library": "^2.0.0", "@twilio-paste/utils": "^5.0.0", @@ -89,6 +90,7 @@ "@twilio-paste/styling-library": "^3.0.0", "@twilio-paste/text": "^10.1.0", "@twilio-paste/theme": "^11.0.1", + "@twilio-paste/truncate": "^14.1.0", "@twilio-paste/types": "^6.0.0", "@twilio-paste/uid-library": "^2.0.0", "@twilio-paste/utils": "^5.0.0", diff --git a/packages/paste-core/components/combobox/src/singleselect/Combobox.tsx b/packages/paste-core/components/combobox/src/singleselect/Combobox.tsx index 7c26b25738..dc5346043d 100644 --- a/packages/paste-core/components/combobox/src/singleselect/Combobox.tsx +++ b/packages/paste-core/components/combobox/src/singleselect/Combobox.tsx @@ -168,6 +168,7 @@ const Combobox = React.forwardRef( autocomplete={autocomplete} aria-describedby={helpText != null ? helpTextId : null} element={`${element}_ELEMENT`} + textOverflow="ellipsis" /> {!autocomplete && ( diff --git a/packages/paste-core/components/combobox/stories/Combobox.stories.tsx b/packages/paste-core/components/combobox/stories/Combobox.stories.tsx index 2f95af2ed4..7338ec5e78 100644 --- a/packages/paste-core/components/combobox/stories/Combobox.stories.tsx +++ b/packages/paste-core/components/combobox/stories/Combobox.stories.tsx @@ -887,6 +887,16 @@ ComboboxInModal.parameters = { }, }; +export const ComboboxErrorNarrowContainer: StoryFn = () => { + return ( + + + + ); +}; + +ComboboxErrorNarrowContainer.storyName = "Combobox - Error narrow container"; + export const ComboboxInPopover: StoryFn = () => { return ( diff --git a/packages/paste-core/components/combobox/stories/MultiselectCombobox.stories.tsx b/packages/paste-core/components/combobox/stories/MultiselectCombobox.stories.tsx index 6a515a2a9e..62624785b2 100644 --- a/packages/paste-core/components/combobox/stories/MultiselectCombobox.stories.tsx +++ b/packages/paste-core/components/combobox/stories/MultiselectCombobox.stories.tsx @@ -713,3 +713,27 @@ export default { ), ], } as Meta; + +export const MultiselectComboboxInNarrowContainer = (): StoryFn => { + const [inputValue, setInputValue] = React.useState(""); + const filteredItems = React.useMemo(() => getFilteredItems(inputValue), [inputValue]); + + return ( + + { + setInputValue(newInputValue); + }} + onSelectedItemsChange={(selectedItems) => { + // eslint-disable-next-line no-console + console.log(selectedItems); + }} + /> + + ); +}; +MultiselectComboboxInNarrowContainer.storyName = "Narrow Container"; diff --git a/packages/paste-core/components/form-pill-group/package.json b/packages/paste-core/components/form-pill-group/package.json index 0e92e43744..23f96e49e4 100644 --- a/packages/paste-core/components/form-pill-group/package.json +++ b/packages/paste-core/components/form-pill-group/package.json @@ -39,6 +39,7 @@ "@twilio-paste/style-props": "^9.0.0", "@twilio-paste/styling-library": "^3.0.0", "@twilio-paste/theme": "^11.0.0", + "@twilio-paste/truncate": "^14.0.0", "@twilio-paste/types": "^6.0.0", "@twilio-paste/uid-library": "^2.0.0", "@types/react": "^16.8.6 || ^17.0.2 || ^18.0.27", @@ -58,6 +59,7 @@ "@twilio-paste/style-props": "^9.1.0", "@twilio-paste/styling-library": "^3.0.0", "@twilio-paste/theme": "^11.0.0", + "@twilio-paste/truncate": "^14.1.0", "@twilio-paste/types": "^6.0.0", "@twilio-paste/uid-library": "^2.0.0", "@types/react": "^18.0.27", diff --git a/packages/paste-core/components/form-pill-group/src/FormPill.tsx b/packages/paste-core/components/form-pill-group/src/FormPill.tsx index 11ebc071a8..976c8f576d 100644 --- a/packages/paste-core/components/form-pill-group/src/FormPill.tsx +++ b/packages/paste-core/components/form-pill-group/src/FormPill.tsx @@ -140,6 +140,7 @@ export const FormPill = React.forwardRef( position="relative" display="inline-block" borderRadius="borderRadiusPill" + maxWidth="100%" {...computedStyles} > const { size, variant: groupVariant } = React.useContext(FormPillGroupContext); const { height, fontSize } = sizeStyles[size]; + const renderChildren = (children: React.ReactNode): React.ReactNode => { + if (typeof children === "string") { + return {children}; + } + + if (React.isValidElement(children)) { + if (children.props.children && typeof children.props.children === "string") { + return ( + + {renderChildren(children.props.children)} + + ); + } + return {renderChildren(children.props.children)}; + } + + if (Array.isArray(children)) { + return children.map((child) => renderChildren(child)); + } + + return children; + }; + return ( paddingLeft="space30" paddingRight={isDismissable ? (size === "large" ? "space90" : "space80") : "space30"} transition="background-color 150ms ease-in, border-color 150ms ease-in, box-shadow 150ms ease-in, color 150ms ease-in" + maxWidth="100%" {...computedStyles} > @@ -86,7 +111,7 @@ export const FormPillButton = React.forwardRef {i18nErrorLabel} ) : null} - {props.children} + {renderChildren(props.children)} ); 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 217eead602..8dbd906f1e 100644 --- a/packages/paste-core/components/form-pill-group/src/FormPillGroup.tsx +++ b/packages/paste-core/components/form-pill-group/src/FormPillGroup.tsx @@ -88,6 +88,7 @@ const FormPillGroupStyles = React.forwardRef {props.children} 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 6fe794b0b0..caaf707757 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 @@ -1,7 +1,10 @@ +import { StoryFn } from "@storybook/react"; // eslint-disable-next-line import/no-extraneous-dependencies import { Avatar } from "@twilio-paste/avatar"; import { Box } from "@twilio-paste/box"; import { CalendarIcon } from "@twilio-paste/icons/esm/CalendarIcon"; +import { Stack } from "@twilio-paste/stack"; +import { Text } from "@twilio-paste/text"; import * as React from "react"; import { FormPill, FormPillGroup, useFormPillState } from "../src"; @@ -177,6 +180,152 @@ export const FormPillTreeVariant = (): JSX.Element => { FormPillTreeVariant.storyName = "FormPillGroup Tree Variant"; +export const PillStringOverflowVSComposed: StoryFn< + React.PropsWithChildren<{ + selected?: boolean; + dismissable?: boolean; + disabled?: boolean; + ariaLabel?: string; + size?: FormPillGroupSizeVariant; + }> +> = ({ selected = false, dismissable = true, disabled = false, ariaLabel = "Basic pills:", size }) => { + const pillState = useFormPillState(); + const pillState2 = useFormPillState(); + + return ( + + + + {PILL_NAMES.map((pill, index) => ( + 2 ? "error" : "default"} + onDismiss={dismissable ? () => {} : undefined} + disabled={disabled} + > + {index % 3 === 2 ? ( + + ) : null} + {index % 3 === 1 ? ( + + ) : null} + {pill} + + ))} + + + + {PILL_NAMES.map((pill, index) => ( + 2 ? "error" : "default"} + onDismiss={dismissable ? () => {} : undefined} + disabled={disabled} + > + {pill} + + ))} + + + + ); +}; + +PillStringOverflowVSComposed.storyName = "Pill String Overflow vs Composed"; + +export const PillNarrowContainerDecorationsEnd: StoryFn< + React.PropsWithChildren<{ + selected?: boolean; + dismissable?: boolean; + disabled?: boolean; + ariaLabel?: string; + size?: FormPillGroupSizeVariant; + }> +> = ({ selected = false, dismissable = true, disabled = false, ariaLabel = "Basic pills:", size }) => { + const pillState = useFormPillState(); + const pillState2 = useFormPillState(); + + return ( + + + {PILL_NAMES.map((pill, index) => ( + 2 ? "error" : "default"} + onDismiss={dismissable ? () => {} : undefined} + disabled={disabled} + > + {pill} + {index % 3 === 2 ? ( + + ) : null} + {index % 3 === 1 ? : null} + + ))} + + + ); +}; + +export const PillNarrowContainerFormattedTextContent: StoryFn< + React.PropsWithChildren<{ + selected?: boolean; + dismissable?: boolean; + disabled?: boolean; + ariaLabel?: string; + size?: FormPillGroupSizeVariant; + }> +> = ({ selected = false, dismissable = true, disabled = false, ariaLabel = "Basic pills:", size }) => { + const pillState = useFormPillState(); + + return ( + + + {PILL_NAMES.map((pill, index) => ( + 2 ? "error" : "default"} + onDismiss={dismissable ? () => {} : undefined} + disabled={disabled} + > + {index % 3 === 2 ? ( + + ) : null} + {index % 3 === 1 ? : null} + + {pill} + + + ))} + + + ); +}; + // eslint-disable-next-line import/no-default-export export default { title: "Components/Form Pill Group", diff --git a/packages/paste-core/components/popover/package.json b/packages/paste-core/components/popover/package.json index 91a3eb40c2..d47893ce09 100644 --- a/packages/paste-core/components/popover/package.json +++ b/packages/paste-core/components/popover/package.json @@ -44,6 +44,7 @@ "@twilio-paste/styling-library": "^3.0.0", "@twilio-paste/text": "^10.0.0", "@twilio-paste/theme": "^11.0.0", + "@twilio-paste/truncate": "^14.0.0", "@twilio-paste/types": "^6.0.0", "@twilio-paste/uid-library": "^2.0.0", "@types/react": "^16.8.6 || ^17.0.2 || ^18.0.27", @@ -71,6 +72,7 @@ "@twilio-paste/styling-library": "^3.0.0", "@twilio-paste/text": "^10.1.0", "@twilio-paste/theme": "^11.0.0", + "@twilio-paste/truncate": "^14.1.0", "@twilio-paste/types": "^6.0.0", "@twilio-paste/uid-library": "^2.0.0", "@types/react": "^18.0.27", diff --git a/yarn.lock b/yarn.lock index 345a9283f8..ef15b4e291 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12207,6 +12207,7 @@ __metadata: "@twilio-paste/styling-library": ^3.0.0 "@twilio-paste/text": ^10.1.0 "@twilio-paste/theme": ^11.0.1 + "@twilio-paste/truncate": ^14.1.0 "@twilio-paste/types": ^6.0.0 "@twilio-paste/uid-library": ^2.0.0 "@twilio-paste/utils": ^5.0.0 @@ -12244,6 +12245,7 @@ __metadata: "@twilio-paste/styling-library": ^3.0.0 "@twilio-paste/text": ^10.0.0 "@twilio-paste/theme": ^11.0.0 + "@twilio-paste/truncate": ^14.0.0 "@twilio-paste/types": ^6.0.0 "@twilio-paste/uid-library": ^2.0.0 "@twilio-paste/utils": ^5.0.0 @@ -13073,6 +13075,7 @@ __metadata: "@twilio-paste/style-props": ^9.1.0 "@twilio-paste/styling-library": ^3.0.0 "@twilio-paste/theme": ^11.0.0 + "@twilio-paste/truncate": ^14.1.0 "@twilio-paste/types": ^6.0.0 "@twilio-paste/uid-library": ^2.0.0 "@types/react": ^18.0.27 @@ -13094,6 +13097,7 @@ __metadata: "@twilio-paste/style-props": ^9.0.0 "@twilio-paste/styling-library": ^3.0.0 "@twilio-paste/theme": ^11.0.0 + "@twilio-paste/truncate": ^14.0.0 "@twilio-paste/types": ^6.0.0 "@twilio-paste/uid-library": ^2.0.0 "@types/react": ^16.8.6 || ^17.0.2 || ^18.0.27 @@ -14109,6 +14113,7 @@ __metadata: "@twilio-paste/styling-library": ^3.0.0 "@twilio-paste/text": ^10.1.0 "@twilio-paste/theme": ^11.0.0 + "@twilio-paste/truncate": ^14.1.0 "@twilio-paste/types": ^6.0.0 "@twilio-paste/uid-library": ^2.0.0 "@types/react": ^18.0.27 @@ -14137,6 +14142,7 @@ __metadata: "@twilio-paste/styling-library": ^3.0.0 "@twilio-paste/text": ^10.0.0 "@twilio-paste/theme": ^11.0.0 + "@twilio-paste/truncate": ^14.0.0 "@twilio-paste/types": ^6.0.0 "@twilio-paste/uid-library": ^2.0.0 "@types/react": ^16.8.6 || ^17.0.2 || ^18.0.27