From 1bdf32b9f894b3ed65fd0415004e0807ad8c6973 Mon Sep 17 00:00:00 2001 From: Shelvin Date: Thu, 29 Jun 2023 17:53:29 -0700 Subject: [PATCH] create select component (#327) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Changes Adds ` setShippingVolume(selected)} + label="Label" + selectedKey={selectedOption} + onSelectionChange={(selected) => setSelectedOption(selected)} + helperText="Helper text" > - # of packages - 1000 - 50000 - 1M+ + Option 1 + Option 2 + Option 3 ); } ``` -_With helper text and passing data from external source:_ +_Simple controlled selection with separator:_ ```tsx import { Select } from "@easypost/easy-ui/Select"; -const options = [ - { volume: "# of packages" }, - { volume: "1000" }, - { volume: "50000" }, - { volume: "1M+" }, -]; - export function Component() { - const [shippingVolume, setShippingVolume] = React.useState("# of packages"); + const [selectedOption, setSelectedOption] = React.useState("Option 1"); return ( ); } @@ -168,14 +182,13 @@ import { Select } from "@easypost/easy-ui/Select"; export function Component() { return ( ); } @@ -189,11 +202,10 @@ import SomeIcon from "@easypost/easy-ui-icons/Some"; export function Component() { return ( - + Option 1 + Option 2 + Option 3 ); } @@ -208,8 +220,9 @@ export function Component() { Accessibility - Labels should be included on all select fields as they describe the purpose of any associated form control. In situations when you may want the label to be visually hidden, use the `isLabelVisuallyHidden` prop. +- The dropdown has an ARIA role of `listbox`. ## Dependencies -- `react-aria`— `useSelect` `usePopover` `OverlayContainer` -- `react-stately` - `useSelectState` `Item` +- `react-aria`— `useSelect` `usePopover` `OverlayContainer` `useListBox` `useOption` `useListBoxSection` `useSeparator` +- `react-stately` - `useSelectState` `Item` `Section` diff --git a/easy-ui-icons/src/CalendarMonth.json b/easy-ui-icons/src/CalendarMonth.json new file mode 100644 index 00000000..ae564c42 --- /dev/null +++ b/easy-ui-icons/src/CalendarMonth.json @@ -0,0 +1,5 @@ +{ + "name": "calendar_month", + "style": "outlined", + "source": "@material-symbols/svg-300" +} diff --git a/easy-ui-react/src/InputField/InputField.module.scss b/easy-ui-react/src/InputField/InputField.module.scss index ed6d8620..6b94c6a0 100644 --- a/easy-ui-react/src/InputField/InputField.module.scss +++ b/easy-ui-react/src/InputField/InputField.module.scss @@ -1,85 +1,12 @@ @use "../styles/common" as *; +@use "mixins" as Input; .root { - @include component-token( - "inputfield", - "border_radius", - design-token("shape.border_radius.md") - ); - @include component-token( - "inputfield", - "box_shadow", - design-token("shadow.input") - ); - @include component-token( - "inputfield", - "color.text.resting", - theme-token("color.text") - ); - @include component-token( - "inputfield", - "color.text.gray.resting", - theme-token("color.text.gray.resting") - ); - @include component-token( - "inputfield", - "color.text.gray.bold", - theme-token("color.text.gray.bold") - ); - @include component-token( - "inputfield", - "color.text.disabled", - theme-token("color.text.disabled") - ); - @include component-token( - "inputfield", - "color.text.engaged", - theme-token("color.text.engaged") - ); - @include component-token( - "inputfield", - "color.text.danger", - theme-token("color.text.danger") - ); - @include component-token( - "inputfield", - "color.border.resting", - theme-token("color.border.resting") - ); - @include component-token( - "inputfield", - "color.border.engaged", - theme-token("color.border.engaged") - ); - @include component-token( - "inputfield", - "color.border.danger", - theme-token("color.border.danger") - ); - @include component-token( - "inputfield", - "color.background", - theme-token("color.background") - ); - @include component-token( - "inputfield", - "color.background.disabled", - theme-token("color.background.disabled.subtle") - ); - @include component-token("inputfield", "max-height-sm", 32px); - @include component-token( - "inputfield", - "z-index", - design-token("z_index.input_icon") - ); - display: flex; - flex-direction: column; + @include Input.root; } .inputIconContainer { - display: flex; - align-items: center; - position: relative; + @include Input.inputIconContainer; } .label { @@ -91,79 +18,19 @@ } .input { - @include font-style("body1"); - @include component-token("inputfield", "min-height-textarea", 48px); - @include component-token( - "inputfield", - "icon-input-padding", - design-token("space.6") - ); - color: component-token("inputfield", "color.text.resting"); - background-color: component-token("inputfield", "color.background"); - border: design-token("shape.border_width.1") solid - component-token("inputfield", "color.border.resting"); - border-radius: component-token("inputfield", "border_radius"); - padding: calc( - #{design-token("space.1.5")} - #{design-token("shape.border_width.1")} - ); - outline: none; - position: relative; - width: 100%; - - &:focus, - &:active { - color: component-token("inputfield", "color.text.engaged"); - border-color: component-token("inputfield", "color.border.engaged"); - } - - &:focus { - box-shadow: component-token("inputfield", "box_shadow"); - } - - &::placeholder { - color: component-token("inputfield", "color.text.gray.resting"); - } - - &:disabled { - background-color: component-token( - "inputfield", - "color.background.disabled" - ); - color: component-token("inputfield", "color.text.disabled"); - } + @include Input.input; } .errorInput { - color: component-token("inputfield", "color.text.danger"); - border-color: component-token("inputfield", "color.border.danger"); - - &:focus, - &:active { - border-color: component-token("inputfield", "color.border.danger"); - } + @include Input.error; } .inputSizeSm { - @include font-style("body2"); - padding: calc( - #{design-token("space.1")} - #{design-token("shape.border_width.1")} - ) - calc(#{design-token("space.1.5")} - #{design-token("shape.border_width.1")}); - max-height: component-token("inputfield", "max-height-sm"); - @include component-token("inputfield", "password-input-padding-right", 0); - @include component-token( - "inputfield", - "icon-input-padding", - design-token("space.4.5") - ); + @include Input.inputSm; } .inputSizeLg { - padding: calc( - #{design-token("space.2")} - #{design-token("shape.border_width.1")} - ); - @include component-token("inputfield", "min-height-textarea", 56px); - @include component-token("inputfield", "password-input-padding-right", 0); + @include Input.inputLg; } .passwordInput { @@ -222,7 +89,7 @@ } .hovered { - border-color: component-token("inputfield", "color.border.engaged"); + @include Input.hovered; } .input:active + .passwordBtn, @@ -282,11 +149,11 @@ } .iconStartInput { - padding-left: component-token("inputfield", "icon-input-padding"); + @include Input.iconStartInput; } .iconEndInput { - padding-right: component-token("inputfield", "icon-input-padding"); + @include Input.iconEndInput; } .inputIconPlacementSm { diff --git a/easy-ui-react/src/InputField/InputField.tsx b/easy-ui-react/src/InputField/InputField.tsx index 1052fe52..4887cd5c 100644 --- a/easy-ui-react/src/InputField/InputField.tsx +++ b/easy-ui-react/src/InputField/InputField.tsx @@ -172,7 +172,7 @@ export function InputField(props: InputFieldProps) {