@workday/canvas-kit-mcp 16.1.4 → 16.2.0-0604-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -18,7 +18,7 @@ import { z as z2 } from "zod";
18
18
  // package.json
19
19
  var package_default = {
20
20
  name: "@workday/canvas-kit-mcp",
21
- version: "16.1.4",
21
+ version: "16.1.1",
22
22
  description: "MCP package for Canvas Kit",
23
23
  author: "Workday, Inc. (https://www.workday.com)",
24
24
  license: "Apache-2.0",
@@ -1563,8 +1563,8 @@ var stories_config_default = {
1563
1563
  title: "Components/Inputs/Select",
1564
1564
  storybookUrl: "https://workday.github.io/canvas-kit/?path=/docs/components-inputs-select--docs",
1565
1565
  mdxPath: "modules/react/select/stories/Select.mdx",
1566
- mdxProse: "# Canvas Kit Select\n\nSelect inputs allow users to choose one option from a list of items or type a matching option.\n\n[> Workday Design Reference](https://design.workday.com/components/inputs/select)\n\n## Installation\n\n```sh\nyarn add @workday/canvas-kit-react\n```\n\n## Usage\n\n### Basic Example\n\n`Select` supports a [dynamic API](/get-started/for-developers/guides/collection-api/#dynamic-items)\nwhere you pass an array of items via the `items` prop and provide a render function to display the\nitems. The items may be provided as an\n[array of strings](/get-started/for-developers/guides/collection-api/#array-of-strings) or an\n[array of objects](/get-started/for-developers/guides/collection-api/#array-of-objects).\n\n`Select` should be used in tandem with [Form Field](/components/inputs/form-field/) to ensure proper\nlabel association and screen reader support. Wrap **`Select`** with **`FormField`**, and compose\n**`FormField.Input as={Select.Input}`** so the combobox receives the field label. Include\n**`Select.Popper`**, **`Select.Card`**, **`Select.List`**, and **`Select.Item`**.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n 'Thisisalongstringwithnobreaksandwillwrap',\n];\n\nexport const Basic = () => {\n const [value, setValue] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n console.log('change', event.currentTarget.value);\n setValue(event.target.value);\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options}>\n <FormField.Input as={Select.Input} onChange={handleChange} />\n <Select.Popper>\n <Select.Card>\n <Select.List>\n {item => {\n return <Select.Item>{item}</Select.Item>;\n }}\n </Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n Selected Value: {value}\n </Flex>\n );\n};\n```\n\nOur example uses [React state](<(https://react.dev/learn/state-a-components-memory)>) to track the\nvalue of the `Select`.\n\n### Hoisted Model\n\nBy default, `Select` will create and use its own model internally. Alternatively, you may configure\nyour own model with `useSelectModel` and pass it to `Select` via the `model` prop. This pattern is\nreferred to as\n[hoisting the model](/get-started/for-developers/documentation/compound-components/#configuring-a-model)\nand provides direct access to its `state` and `events` outside of the `Select` component.\n\nIn this example, we set up external observation of the model state and create an external button to\ntrigger an event to change the selected item.\n\n**Note: If your array of objects uses an `id` property and a `text` property there is no need to use\nthe helper functions of `getId` or `getTextValue`. The collection system and the `Select` use these\nproperties by default for keyboard navigation and selected the `id` based on the item clicked.**\n```tsx\nimport React from 'react';\n\nimport {SecondaryButton} from '@workday/canvas-kit-react/button';\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Select, useSelectModel} from '@workday/canvas-kit-react/select';\nimport {BodyText} from '@workday/canvas-kit-react/text';\n\nconst options = [\n {text: 'E-mail', id: 'email-1'},\n {text: 'Phone', id: 'phone-2'},\n {text: 'Fax', id: 'fax-3'},\n {text: 'Mail', id: 'mail-4'},\n {text: 'Mobile Phone', id: 'mobile-phone-5'},\n];\n\nexport const HoistedModel = () => {\n const model = useSelectModel({\n items: options,\n initialSelectedIds: ['fax-3'],\n });\n\n return (\n <>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select model={model}>\n <FormField.Input as={Select.Input} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item.text}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n <BodyText size=\"small\">Selected Value: {model.state.selectedIds[0]}</BodyText>\n <SecondaryButton\n onClick={() => {\n model.events.select({id: 'phone-2'});\n }}\n >\n Select Phone Item\n </SecondaryButton>\n </>\n );\n};\n```\n\n### Label Position Horizontal\n\nSet the `orientation` prop of the Form Field to designate the position of the label relative to the\ninput component. By default, the orientation will be set to `vertical`.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select, useSelectModel} from '@workday/canvas-kit-react/select';\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const LabelPosition = () => {\n const model = useSelectModel({\n items: options,\n });\n\n return (\n <Flex>\n <FormField orientation=\"horizontalStart\">\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select model={model}>\n <FormField.Input as={Select.Input} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n <FormField.Hint>Choose a form of contact</FormField.Hint>\n </Select>\n </FormField.Field>\n </FormField>\n </Flex>\n );\n};\n```\n\n### Required\n\nSet the `isRequired` prop of the wrapping `FormField` to `true` to indicate that the field is\nrequired. Labels for required fields are suffixed by a red asterisk.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const Required = () => {\n const [value, setValue] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.target.value);\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField isRequired>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options}>\n <FormField.Input as={Select.Input} onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n Selected Value: {value}\n </Flex>\n );\n};\n```\n\n### Disabled\n\nSet the `disabled` prop on **`FormField.Input as={Select.Input}`** to prevent users from interacting\nwith the combobox.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax (disabled)',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const Disabled = () => {\n const [_, setValue] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.target.value);\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options} nonInteractiveIds={['Fax (disabled)']}>\n <FormField.Input as={Select.Input} disabled onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>\n {item => (\n <Select.Item aria-disabled={item === 'Fax (disabled)' ? true : undefined}>\n {item}\n </Select.Item>\n )}\n </Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n </Flex>\n );\n};\n```\n\n### Disabled Items\n\nIn order to disable items and prevent users from interacting with them:\n\n1. Set the `nonInteractiveIds` prop of `Select` to an array of disabled item `id`s. If your items\n are an array of `strings` this will be just the text value. If your items are an array of\n `objects`, this will be that value of the `id` property. This will disable interaction for those\n items and exclude them from type-ahead.\n\n2. Set the `aria-disabled` attribute of all disabled `Select.Item`s to `true`. This ensures the\n items are styled as disabled.\n\nThe following example adds the string value of the items we want disable to `nonInteractiveIds` and\nsets `aria-disabled` for the disabled items.\n\n### With Icons\n\nUse `Select.Item.Icon` to render an icon for a `Select.Item`. The `icon` prop for `Select.Item.Icon`\naccepts [system icons](/assets/system-icons/) from `@workday/canvas-system-icons-web`.\n\nIn order to render the icon for the selected item on **`FormField.Input as={Select.Input}`**:\n\n1. Obtain a reference to the `model` by registering your `items` with `useSelectModel`.\n2. Get the selected item:\n `const selectedItem = model.navigation.getItem(model.state.selectedIds[0], model)`\n3. Pass the icon for the selected item to the input:\n `<FormField.Input as={Select.Input} inputStartIcon={selectedItem?.value.icon} />`\n\n> **Note:** Dynamic `{item => <Select.Item>}` registration already uses the collection `id`. Set\n> **`data-id`** only on static **`Select.Item`** children (see [Grouped Items](#grouped-items)), and\n> keep it equal to that id (`id` or **`getId`**).\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select, useSelectModel} from '@workday/canvas-kit-react/select';\nimport {createStyles, px2rem} from '@workday/canvas-kit-styling';\nimport {cloudArrowUpIcon, cloudIcon, commentIcon, userIcon} from '@workday/canvas-system-icons-web';\n\nconst styleOverrides = {\n formfieldInputStyles: createStyles({\n width: px2rem(300),\n }),\n selectCardStyles: createStyles({\n maxHeight: px2rem(200),\n }),\n};\n\nconst customOptions = [\n {text: 'Activity Stream', id: 'activity-stream', icon: commentIcon},\n {text: 'Avatar', id: 'avatar', icon: cloudIcon},\n {text: 'Upload Cloud', id: 'upload-cloud', icon: cloudArrowUpIcon},\n {text: 'User', id: 'user', icon: userIcon},\n];\n\nexport const WithIcons = () => {\n const model = useSelectModel({\n items: customOptions,\n });\n const selectedItem = model.navigation.getItem(model.state.selectedIds[0], model);\n return (\n <Flex>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select model={model}>\n <FormField.Input\n as={Select.Input}\n cs={styleOverrides.formfieldInputStyles}\n inputStartIcon={selectedItem?.value.icon}\n />\n <Select.Popper>\n <Select.Card cs={styleOverrides.selectCardStyles}>\n {model.state.items.length > 0 && (\n <Select.List>\n {item => (\n <Select.Item>\n <Select.Item.Icon icon={item.icon} />\n {item.text}\n </Select.Item>\n )}\n </Select.List>\n )}\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n </Flex>\n );\n};\n```\n\n**Note: that `FormField.Input as={Select.Input}` will only render an icon if an item is selected.**\n\n### Grow\n\nSet the `grow` prop of the wrapping `FormField` to `true` to configure the `Select.Input` to expand\nto the width of its container.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select, useSelectModel} from '@workday/canvas-kit-react/select';\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const Grow = () => {\n const model = useSelectModel({\n items: options,\n });\n\n return (\n <Flex>\n <FormField grow>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select model={model}>\n <FormField.Input as={Select.Input} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n </Flex>\n );\n};\n```\n\n### Menu Height\n\n`Select.Card` has a default maximum height of `300px` to restrict the height of the dropdown menu.\nSet its `maxHeight` prop to override this value.\n```tsx\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Box} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles, px2rem} from '@workday/canvas-kit-styling';\n\nconst selectCardStyles = createStyles({\n maxHeight: px2rem(200),\n});\n\nconst cities = [\n 'Atlanta (United States)',\n 'Amsterdam (Europe)',\n 'Austin (United States)',\n 'Beaverton (United States)',\n 'Belfast (Europe)',\n 'Berlin (Europe)',\n 'Boston (United States)',\n 'Boulder (United States)',\n 'Chicago (United States)',\n 'Dallas (United States)',\n 'Denver (United States)',\n 'Dublin (Europe)',\n 'Irvine (United States)',\n 'Minneapolis (United States)',\n 'New York (United States)',\n 'Orlando (United States)',\n 'Palo Alto (United States)',\n 'Philadelphia (United States)',\n 'Pleasanton (United States)',\n 'Raleigh (United States)',\n 'San Francisco (United States)',\n 'San Mateo (United States)',\n 'Stockholm (Europe)',\n 'Toronto (Canada)',\n 'Victoria (Canada)',\n 'Vienna (Europe)',\n 'Warsaw (Europe)',\n 'Washington, DC (United States)',\n 'Zurich (Europe)',\n];\n\nexport const MenuHeight = () => {\n return (\n <Box>\n <FormField>\n <FormField.Label>Choose a City</FormField.Label>\n <FormField.Field>\n <Select items={cities}>\n <FormField.Input as={Select.Input} />\n <Select.Popper>\n <Select.Card cs={selectCardStyles}>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n </Box>\n );\n};\n```\n\n### Ref Forwarding\n\n`Select.Input` supports [ref forwarding](https://reactjs.org/docs/forwarding-refs.html). It will\nforward `ref` to its underlying `<input type=\"text\" role=\"combobox\">` element.\n```tsx\nimport React from 'react';\n\nimport {PrimaryButton} from '@workday/canvas-kit-react/button';\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Select} from '@workday/canvas-kit-react/select';\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const RefForwarding = () => {\n // @ts-ignore\n const [value, setValue] = React.useState('medium');\n const ref = React.useRef(null);\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.target.value);\n };\n\n const handleClick = () => {\n if (ref && ref.current) {\n console.log(ref);\n ref.current.focus();\n }\n };\n\n return (\n <>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options}>\n <FormField.Input as={Select.Input} ref={ref} onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n <PrimaryButton onClick={handleClick}>Focus Select</PrimaryButton>\n </>\n );\n};\n```\n\n### Error States\n\nForm Field provides error and caution states for Select. Set the `error` prop on Form Field to\n`\"error\"` or `\"caution\"` and use `FormField.Hint` to provide messages. See\n[Form Field's Error documentation](/components/inputs/form-field/#error-states) for examples and\naccessibility guidance.\n\n#### Caution\n\nUse the alert state when a selection is valid but there is additional information.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const Caution = () => {\n const [value, setValue] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.target.value);\n };\n return (\n <Flex cs={parentContainerStyles}>\n <FormField error=\"caution\">\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options}>\n <FormField.Input as={Select.Input} onChange={e => handleChange(e)} id=\"alert-select\" />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n <FormField.Hint>Please choose a form of contact.</FormField.Hint>\n </Select>\n </FormField.Field>\n </FormField>\n Selected value: {value}\n </Flex>\n );\n};\n```\n\n#### Error\n\nUse the error state when the selection is no longer valid.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax (disabled)',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const Error = () => {\n const [value, setValue] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.target.value);\n };\n return (\n <Flex cs={parentContainerStyles}>\n <FormField error=\"error\">\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options} nonInteractiveIds={['Fax (disabled)']}>\n <FormField.Input as={Select.Input} onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>\n {item => (\n <Select.Item aria-disabled={item === 'Fax (disabled)' ? true : undefined}>\n {item}\n </Select.Item>\n )}\n </Select.List>\n </Select.Card>\n </Select.Popper>\n <FormField.Hint>Fax is disabled. Please choose a different option.</FormField.Hint>\n </Select>\n </FormField.Field>\n </FormField>\n Selected Value: {value}\n </Flex>\n );\n};\n```\n\n### Initial Selected Item\n\nYou can set `initialSelectedIds` to the value that you want initially selected.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n {\n id: 'b310c757b2d341f99d40d76f4d563c5b',\n descriptor: 'Arabic',\n languageCode: 'ar',\n label: 'Arabic',\n nativeLanguageName: '\u0627\u0644\u0639\u0631\u0628\u064A\u0629',\n },\n {\n id: 'a675a6b6e22d100017d7fe2a784d1255',\n descriptor: 'Bulgarian (Bulgaria)',\n languageCode: 'bg_BG',\n label: 'Bulgarian (Bulgaria)',\n nativeLanguageName: '\u0431\u044A\u043B\u0433\u0430\u0440\u0441\u043A\u0438 (\u0420\u0435\u043F\u0443\u0431\u043B\u0438\u043A\u0430 \u0411\u044A\u043B\u0433\u0430\u0440\u0438\u044F)',\n },\n {\n id: 'da594226446c11de98360015c5e6daf6',\n descriptor: 'English (United States)',\n languageCode: 'en_US',\n label: 'English (United States)',\n nativeLanguageName: 'English',\n },\n];\n\nexport const InitialSelectedItem = () => {\n const [value, setValue] = React.useState('English (United States)');\n const [id, setId] = React.useState('da594226446c11de98360015c5e6daf6');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setId(event.target.value);\n setValue(options.find(item => item.id === event.target.value).label);\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select\n items={options}\n initialSelectedIds={['da594226446c11de98360015c5e6daf6']}\n getId={item => item.id}\n getTextValue={item => item.label}\n >\n <Select.Input onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item.label}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n <p>Id: {id}</p>\n <p>Value: {value}</p>\n </Flex>\n );\n};\n```\n\n### Placeholder\n\nYou can change the placeholder text by passing a string to the `placeholder` prop on\n**`FormField.Input as={Select.Input}`**. Placeholder text is not a substitute for\n**`FormField.Label`**.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const Placeholder = () => {\n const [value, setValue] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.target.value);\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options}>\n <Select.Input placeholder=\"Make a Selection\" onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>\n {item => {\n return <Select.Item>{item}</Select.Item>;\n }}\n </Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n Selected Value: {value}\n </Flex>\n );\n};\n```\n\n### Fetching Dynamic Items\n\nIt's common to load items from a server call. Hoisting the `model` and setting your items on state\nallows you to pass those items to your `model`. You can leverage React state to set your items on\nload as well as displaying a placeholder indicating when items are loaded.\n\n**Note: In this case we need to use `getId` and `getTextValue` because our data doesn't have the\nproperties of `id` or `text`. Using these helper functions sets the `serverId` to be `id` and\n`label` to be `text`.**\n```tsx\nimport React from 'react';\n\nimport {PrimaryButton} from '@workday/canvas-kit-react/button';\nimport {useMount} from '@workday/canvas-kit-react/common';\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select, useSelectModel} from '@workday/canvas-kit-react/select';\nimport {createStyles, px2rem} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n maxWidth: px2rem(300),\n});\n\nconst movieListItems = [\n {\n label: 'The Lion King',\n serverId: '123',\n Year: '2019',\n Runtime: '118 min',\n },\n {\n label: 'Mowgli: Legend of the Jungle',\n serverId: '234',\n Year: '2018',\n Runtime: '104 min',\n },\n {\n label: 'Doctor Strange',\n serverId: '345',\n Year: '2016',\n Runtime: '115 min',\n },\n {\n label: 'John Wick',\n Year: '2014',\n serverId: '456',\n Runtime: '101 min',\n },\n {\n label: 'The Notebook',\n serverId: '567',\n Year: '2004',\n Runtime: '123 min',\n },\n];\n\nexport const FetchingDynamicItems = () => {\n const [id, setId] = React.useState('456');\n const [moviesLists, setMoviesList] = React.useState<typeof movieListItems>([]);\n const [loadingStatus, setLoadingStatus] = React.useState<'idle' | 'loading' | 'success'>('idle');\n const loadingRef = React.useRef<ReturnType<typeof setTimeout>>();\n\n const model = useSelectModel({\n items: moviesLists,\n getTextValue: item => item.label,\n getId: item => item.serverId,\n initialSelectedIds: [id],\n });\n\n const stringValue = moviesLists.find(item => item.serverId === id)?.label || '';\n\n function loadItems() {\n setLoadingStatus('loading');\n loadingRef.current = setTimeout(() => {\n setLoadingStatus('success');\n setMoviesList(movieListItems);\n }, 1500);\n }\n\n useMount(() => {\n return () => {\n clearTimeout(loadingRef.current);\n };\n });\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Choose a Film</FormField.Label>\n <FormField.Field>\n <Select model={model}>\n <FormField.Input\n as={Select.Input}\n onChange={e => {\n setId(e.target.value);\n }}\n placeholder={loadingStatus}\n />\n <Select.Popper>\n <Select.Card>\n <Select.List>\n {item => {\n return <Select.Item>{item.label}</Select.Item>;\n }}\n </Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n <div data-testid=\"selected-id\">Selected Id: {id}</div>\n <div data-testid=\"selected-value\">Selected value: {stringValue}</div>\n <PrimaryButton\n onClick={() => {\n loadItems();\n }}\n >\n Get Items\n </PrimaryButton>\n </Flex>\n );\n};\n```\n\n### Complex\n\nWhen registering items in an array of objects, it's common to have the text that is displayed to the\nuser be different than an id. In this example, `serverId` and `label` properties need to be remapped\nto `id` and `text` hence the usage of `getId` and `getTextValue`. If your object has the properties\n`text` and `id`, there would be no need for this.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n {serverId: 'email', label: 'E-mail'},\n {serverId: 'phone', label: 'Phone'},\n {serverId: 'fax', label: 'Fax'},\n {serverId: 'mail', label: 'Mail'},\n {serverId: 'mobile', label: 'Mobile Phone'},\n {\n serverId: 'oasis',\n label: 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n },\n];\n\nexport const Complex = () => {\n const [value, setValue] = React.useState('');\n const [id, setId] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setId(event.target.value);\n setValue(options.find(item => item.serverId === event.target.value)!.label);\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options} getId={item => item.serverId} getTextValue={item => item.label}>\n <FormField.Input as={Select.Input} onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item.label}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n <p>Id: {id}</p>\n <p>Value: {value}</p>\n </Flex>\n );\n};\n```\n\n**Note: By default, the identifier and text value are `id` and `text` properties respectively. If\nyour data object for each item is different, provide `getId` and/or `getTextValue`. If a custom\n`getId` does not return the display text, also pass `getTextValue` \u2014 otherwise the model uses\n`getId` for type-ahead and the selected value. For example:**\n\n```jsx\nconst items = [\n {\n serverId: '1',\n label: 'First Option',\n },\n];\n\n<Select items={items} getId={item => item.serverId} getTextValue={item => item.label}>\n {/* etc */}\n</Select>;\n```\n\n### Controlled\n\nThe Select can be a\n[controlled input](https://react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable)\ncomponent by passing the `value` and `onChange` to either the `<Select>` component or the\n`<Select.Input>` component. Internally, the `Select.Input` watches for changes on the `value` React\nprop as well as the `value` DOM property and will update the model accordingly.\n```tsx\nimport React from 'react';\n\nimport {SecondaryButton} from '@workday/canvas-kit-react/button';\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n {serverId: 'email', label: 'E-mail'},\n {serverId: 'phone', label: 'Phone'},\n {serverId: 'fax', label: 'Fax'},\n {serverId: 'mail', label: 'Mail'},\n {serverId: 'mobile', label: 'Mobile Phone'},\n {\n serverId: 'oasis',\n label: 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n },\n];\n\nexport const Controlled = () => {\n const [value, setValue] = React.useState('');\n const [label, setLabel] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.currentTarget.value);\n setLabel(options.find(item => item.serverId === event.currentTarget.value)?.label || '');\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options} getId={item => item.serverId} getTextValue={item => item.label}>\n <FormField.Input\n as={Select.Input}\n onChange={handleChange}\n value={value}\n name=\"contact\"\n />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item.label}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n <p>Id: {value}</p>\n <p>Label: {label}</p>\n <Flex cs={{gap: system.gap.md}}>\n <SecondaryButton\n onClick={e => {\n setValue('fax');\n }}\n >\n Set to \"Fax\"\n </SecondaryButton>\n <SecondaryButton\n onClick={e => {\n setValue('');\n }}\n >\n Clear\n </SecondaryButton>\n </Flex>\n </Flex>\n );\n};\n```\n\n### When to use `getId`, or `getTextValue`\n\n- `getId`: This is an optional function to return the id of an item. If not provided, the default\n function will return the `id` property from the object of each item. If you did not provide\n `items`, do not override this function. Instead provide static items via JSX. the list will create\n an internal array of items where `id` is the only property and the default `getId` will return the\n desired result. **Note: If your array of objects has a different property for `id`, like\n `serverId`, use this function to set the id. If that function does not return the display text,\n also pass `getTextValue`.**\n\n ```tsx\n const options = [{text: 'Pizza', serverId: 'pizza-1'}, {text: 'Cheeseburger', serverId: 'cheeseburger'}]\n <FormField>\n <FormField.Label>Your Label</FormField.Label>\n <FormField.Field>\n <Select items={options} getId={(item) => item.serverId} getTextValue={(item) => item.text}>\n <FormField.Input as={Select.Input} onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item.text}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n ```\n\n- `getTextValue`: Optional function to return the text representation of an item. If not provided,\n the default function will return the `text` property of the object of each item or an empty string\n if there is no `text` property. If you did not provide `items`, do not override this function.\n **Note: If your array of objects has a different property for `text`, like `label`, use this\n function to set the text.**\n\n ```tsx\n const options = [{label: 'Pizza', id: 'pizza-1'}, {label: 'Cheeseburger', id: 'cheeseburger'}]\n <FormField>\n <FormField.Label>Your Label</FormField.Label>\n <FormField.Field>\n <Select items={options} getTextValue={(item) => item.label}>\n <FormField.Input as={Select.Input} onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item.label}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n ```\n\n### Grouped Items\n\nIn order to group items, use the static item API with **`Menu.Group`** inside **`Select.List`**, and\nstill pass **`items`** whose ids match each **`Select.Item`** **`data-id`**.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Menu} from '@workday/canvas-kit-react/menu';\nimport {Select} from '@workday/canvas-kit-react/select';\n\nconst items = [\n {\n id: 'first',\n text: 'First Item',\n },\n {\n id: 'second',\n text: 'Second Item',\n },\n {\n id: 'third',\n text: 'Third Item',\n },\n {\n id: 'fourth',\n text: 'Fourth Item',\n },\n];\n\nexport const GroupedItems = () => {\n return (\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={items} getId={item => item.id} getTextValue={item => item.text}>\n <FormField.Input as={Select.Input} />\n <Select.Popper>\n <Select.Card>\n <Select.List>\n <Menu.Group title=\"First Group\">\n <Select.Item data-id=\"first\">First Item</Select.Item>\n <Select.Item data-id=\"second\">Second Item</Select.Item>\n </Menu.Group>\n <Menu.Group title=\"Second Group\">\n <Select.Item data-id=\"third\">\n Third Item (with a really, really, really long label)\n </Select.Item>\n <Select.Item data-id=\"fourth\">Fourth Item</Select.Item>\n </Menu.Group>\n </Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n );\n};\n```\n\n### Custom Styles\n\nSelect and its subcomponents support custom styling via the `cs` prop. For more information, check\nour\n[\"How To Customize Styles\"](https://workday.github.io/canvas-kit/?path=/docs/styling-guides-customizing-styles--docs).\n\n## Accessibility\n\nThe primary accessibility goal for `Select` is a visible, persistent label and a single choice from\na known list that assistive technology identifies as a combobox. Use **`Select`** when the user must\npick one option. For multiple selections, use [**MultiSelect**](/docs/preview-multiselect--docs).\nFor a value outside a fixed list, use [**Combobox**](/features/combobox/). See\n[FormField's accessibility documentation](/components/inputs/form-field/#accessibility) for label,\nhint, error, and required wiring. This follows the WAI-ARIA\n[Select-Only Combobox](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/)\npattern.\n\n### Minimum Accessible Structure\n\nBuild on the [Basic Example](#basic-example): label first, then **`Select`** inside\n**`FormField.Field`**, with the combobox, popup, list, and items in this order.\n\n```tsx\n\nconst options = ['E-mail', 'Phone', 'Fax'];\n\n<FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options}>\n <FormField.Input as={Select.Input} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n</FormField>;\n```\n\nEvery `Select` requires **`FormField`**, a visible **`FormField.Label`**, and\n**`FormField.Input as={Select.Input}`** so the combobox has a programmatically determinable name,\nrelationships, and instructions. See\n[FormField's accessibility documentation](/components/inputs/form-field/#accessibility) for hint,\nerror, and required wiring.\n\n### Built-in Behaviors\n\nCanvas Kit applies these automatically when you compose `Select` with `FormField` subcomponents.\n**Do not duplicate them** in consuming code.\n\n**ARIA and DOM** (_applied by subcomponents_):\n\n- **`Select.Input`**: Visual `<input>` with `role=\"combobox\"`, `aria-haspopup=\"listbox\"`,\n `aria-expanded` from menu visibility, `aria-autocomplete=\"list\"` (do not change to `\"none\"`),\n `aria-controls` pointing at the listbox id (`{modelId}-list`), and `aria-activedescendant` while\n the list is open (removed when the list is closed). `autoComplete` is `\"off\"`. Keyboard characters\n are not inserted into the input; type-ahead is handled by the model. **`FormField.Label`** (via\n **`FormField.Input`**) is the accessible name of the combobox \u2014 do not add a second name on the\n listbox.\n- **Hidden form input**: A second input holds the selected id(s) for form submission. It is\n `aria-hidden`, has `tabIndex={-1}`, and is not in the tab order. `onChange` and `name` apply to\n this input. Focus and blur on a `ref` are forwarded to the visual combobox.\n- **`Select.List`**: `role=\"listbox\"` with an id that matches the combobox `aria-controls`. Options\n are not in the tab order; keyboard focus stays on the combobox. Listbox labelling is library-owned\n \u2014 do not set `aria-labelledby` (or `aria-label`) on **`Select.List`**.\n- **`Select.Item`**: `role=\"option\"` and `aria-selected` from selection state. Disabled options need\n **`aria-disabled`** from application code (see **Accessibility Requirements**).\n- **`Menu.Group`** (when used inside **`Select.List`**): `role=\"group\"` with `aria-labelledby`\n referencing the group heading (`title` or **`Menu.Group.Heading`**).\n- **`Select.Item.Icon`** and the caret / start icons on **`Select.Input`**: Canvas Kit icons use\n `role=\"presentation\"` and `focusable=\"false\"`. Decorative icons need no extra attributes.\n- **`disabled` on `Select.Input`**: Maps to the native `disabled` attribute on both inputs; the\n combobox is removed from the tab order.\n- **`ref`**: Forwards to the visual combobox (`<input type=\"text\" role=\"combobox\">`).\n\n**Keyboard** (_select-only combobox; focus remains on **`Select.Input`**_):\n\n- <kbd>Tab</kbd> / <kbd>Shift</kbd>+<kbd>Tab</kbd> move to and from the combobox (native tab order).\n Other keys are prevented from editing the input.\n- Clicking **`FormField.Label`** moves focus to the combobox. Clicking the combobox opens or closes\n the list.\n- <kbd>ArrowDown</kbd> / <kbd>ArrowUp</kbd> open the list. While the list is open, those keys move\n the active option (skipping ids in **`nonInteractiveIds`**). <kbd>Home</kbd> / <kbd>End</kbd> move\n to the first or last option while the list is open.\n- <kbd>Space</kbd> opens the list when it is closed and no type-ahead string is in progress. While\n the list is open and type-ahead is empty, <kbd>Space</kbd> selects the active option and closes\n the list.\n- Printable characters type-ahead: with the list closed, matching options are selected; with the\n list open, assistive focus moves to the matching option. Consecutive keys within 500ms form a\n search string.\n- <kbd>Enter</kbd> while the list is open selects the active option (unless **`aria-disabled`**) and\n closes the list in single-select mode. It does not submit the form while the list is open.\n- <kbd>Escape</kbd> closes the list. Blur also hides the list. After close, `aria-activedescendant`\n is removed; the active option returns to the selected item when one is selected.\n- Activating an option with the pointer keeps focus on the combobox and closes the list.\n\n**Screen reader expectations** (_when built-in behaviors are used as intended_):\n\n- On focus, assistive technology announces the field label and, when applicable: required state,\n invalid state (`error=\"error\"`), hint or error text via `aria-describedby`, and the current\n selected text (or the placeholder when nothing is selected).\n- The control is announced as a combobox. Collapsed vs expanded follows `aria-expanded`. While the\n list is open, the active option is exposed through `aria-activedescendant`.\n- Options are announced with selected or not-selected state (`aria-selected`). Disabled options are\n announced as disabled when **`aria-disabled`** is set.\n- The Caution state is visual only \u2014 `aria-invalid` is **not** set for `error=\"caution\"`.\n- Disabled comboboxes may be announced as unavailable and are skipped in the tab order.\n- The hidden form input and decorative icons are not announced.\n\nFor rendered label, input, and hint association markup, see the DOM examples in\n[FormField's Built-in Behaviors](/components/inputs/form-field/#built-in-behaviors).\n\n### Accessibility Requirements\n\nRequired in application code for an accessible `Select`. Rows marked _(conditional)_ apply only when\nthe situation matches\u2014otherwise omit.\n\n**If no design spec is provided:** use a visible `FormField.Label`, wrap **`Select`** with\n**`FormField`**, use **`FormField.Input as={Select.Input}`**, include **`Select.Popper`**,\n**`Select.Card`**, **`Select.List`**, and **`Select.Item`**, and pass **`items`**. Omit `isHidden`,\nomit a custom `id` unless testing or composition requires it, omit a `ref` unless programmatic focus\nis required, omit **`disabled`**, **`nonInteractiveIds`**, icons, grouped list items, and a custom\n**`placeholder`** unless the spec includes them.\n\n**Programmatic focus** _(conditional \u2014 omit by default)_:\n\nUse a ref when the product needs to move focus to the combobox after an action. Do not attach a\n`ref` or call `focus()` unless the design or developer asks for it. See\n[Ref Forwarding](#ref-forwarding) under Usage for a complete Storybook example (imports, `ref` on\n**`FormField.Input as={Select.Input}`**, and a button that calls `focus()`).\n\n**Disabled options** _(conditional)_:\n\nWhen an option is unavailable, set **`nonInteractiveIds`** on **`Select`** and **`aria-disabled`**\non those **`Select.Item`**s. See [Disabled Items](#disabled-items) under Usage for a complete\nStorybook example. Do not use styling alone.\n\n| Requirement | How to satisfy |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| Input wiring | **`FormField.Input as={Select.Input}`** for the combobox, with **`Select.Popper`**, **`Select.Card`**, **`Select.List`**, and **`Select.Item`**. See [FormField accessibility](/components/inputs/form-field/#accessibility) for label, hint, error, and required wiring |\n| Disabled combobox _(conditional)_ | `disabled` on **`FormField.Input as={Select.Input}`**. See [Disabled](#disabled) |\n| Disabled options _(conditional)_ | **`nonInteractiveIds`** on **`Select`** (ids skipped by keyboard and type-ahead) **and** **`aria-disabled`** on those **`Select.Item`**s. See [Disabled Items](#disabled-items) |\n| Grouped list items _(conditional)_ | Keep **`items`**. Inside **`Select.List`**, render static **`Menu.Group`** (`title` or **`Menu.Group.Heading`**) and **`Select.Item`**s with matching **`data-id`** \u2014 not `{item => \u2026}`. See [Grouped Items](#grouped-items) |\n| Option icons _(conditional)_ | **`Select.Item.Icon`** on each item; **`inputStartIcon`** on **`FormField.Input as={Select.Input}`** for the selected item. Decorative icons need no extra attributes; meaning beyond the label must be text |\n| Custom placeholder _(conditional)_ | `placeholder` on **`FormField.Input as={Select.Input}`** only as short prompt text\u2014never as the only name. Default is `\"Choose an option\"` |\n| Programmatic focus _(conditional)_ | `ref` on **`FormField.Input as={Select.Input}`** and call `focus()` when moving focus to the field after an action\u2014omit by default (see **Programmatic focus** above) |\n\n**Summary for code generation:**\n\n- **REQUIRED:** visible label, **`FormField.Input as={Select.Input}`**, popup list composition\n (**`Select.Popper`**, **`Select.Card`**, **`Select.List`**, **`Select.Item`**), **`items`**.\n Default list rendering is `{item => <Select.Item>{item}</Select.Item>}` (or `item.text` /\n **`getTextValue`**).\n- **CONDITIONAL:** disabled combobox, disabled options (`nonInteractiveIds` + `aria-disabled`),\n grouped list items (**`items`** plus static **`Menu.Group`** / **`data-id`** children \u2014 do not\n omit **`items`**), option icons, custom placeholder, programmatic focus via `ref`, **`getId`** and\n **`getTextValue`** when item shape is not `{id, text}` (always pass **`getTextValue`** if custom\n **`getId`** is not the display text), **`data-id`** on static JSX **`Select.Item`**s. See\n [FormField accessibility](/components/inputs/form-field/#accessibility) for shared FormField\n conditionals (hint/error, required, stable `id`).\n\n### Anti-Patterns\n\nDo **not** generate code that does the following (see **Accessibility Requirements** above for what\nto supply instead):\n\n- **Missing `FormField` wiring**: Do not use `Select` without **`FormField`** and\n **`FormField.Label`**, and do not render a bare **`Select.Input`** when a **`FormField`** is\n present. Use **`FormField.Input as={Select.Input}`** (see **Minimum accessible structure**). For\n shared FormField anti-patterns (manual ARIA, placeholder-only labels, color-only errors, broken ID\n references), see [FormField Anti-Patterns](/components/inputs/form-field/#anti-patterns).\n- **Duplicating combobox or listbox ARIA**: Do not set `role`, `aria-haspopup`, `aria-expanded`,\n `aria-autocomplete` (including `\"none\"`), `aria-controls`, `aria-activedescendant`,\n `autoComplete`, or listbox `role` / `id` / `aria-labelledby` / `aria-label`. Do not make\n **`Select.Item`** focusable \u2014 the active option is **`aria-activedescendant`** on the combobox.\n- **Wrong component**: Do not use a native `<select>`, **`Menu`**, **`Combobox`**, **`TextInput`**,\n or **`FormFieldGroup`** for a single submitted list value. Use\n [**MultiSelect**](/docs/preview-multiselect--docs) when more than one option can be selected.\n- **Item identity / grouping**: Do not set **`data-id`** on `{item => <Select.Item>}`. Do not omit\n **`items`** when grouping, and do not group with a render callback alone \u2014 use **`Menu.Group`**\n and **`data-id`** (see **Static item ids** and **Grouped list items**).\n- **Free-text keyboard on the combobox**: Do not add `onKeyDown` that types into the input or calls\n `preventDefault` on <kbd>Tab</kbd> \u2014 Select is select-only.\n\n## Component API\n\n## Specifications\n\n",
1567
- accessibilityProse: '## Accessibility\n\nThe primary accessibility goal for `Select` is a visible, persistent label and a single choice from\na known list that assistive technology identifies as a combobox. Use **`Select`** when the user must\npick one option. For multiple selections, use [**MultiSelect**](/docs/preview-multiselect--docs).\nFor a value outside a fixed list, use [**Combobox**](/features/combobox/). See\n[FormField\'s accessibility documentation](/components/inputs/form-field/#accessibility) for label,\nhint, error, and required wiring. This follows the WAI-ARIA\n[Select-Only Combobox](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/)\npattern.\n\n### Minimum Accessible Structure\n\nBuild on the [Basic Example](#basic-example): label first, then **`Select`** inside\n**`FormField.Field`**, with the combobox, popup, list, and items in this order.\n\n```tsx\n\nconst options = [\'E-mail\', \'Phone\', \'Fax\'];\n\n<FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options}>\n <FormField.Input as={Select.Input} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n</FormField>;\n```\n\nEvery `Select` requires **`FormField`**, a visible **`FormField.Label`**, and\n**`FormField.Input as={Select.Input}`** so the combobox has a programmatically determinable name,\nrelationships, and instructions. See\n[FormField\'s accessibility documentation](/components/inputs/form-field/#accessibility) for hint,\nerror, and required wiring.\n\n### Built-in Behaviors\n\nCanvas Kit applies these automatically when you compose `Select` with `FormField` subcomponents.\n**Do not duplicate them** in consuming code.\n\n**ARIA and DOM** (_applied by subcomponents_):\n\n- **`Select.Input`**: Visual `<input>` with `role="combobox"`, `aria-haspopup="listbox"`,\n `aria-expanded` from menu visibility, `aria-autocomplete="list"` (do not change to `"none"`),\n `aria-controls` pointing at the listbox id (`{modelId}-list`), and `aria-activedescendant` while\n the list is open (removed when the list is closed). `autoComplete` is `"off"`. Keyboard characters\n are not inserted into the input; type-ahead is handled by the model. **`FormField.Label`** (via\n **`FormField.Input`**) is the accessible name of the combobox \u2014 do not add a second name on the\n listbox.\n- **Hidden form input**: A second input holds the selected id(s) for form submission. It is\n `aria-hidden`, has `tabIndex={-1}`, and is not in the tab order. `onChange` and `name` apply to\n this input. Focus and blur on a `ref` are forwarded to the visual combobox.\n- **`Select.List`**: `role="listbox"` with an id that matches the combobox `aria-controls`. Options\n are not in the tab order; keyboard focus stays on the combobox. Listbox labelling is library-owned\n \u2014 do not set `aria-labelledby` (or `aria-label`) on **`Select.List`**.\n- **`Select.Item`**: `role="option"` and `aria-selected` from selection state. Disabled options need\n **`aria-disabled`** from application code (see **Accessibility Requirements**).\n- **`Menu.Group`** (when used inside **`Select.List`**): `role="group"` with `aria-labelledby`\n referencing the group heading (`title` or **`Menu.Group.Heading`**).\n- **`Select.Item.Icon`** and the caret / start icons on **`Select.Input`**: Canvas Kit icons use\n `role="presentation"` and `focusable="false"`. Decorative icons need no extra attributes.\n- **`disabled` on `Select.Input`**: Maps to the native `disabled` attribute on both inputs; the\n combobox is removed from the tab order.\n- **`ref`**: Forwards to the visual combobox (`<input type="text" role="combobox">`).\n\n**Keyboard** (_select-only combobox; focus remains on **`Select.Input`**_):\n\n- <kbd>Tab</kbd> / <kbd>Shift</kbd>+<kbd>Tab</kbd> move to and from the combobox (native tab order).\n Other keys are prevented from editing the input.\n- Clicking **`FormField.Label`** moves focus to the combobox. Clicking the combobox opens or closes\n the list.\n- <kbd>ArrowDown</kbd> / <kbd>ArrowUp</kbd> open the list. While the list is open, those keys move\n the active option (skipping ids in **`nonInteractiveIds`**). <kbd>Home</kbd> / <kbd>End</kbd> move\n to the first or last option while the list is open.\n- <kbd>Space</kbd> opens the list when it is closed and no type-ahead string is in progress. While\n the list is open and type-ahead is empty, <kbd>Space</kbd> selects the active option and closes\n the list.\n- Printable characters type-ahead: with the list closed, matching options are selected; with the\n list open, assistive focus moves to the matching option. Consecutive keys within 500ms form a\n search string.\n- <kbd>Enter</kbd> while the list is open selects the active option (unless **`aria-disabled`**) and\n closes the list in single-select mode. It does not submit the form while the list is open.\n- <kbd>Escape</kbd> closes the list. Blur also hides the list. After close, `aria-activedescendant`\n is removed; the active option returns to the selected item when one is selected.\n- Activating an option with the pointer keeps focus on the combobox and closes the list.\n\n**Screen reader expectations** (_when built-in behaviors are used as intended_):\n\n- On focus, assistive technology announces the field label and, when applicable: required state,\n invalid state (`error="error"`), hint or error text via `aria-describedby`, and the current\n selected text (or the placeholder when nothing is selected).\n- The control is announced as a combobox. Collapsed vs expanded follows `aria-expanded`. While the\n list is open, the active option is exposed through `aria-activedescendant`.\n- Options are announced with selected or not-selected state (`aria-selected`). Disabled options are\n announced as disabled when **`aria-disabled`** is set.\n- The Caution state is visual only \u2014 `aria-invalid` is **not** set for `error="caution"`.\n- Disabled comboboxes may be announced as unavailable and are skipped in the tab order.\n- The hidden form input and decorative icons are not announced.\n\nFor rendered label, input, and hint association markup, see the DOM examples in\n[FormField\'s Built-in Behaviors](/components/inputs/form-field/#built-in-behaviors).\n\n### Accessibility Requirements\n\nRequired in application code for an accessible `Select`. Rows marked _(conditional)_ apply only when\nthe situation matches\u2014otherwise omit.\n\n**If no design spec is provided:** use a visible `FormField.Label`, wrap **`Select`** with\n**`FormField`**, use **`FormField.Input as={Select.Input}`**, include **`Select.Popper`**,\n**`Select.Card`**, **`Select.List`**, and **`Select.Item`**, and pass **`items`**. Omit `isHidden`,\nomit a custom `id` unless testing or composition requires it, omit a `ref` unless programmatic focus\nis required, omit **`disabled`**, **`nonInteractiveIds`**, icons, grouped list items, and a custom\n**`placeholder`** unless the spec includes them.\n\n**Programmatic focus** _(conditional \u2014 omit by default)_:\n\nUse a ref when the product needs to move focus to the combobox after an action. Do not attach a\n`ref` or call `focus()` unless the design or developer asks for it. See\n[Ref Forwarding](#ref-forwarding) under Usage for a complete Storybook example (imports, `ref` on\n**`FormField.Input as={Select.Input}`**, and a button that calls `focus()`).\n\n**Disabled options** _(conditional)_:\n\nWhen an option is unavailable, set **`nonInteractiveIds`** on **`Select`** and **`aria-disabled`**\non those **`Select.Item`**s. See [Disabled Items](#disabled-items) under Usage for a complete\nStorybook example. Do not use styling alone.\n\n| Requirement | How to satisfy |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| Input wiring | **`FormField.Input as={Select.Input}`** for the combobox, with **`Select.Popper`**, **`Select.Card`**, **`Select.List`**, and **`Select.Item`**. See [FormField accessibility](/components/inputs/form-field/#accessibility) for label, hint, error, and required wiring |\n| Disabled combobox _(conditional)_ | `disabled` on **`FormField.Input as={Select.Input}`**. See [Disabled](#disabled) |\n| Disabled options _(conditional)_ | **`nonInteractiveIds`** on **`Select`** (ids skipped by keyboard and type-ahead) **and** **`aria-disabled`** on those **`Select.Item`**s. See [Disabled Items](#disabled-items) |\n| Grouped list items _(conditional)_ | Keep **`items`**. Inside **`Select.List`**, render static **`Menu.Group`** (`title` or **`Menu.Group.Heading`**) and **`Select.Item`**s with matching **`data-id`** \u2014 not `{item => \u2026}`. See [Grouped Items](#grouped-items) |\n| Option icons _(conditional)_ | **`Select.Item.Icon`** on each item; **`inputStartIcon`** on **`FormField.Input as={Select.Input}`** for the selected item. Decorative icons need no extra attributes; meaning beyond the label must be text |\n| Custom placeholder _(conditional)_ | `placeholder` on **`FormField.Input as={Select.Input}`** only as short prompt text\u2014never as the only name. Default is `"Choose an option"` |\n| Programmatic focus _(conditional)_ | `ref` on **`FormField.Input as={Select.Input}`** and call `focus()` when moving focus to the field after an action\u2014omit by default (see **Programmatic focus** above) |\n\n**Summary for code generation:**\n\n- **REQUIRED:** visible label, **`FormField.Input as={Select.Input}`**, popup list composition\n (**`Select.Popper`**, **`Select.Card`**, **`Select.List`**, **`Select.Item`**), **`items`**.\n Default list rendering is `{item => <Select.Item>{item}</Select.Item>}` (or `item.text` /\n **`getTextValue`**).\n- **CONDITIONAL:** disabled combobox, disabled options (`nonInteractiveIds` + `aria-disabled`),\n grouped list items (**`items`** plus static **`Menu.Group`** / **`data-id`** children \u2014 do not\n omit **`items`**), option icons, custom placeholder, programmatic focus via `ref`, **`getId`** and\n **`getTextValue`** when item shape is not `{id, text}` (always pass **`getTextValue`** if custom\n **`getId`** is not the display text), **`data-id`** on static JSX **`Select.Item`**s. See\n [FormField accessibility](/components/inputs/form-field/#accessibility) for shared FormField\n conditionals (hint/error, required, stable `id`).\n\n### Anti-Patterns\n\nDo **not** generate code that does the following (see **Accessibility Requirements** above for what\nto supply instead):\n\n- **Missing `FormField` wiring**: Do not use `Select` without **`FormField`** and\n **`FormField.Label`**, and do not render a bare **`Select.Input`** when a **`FormField`** is\n present. Use **`FormField.Input as={Select.Input}`** (see **Minimum accessible structure**). For\n shared FormField anti-patterns (manual ARIA, placeholder-only labels, color-only errors, broken ID\n references), see [FormField Anti-Patterns](/components/inputs/form-field/#anti-patterns).\n- **Duplicating combobox or listbox ARIA**: Do not set `role`, `aria-haspopup`, `aria-expanded`,\n `aria-autocomplete` (including `"none"`), `aria-controls`, `aria-activedescendant`,\n `autoComplete`, or listbox `role` / `id` / `aria-labelledby` / `aria-label`. Do not make\n **`Select.Item`** focusable \u2014 the active option is **`aria-activedescendant`** on the combobox.\n- **Wrong component**: Do not use a native `<select>`, **`Menu`**, **`Combobox`**, **`TextInput`**,\n or **`FormFieldGroup`** for a single submitted list value. Use\n [**MultiSelect**](/docs/preview-multiselect--docs) when more than one option can be selected.\n- **Item identity / grouping**: Do not set **`data-id`** on `{item => <Select.Item>}`. Do not omit\n **`items`** when grouping, and do not group with a render callback alone \u2014 use **`Menu.Group`**\n and **`data-id`** (see **Static item ids** and **Grouped list items**).\n- **Free-text keyboard on the combobox**: Do not add `onKeyDown` that types into the input or calls\n `preventDefault` on <kbd>Tab</kbd> \u2014 Select is select-only.'
1566
+ mdxProse: "# Canvas Kit Select\n\nSelect inputs allow users to choose one option from a list of items or type a matching option.\n\n[> Workday Design Reference](https://design.workday.com/components/inputs/select)\n\n## Installation\n\n```sh\nyarn add @workday/canvas-kit-react\n```\n\n## Usage\n\n### Basic Example\n\n`Select` supports a\n[dynamic API](/get-started/for-developers/guides/collection-api/#dynamic-items) where you\npass an array of items via the `items` prop and provide a render function to display the items. The\nitems may be provided as an\n[array of strings](/get-started/for-developers/guides/collection-api/#array-of-strings) or an\n[array of objects](/get-started/for-developers/guides/collection-api/#array-of-objects).\n\n`Select` should be used in tandem with [Form Field](/components/inputs/form-field/) where the\n`Select` wraps the `FormField` element and the `FormField` element wraps the children of `Select` to\nmeet accessibility standards. This ensures the `label` text from `FormField` is attached to the\n`Select.Input` and read out as a group for voiceover.\n\n```tsx\n<Select items={options}>\n <FormField label=\"Your Label\">\n <Select.Input onChange={e => handleChange(e)} id=\"contact-select\" />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item.id}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </FormField>\n</Select>\n```\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n 'Thisisalongstringwithnobreaksandwillwrap',\n];\n\nexport const Basic = () => {\n const [value, setValue] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n console.log('change', event.currentTarget.value);\n setValue(event.target.value);\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options}>\n <FormField.Input as={Select.Input} onChange={handleChange} />\n <Select.Popper>\n <Select.Card>\n <Select.List>\n {item => {\n return <Select.Item>{item}</Select.Item>;\n }}\n </Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n Selected Value: {value}\n </Flex>\n );\n};\n```\n\nOur example uses [React state](<(https://react.dev/learn/state-a-components-memory)>) to track the\nvalue of the `Select`.\n\n### Hoisted Model\n\nBy default, `Select` will create and use its own model internally. Alternatively, you may configure\nyour own model with `useSelectModel` and pass it to `Select` via the `model` prop. This pattern is\nreferred to as\n[hoisting the model](/get-started/for-developers/documentation/compound-components/#configuring-a-model)\nand provides direct access to its `state` and `events` outside of the `Select` component.\n\nIn this example, we set up external observation of the model state and create an external button to\ntrigger an event to change the selected item.\n\n**Note: If your array of objects uses an `id` property and a `text` property there is no need to use\nthe helper functions of `getId` or `getTextValue`. The collection system and the `Select` use these\nproperties by default for keyboard navigation and selected the `id` based on the item clicked.**\n```tsx\nimport React from 'react';\n\nimport {SecondaryButton} from '@workday/canvas-kit-react/button';\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Select, useSelectModel} from '@workday/canvas-kit-react/select';\nimport {BodyText} from '@workday/canvas-kit-react/text';\n\nconst options = [\n {text: 'E-mail', id: 'email-1'},\n {text: 'Phone', id: 'phone-2'},\n {text: 'Fax', id: 'fax-3'},\n {text: 'Mail', id: 'mail-4'},\n {text: 'Mobile Phone', id: 'mobile-phone-5'},\n];\n\nexport const HoistedModel = () => {\n const model = useSelectModel({\n items: options,\n initialSelectedIds: ['fax-3'],\n });\n\n return (\n <>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select model={model}>\n <FormField.Input as={Select.Input} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item.text}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n <BodyText size=\"small\">Selected Value: {model.state.selectedIds[0]}</BodyText>\n <SecondaryButton\n onClick={() => {\n model.events.select({id: 'phone-2'});\n }}\n >\n Select Phone Item\n </SecondaryButton>\n </>\n );\n};\n```\n\n### Label Position Horizontal\n\nSet the `orientation` prop of the Form Field to designate the position of the label relative to the\ninput component. By default, the orientation will be set to `vertical`.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select, useSelectModel} from '@workday/canvas-kit-react/select';\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const LabelPosition = () => {\n const model = useSelectModel({\n items: options,\n });\n\n return (\n <Flex>\n <FormField orientation=\"horizontalStart\">\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select model={model}>\n <FormField.Input as={Select.Input} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n <FormField.Hint>Choose a form of contact</FormField.Hint>\n </Select>\n </FormField.Field>\n </FormField>\n </Flex>\n );\n};\n```\n\n### Required\n\nSet the `required` prop of the wrapping `FormField` to `true` to indicate that the field is\nrequired. Labels for required fields are suffixed by a red asterisk.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const Required = () => {\n const [value, setValue] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.target.value);\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField isRequired>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options}>\n <FormField.Input as={Select.Input} onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n Selected Value: {value}\n </Flex>\n );\n};\n```\n\n### Disabled\n\nSet the `disabled` prop of `Select.Input` to prevent users from interacting with it.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax (disabled)',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const Disabled = () => {\n const [_, setValue] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.target.value);\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options} nonInteractiveIds={['Fax (disabled)']}>\n <FormField.Input as={Select.Input} disabled onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>\n {item => (\n <Select.Item aria-disabled={item === 'Fax (disabled)' ? true : undefined}>\n {item}\n </Select.Item>\n )}\n </Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n </Flex>\n );\n};\n```\n\n### Disabled Items\n\nIn order to disable items and prevent users from interacting with them:\n\n1. Set the `nonInteractiveIds` prop of `Select` to an array of disabled item `id`s. If your items\n are an array of `strings` this will be just the text value. If your items are an array of\n `objects`, this will be that value of the `id` property. This will disable interaction for those\n items and exclude them from type-ahead.\n\n2. Set the `aria-disabled` attribute of all disabled `Select.Item`s to `true`. This ensures the\n items are styled as disabled.\n\nThe following example adds the string value of the items we want disable to `nonInteractiveIds` and\nsets `aria-disabled` for the disabled items.\n\n### With Icons\n\nUse `Select.Item.Icon` to render an icon for a `Select.Item`. The `icon` prop for `Select.Item.Icon`\naccepts [system icons](/assets/system-icons/) from `@workday/canvas-system-icons-web`.\n\nIn order to render the icon for the selected item in the `Select.Input`:\n\n1. Obtain a reference to the `model` by registering your `items` with `useSelectModel`.\n2. Get the selected item:\n `const selectedItem = model.navigation.getItem(model.state.selectedIds[0], model)`\n3. Pass the icon for the selected item to the input:\n `<Select.Input inputStartIcon={selectedItem.value.icon}>`\n\n> **Note: `data-id` on `Select.Item` must match the `id` property in your array of objects. This\n> ensures proper keyboard handling and type-ahead.**\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select, useSelectModel} from '@workday/canvas-kit-react/select';\nimport {createStyles, px2rem} from '@workday/canvas-kit-styling';\nimport {cloudArrowUpIcon, cloudIcon, commentIcon, userIcon} from '@workday/canvas-system-icons-web';\n\nconst styleOverrides = {\n formfieldInputStyles: createStyles({\n width: px2rem(300),\n }),\n selectCardStyles: createStyles({\n maxHeight: px2rem(200),\n }),\n};\n\nconst customOptions = [\n {text: 'Activity Stream', id: 'activity-stream', icon: commentIcon},\n {text: 'Avatar', id: 'avatar', icon: cloudIcon},\n {text: 'Upload Cloud', id: 'upload-cloud', icon: cloudArrowUpIcon},\n {text: 'User', id: 'user', icon: userIcon},\n];\n\nexport const WithIcons = () => {\n const model = useSelectModel({\n items: customOptions,\n });\n const selectedItem = model.navigation.getItem(model.state.selectedIds[0], model);\n return (\n <Flex>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select model={model}>\n <FormField.Input\n as={Select.Input}\n cs={styleOverrides.formfieldInputStyles}\n inputStartIcon={selectedItem?.value.icon}\n />\n <Select.Popper>\n <Select.Card cs={styleOverrides.selectCardStyles}>\n {model.state.items.length > 0 && (\n <Select.List>\n {item => (\n <Select.Item data-id={item.id}>\n <Select.Item.Icon icon={item.icon} />\n {item.text}\n </Select.Item>\n )}\n </Select.List>\n )}\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n </Flex>\n );\n};\n```\n\n**Note: that `Select.Input` will only render an icon if an item is selected.**\n\n### Grow\n\nSet the `grow` prop of the wrapping `FormField` to `true` to configure the `Select.Input` to expand\nto the width of its container.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select, useSelectModel} from '@workday/canvas-kit-react/select';\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const Grow = () => {\n const model = useSelectModel({\n items: options,\n });\n\n return (\n <Flex>\n <FormField grow>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select model={model}>\n <FormField.Input as={Select.Input} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n </Flex>\n );\n};\n```\n\n### Menu Height\n\n`Select.Card` has a default maximum height of `300px` to restrict the height of the dropdown menu.\nSet its `maxHeight` prop to override this value.\n```tsx\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Box} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles, px2rem} from '@workday/canvas-kit-styling';\n\nconst selectCardStyles = createStyles({\n maxHeight: px2rem(200),\n});\n\nconst cities = [\n 'Atlanta (United States)',\n 'Amsterdam (Europe)',\n 'Austin (United States)',\n 'Beaverton (United States)',\n 'Belfast (Europe)',\n 'Berlin (Europe)',\n 'Boston (United States)',\n 'Boulder (United States)',\n 'Chicago (United States)',\n 'Dallas (United States)',\n 'Denver (United States)',\n 'Dublin (Europe)',\n 'Irvine (United States)',\n 'Minneapolis (United States)',\n 'New York (United States)',\n 'Orlando (United States)',\n 'Palo Alto (United States)',\n 'Philadelphia (United States)',\n 'Pleasanton (United States)',\n 'Raleigh (United States)',\n 'San Francisco (United States)',\n 'San Mateo (United States)',\n 'Stockholm (Europe)',\n 'Toronto (Canada)',\n 'Victoria (Canada)',\n 'Vienna (Europe)',\n 'Warsaw (Europe)',\n 'Washington, DC (United States)',\n 'Zurich (Europe)',\n];\n\nexport const MenuHeight = () => {\n return (\n <Box>\n <FormField>\n <FormField.Label>Choose a City</FormField.Label>\n <FormField.Field>\n <Select items={cities}>\n <FormField.Input as={Select.Input} />\n <Select.Popper>\n <Select.Card cs={selectCardStyles}>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n </Box>\n );\n};\n```\n\n### Ref Forwarding\n\n`Select.Input` supports [ref forwarding](https://reactjs.org/docs/forwarding-refs.html). It will\nforward `ref` to its underlying `<input type=\"text\" role=\"combobox\">` element.\n```tsx\nimport React from 'react';\n\nimport {PrimaryButton} from '@workday/canvas-kit-react/button';\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Select} from '@workday/canvas-kit-react/select';\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const RefForwarding = () => {\n // @ts-ignore\n const [value, setValue] = React.useState('medium');\n const ref = React.useRef(null);\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.target.value);\n };\n\n const handleClick = () => {\n if (ref && ref.current) {\n console.log(ref);\n ref.current.focus();\n }\n };\n\n return (\n <>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options}>\n <FormField.Input as={Select.Input} ref={ref} onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n <PrimaryButton onClick={handleClick}>Focus Select</PrimaryButton>\n </>\n );\n};\n```\n\n### Error States\n\nSet the `error` prop of the wrapping `FormField` to `\"caution\"` or `\"error\"` to set the `Select` to\nthe caution or error state, respectively. You will also need to set the `hintId` and `hintText`\nprops on the `FormField` to meet accessibility standards. You must set an `id` attribute on the\n`Select.Input` element that matches the value of `inputId` set on the `FormField` element. These\nattributes ensure that the caution message is associated to the `Select` and read out by voiceover.\n\n**Note: The Select container component, `Select`, must wrap `FormField` to ensure `Select.Input` is\nstyled correctly.**\n\n```tsx\n<Select items={options}>\n <FormField label=\"Contact\" inputId=\"contact-id-formfield\">\n <Select.Input id=\"contact-id-formfield\" />\n ...\n </FormField>\n</Select>\n```\n\n#### Caution\n\nUse the alert state when a selection is valid but there is additional information.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const Caution = () => {\n const [value, setValue] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.target.value);\n };\n return (\n <Flex cs={parentContainerStyles}>\n <FormField error=\"caution\">\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options}>\n <FormField.Input as={Select.Input} onChange={e => handleChange(e)} id=\"alert-select\" />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n <FormField.Hint>Please choose a form of contact.</FormField.Hint>\n </Select>\n </FormField.Field>\n </FormField>\n Selected value: {value}\n </Flex>\n );\n};\n```\n\n#### Error\n\nUse the error state when the selection is no longer valid.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax (disabled)',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const Error = () => {\n const [value, setValue] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.target.value);\n };\n return (\n <Flex cs={parentContainerStyles}>\n <FormField error=\"error\">\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options} nonInteractiveIds={['Fax (disabled)']}>\n <FormField.Input as={Select.Input} onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>\n {item => (\n <Select.Item aria-disabled={item === 'Fax (disabled)' ? true : undefined}>\n {item}\n </Select.Item>\n )}\n </Select.List>\n </Select.Card>\n </Select.Popper>\n <FormField.Hint>Fax is disabled. Please choose a different option.</FormField.Hint>\n </Select>\n </FormField.Field>\n </FormField>\n Selected Value: {value}\n </Flex>\n );\n};\n```\n\n### Initial Selected Item\n\nYou can set `initialSelectedIds` to the value that you want initially selected.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n {\n id: 'b310c757b2d341f99d40d76f4d563c5b',\n descriptor: 'Arabic',\n languageCode: 'ar',\n label: 'Arabic',\n nativeLanguageName: '\u0627\u0644\u0639\u0631\u0628\u064A\u0629',\n },\n {\n id: 'a675a6b6e22d100017d7fe2a784d1255',\n descriptor: 'Bulgarian (Bulgaria)',\n languageCode: 'bg_BG',\n label: 'Bulgarian (Bulgaria)',\n nativeLanguageName: '\u0431\u044A\u043B\u0433\u0430\u0440\u0441\u043A\u0438 (\u0420\u0435\u043F\u0443\u0431\u043B\u0438\u043A\u0430 \u0411\u044A\u043B\u0433\u0430\u0440\u0438\u044F)',\n },\n {\n id: 'da594226446c11de98360015c5e6daf6',\n descriptor: 'English (United States)',\n languageCode: 'en_US',\n label: 'English (United States)',\n nativeLanguageName: 'English',\n },\n];\n\nexport const InitialSelectedItem = () => {\n const [value, setValue] = React.useState('English (United States)');\n const [id, setId] = React.useState('da594226446c11de98360015c5e6daf6');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setId(event.target.value);\n setValue(options.find(item => item.id === event.target.value).label);\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select\n items={options}\n initialSelectedIds={['da594226446c11de98360015c5e6daf6']}\n getId={item => item.id}\n getTextValue={item => item.label}\n >\n <Select.Input onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item.label}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n <p>Id: {id}</p>\n <p>Value: {value}</p>\n </Flex>\n );\n};\n```\n\n### Placeholder\n\nYou can change the placeholder text by passing in a string value to the `placeholder` attribute on\nthe `Select.Input`.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n 'E-mail',\n 'Phone',\n 'Fax',\n 'Mail',\n 'Mobile Phone',\n 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n];\n\nexport const Placeholder = () => {\n const [value, setValue] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.target.value);\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options}>\n <Select.Input placeholder=\"Make a Selection\" onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>\n {item => {\n return <Select.Item>{item}</Select.Item>;\n }}\n </Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n Selected Value: {value}\n </Flex>\n );\n};\n```\n\n### Fetching Dynamic Items\n\nIt's common to load items from a server call. Hoisting the `model` and setting your items on state\nallows you to pass those items to your `model`. You can leverage React state to set your items on\nload as well as displaying a placeholder indicating when items are loaded.\n\n**Note: In this case we need to use `getId` and `getTextValue` because our data doesn't have the\nproperties of `id` or `text`. Using these helper functions sets the `serverId` to be `id` and\n`label` to be `text`.**\n```tsx\nimport React from 'react';\n\nimport {PrimaryButton} from '@workday/canvas-kit-react/button';\nimport {useMount} from '@workday/canvas-kit-react/common';\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select, useSelectModel} from '@workday/canvas-kit-react/select';\nimport {createStyles, px2rem} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n maxWidth: px2rem(300),\n});\n\nconst movieListItems = [\n {\n label: 'The Lion King',\n serverId: '123',\n Year: '2019',\n Runtime: '118 min',\n },\n {\n label: 'Mowgli: Legend of the Jungle',\n serverId: '234',\n Year: '2018',\n Runtime: '104 min',\n },\n {\n label: 'Doctor Strange',\n serverId: '345',\n Year: '2016',\n Runtime: '115 min',\n },\n {\n label: 'John Wick',\n Year: '2014',\n serverId: '456',\n Runtime: '101 min',\n },\n {\n label: 'The Notebook',\n serverId: '567',\n Year: '2004',\n Runtime: '123 min',\n },\n];\n\nexport const FetchingDynamicItems = () => {\n const [id, setId] = React.useState('456');\n const [moviesLists, setMoviesList] = React.useState<typeof movieListItems>([]);\n const [loadingStatus, setLoadingStatus] = React.useState<'idle' | 'loading' | 'success'>('idle');\n const loadingRef = React.useRef<ReturnType<typeof setTimeout>>();\n\n const model = useSelectModel({\n items: moviesLists,\n getTextValue: item => item.label,\n getId: item => item.serverId,\n initialSelectedIds: [id],\n });\n\n const stringValue = moviesLists.find(item => item.serverId === id)?.label || '';\n\n function loadItems() {\n setLoadingStatus('loading');\n loadingRef.current = setTimeout(() => {\n setLoadingStatus('success');\n setMoviesList(movieListItems);\n }, 1500);\n }\n\n useMount(() => {\n return () => {\n clearTimeout(loadingRef.current);\n };\n });\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Choose a Film</FormField.Label>\n <FormField.Field>\n <Select model={model}>\n <FormField.Input\n as={Select.Input}\n onChange={e => {\n setId(e.target.value);\n }}\n placeholder={loadingStatus}\n />\n <Select.Popper>\n <Select.Card>\n <Select.List>\n {item => {\n return <Select.Item>{item.label}</Select.Item>;\n }}\n </Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n <div data-testid=\"selected-id\">Selected Id: {id}</div>\n <div data-testid=\"selected-value\">Selected value: {stringValue}</div>\n <PrimaryButton\n onClick={() => {\n loadItems();\n }}\n >\n Get Items\n </PrimaryButton>\n </Flex>\n );\n};\n```\n\n### Complex\n\nWhen registering items in an array of objects, it's common to have the text that is displayed to the\nuser be different than an id. In this example, `serverId` and `label` properties need to be remapped\nto `id` and `text` hence the usage of `getId` and `getTextValue`. If your object has the properties\n`text` and `id`, there would be no need for this.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n {serverId: 'email', label: 'E-mail'},\n {serverId: 'phone', label: 'Phone'},\n {serverId: 'fax', label: 'Fax'},\n {serverId: 'mail', label: 'Mail'},\n {serverId: 'mobile', label: 'Mobile Phone'},\n {\n serverId: 'oasis',\n label: 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n },\n];\n\nexport const Complex = () => {\n const [value, setValue] = React.useState('');\n const [id, setId] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setId(event.target.value);\n setValue(options.find(item => item.serverId === event.target.value)!.label);\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options} getId={item => item.serverId} getTextValue={item => item.label}>\n <FormField.Input as={Select.Input} onChange={e => handleChange(e)} />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item.label}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n <p>Id: {id}</p>\n <p>Value: {value}</p>\n </Flex>\n );\n};\n```\n\n**Note: By default, the identifier and text value are `id` and `text` properties respectively. If\nyour data object for each item is different, provide a `getId` or `getTextValue` function to the\nmodel config. For example:**\n\n```jsx\nconst items = [\n {\n serverId: '1',\n label: 'First Option',\n },\n];\n\n<Select items={items} getId={item => item.serverId} getTextValue={item => item.label}>\n {/* etc */}\n</Select>;\n```\n\n### Controlled\n\nThe Select can be a\n[controlled input](https://react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable)\ncomponent by passing the `value` and `onChange` to either the `<Select>` component or the\n`<Select.Input>` component. Internally, the `Select.Input` watches for changes on the `value` React\nprop as well as the `value` DOM property and will update the model accordingly.\n```tsx\nimport React from 'react';\n\nimport {SecondaryButton} from '@workday/canvas-kit-react/button';\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Flex} from '@workday/canvas-kit-react/layout';\nimport {Select} from '@workday/canvas-kit-react/select';\nimport {createStyles} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nconst parentContainerStyles = createStyles({\n flexDirection: 'column',\n});\n\nconst options = [\n {serverId: 'email', label: 'E-mail'},\n {serverId: 'phone', label: 'Phone'},\n {serverId: 'fax', label: 'Fax'},\n {serverId: 'mail', label: 'Mail'},\n {serverId: 'mobile', label: 'Mobile Phone'},\n {\n serverId: 'oasis',\n label: 'The Ontologically Anthropocentric Sensory Immersive Simulation',\n },\n];\n\nexport const Controlled = () => {\n const [value, setValue] = React.useState('');\n const [label, setLabel] = React.useState('');\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setValue(event.currentTarget.value);\n setLabel(options.find(item => item.serverId === event.currentTarget.value)?.label || '');\n };\n\n return (\n <Flex cs={parentContainerStyles}>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={options} getId={item => item.serverId} getTextValue={item => item.label}>\n <FormField.Input\n as={Select.Input}\n onChange={handleChange}\n value={value}\n name=\"contact\"\n />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item.label}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n <p>Id: {value}</p>\n <p>Label: {label}</p>\n <Flex cs={{gap: system.gap.md}}>\n <SecondaryButton\n onClick={e => {\n setValue('fax');\n }}\n >\n Set to \"Fax\"\n </SecondaryButton>\n <SecondaryButton\n onClick={e => {\n setValue('');\n }}\n >\n Clear\n </SecondaryButton>\n </Flex>\n </Flex>\n );\n};\n```\n\n### When to use `getId`, or `getTextValue`\n\n- `getId`: This is an optional function to return the id of an item. If not provided, the default\n function will return the `id` property from the object of each item. If you did not provide\n `items`, do not override this function. Instead provide static items via JSX. the list will create\n an internal array of items where `id` is the only property and the default `getId` will return the\n desired result. **Note: If your array of objects has a different property for `id`, like\n `serverId`, use this function to set the id.**\n\n ```tsx\n const options = [{text: 'Pizza', serverId: 'pizza-1'}, {text: 'Cheeseburger', serverId: 'cheeseburger'}]\n <Select items={options} getId={(item) => item.serverId}>\n <FormField label=\"Your Label\">\n <Select.Input onChange={e => handleChange(e)} id=\"contact-select\" />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item.text}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </FormField>\n </Select>\n ```\n\n- `getTextValue`: Optional function to return the text representation of an item. If not provided,\n the default function will return the `text` property of the object of each item or an empty string\n if there is no `text` property. If you did not provide `items`, do not override this function.\n **Note: If your array of objects has a different property for `text`, like `label`, use this\n function to set the text.**\n\n ```tsx\n const options = [{label: 'Pizza', id: 'pizza-1'}, {label: 'Cheeseburger', id: 'cheeseburger'}]\n <Select items={options} getTextValue={(item) => item.label}>\n <FormField label=\"Your Label\">\n <Select.Input onChange={e => handleChange(e)} id=\"contact-select\" />\n <Select.Popper>\n <Select.Card>\n <Select.List>{item => <Select.Item>{item.label}</Select.Item>}</Select.List>\n </Select.Card>\n </Select.Popper>\n </FormField>\n </Select>\n ```\n\n### Grouped Items\n\nIn order to group items, you have to use the static API in combination of the `Menu.Group` component.\n```tsx\nimport React from 'react';\n\nimport {FormField} from '@workday/canvas-kit-react/form-field';\nimport {Menu} from '@workday/canvas-kit-react/menu';\nimport {Select} from '@workday/canvas-kit-react/select';\n\nconst items = [\n {\n id: 'first',\n text: 'First Item',\n },\n {\n id: 'second',\n text: 'Second Item',\n },\n {\n id: 'third',\n text: 'Third Item',\n },\n {\n id: 'fourth',\n text: 'Fourth Item',\n },\n];\n\nexport const GroupedItems = () => {\n const [selected, setSelected] = React.useState('');\n\n return (\n <>\n <FormField>\n <FormField.Label>Contact</FormField.Label>\n <FormField.Field>\n <Select items={items} getId={item => item.id} getTextValue={item => item.text}>\n <FormField.Input as={Select.Input} />\n <Select.Popper>\n <Select.Card>\n <Select.List>\n <Menu.Group title=\"First Group\">\n <Select.Item data-id=\"first\">First Item</Select.Item>\n <Select.Item data-id=\"second\">Second Item</Select.Item>\n </Menu.Group>\n <Menu.Group title=\"Second Group\">\n <Select.Item data-id=\"third\">\n Third Item (with a really, really, really long label)\n </Select.Item>\n <Select.Item aria-disabled data-id=\"fourth\">\n Fourth Item\n </Select.Item>\n </Menu.Group>\n </Select.List>\n </Select.Card>\n </Select.Popper>\n </Select>\n </FormField.Field>\n </FormField>\n </>\n );\n};\n```\n\n### Custom Styles\n\nSelect and its subcomponents support custom styling via the `cs` prop. For more information, check\nour\n[\"How To Customize Styles\"](https://workday.github.io/canvas-kit/?path=/docs/styling-guides-customizing-styles--docs).\n\n## Component API\n\n## Specifications\n\n",
1567
+ accessibilityProse: ""
1568
1568
  },
1569
1569
  "segmented-control": {
1570
1570
  title: "Components/Buttons/Segmented Control",
@@ -1661,8 +1661,8 @@ var stories_config_default = {
1661
1661
  title: "Components/Containers/Expandable",
1662
1662
  storybookUrl: "https://workday.github.io/canvas-kit/?path=/docs/components-containers-expandable--docs",
1663
1663
  mdxPath: "modules/react/expandable/stories/Expandable.mdx",
1664
- mdxProse: '# Canvas Kit Expandable\n\n`Expandable` is a compound component that creates a header to expand or collapse related content.\n\n## Installation\n\n```sh\nyarn add @workday/canvas-kit-react\n```\n\n## Usage\n\n### Start Icon\n\nFor a basic expandable container with a chevron icon before the title, place `Expandable.Icon`\nbefore `Expandable.Title` as children of `Expandable.Target` and pass the `iconPosition` prop to\n`Expandable.Icon` with a value of `start`. `Expandable.Icon` will use a right chevron icon when\ncollapsed and a down chevron icon when expanded.\n```tsx\nimport {Expandable} from \'@workday/canvas-kit-react/expandable\';\n\nexport const StartIcon = () => (\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Icon iconPosition="start" />\n <Expandable.Title>Title</Expandable.Title>\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n);\n```\n\n### End Icon\n\nFor an expandable container with a chevron icon after the title, place `Expandable.Title` before\n`Expandable.Icon` as children of `Expandable.Target` and pass the `iconPosition` prop to\n`Expandable.Icon` with a value of `end`. `Expandable.Icon` will use a down chevron icon when\ncollapsed and an up chevron icon when expanded.\n```tsx\nimport {Expandable} from \'@workday/canvas-kit-react/expandable\';\n\nexport const EndIcon = () => (\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Title>\n This is a really long title that should wrap to multiple lines\n </Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n);\n```\n\n### With Avatar\n\nTo include an avatar image, `Expandable.Avatar` should be placed between `Expandable.Icon` and\n`Expandable.Title`. An `iconPosition` prop with a value of either `start` or `end` should be passed\nto `Expandable.Icon` depending on whether the `Expandable.Icon` is placed before or after\n`Expandable.Title`.\n\n**Note:** If using an avatar image, do not also include an Icon component in addition to the\nExpandable.Icon. This component is meant to have either an avatar image or an icon in addition to\nthe Expandable.Icon, or neither an avatar image nor an extra icon.\n```tsx\nimport {Expandable} from \'@workday/canvas-kit-react/expandable\';\n\n// @ts-ignore: Cannot find module error\nimport testAvatar from \'./test-avatar.png\';\n\nexport const Avatar = () => (\n <div>\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Icon iconPosition="start" />\n <Expandable.Avatar name="Avatar" url={testAvatar} />\n <Expandable.Title>Title</Expandable.Title>\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Avatar name="Avatar" url={testAvatar} />\n <Expandable.Title>Title</Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n </div>\n);\n```\n\n### Right to Left (RTL)\n\nExpandable container has bidirectional support and should function as expected with RTL languages as\nlong as the content direction is set in your Canvas theme.\n```tsx\nimport {CanvasProvider} from \'@workday/canvas-kit-react/common\';\nimport {Expandable} from \'@workday/canvas-kit-react/expandable\';\n\nexport const RTL = () => {\n return (\n <CanvasProvider dir="rtl">\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Icon iconPosition="start" />\n <Expandable.Avatar name="Avatar" />\n <Expandable.Title>Title</Expandable.Title>\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Avatar name="Avatar" />\n <Expandable.Title>Title</Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n </CanvasProvider>\n );\n};\n```\n\n### Depth\n\nThe `depth` prop passed to `Expandable` allows you to adjust the visual elevation of a component\nusing our depth tokens.\n```tsx\nimport {Expandable} from \'@workday/canvas-kit-react/expandable\';\nimport {createStyles} from \'@workday/canvas-kit-styling\';\nimport {system} from \'@workday/canvas-tokens-web\';\n\nconst expandableStyles = createStyles({\n boxShadow: system.depth[3],\n borderRadius: system.shape.lg,\n padding: system.padding.xs,\n margin: system.gap.xs,\n});\n\nexport const Depth = () => {\n return (\n <Expandable cs={expandableStyles}>\n <Expandable.Target headingLevel="h4">\n <Expandable.Title>Additional Information</Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n\n <Expandable.Content>This Expandable Container has a depth of 3.</Expandable.Content>\n </Expandable>\n );\n};\n```\n\n### Title Wrap\n\nLong titles will wrap to the next line and increase the height of the container.\n```tsx\nimport {Expandable} from \'@workday/canvas-kit-react/expandable\';\n\n// @ts-ignore: Cannot find module error\nimport testAvatar from \'./test-avatar.png\';\n\nexport const LongTitle = () => (\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Icon iconPosition="start" />\n <Expandable.Avatar name="Avatar" url={testAvatar} />\n <Expandable.Title>\n Our house special supreme pizza includes pepperoni, sausage, bell peppers, mushrooms,\n onions, and oregano.\n </Expandable.Title>\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n);\n```\n\n### Hoisted Model\n\nIf you need direct access to the model, you can hoist it with the `useExpandableModel` hook. In the\nexample below, we\'re hoisting the models to expand and collapse all three containers at once.\n```tsx\nimport {SecondaryButton} from \'@workday/canvas-kit-react/button\';\nimport {useUniqueId} from \'@workday/canvas-kit-react/common\';\nimport {Expandable, useExpandableModel} from \'@workday/canvas-kit-react/expandable\';\nimport {Flex} from \'@workday/canvas-kit-react/layout\';\nimport {createStyles} from \'@workday/canvas-kit-styling\';\nimport {system} from \'@workday/canvas-tokens-web\';\n\nconst listStyles = createStyles({\n flexDirection: \'column\',\n gap: system.gap.sm,\n padding: \'0\',\n marginInline: system.padding.md,\n marginBlock: \'0\',\n});\n\nexport const HoistedModel = () => {\n const modelOne = useExpandableModel();\n const modelTwo = useExpandableModel();\n const modelThree = useExpandableModel();\n\n const idOne = useUniqueId();\n const idTwo = useUniqueId();\n const idThree = useUniqueId();\n\n const handleExpandAll = () => {\n modelOne.events.show();\n modelTwo.events.show();\n modelThree.events.show();\n };\n\n const handleCollapseAll = () => {\n modelOne.events.hide();\n modelTwo.events.hide();\n modelThree.events.hide();\n };\n\n return (\n <Flex cs={{gap: system.gap.lg, flexDirection: \'column\'}}>\n <Flex cs={{gap: system.gap.md}}>\n <SecondaryButton onClick={handleExpandAll}>Expand All</SecondaryButton>\n <SecondaryButton onClick={handleCollapseAll}>Collapse All</SecondaryButton>\n </Flex>\n <Flex cs={{flexDirection: \'column\'}}>\n <Expandable model={modelOne}>\n <Expandable.Target headingLevel="h4">\n <Expandable.Title id={idOne}>Usage Guidance</Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n\n <Expandable.Content as="section" aria-labelledby={idOne}>\n This component highlights the most important details of a section and reveals more when\n a user taps or clicks on the header part of the container. Enabling users to hide and\n show information ensures the design remains focused and relevant to their expectations.\n Scanning through the most critical information first makes processing more efficient\n without compromising the ability to access additional information.\n </Expandable.Content>\n </Expandable>\n <Expandable model={modelTwo}>\n <Expandable.Target headingLevel="h4">\n <Expandable.Title id={idTwo}>Accessibility Guidelines</Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n\n <Expandable.Content as="section" aria-labelledby={idTwo}>\n <Flex as="ul" cs={listStyles}>\n <li>\n The state of a component being open or closed must be conveyed to assistive\n technologies.\n </li>\n <li>A Button must be used as the control to toggle the display of any content.</li>\n <li>\n If there are multiple toggle Buttons on the same page, provide additional\n information in their labels to make them uniquely distinguishable to a screen\n reader.\n </li>\n <li>\n Do not change the toggle Button label to convey state. An exception to this would be\n a scenario where a visual hint text is decoupled from both the state and the label\n for a control so the hint text is not announced by assistive technologies.\n </li>\n <li>\n Avoid keyboard traps when adding components to the accordion panel. For example, the\n user expands an accordion, but is unable to tab to the next focusable element.\n </li>\n <li>\n Hidden content must be hidden correctly from keyboard, screen reader, and touch\n interaction.\n </li>\n <li>\n Changing the label of something to indicate its state will not always be accounted\n for in live time for a screen reader user. For example, a play button should have a\n non-changing, persistent label and the state (pressed or unpressed) is conveyed\n visually as well as to assistive technology once the state is changed.\n </li>\n </Flex>\n </Expandable.Content>\n </Expandable>\n <Expandable model={modelThree}>\n <Expandable.Target headingLevel="h4">\n <Expandable.Title id={idThree}>Content Guidelines</Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n <Expandable.Content as="section" aria-labelledby={idThree}>\n Titles should be short and concise, yet long enough to explain what the user would\n expect to see when the content is expanded. If titles must be long, make sure it doesn\'t\n wrap more than two lines.\n </Expandable.Content>\n </Expandable>\n </Flex>\n </Flex>\n );\n};\n```\n\nFor the accordion composition (named regions on each panel), see\n[Accessibility Requirements](#accessibility-requirements).\n\n## Accessibility\n\nEnsure users of assistive technology can find the control, understand whether related content is\nshown or hidden, and reveal or hide that content from the keyboard. **`Expandable`** is an inline\n[disclosure (show/hide)](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/) widget: a button\ntoggles content that stays in the document flow.\n\nUse **`Expandable`** for show/hide sections in the page. Compose multiple instances to build an\n[accordion](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/) \u2014 see\n[Hoisted Model](#hoisted-model). For a navigation accordion, see\n[Side Panel with Navigation](https://workday.github.io/canvas-kit/?path=/docs/guides-accessibility-examples-side-panel-navigation--docs).\n\n### Minimum Accessible Structure\n\nThe following matches the [Start Icon](#start-icon) example layout: **`Expandable.Icon`** before\n**`Expandable.Title`** inside **`Expandable.Target`**, then **`Expandable.Content`**.\n**`headingLevel`** is omitted here on purpose \u2014 add it only after asking which level matches the\npage outline (see **Accessibility Requirements**). The Basic Example code uses `headingLevel="h4"`\nas a sample, not a default.\n\n```tsx\n\n<Expandable>\n <Expandable.Target>\n <Expandable.Icon iconPosition="start" />\n <Expandable.Title>Title</Expandable.Title>\n </Expandable.Target>\n <Expandable.Content>Content</Expandable.Content>\n</Expandable>;\n```\n\n### Built-in Behaviors\n\nCanvas Kit applies these automatically via `useExpandableModel` (a `DisclosureModel`) and Expandable\nsubcomponents. **Do not duplicate them** in consuming code.\n\n**ARIA and DOM** (_applied by hooks/subcomponents_):\n\n- **`Expandable.Target`**: native `<button>` with `aria-expanded` (`true` when\n `visibility !== \'hidden\'`) and `aria-controls` set to the disclosure `id`. `onClick` toggles\n `events.show()` / `events.hide()`.\n- **`headingLevel`**: when set (`\'h1\'`\u2013`\'h6\'`), wraps the button in **`Heading`** rendered as that\n heading element. When omitted, the button is not wrapped in a heading.\n- **`Expandable.Content`**: `id` set to the same disclosure `id`. Collapsed content stays in the DOM\n with `display: none` (not unmounted). Default element is a `<div>`.\n- **`Expandable.Title`**: styled `<div>` for the visible name. It does **not** receive an `id` from\n the model.\n- **`Expandable.Icon`**: decorative chevron that rotates from `visibility`. Expanded/collapsed state\n for assistive technology comes from `aria-expanded`, not from the icon.\n- **`Expandable.Avatar`**: `isDecorative={true}` by default so the image is hidden from assistive\n technology when paired with **`Expandable.Title`**.\n- Disclosure `id`: generated with `useUniqueId` unless you pass `id` to **`useExpandableModel`**.\n Default `initialVisibility` is `\'hidden\'`.\n\n**Keyboard** (_native button behavior_):\n\n**`Expandable.Target`** uses native `<button>` keyboard behavior (tab order, <kbd>Enter</kbd> /\n\n<kbd>Space</kbd> to toggle). Collapsed content is not in the tab order (`display: none`). Focus\nstays on the button; Canvas Kit does not move focus into **`Expandable.Content`**.\n\n**Screen reader expectations** (_when built-in behaviors are used as intended_):\n\n- On focus, assistive technology announces the title text, the button role, and expanded/collapsed\n state from `aria-expanded` (for example, "Title, button, collapsed")\n- Activating the button announces the updated expanded/collapsed state from `aria-expanded`\n- While collapsed, content is removed from the accessibility tree (`display: none`)\n- While expanded, content follows the button in reading order\n- When **`headingLevel`** is set, heading navigation includes the heading that wraps the button\n- When **`Expandable.Content as="section"`** is used with `aria-labelledby` pointing at\n **`Expandable.Title`**, region/landmark navigation can name each open section\n\n### Accessibility Requirements\n\nRequired in application code for an accessible Expandable. Hoist **`useExpandableModel`** when you\nneed programmatic show/hide (for example, expand all) or a stable disclosure `id`. Rows marked\n_(conditional)_ apply only when the situation matches\u2014otherwise omit.\n\n**If no design spec is provided:** use the **single disclosure** composition\n([Basic Example](#basic-example)). If the spec is several related headers, use the **accordion**\ncomposition. Omit **`Expandable.Avatar`**, **`initialVisibility`**, and a custom **`id`**.\n\n**Choose a composition** (pick one; **`Expandable.Content as="section"`** and **`as="ul"`** are\nmutually exclusive):\n\n- **Single disclosure** \u2014 one show/hide section. [Basic Example](#basic-example) /\n [Minimum Accessible Structure](#minimum-accessible-structure). Default Content is a `<div>`.\n- **Accordion** \u2014 several related headers. [Hoisted Model](#hoisted-model): unique `id` on\n **`Expandable.Title`**, **`Expandable.Content as="section"`** with `aria-labelledby`.\n- **Navigation list** \u2014 disclosed links.\n [Side Panel with Navigation](https://workday.github.io/canvas-kit/?path=/docs/guides-accessibility-examples-side-panel-navigation--docs):\n **`as="ul"`**, omit **`headingLevel`**.\n\n**Heading level:** Ask which heading (`h1`\u2013`h6`) belongs in the document outline before setting\n**`headingLevel`**. Omit **`headingLevel`** for navigation. Do not generate **`headingLevel`** by\ndefault \u2014 the Basic Example code uses `h4` only as a sample.\n\n| Requirement | How to satisfy |\n| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Accessible name | Non-empty **`Expandable.Title`** inside **`Expandable.Target`**. |\n| Keyboard-operable toggle | **`Expandable.Target`** (native `<button>`). |\n| Visual expanded/collapsed indicator | **`Expandable.Icon`** with `iconPosition` matching layout (`start` or `end`). |\n| Heading in the document outline _(conditional)_ | **`headingLevel`** on **`Expandable.Target`** when the control titles body content (single disclosure or accordion). Omit **`headingLevel`** for the navigation-list composition. Ask which level. |\n| Accordion named regions _(conditional)_ | Accordion composition: **`Expandable.Content as="section"`** plus `aria-labelledby` referencing a unique `id` on **`Expandable.Title`**. |\n| List markup _(conditional)_ | Navigation-list composition: **`Expandable.Content as="ul"`** (and list items as children). |\n| Decorative avatar _(conditional)_ | **`Expandable.Avatar`** when the design includes an avatar. Keep **`isDecorative`** at the default `true`. |\n| Start expanded _(conditional)_ | `initialVisibility: \'visible\'` on **`useExpandableModel`** (or the equivalent model config). |\n| Programmatic expand/collapse _(conditional)_ | Hoist **`useExpandableModel`** and call `model.events.show()` / `model.events.hide()`. |\n\n**Summary for code generation:**\n\n- **REQUIRED:** **`Expandable.Target`**, non-empty **`Expandable.Title`**, **`Expandable.Content`**,\n **`Expandable.Icon`**\n- **CONDITIONAL:** composition (single disclosure vs accordion vs navigation list),\n **`headingLevel`** (ask which; omit for navigation), accordion **`as="section"`** +\n `aria-labelledby`, navigation **`as="ul"`**, **`Expandable.Avatar`**, hoisted\n **`useExpandableModel`**, **`initialVisibility`**\n\n### Anti-Patterns\n\nDo **not** generate code that does the following (see **Accessibility Requirements** above for what\nto supply instead):\n\n- Manually set `aria-expanded`, `aria-controls`, or the disclosure `id` on **`Expandable.Target`**\n or **`Expandable.Content`** \u2014 `useExpandableTarget` and `useExpandableContent` wire these\n- Rely on **`Expandable.Icon`** or **`Expandable.Avatar`** for the accessible name \u2014 use\n **`Expandable.Title`**\n- Override **`Expandable.Target`** with a custom **`as`** \u2014 **`Expandable.Target`** already renders\n a native `<button>`\n- Set `id` on **`Expandable`** to identify the outer wrapper \u2014 `id` is model config **and** is\n forwarded to the container element, while **`Expandable.Content`** also uses `state.id`, which can\n produce duplicate IDs. For a stable content `id`, hoist **`useExpandableModel({id: \'\u2026\'})`**.\n **`Expandable.Title`** still needs its own `id` when you set `aria-labelledby` on\n **`Expandable.Content`**\n- Wrap **`Expandable.Target`** in your own heading \u2014 use **`headingLevel`** instead\n- Default **`headingLevel`** to `h4` (or any level) without asking, or set **`headingLevel`** on\n navigation disclosures\n- Generate several Basic Example disclosures with default `div` Content when the spec is an\n accordion \u2014 use the **accordion** composition (see **Choose a composition**)\n- Set **`as="section"`** and **`as="ul"`** on the same **`Expandable.Content`** \u2014 pick one\n composition\n- Change **`Expandable.Title`** to encode state (for example "Collapsed" / "Expanded" or "Show" /\n "Hide") \u2014 `aria-expanded` already exposes state\n- Unmount **`Expandable.Content`** when collapsed, or add `aria-hidden` on it \u2014 the library uses\n `display: none`\n- Set **`isDecorative={false}`** on **`Expandable.Avatar`** by default, or pair an avatar with an\n extra non-chevron icon\n- Use **`open`**, **`expanded`**, or **`onToggle`** props on **`Expandable`** \u2014 visibility is\n `initialVisibility` plus **`useExpandableModel`** events\n- Assume default **`Expandable.Content`** is a landmark region \u2014 that is only true with\n **`as="section"`**\n\n## Component API\n\n',
1665
- accessibilityProse: '## Accessibility\n\nEnsure users of assistive technology can find the control, understand whether related content is\nshown or hidden, and reveal or hide that content from the keyboard. **`Expandable`** is an inline\n[disclosure (show/hide)](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/) widget: a button\ntoggles content that stays in the document flow.\n\nUse **`Expandable`** for show/hide sections in the page. Compose multiple instances to build an\n[accordion](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/) \u2014 see\n[Hoisted Model](#hoisted-model). For a navigation accordion, see\n[Side Panel with Navigation](https://workday.github.io/canvas-kit/?path=/docs/guides-accessibility-examples-side-panel-navigation--docs).\n\n### Minimum Accessible Structure\n\nThe following matches the [Start Icon](#start-icon) example layout: **`Expandable.Icon`** before\n**`Expandable.Title`** inside **`Expandable.Target`**, then **`Expandable.Content`**.\n**`headingLevel`** is omitted here on purpose \u2014 add it only after asking which level matches the\npage outline (see **Accessibility Requirements**). The Basic Example code uses `headingLevel="h4"`\nas a sample, not a default.\n\n```tsx\n\n<Expandable>\n <Expandable.Target>\n <Expandable.Icon iconPosition="start" />\n <Expandable.Title>Title</Expandable.Title>\n </Expandable.Target>\n <Expandable.Content>Content</Expandable.Content>\n</Expandable>;\n```\n\n### Built-in Behaviors\n\nCanvas Kit applies these automatically via `useExpandableModel` (a `DisclosureModel`) and Expandable\nsubcomponents. **Do not duplicate them** in consuming code.\n\n**ARIA and DOM** (_applied by hooks/subcomponents_):\n\n- **`Expandable.Target`**: native `<button>` with `aria-expanded` (`true` when\n `visibility !== \'hidden\'`) and `aria-controls` set to the disclosure `id`. `onClick` toggles\n `events.show()` / `events.hide()`.\n- **`headingLevel`**: when set (`\'h1\'`\u2013`\'h6\'`), wraps the button in **`Heading`** rendered as that\n heading element. When omitted, the button is not wrapped in a heading.\n- **`Expandable.Content`**: `id` set to the same disclosure `id`. Collapsed content stays in the DOM\n with `display: none` (not unmounted). Default element is a `<div>`.\n- **`Expandable.Title`**: styled `<div>` for the visible name. It does **not** receive an `id` from\n the model.\n- **`Expandable.Icon`**: decorative chevron that rotates from `visibility`. Expanded/collapsed state\n for assistive technology comes from `aria-expanded`, not from the icon.\n- **`Expandable.Avatar`**: `isDecorative={true}` by default so the image is hidden from assistive\n technology when paired with **`Expandable.Title`**.\n- Disclosure `id`: generated with `useUniqueId` unless you pass `id` to **`useExpandableModel`**.\n Default `initialVisibility` is `\'hidden\'`.\n\n**Keyboard** (_native button behavior_):\n\n**`Expandable.Target`** uses native `<button>` keyboard behavior (tab order, <kbd>Enter</kbd> /\n\n<kbd>Space</kbd> to toggle). Collapsed content is not in the tab order (`display: none`). Focus\nstays on the button; Canvas Kit does not move focus into **`Expandable.Content`**.\n\n**Screen reader expectations** (_when built-in behaviors are used as intended_):\n\n- On focus, assistive technology announces the title text, the button role, and expanded/collapsed\n state from `aria-expanded` (for example, "Title, button, collapsed")\n- Activating the button announces the updated expanded/collapsed state from `aria-expanded`\n- While collapsed, content is removed from the accessibility tree (`display: none`)\n- While expanded, content follows the button in reading order\n- When **`headingLevel`** is set, heading navigation includes the heading that wraps the button\n- When **`Expandable.Content as="section"`** is used with `aria-labelledby` pointing at\n **`Expandable.Title`**, region/landmark navigation can name each open section\n\n### Accessibility Requirements\n\nRequired in application code for an accessible Expandable. Hoist **`useExpandableModel`** when you\nneed programmatic show/hide (for example, expand all) or a stable disclosure `id`. Rows marked\n_(conditional)_ apply only when the situation matches\u2014otherwise omit.\n\n**If no design spec is provided:** use the **single disclosure** composition\n([Basic Example](#basic-example)). If the spec is several related headers, use the **accordion**\ncomposition. Omit **`Expandable.Avatar`**, **`initialVisibility`**, and a custom **`id`**.\n\n**Choose a composition** (pick one; **`Expandable.Content as="section"`** and **`as="ul"`** are\nmutually exclusive):\n\n- **Single disclosure** \u2014 one show/hide section. [Basic Example](#basic-example) /\n [Minimum Accessible Structure](#minimum-accessible-structure). Default Content is a `<div>`.\n- **Accordion** \u2014 several related headers. [Hoisted Model](#hoisted-model): unique `id` on\n **`Expandable.Title`**, **`Expandable.Content as="section"`** with `aria-labelledby`.\n- **Navigation list** \u2014 disclosed links.\n [Side Panel with Navigation](https://workday.github.io/canvas-kit/?path=/docs/guides-accessibility-examples-side-panel-navigation--docs):\n **`as="ul"`**, omit **`headingLevel`**.\n\n**Heading level:** Ask which heading (`h1`\u2013`h6`) belongs in the document outline before setting\n**`headingLevel`**. Omit **`headingLevel`** for navigation. Do not generate **`headingLevel`** by\ndefault \u2014 the Basic Example code uses `h4` only as a sample.\n\n| Requirement | How to satisfy |\n| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Accessible name | Non-empty **`Expandable.Title`** inside **`Expandable.Target`**. |\n| Keyboard-operable toggle | **`Expandable.Target`** (native `<button>`). |\n| Visual expanded/collapsed indicator | **`Expandable.Icon`** with `iconPosition` matching layout (`start` or `end`). |\n| Heading in the document outline _(conditional)_ | **`headingLevel`** on **`Expandable.Target`** when the control titles body content (single disclosure or accordion). Omit **`headingLevel`** for the navigation-list composition. Ask which level. |\n| Accordion named regions _(conditional)_ | Accordion composition: **`Expandable.Content as="section"`** plus `aria-labelledby` referencing a unique `id` on **`Expandable.Title`**. |\n| List markup _(conditional)_ | Navigation-list composition: **`Expandable.Content as="ul"`** (and list items as children). |\n| Decorative avatar _(conditional)_ | **`Expandable.Avatar`** when the design includes an avatar. Keep **`isDecorative`** at the default `true`. |\n| Start expanded _(conditional)_ | `initialVisibility: \'visible\'` on **`useExpandableModel`** (or the equivalent model config). |\n| Programmatic expand/collapse _(conditional)_ | Hoist **`useExpandableModel`** and call `model.events.show()` / `model.events.hide()`. |\n\n**Summary for code generation:**\n\n- **REQUIRED:** **`Expandable.Target`**, non-empty **`Expandable.Title`**, **`Expandable.Content`**,\n **`Expandable.Icon`**\n- **CONDITIONAL:** composition (single disclosure vs accordion vs navigation list),\n **`headingLevel`** (ask which; omit for navigation), accordion **`as="section"`** +\n `aria-labelledby`, navigation **`as="ul"`**, **`Expandable.Avatar`**, hoisted\n **`useExpandableModel`**, **`initialVisibility`**\n\n### Anti-Patterns\n\nDo **not** generate code that does the following (see **Accessibility Requirements** above for what\nto supply instead):\n\n- Manually set `aria-expanded`, `aria-controls`, or the disclosure `id` on **`Expandable.Target`**\n or **`Expandable.Content`** \u2014 `useExpandableTarget` and `useExpandableContent` wire these\n- Rely on **`Expandable.Icon`** or **`Expandable.Avatar`** for the accessible name \u2014 use\n **`Expandable.Title`**\n- Override **`Expandable.Target`** with a custom **`as`** \u2014 **`Expandable.Target`** already renders\n a native `<button>`\n- Set `id` on **`Expandable`** to identify the outer wrapper \u2014 `id` is model config **and** is\n forwarded to the container element, while **`Expandable.Content`** also uses `state.id`, which can\n produce duplicate IDs. For a stable content `id`, hoist **`useExpandableModel({id: \'\u2026\'})`**.\n **`Expandable.Title`** still needs its own `id` when you set `aria-labelledby` on\n **`Expandable.Content`**\n- Wrap **`Expandable.Target`** in your own heading \u2014 use **`headingLevel`** instead\n- Default **`headingLevel`** to `h4` (or any level) without asking, or set **`headingLevel`** on\n navigation disclosures\n- Generate several Basic Example disclosures with default `div` Content when the spec is an\n accordion \u2014 use the **accordion** composition (see **Choose a composition**)\n- Set **`as="section"`** and **`as="ul"`** on the same **`Expandable.Content`** \u2014 pick one\n composition\n- Change **`Expandable.Title`** to encode state (for example "Collapsed" / "Expanded" or "Show" /\n "Hide") \u2014 `aria-expanded` already exposes state\n- Unmount **`Expandable.Content`** when collapsed, or add `aria-hidden` on it \u2014 the library uses\n `display: none`\n- Set **`isDecorative={false}`** on **`Expandable.Avatar`** by default, or pair an avatar with an\n extra non-chevron icon\n- Use **`open`**, **`expanded`**, or **`onToggle`** props on **`Expandable`** \u2014 visibility is\n `initialVisibility` plus **`useExpandableModel`** events\n- Assume default **`Expandable.Content`** is a landmark region \u2014 that is only true with\n **`as="section"`**'
1664
+ mdxProse: '# Canvas Kit Expandable\n\n`Expandable` is a compound component that creates a header to expand or collapse related content.\n\n## Installation\n\n```sh\nyarn add @workday/canvas-kit-react\n```\n\n## Usage\n\n### Start Icon\n\nFor a basic expandable container with a chevron icon before the title, place`Expandable.Icon` before\n`Expandable.Title` as children of `Expandable.Target` and pass the `iconPosition` prop to\n`Expandable.Icon` with a value of `start`. `Expandable.Icon` will use a right chevron icon when\ncollapsed and a down chevron icon when expanded.\n```tsx\nimport {Expandable} from \'@workday/canvas-kit-react/expandable\';\n\nexport const StartIcon = () => (\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Icon iconPosition="start" />\n <Expandable.Title>Title</Expandable.Title>\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n);\n```\n\n### End Icon\n\nFor an expandable container with a chevron icon after the title, place `Expandable.Title` before\n`Expandable.Icon` as children of `Expandable.Target` and pass the `iconPosition` prop to\n`Expandable.Icon` with a value of `end`. `Expandable.Icon` will use a down chevron icon when\ncollapsed and an up chevron icon when expanded.\n```tsx\nimport {Expandable} from \'@workday/canvas-kit-react/expandable\';\n\nexport const EndIcon = () => (\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Title>\n This is a really long title that should wrap to multiple lines\n </Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n);\n```\n\n### With Avatar\n\nTo include an avatar image, `Expandable.Avatar` should be placed between `Expandable.Icon` and\n`Expandable.Title`. An `iconPosition` prop with a value of either `start` or `end` should be passed\nto `Expandable.Icon` depending on whether the `Expandable.Icon` is placed before or after\n`Expandable.Title`.\n\n**Note:** If using an avatar image, do not also include an Icon component in addition to the Expandable.Icon.\nThis component is meant to have either an avatar image or an icon in addition to the Expandable.Icon, or neither\nan avatar image nor an extra icon.\n```tsx\nimport {Expandable} from \'@workday/canvas-kit-react/expandable\';\n\n// @ts-ignore: Cannot find module error\nimport testAvatar from \'./test-avatar.png\';\n\nexport const Avatar = () => (\n <div>\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Icon iconPosition="start" />\n <Expandable.Avatar name="Avatar" url={testAvatar} />\n <Expandable.Title>Title</Expandable.Title>\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Avatar name="Avatar" url={testAvatar} />\n <Expandable.Title>Title</Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n </div>\n);\n```\n\n> **Accessibility Note:** In this situation, the Avatar is decorative and should not be announced to\n> screen readers. The `<Expandable.Avatar>` component has `isDecorative` set to `true` by default to\n> hide it from screen readers, as avatars in expandable headers are typically decorative when paired\n> with adjacent text.\n\n### Right to Left (RTL)\n\nExpandable container has bidirectional support and should function as expected with RTL languages as\nlong as the content direction is set in your Canvas theme.\n```tsx\nimport {CanvasProvider} from \'@workday/canvas-kit-react/common\';\nimport {Expandable} from \'@workday/canvas-kit-react/expandable\';\n\nexport const RTL = () => {\n return (\n <CanvasProvider dir="rtl">\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Icon iconPosition="start" />\n <Expandable.Avatar name="Avatar" />\n <Expandable.Title>Title</Expandable.Title>\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Avatar name="Avatar" />\n <Expandable.Title>Title</Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n </CanvasProvider>\n );\n};\n```\n\n### Depth\n\nThe `depth` prop passed to `Expandable` allows you to adjust the visual elevation of a component\nusing our depth tokens.\n```tsx\nimport {Expandable} from \'@workday/canvas-kit-react/expandable\';\nimport {createStyles} from \'@workday/canvas-kit-styling\';\nimport {system} from \'@workday/canvas-tokens-web\';\n\nconst expandableStyles = createStyles({\n boxShadow: system.depth[3],\n borderRadius: system.shape.lg,\n padding: system.padding.xs,\n margin: system.gap.xs,\n});\n\nexport const Depth = () => {\n return (\n <Expandable cs={expandableStyles}>\n <Expandable.Target headingLevel="h4">\n <Expandable.Title>Additional Information</Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n\n <Expandable.Content>This Expandable Container has a depth of 3.</Expandable.Content>\n </Expandable>\n );\n};\n```\n\n### Title Wrap\n\nLong titles will wrap to the next line and increase the height of the container.\n```tsx\nimport {Expandable} from \'@workday/canvas-kit-react/expandable\';\n\n// @ts-ignore: Cannot find module error\nimport testAvatar from \'./test-avatar.png\';\n\nexport const LongTitle = () => (\n <Expandable>\n <Expandable.Target headingLevel="h4">\n <Expandable.Icon iconPosition="start" />\n <Expandable.Avatar name="Avatar" url={testAvatar} />\n <Expandable.Title>\n Our house special supreme pizza includes pepperoni, sausage, bell peppers, mushrooms,\n onions, and oregano.\n </Expandable.Title>\n </Expandable.Target>\n\n <Expandable.Content>Content</Expandable.Content>\n </Expandable>\n);\n```\n\nYou can also have direct access to the model if\n\n### Hoisted Model\n\nIf you need direct access to the model, you can hoist it with the `useExpandableModel` hook. In the\nexample below, we\'re hoisting the models to expand and collapse all three containers at once.\n```tsx\nimport {SecondaryButton} from \'@workday/canvas-kit-react/button\';\nimport {useUniqueId} from \'@workday/canvas-kit-react/common\';\nimport {Expandable, useExpandableModel} from \'@workday/canvas-kit-react/expandable\';\nimport {Flex} from \'@workday/canvas-kit-react/layout\';\nimport {createStyles} from \'@workday/canvas-kit-styling\';\nimport {system} from \'@workday/canvas-tokens-web\';\n\nconst listStyles = createStyles({\n flexDirection: \'column\',\n gap: system.gap.sm,\n padding: \'0\',\n marginInline: system.padding.md,\n marginBlock: \'0\',\n});\n\nexport const HoistedModel = () => {\n const modelOne = useExpandableModel();\n const modelTwo = useExpandableModel();\n const modelThree = useExpandableModel();\n\n const idOne = useUniqueId();\n const idTwo = useUniqueId();\n const idThree = useUniqueId();\n\n const handleExpandAll = () => {\n modelOne.events.show();\n modelTwo.events.show();\n modelThree.events.show();\n };\n\n const handleCollapseAll = () => {\n modelOne.events.hide();\n modelTwo.events.hide();\n modelThree.events.hide();\n };\n\n return (\n <Flex cs={{gap: system.gap.lg, flexDirection: \'column\'}}>\n <Flex cs={{gap: system.gap.md}}>\n <SecondaryButton onClick={handleExpandAll}>Expand All</SecondaryButton>\n <SecondaryButton onClick={handleCollapseAll}>Collapse All</SecondaryButton>\n </Flex>\n <Flex cs={{flexDirection: \'column\'}}>\n <Expandable model={modelOne}>\n <Expandable.Target headingLevel="h4">\n <Expandable.Title id={idOne}>Usage Guidance</Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n\n <Expandable.Content as="section" aria-labelledby={idOne}>\n This component highlights the most important details of a section and reveals more when\n a user taps or clicks on the header part of the container. Enabling users to hide and\n show information ensures the design remains focused and relevant to their expectations.\n Scanning through the most critical information first makes processing more efficient\n without compromising the ability to access additional information.\n </Expandable.Content>\n </Expandable>\n <Expandable model={modelTwo}>\n <Expandable.Target headingLevel="h4">\n <Expandable.Title id={idTwo}>Accessibility Guidelines</Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n\n <Expandable.Content as="section" aria-labelledby={idTwo}>\n <Flex as="ul" cs={listStyles}>\n <li>\n The state of a component being open or closed must be conveyed to assistive\n technologies.\n </li>\n <li>A Button must be used as the control to toggle the display of any content.</li>\n <li>\n If there are multiple toggle Buttons on the same page, provide additional\n information in their labels to make them uniquely distinguishable to a screen\n reader.\n </li>\n <li>\n Do not change the toggle Button label to convey state. An exception to this would be\n a scenario where a visual hint text is decoupled from both the state and the label\n for a control so the hint text is not announced by assistive technologies.\n </li>\n <li>\n Avoid keyboard traps when adding components to the accordion panel. For example, the\n user expands an accordion, but is unable to tab to the next focusable element.\n </li>\n <li>\n Hidden content must be hidden correctly from keyboard, screen reader, and touch\n interaction.\n </li>\n <li>\n Changing the label of something to indicate its state will not always be accounted\n for in live time for a screen reader user. For example, a play button should have a\n non-changing, persistent label and the state (pressed or unpressed) is conveyed\n visually as well as to assistive technology once the state is changed.\n </li>\n </Flex>\n </Expandable.Content>\n </Expandable>\n <Expandable model={modelThree}>\n <Expandable.Target headingLevel="h4">\n <Expandable.Title id={idThree}>Content Guidelines</Expandable.Title>\n <Expandable.Icon iconPosition="end" />\n </Expandable.Target>\n <Expandable.Content as="section" aria-labelledby={idThree}>\n Titles should be short and concise, yet long enough to explain what the user would\n expect to see when the content is expanded. If titles must be long, make sure it doesn\'t\n wrap more than two lines.\n </Expandable.Content>\n </Expandable>\n </Flex>\n </Flex>\n );\n};\n```\n\n> **Accessibility Note:** When using multiple Expandable Containers on a page, use the `as` prop to\n> render the `<Expandable.Content>` sub-component as an HTML `<section>` element. Then, use\n> `aria-labelledby` to reference the unique `id` of the `<Expandable.Title>` element. This practice\n> can be useful to screen reader users when multiple Expandable Containers are opened at one time\n> for uniquely describing the boundaries of the expandable content.\n\n## Accessibility\n\nOur Expandable component renders a semantic HTML `<button>` element to the DOM, with an optional\nparent heading element as defined by the `headingLevel` prop. The `aria-expanded` property is\nincluded on the button to indicate the state of the content to screen readers.\n\n[Accordion Pattern | APG | WAI | W3C](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/)\n\n- Use the `headingLevel` prop to assign an appropriate heading level based on the context of the\n page content.\n- When using Expandable Container for navigation elements, then we don\'t recommend using the\n `headingLevel` prop. This will render only expandable buttons to the DOM, reserving headings for\n organizing content in the main body of the page.\n- The `as` prop may also be used on `<Expandable.Content>` to render an HTML `<ul>` element for\n displaying a list of items. For example, check out\n [Side Panel with Navigation](https://workday.github.io/canvas-kit/?path=/docs/guides-accessibility-examples-side-panel-navigation--docs).\n\n### Navigation\n\n- **Tab key**: Moves focus to the next expandable button or focusable element\n- **Shift + Tab**: Moves focus to the previous focusable element\n- **Enter or Space**: Toggles the expanded/collapsed state\n\n### Screen Reader Experience\n\n- The expandable button will be announced with its title text followed by the button role\n- The current state will be announced as either "collapsed" or "expanded" (For example: "Usage\n Guidance, button, collapsed" or "Usage Guidance, button, expanded")\n- **State Changes:** When activating the button to expand content, screen readers will announce the\n new "expanded" state and vice versa when collapsing content.\n- **Content Regions:** Screen reader users can use landmark navigation to jump between sections and\n each section will be announced with its associated title (For example: "Usage Guidance, landmark\n region")\n- **Heading Structure:** Using heading levels with expandable buttons allows screen reader users to\n navigate by headings, making the document structure and hierarchy easier to understand.\n\n## Component API\n\n',
1665
+ accessibilityProse: '## Accessibility\n\nOur Expandable component renders a semantic HTML `<button>` element to the DOM, with an optional\nparent heading element as defined by the `headingLevel` prop. The `aria-expanded` property is\nincluded on the button to indicate the state of the content to screen readers.\n\n[Accordion Pattern | APG | WAI | W3C](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/)\n\n- Use the `headingLevel` prop to assign an appropriate heading level based on the context of the\n page content.\n- When using Expandable Container for navigation elements, then we don\'t recommend using the\n `headingLevel` prop. This will render only expandable buttons to the DOM, reserving headings for\n organizing content in the main body of the page.\n- The `as` prop may also be used on `<Expandable.Content>` to render an HTML `<ul>` element for\n displaying a list of items. For example, check out\n [Side Panel with Navigation](https://workday.github.io/canvas-kit/?path=/docs/guides-accessibility-examples-side-panel-navigation--docs).\n\n### Navigation\n\n- **Tab key**: Moves focus to the next expandable button or focusable element\n- **Shift + Tab**: Moves focus to the previous focusable element\n- **Enter or Space**: Toggles the expanded/collapsed state\n\n### Screen Reader Experience\n\n- The expandable button will be announced with its title text followed by the button role\n- The current state will be announced as either "collapsed" or "expanded" (For example: "Usage\n Guidance, button, collapsed" or "Usage Guidance, button, expanded")\n- **State Changes:** When activating the button to expand content, screen readers will announce the\n new "expanded" state and vice versa when collapsing content.\n- **Content Regions:** Screen reader users can use landmark navigation to jump between sections and\n each section will be announced with its associated title (For example: "Usage Guidance, landmark\n region")\n- **Heading Structure:** Using heading levels with expandable buttons allows screen reader users to\n navigate by headings, making the document structure and hierarchy easier to understand.'
1666
1666
  },
1667
1667
  dialog: {
1668
1668
  title: "Components/Popups/Dialog",
@@ -1769,6 +1769,13 @@ var stories_config_default = {
1769
1769
  mdxProse: "# Divider\n\nA `Divider` segments and visually organizes content.\n\n## Installation\n\n```sh\nyarn add @workday/canvas-kit-preview-react\n```\n\n## Usage\n\nUse a `Divider` to separate content and create visual hierarchy. Typically they are used between\nparagraph sections to indicate a break or shift in content. However, they can also be used as\ndecorative elements to provide greater emphasis and visual hierarchy.\n\n### Basic Example\n\nBy default, `Divider` renders a `<hr>` (horizontal rule) element with `0.5rem` of margin on top and\nbottom. The `space` prop allows you to adjust the vertical margin evenly. In the example below, the\n`Divider`s provide a subtle deliniation between each profile card without being as visually\nprominent as a `Card`. The `space` is adjusted to `0.25rem` which applied `0.125rem` to the top and\nbottom margin.\n```tsx\nimport {Divider} from '@workday/canvas-kit-preview-react/divider';\nimport {Avatar} from '@workday/canvas-kit-react/avatar';\nimport {createStyles} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nconst sectionStyles = createStyles({\n display: 'flex',\n flexDirection: 'column',\n gap: system.gap.md,\n maxWidth: '40rem',\n});\n\nexport const Basic = () => {\n const lastIndex = maintainerList.length - 1;\n return (\n <section className={sectionStyles}>\n {maintainerList.map((maintainerData, index) => (\n <>\n <ProfileCard {...maintainerData} />\n {index !== lastIndex && <Divider space={system.gap.xs} />}\n </>\n ))}\n </section>\n );\n};\n\nconst maintainerList = [\n {\n id: '44883293',\n name: 'Josh Bagwell',\n bio: 'Master of Cocktails and Fast Cars',\n },\n {\n id: '338257',\n name: 'Nicholas Boll',\n bio: 'Principal Potato Engineer',\n },\n {\n id: '7966550',\n name: 'Manuel Carrera',\n bio: 'Sr. Rock Climber and Artist',\n },\n {\n id: '146020',\n name: 'James Fan',\n bio: 'Sr. Television Consultant',\n },\n {\n id: '48605821',\n name: 'Raisa Primerova',\n bio: 'Principal Borscht Connoisseur',\n },\n {\n id: '4818182',\n name: 'Alan Smith',\n bio: 'Principal Pizza Tosser',\n },\n];\n\nconst profileCardStyles = createStyles({\n display: 'flex',\n gap: '0.5rem',\n flexDirection: 'row',\n});\n\nconst profileCardAvatarStyles = createStyles({\n gridColumn: '1',\n gridRow: '1 / 3',\n});\n\nconst profileCardHeadingStyles = createStyles({\n ...system.type.body.lg,\n fontWeight: system.fontWeight.bold,\n gridColumn: '2/3',\n gridRow: '1',\n margin: 0,\n});\n\nconst profileCardBodyStyles = createStyles({\n ...system.type.body.sm,\n gridColumn: '2',\n gridRow: '2',\n margin: 0,\n});\n\nconst profileCardContentStyles = createStyles({\n display: 'flex',\n flexDirection: 'column',\n gap: system.gap.xs,\n});\n\ninterface ProfileCardProps {\n id: string;\n name: string;\n bio: string;\n}\n\nconst ProfileCard = ({id, name, bio}: ProfileCardProps) => (\n <div className={profileCardStyles}>\n <Avatar\n size=\"large\"\n url={`https://avatars.githubusercontent.com/u/${id}?v=4`}\n name={`${name}'s avatar`}\n className={profileCardAvatarStyles}\n />\n <div className={profileCardContentStyles}>\n <h3 className={profileCardHeadingStyles}>{name}</h3>\n <p className={profileCardBodyStyles}>{bio}</p>\n </div>\n </div>\n);\n```\n\n### Vertical Example\n```tsx\nimport {Divider} from '@workday/canvas-kit-preview-react/divider';\nimport {createStyles} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nconst rowStyles = createStyles({\n display: 'flex',\n alignItems: 'center',\n height: system.size.xxl,\n});\n\nconst statStyles = createStyles({\n display: 'flex',\n flexDirection: 'column',\n gap: system.gap.none,\n});\n\nconst labelStyles = createStyles({\n ...system.type.subtext.medium,\n color: system.color.fg.default,\n margin: 0,\n});\n\nconst valueStyles = createStyles({\n ...system.type.body.large,\n fontWeight: system.fontWeight.bold,\n margin: 0,\n});\n\nexport const Vertical = () => {\n const lastIndex = stats.length - 1;\n return (\n <div className={rowStyles}>\n {stats.map((stat, index) => (\n <>\n <div className={statStyles}>\n <p className={labelStyles}>{stat.label}</p>\n <p className={valueStyles}>{stat.value}</p>\n </div>\n {index !== lastIndex && <Divider orientation=\"vertical\" space={system.gap.md} />}\n </>\n ))}\n </div>\n );\n};\n\nconst stats = [\n {label: 'Components', value: '128'},\n {label: 'Contributors', value: '64'},\n {label: 'Releases', value: '512'},\n];\n```\n\n### Custom Space\n\nYou might also want to apply custom space to `Divider` where the top and bottom margin are not\nequal. The best way to achieve this is with `createStyles` and the `cs` property. In the example\nbelow, the `Divider` is applied as a decorative element to add emphasis to the section heading.\nCustom styles are defined in the `createStyles` function outside the component and are passed to\n`Divider`'s `cs` prop. These styles remove the top margin and set the bottom margin to `1rem`.\n```tsx\nimport React from 'react';\n\nimport {Divider} from '@workday/canvas-kit-preview-react/divider';\nimport {createStyles} from '@workday/canvas-kit-styling';\nimport {system} from '@workday/canvas-tokens-web';\n\nconst headingStyles = createStyles({\n ...system.type.body.lg,\n fontWeight: system.fontWeight.bold,\n margin: 0,\n});\n\nconst bodyStyles = createStyles({\n ...system.type.body.sm,\n margin: 0,\n});\n\nconst customDividerSpace = createStyles({\n margin: `0 0 ${system.gap.md}`,\n});\n\nexport const CustomSpace = () => {\n return (\n <section>\n <h3 className={headingStyles}>Quote of the Day</h3>\n <Divider cs={customDividerSpace} />\n <p className={bodyStyles}>\n \"It is not our differences that divide us. It is our inability to recognize, accept, and\n celebrate those differences.\" \u2013 Audre Lorde\n </p>\n </section>\n );\n};\n```\n\n## Component API\n\n",
1770
1770
  accessibilityProse: ""
1771
1771
  },
1772
+ "selection-group": {
1773
+ title: "Labs/Selection Group",
1774
+ storybookUrl: "https://workday.github.io/canvas-kit/?path=/docs/labs-selection-group--docs",
1775
+ mdxPath: "modules/labs-react/selection-group/stories/SelectionGroup.mdx",
1776
+ mdxProse: '# Canvas Kit Selection Group\n\nSelection Group is a\n[compound component](/getting-started/for-developers/resources/compound-components/) that lets users\nselect one or more options from a predefined list using chip-style controls with a lightweight glyph\nindicator.\n\nReach for Selection Group instead of standard radio buttons or checkboxes when a larger, more\nscannable tap target and a lighter visual footprint are preferred. It works best with roughly seven\nor fewer options and short, concise labels.\n\n## Installation\n\n```sh\nyarn add @workday/canvas-kit-labs-react\n```\n\n## Usage\n\n### Basic Example\n\n`SelectionGroup` includes a container `SelectionGroup` component and the following subcomponents:\n`SelectionGroup.List` and `SelectionGroup.Item`.\n```tsx\nimport {SelectionGroup} from \'@workday/canvas-kit-labs-react/selection-group\';\n\nexport const Basic = () => (\n <SelectionGroup mode="single">\n <SelectionGroup.List aria-label="Preferred contact method (select one)">\n <SelectionGroup.Item data-id="email">Email</SelectionGroup.Item>\n <SelectionGroup.Item data-id="phone">Phone</SelectionGroup.Item>\n <SelectionGroup.Item data-id="text">Text Message</SelectionGroup.Item>\n </SelectionGroup.List>\n </SelectionGroup>\n);\n```\n\n### Single Select\n\nUse `mode="single"` to allow only one selection at a time. Single-select groups use a circle glyph\nand behave like a radio group: they have a single tab stop and arrow keys move both focus and\nselection.\n```tsx\nimport React from \'react\';\n\nimport {SelectionGroup} from \'@workday/canvas-kit-labs-react/selection-group\';\nimport {FormField} from \'@workday/canvas-kit-react/form-field\';\nimport {BodyText} from \'@workday/canvas-kit-react/text\';\nimport {system} from \'@workday/canvas-tokens-web\';\n\nexport const SingleSelect = () => {\n const [selected, setSelected] = React.useState(\'email\');\n\n return (\n <>\n <FormField as="fieldset">\n <FormField.Label as="legend">Preferred Contact Method (Select one)</FormField.Label>\n <FormField.Input\n as={SelectionGroup}\n mode="single"\n selectedIds={[selected]}\n onSelect={data => setSelected(data.id)}\n >\n <SelectionGroup.List aria-label="Preferred contact method (select one)">\n <SelectionGroup.Item data-id="email">Email</SelectionGroup.Item>\n <SelectionGroup.Item data-id="phone">Phone</SelectionGroup.Item>\n <SelectionGroup.Item data-id="text">Text Message</SelectionGroup.Item>\n </SelectionGroup.List>\n </FormField.Input>\n </FormField>\n <BodyText size="small" cs={{marginBlockStart: system.gap.md}}>\n Selected: {selected}\n </BodyText>\n </>\n );\n};\n```\n\n### Multi Select\n\nUse `mode="multiple"` to allow more than one selection. Multi-select groups use a square glyph and\nbehave like a checkbox group, where every item is its own tab stop. The group label must state that\nmultiple selections are allowed.\n```tsx\nimport React from \'react\';\n\nimport {SelectionGroup} from \'@workday/canvas-kit-labs-react/selection-group\';\nimport {FormField} from \'@workday/canvas-kit-react/form-field\';\nimport {BodyText} from \'@workday/canvas-kit-react/text\';\nimport {system} from \'@workday/canvas-tokens-web\';\n\nexport const MultiSelect = () => {\n const [selected, setSelected] = React.useState<string[]>([\'monday\']);\n\n const handleSelect = (data: {id: string}) => {\n setSelected(previous =>\n previous.includes(data.id) ? previous.filter(id => id !== data.id) : previous.concat(data.id)\n );\n };\n\n return (\n <>\n <FormField as="fieldset">\n <FormField.Label as="legend">Available Days (Select all that apply)</FormField.Label>\n <FormField.Input\n as={SelectionGroup}\n mode="multiple"\n selectedIds={selected}\n onSelect={handleSelect}\n >\n <SelectionGroup.List aria-label="Available days (select all that apply)">\n <SelectionGroup.Item data-id="monday">Monday</SelectionGroup.Item>\n <SelectionGroup.Item data-id="tuesday">Tuesday</SelectionGroup.Item>\n <SelectionGroup.Item data-id="wednesday">Wednesday</SelectionGroup.Item>\n <SelectionGroup.Item data-id="thursday">Thursday</SelectionGroup.Item>\n <SelectionGroup.Item data-id="friday">Friday</SelectionGroup.Item>\n </SelectionGroup.List>\n </FormField.Input>\n </FormField>\n <BodyText size="small" cs={{marginBlockStart: system.gap.md}}>\n Selected: {selected.join(\', \') || \'None\'}\n </BodyText>\n </>\n );\n};\n```\n\n### Width Variations\n\nAll items within a group use the same sizing method \u2014 don\'t mix sizing methods within one group.\n\n#### Content Width\n\nEach item is sized to its own label, so items within a group may differ in width.\n```tsx\nimport {SelectionGroup} from \'@workday/canvas-kit-labs-react/selection-group\';\n\nexport const ContentWidth = () => (\n <SelectionGroup mode="single" width="content" initialSelectedIds={[\'short\']}>\n <SelectionGroup.List aria-label="Content width selection group (select one)">\n <SelectionGroup.Item data-id="short">Short</SelectionGroup.Item>\n <SelectionGroup.Item data-id="medium-length">Medium Length</SelectionGroup.Item>\n <SelectionGroup.Item data-id="a-much-longer-label">A Much Longer Label</SelectionGroup.Item>\n </SelectionGroup.List>\n </SelectionGroup>\n);\n```\n\n#### Equal Width\n\nEvery item is sized to match the width of the longest label, so all items end up the same width.\n```tsx\nimport {SelectionGroup} from \'@workday/canvas-kit-labs-react/selection-group\';\n\nexport const EqualWidth = () => (\n <SelectionGroup mode="single" width="equal" initialSelectedIds={[\'short\']}>\n <SelectionGroup.List aria-label="Equal width selection group (select one)">\n <SelectionGroup.Item data-id="short">Short</SelectionGroup.Item>\n <SelectionGroup.Item data-id="medium-length">Medium Length</SelectionGroup.Item>\n <SelectionGroup.Item data-id="a-much-longer-label">A Much Longer Label</SelectionGroup.Item>\n </SelectionGroup.List>\n </SelectionGroup>\n);\n```\n\n#### Column Width\n\nEvery item spans the full width of the column. Best for longer labels, or when the group is the\nprimary input on the page.\n```tsx\nimport {SelectionGroup} from \'@workday/canvas-kit-labs-react/selection-group\';\n\nexport const ColumnWidth = () => (\n <SelectionGroup mode="single" width="column" initialSelectedIds={[\'option-a\']}>\n <SelectionGroup.List aria-label="Column width selection group (select one)">\n <SelectionGroup.Item data-id="option-a">\n Option A with a longer descriptive label\n </SelectionGroup.Item>\n <SelectionGroup.Item data-id="option-b">\n Option B with a longer descriptive label\n </SelectionGroup.Item>\n <SelectionGroup.Item data-id="option-c">\n Option C with a longer descriptive label\n </SelectionGroup.Item>\n </SelectionGroup.List>\n </SelectionGroup>\n);\n```\n\n### Disabled\n\nSet the `disabled` prop on `SelectionGroup` to disable the entire group. To disable individual\nitems, pass their ids to `nonInteractiveIds` so that keyboard navigation skips over them as well.\n```tsx\nimport {SelectionGroup} from \'@workday/canvas-kit-labs-react/selection-group\';\nimport {BodyText} from \'@workday/canvas-kit-react/text\';\nimport {system} from \'@workday/canvas-tokens-web\';\n\nexport const Disabled = () => (\n <>\n <BodyText size="small" cs={{marginBlockEnd: system.gap.xs}}>\n The whole group is disabled\n </BodyText>\n <SelectionGroup mode="single" disabled initialSelectedIds={[\'option-a\']}>\n <SelectionGroup.List aria-label="Fully disabled selection group (select one)">\n <SelectionGroup.Item data-id="option-a">Option A</SelectionGroup.Item>\n <SelectionGroup.Item data-id="option-b">Option B</SelectionGroup.Item>\n <SelectionGroup.Item data-id="option-c">Option C</SelectionGroup.Item>\n </SelectionGroup.List>\n </SelectionGroup>\n\n <BodyText size="small" cs={{marginBlockStart: system.gap.md, marginBlockEnd: system.gap.xs}}>\n A single item is disabled\n </BodyText>\n <SelectionGroup\n mode="single"\n nonInteractiveIds={[\'option-c\']}\n initialSelectedIds={[\'option-a\']}\n >\n <SelectionGroup.List aria-label="Partially disabled selection group (select one)">\n <SelectionGroup.Item data-id="option-a">Option A</SelectionGroup.Item>\n <SelectionGroup.Item data-id="option-b">Option B</SelectionGroup.Item>\n <SelectionGroup.Item data-id="option-c">Option C</SelectionGroup.Item>\n </SelectionGroup.List>\n </SelectionGroup>\n </>\n);\n```\n\n### Error\n\nNotification states apply to the whole group rather than to individual items. Wrapping the group in\na `FormField` with `error="error"` applies the error state and associates the hint text with the\ngroup. This is the recommended approach, because `FormField` also renders the visible hint text,\nsets `aria-invalid`, and points the group\'s `aria-describedby` at that text.\n\nYou can set `error="error"` directly on `SelectionGroup` when you aren\'t using `FormField`, but the\nprop only changes the group\'s border color. Color on its own is not an accessible way to\ncommunicate a notification state, so pair it with your own visible text and pass that element\'s id\nto `aria-describedby` on `SelectionGroup`.\n```tsx\nimport React from \'react\';\n\nimport {SelectionGroup} from \'@workday/canvas-kit-labs-react/selection-group\';\nimport {FormField} from \'@workday/canvas-kit-react/form-field\';\n\nexport const Error = () => {\n const [selected, setSelected] = React.useState<string[]>([]);\n\n return (\n <FormField error="error" as="fieldset">\n <FormField.Label as="legend">Select Your Pizza Crust (Select one)</FormField.Label>\n <FormField.Input\n as={SelectionGroup}\n mode="single"\n selectedIds={selected}\n onSelect={data => setSelected([data.id])}\n >\n <SelectionGroup.List aria-label="Pizza crust options (select one)">\n <SelectionGroup.Item data-id="deep-dish">Deep Dish</SelectionGroup.Item>\n <SelectionGroup.Item data-id="thin">Thin</SelectionGroup.Item>\n <SelectionGroup.Item data-id="gluten-free">Gluten Free</SelectionGroup.Item>\n </SelectionGroup.List>\n </FormField.Input>\n <FormField.Hint>Please select a crust to continue</FormField.Hint>\n </FormField>\n );\n};\n```\n\n### Caution\n```tsx\nimport React from \'react\';\n\nimport {SelectionGroup} from \'@workday/canvas-kit-labs-react/selection-group\';\nimport {FormField} from \'@workday/canvas-kit-react/form-field\';\n\nexport const Caution = () => {\n const [selected, setSelected] = React.useState([\'deep-dish\']);\n\n return (\n <FormField error="caution" as="fieldset">\n <FormField.Label as="legend">Select Your Pizza Crust (Select one)</FormField.Label>\n <FormField.Input\n as={SelectionGroup}\n mode="single"\n selectedIds={selected}\n onSelect={data => setSelected([data.id])}\n >\n <SelectionGroup.List aria-label="Pizza crust options (select one)">\n <SelectionGroup.Item data-id="deep-dish">Deep Dish</SelectionGroup.Item>\n <SelectionGroup.Item data-id="thin">Thin</SelectionGroup.Item>\n <SelectionGroup.Item data-id="gluten-free">Gluten Free</SelectionGroup.Item>\n </SelectionGroup.List>\n </FormField.Input>\n <FormField.Hint>Deep dish is an extra $2.99</FormField.Hint>\n </FormField>\n );\n};\n```\n\n### Right-to-Left (RTL)\n\n`SelectionGroup` supports right-to-left languages when specified in the `CanvasProvider` `theme` or\nvia the `dir` attribute on a parent element.\n```tsx\nimport {SelectionGroup} from \'@workday/canvas-kit-labs-react/selection-group\';\n\nexport const RTL = () => (\n <div dir="rtl">\n <SelectionGroup mode="single" initialSelectedIds={[\'option-b\']}>\n <SelectionGroup.List aria-label="\u0627\u062E\u062A\u0631 \u0648\u0627\u062D\u062F\u0627">\n <SelectionGroup.Item data-id="option-a">\u0627\u0644\u062E\u064A\u0627\u0631 \u0623</SelectionGroup.Item>\n <SelectionGroup.Item data-id="option-b">\u0627\u0644\u062E\u064A\u0627\u0631 \u0628</SelectionGroup.Item>\n <SelectionGroup.Item data-id="option-c">\u0627\u0644\u062E\u064A\u0627\u0631 \u062C</SelectionGroup.Item>\n </SelectionGroup.List>\n </SelectionGroup>\n </div>\n);\n```\n\n## Accessibility\n\n- Single-select groups render `role="radiogroup"` with `role="radio"` items and `aria-checked`, and\n follow the [radio group keyboard pattern](https://www.w3.org/WAI/ARIA/apg/patterns/radio/): one\n tab stop for the group, with arrow keys moving focus and selection together.\n- Multi-select groups render `role="group"` with `role="checkbox"` items and `aria-checked`, and\n follow the [checkbox keyboard pattern](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/): every\n item is in the tab order and <kbd>Space</kbd> toggles it.\n- The icon always renders, in both modes and in both selected states. Selection is communicated by\n the checkmark inside the icon _and_ a color change, never by color alone.\n- `aria-invalid` is only set on a single-select group. The `group` role that a multi-select group\n renders does not allow the attribute, so a multi-select group communicates its error state\n through the text referenced by `aria-describedby`. Make sure that text names the problem.\n- A group label is required. Provide it with `aria-label` or `aria-labelledby` on\n `SelectionGroup.List`, or wrap the group in a `FormField` with a visible label. The label must\n state the selection mode \u2014 "Select one" versus "Select all that apply" \u2014 so the mode is clear\n before interacting.\n\n## Component API\n\n## Specifications\n\n',
1777
+ accessibilityProse: '## Accessibility\n\n- Single-select groups render `role="radiogroup"` with `role="radio"` items and `aria-checked`, and\n follow the [radio group keyboard pattern](https://www.w3.org/WAI/ARIA/apg/patterns/radio/): one\n tab stop for the group, with arrow keys moving focus and selection together.\n- Multi-select groups render `role="group"` with `role="checkbox"` items and `aria-checked`, and\n follow the [checkbox keyboard pattern](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/): every\n item is in the tab order and <kbd>Space</kbd> toggles it.\n- The icon always renders, in both modes and in both selected states. Selection is communicated by\n the checkmark inside the icon _and_ a color change, never by color alone.\n- `aria-invalid` is only set on a single-select group. The `group` role that a multi-select group\n renders does not allow the attribute, so a multi-select group communicates its error state\n through the text referenced by `aria-describedby`. Make sure that text names the problem.\n- A group label is required. Provide it with `aria-label` or `aria-labelledby` on\n `SelectionGroup.List`, or wrap the group in a `FormField` with a visible label. The label must\n state the selection mode \u2014 "Select one" versus "Select all that apply" \u2014 so the mode is clear\n before interacting.'
1778
+ },
1772
1779
  kbd: {
1773
1780
  title: "Labs/KBD",
1774
1781
  storybookUrl: "https://workday.github.io/canvas-kit/?path=/docs/labs-kbd--docs",