diff --git a/.changeset/nice-tires-trade.md b/.changeset/nice-tires-trade.md new file mode 100644 index 00000000..2195bab8 --- /dev/null +++ b/.changeset/nice-tires-trade.md @@ -0,0 +1,5 @@ +--- +"@easypost/easy-ui": minor +--- + +add support for secondary text on select items diff --git a/easy-ui-react/src/Select/Select.mdx b/easy-ui-react/src/Select/Select.mdx index 63cc79c9..44c13c47 100644 --- a/easy-ui-react/src/Select/Select.mdx +++ b/easy-ui-react/src/Select/Select.mdx @@ -1,5 +1,5 @@ import React from "react"; -import { Canvas, Meta, ArgTypes } from "@storybook/addon-docs/blocks"; +import { Canvas, Meta, ArgTypes, Controls } from "@storybook/addon-docs/blocks"; import { Select } from "./Select"; import * as SelectStories from "./Select.stories"; @@ -76,6 +76,12 @@ Use `isDisabled` to disabled the field entirely. +## With Secondary Text + +Each option can render a secondary description. The selected value in the closed field also shows the same secondary text. + + + ## Properties ### Select diff --git a/easy-ui-react/src/Select/Select.module.scss b/easy-ui-react/src/Select/Select.module.scss index a6a7200a..3fa2a48b 100644 --- a/easy-ui-react/src/Select/Select.module.scss +++ b/easy-ui-react/src/Select/Select.module.scss @@ -6,12 +6,14 @@ position: fixed; inset: 0; } + .listboxRoot { @include Menu.root; } .listbox { @include Menu.menu; + outline: none; } .listboxList, @@ -19,34 +21,50 @@ @include Menu.menuList; } -.optionContent, -.separator { - @include Menu.itemContent; +.listboxList { + padding-top: 0; + padding-bottom: 0; } .option { text-decoration: none; -} + outline: none; -.optionContent { - @include Menu.itemContentColor; -} + &:not([data-is-disabled="true"]) { + cursor: pointer; + } -.listbox, -.option { - outline: none; + &[data-is-focused="true"] .optionContent { + @include Menu.itemDataFocused; + } + + &[data-is-disabled="true"] .optionContent { + @include Menu.itemDataDisabled; + } } -.option:not([data-is-disabled="true"]) { - cursor: pointer; +.optionContent, +.separator { + @include Menu.itemContent; } -.option[data-is-focused="true"] .optionContent { - @include Menu.itemDataFocused; +.optionContent { + @include Menu.itemContentColor; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 2px; + min-width: 0; + width: 100%; + height: auto; + padding-top: design-token("space.1"); + padding-bottom: design-token("space.1"); } -.option[data-is-disabled="true"] .optionContent { - @include Menu.itemDataDisabled; +.optionDescription { + width: 100%; + line-height: 1.2; + white-space: nowrap; } .separator::after { @@ -60,6 +78,8 @@ .selectField { display: flex; align-items: center; + flex: 1 1 auto; + min-width: 0; @include Input.input; &:hover { @@ -93,8 +113,29 @@ .selectFieldText { overflow: hidden; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + min-width: 0; + width: 100%; + text-align: left; + gap: 0; +} + +.selectedDescription { + width: 100%; + line-height: 1.2; + white-space: nowrap; } .listboxOpen { border-color: component-token("inputfield", "color.border.engaged"); } + +// Override the absolute-positioned end icon to vertically center +// when the trigger grows taller (e.g. descriptive two-line mode) +.selectFieldIconContainer > :last-child { + top: 50%; + transform: translateY(-50%); +} diff --git a/easy-ui-react/src/Select/Select.stories.tsx b/easy-ui-react/src/Select/Select.stories.tsx index 12955eee..f3e5bf82 100644 --- a/easy-ui-react/src/Select/Select.stories.tsx +++ b/easy-ui-react/src/Select/Select.stories.tsx @@ -187,3 +187,41 @@ export const DisabledSelect: Story = { isDisabled: true, }, }; + +export const WithSecondaryText: Story = { + render: () => { + const [selectedKey, setSelectedKey] = React.useState("standard"); + + return ( + + ); + }, +}; diff --git a/easy-ui-react/src/Select/Select.test.tsx b/easy-ui-react/src/Select/Select.test.tsx index d13c80fc..f0c67503 100644 --- a/easy-ui-react/src/Select/Select.test.tsx +++ b/easy-ui-react/src/Select/Select.test.tsx @@ -102,6 +102,44 @@ describe(" setSelectedOption(selected)} -* helperText="Helper text" -* > -* Option 1 -* Option 2 -* Option 3 -* -* ); -* } -``` -* -* @example -* _Simple controlled selection with separator:_ -*```tsx -* import { Select } from "@easypost/easy-ui/Select"; -* -* export function Component() { -* const [selectedOption, setSelectedOption] = React.useState("Option 1"); -* -* return ( -* -* ); -* } -``` + *```tsx + * import { Select } from "@easypost/easy-ui/Select"; + * + * export function Component() { + * const [selectedOption, setSelectedOption] = React.useState("Option 1"); + * + * return ( + * + * ); + * } + * ``` + * + * @example + * _Simple controlled selection with separator:_ + *```tsx + * import { Select } from "@easypost/easy-ui/Select"; + * + * export function Component() { + * const [selectedOption, setSelectedOption] = React.useState("Option 1"); + * + * return ( + * + * ); + * } + * ``` */ export function Select( props: SelectProps, @@ -165,6 +165,7 @@ export function Select( ); } + /** * Represents a section in a `