Skip to Content

Select

Select allows users to choose one option from a list of items in a Menu.

Interaction Modes

Scanning

Selecting

Install

yarn add @workday/canvas-kit-react

Component Type

Input

Platform

Web

Component

Sana Canvas

Delivery Channels

Web

Version

16.1.7

Experience Surfaces

Page Body Inline

Component Type

Input

Platform

Web

Component

Sana Canvas

Delivery Channels

Web

Version

16.1.7

Experience Surfaces

Page Body Inline

Anatomy

Image of a Select Input in its default state.
  1. Label: Title of the input.
  2. Input Container: Rectangular container that houses the icon and placeholder text.
  3. Placeholder Text (Optional): Placeholder text like “Select One” is typically displayed in the Select field. After the user makes a selection, the placeholder text is replaced with the user’s selection.
  4. Icon: Caret icon positioned to the right of the container visually distinguishes this as a Select input.

Usage Guidance

  • Clicking or tapping anywhere in a Select opens the Menu.
  • A checkmark icon indicates which value is currently selected in the list.
  • Each Menu option should be distinct. If the option isn’t discrete, combine it with another option.
  • The list of Menu options should be sorted in a logical order alphabetically, chronologically, or by order of importance.

When to Use

  • Use Select as a form element where users are only allowed to select one item from a list of more than 7 predefined options.
  • Typically, Selects work best when the list is between 7 to 15 items to prevent overwhelming the user with too many options.

When to Use Something Else

  • Consider using a Switch if the only options are yes or no.
  • For a list between 2 to 7 predefined options, consider using Radio Buttons to select one option or Checkboxes to select multiple options. Radio and Checkbox groups display all options upfront and do not require the user to interact with the input to view the list of options.
  • Use a Prompt when the number of list items is large or unknown. Prompts have search capabilities and folders which provide users with the means to browse options. Prompts can be configured to support single or multi-select.

Examples

Basic Example

Select supports a dynamic API where you pass an array of items via the items prop and provide a render function to display the items. The items may be provided as an array of strings or an array of objects.

Select should be used in tandem with Form Field to ensure proper label association and screen reader support. Wrap Select with FormField, and compose FormField.Input as={Select.Input} so the combobox receives the field label. Include Select.Popper, Select.Card, Select.List, and Select.Item.

Selected Value:
import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select} from '@workday/canvas-kit-react/select';
import {createStyles} from '@workday/canvas-kit-styling';

const parentContainerStyles = createStyles({
  flexDirection: 'column',
});

const options = [
  'E-mail',
  'Phone',
  'Fax',
  'Mail',
  'Mobile Phone',
  'The Ontologically Anthropocentric Sensory Immersive Simulation',
  'Thisisalongstringwithnobreaksandwillwrap',
];

export default () => {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    console.log('change', event.currentTarget.value);
    setValue(event.target.value);
  };

  return (
    <Flex cs={parentContainerStyles}>
      <FormField>
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select items={options}>
            <FormField.Input as={Select.Input} onChange={handleChange} />
            <Select.Popper>
              <Select.Card>
                <Select.List>
                  {item => {
                    return <Select.Item>{item}</Select.Item>;
                  }}
                </Select.List>
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
      Selected Value: {value}
    </Flex>
  );
};

Our example uses React state to track the value of the Select.

Hoisted Model

By default, Select will create and use its own model internally. Alternatively, you may configure your own model with useSelectModel and pass it to Select via the model prop. This pattern is referred to as hoisting the model and provides direct access to its state and events outside of the Select component.

In this example, we set up external observation of the model state and create an external button to trigger an event to change the selected item.

Note: If your array of objects uses an id property and a text property there is no need to use the helper functions of getId or getTextValue. The collection system and the Select use these properties by default for keyboard navigation and selected the id based on the item clicked.

Selected Value: fax-3

import React from 'react';

import {SecondaryButton} from '@workday/canvas-kit-react/button';
import {FormField} from '@workday/canvas-kit-react/form-field';
import {Select, useSelectModel} from '@workday/canvas-kit-react/select';
import {BodyText} from '@workday/canvas-kit-react/text';

const options = [
  {text: 'E-mail', id: 'email-1'},
  {text: 'Phone', id: 'phone-2'},
  {text: 'Fax', id: 'fax-3'},
  {text: 'Mail', id: 'mail-4'},
  {text: 'Mobile Phone', id: 'mobile-phone-5'},
];

export default () => {
  const model = useSelectModel({
    items: options,
    initialSelectedIds: ['fax-3'],
  });

  return (
    <>
      <FormField>
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select model={model}>
            <FormField.Input as={Select.Input} />
            <Select.Popper>
              <Select.Card>
                <Select.List>{item => <Select.Item>{item.text}</Select.Item>}</Select.List>
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
      <BodyText size="small">Selected Value: {model.state.selectedIds[0]}</BodyText>
      <SecondaryButton
        onClick={() => {
          model.events.select({id: 'phone-2'});
        }}
      >
        Select Phone Item
      </SecondaryButton>
    </>
  );
};

Label Position Horizontal

Set the orientation prop of the Form Field to designate the position of the label relative to the input component. By default, the orientation will be set to vertical.

Choose a form of contact

import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select, useSelectModel} from '@workday/canvas-kit-react/select';

const options = [
  'E-mail',
  'Phone',
  'Fax',
  'Mail',
  'Mobile Phone',
  'The Ontologically Anthropocentric Sensory Immersive Simulation',
];

export default () => {
  const model = useSelectModel({
    items: options,
  });

  return (
    <Flex>
      <FormField orientation="horizontalStart">
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select model={model}>
            <FormField.Input as={Select.Input} />
            <Select.Popper>
              <Select.Card>
                <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>
              </Select.Card>
            </Select.Popper>
            <FormField.Hint>Choose a form of contact</FormField.Hint>
          </Select>
        </FormField.Field>
      </FormField>
    </Flex>
  );
};

Required

Set the isRequired prop of the wrapping FormField to true to indicate that the field is required. Labels for required fields are suffixed by a red asterisk.

Selected Value:
import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select} from '@workday/canvas-kit-react/select';
import {createStyles} from '@workday/canvas-kit-styling';

const parentContainerStyles = createStyles({
  flexDirection: 'column',
});

const options = [
  'E-mail',
  'Phone',
  'Fax',
  'Mail',
  'Mobile Phone',
  'The Ontologically Anthropocentric Sensory Immersive Simulation',
];

export default () => {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setValue(event.target.value);
  };

  return (
    <Flex cs={parentContainerStyles}>
      <FormField isRequired>
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select items={options}>
            <FormField.Input as={Select.Input} onChange={e => handleChange(e)} />
            <Select.Popper>
              <Select.Card>
                <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
      Selected Value: {value}
    </Flex>
  );
};

Disabled

Set the disabled prop on FormField.Input as={Select.Input} to prevent users from interacting with the combobox.

import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select} from '@workday/canvas-kit-react/select';
import {createStyles} from '@workday/canvas-kit-styling';

const parentContainerStyles = createStyles({
  flexDirection: 'column',
});

const options = [
  'E-mail',
  'Phone',
  'Fax (disabled)',
  'Mail',
  'Mobile Phone',
  'The Ontologically Anthropocentric Sensory Immersive Simulation',
];

export default () => {
  const [_, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setValue(event.target.value);
  };

  return (
    <Flex cs={parentContainerStyles}>
      <FormField>
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select items={options} nonInteractiveIds={['Fax (disabled)']}>
            <FormField.Input as={Select.Input} disabled onChange={e => handleChange(e)} />
            <Select.Popper>
              <Select.Card>
                <Select.List>
                  {item => (
                    <Select.Item aria-disabled={item === 'Fax (disabled)' ? true : undefined}>
                      {item}
                    </Select.Item>
                  )}
                </Select.List>
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
    </Flex>
  );
};

Disabled Items

In order to disable items and prevent users from interacting with them:

  1. Set the nonInteractiveIds prop of Select to an array of disabled item ids. If your items are an array of strings this will be just the text value. If your items are an array of objects, this will be that value of the id property. This will disable interaction for those items and exclude them from type-ahead.

  2. Set the aria-disabled attribute of all disabled Select.Items to true. This ensures the items are styled as disabled.

The following example adds the string value of the items we want disable to nonInteractiveIds and sets aria-disabled for the disabled items.

Selected Value:
import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select} from '@workday/canvas-kit-react/select';
import {createStyles} from '@workday/canvas-kit-styling';

const parentContainerStyles = createStyles({
  flexDirection: 'column',
});

const options = [
  'E-mail',
  'Phone',
  'Fax (disabled)',
  'Mail',
  'Mobile Phone',
  'The Ontologically Anthropocentric Sensory Immersive Simulation',
];

export default () => {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setValue(event.target.value);
  };

  return (
    <Flex cs={parentContainerStyles}>
      <FormField>
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select items={options} nonInteractiveIds={['Fax (disabled)', 'Mobile Phone']}>
            <FormField.Input as={Select.Input} onChange={e => handleChange(e)} />
            <Select.Popper>
              <Select.Card>
                <Select.List>
                  {item => (
                    <Select.Item
                      aria-disabled={
                        item === 'Mobile Phone' || item === 'Fax (disabled)' ? true : undefined
                      }
                    >
                      {item}
                    </Select.Item>
                  )}
                </Select.List>
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
      Selected Value: {value}
    </Flex>
  );
};

With Icons

Use Select.Item.Icon to render an icon for a Select.Item. The icon prop for Select.Item.Icon accepts system icons from @workday/canvas-system-icons-web.

In order to render the icon for the selected item on FormField.Input as={Select.Input}:

  1. Obtain a reference to the model by registering your items with useSelectModel.
  2. Get the selected item: const selectedItem = model.navigation.getItem(model.state.selectedIds[0], model)
  3. Pass the icon for the selected item to the input: <FormField.Input as={Select.Input} inputStartIcon={selectedItem?.value.icon} />

Note: Dynamic {item => <Select.Item>} registration already uses the collection id. Set data-id only on static Select.Item children (see Grouped Items), and keep it equal to that id (id or getId).

import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select, useSelectModel} from '@workday/canvas-kit-react/select';
import {createStyles, px2rem} from '@workday/canvas-kit-styling';
import {cloudArrowUpIcon, cloudIcon, commentIcon, userIcon} from '@workday/canvas-system-icons-web';

const styleOverrides = {
  formfieldInputStyles: createStyles({
    width: px2rem(300),
  }),
  selectCardStyles: createStyles({
    maxHeight: px2rem(200),
  }),
};

const customOptions = [
  {text: 'Activity Stream', id: 'activity-stream', icon: commentIcon},
  {text: 'Avatar', id: 'avatar', icon: cloudIcon},
  {text: 'Upload Cloud', id: 'upload-cloud', icon: cloudArrowUpIcon},
  {text: 'User', id: 'user', icon: userIcon},
];

export default () => {
  const model = useSelectModel({
    items: customOptions,
  });
  const selectedItem = model.navigation.getItem(model.state.selectedIds[0], model);
  return (
    <Flex>
      <FormField>
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select model={model}>
            <FormField.Input
              as={Select.Input}
              cs={styleOverrides.formfieldInputStyles}
              inputStartIcon={selectedItem?.value.icon}
            />
            <Select.Popper>
              <Select.Card cs={styleOverrides.selectCardStyles}>
                {model.state.items.length > 0 && (
                  <Select.List>
                    {item => (
                      <Select.Item>
                        <Select.Item.Icon icon={item.icon} />
                        {item.text}
                      </Select.Item>
                    )}
                  </Select.List>
                )}
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
    </Flex>
  );
};

Note: that FormField.Input as={Select.Input} will only render an icon if an item is selected.

Grow

Set the grow prop of the wrapping FormField to true to configure the Select.Input to expand to the width of its container.

import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select, useSelectModel} from '@workday/canvas-kit-react/select';

const options = [
  'E-mail',
  'Phone',
  'Fax',
  'Mail',
  'Mobile Phone',
  'The Ontologically Anthropocentric Sensory Immersive Simulation',
];

export default () => {
  const model = useSelectModel({
    items: options,
  });

  return (
    <Flex>
      <FormField grow>
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select model={model}>
            <FormField.Input as={Select.Input} />
            <Select.Popper>
              <Select.Card>
                <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
    </Flex>
  );
};

Select.Card has a default maximum height of 300px to restrict the height of the dropdown menu. Set its maxHeight prop to override this value.

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Box} from '@workday/canvas-kit-react/layout';
import {Select} from '@workday/canvas-kit-react/select';
import {createStyles, px2rem} from '@workday/canvas-kit-styling';

const selectCardStyles = createStyles({
  maxHeight: px2rem(200),
});

const cities = [
  'Atlanta (United States)',
  'Amsterdam (Europe)',
  'Austin (United States)',
  'Beaverton (United States)',
  'Belfast (Europe)',
  'Berlin (Europe)',
  'Boston (United States)',
  'Boulder (United States)',
  'Chicago (United States)',
  'Dallas (United States)',
  'Denver (United States)',
  'Dublin (Europe)',
  'Irvine (United States)',
  'Minneapolis (United States)',
  'New York (United States)',
  'Orlando (United States)',
  'Palo Alto (United States)',
  'Philadelphia (United States)',
  'Pleasanton (United States)',
  'Raleigh (United States)',
  'San Francisco (United States)',
  'San Mateo (United States)',
  'Stockholm (Europe)',
  'Toronto (Canada)',
  'Victoria (Canada)',
  'Vienna (Europe)',
  'Warsaw (Europe)',
  'Washington, DC (United States)',
  'Zurich (Europe)',
];

export default () => {
  return (
    <Box>
      <FormField>
        <FormField.Label>Choose a City</FormField.Label>
        <FormField.Field>
          <Select items={cities}>
            <FormField.Input as={Select.Input} />
            <Select.Popper>
              <Select.Card cs={selectCardStyles}>
                <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
    </Box>
  );
};

Ref Forwarding

Select.Input supports ref forwarding . It will forward ref to its underlying <input type="text" role="combobox"> element.

import React from 'react';

import {PrimaryButton} from '@workday/canvas-kit-react/button';
import {FormField} from '@workday/canvas-kit-react/form-field';
import {Select} from '@workday/canvas-kit-react/select';

const options = [
  'E-mail',
  'Phone',
  'Fax',
  'Mail',
  'Mobile Phone',
  'The Ontologically Anthropocentric Sensory Immersive Simulation',
];

export default () => {
  // @ts-ignore
  const [value, setValue] = React.useState('medium');
  const ref = React.useRef(null);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setValue(event.target.value);
  };

  const handleClick = () => {
    if (ref && ref.current) {
      console.log(ref);
      ref.current.focus();
    }
  };

  return (
    <>
      <FormField>
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select items={options}>
            <FormField.Input as={Select.Input} ref={ref} onChange={e => handleChange(e)} />
            <Select.Popper>
              <Select.Card>
                <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
      <PrimaryButton onClick={handleClick}>Focus Select</PrimaryButton>
    </>
  );
};

Error States

Form Field provides error and caution states for Select. Set the error prop on Form Field to "error" or "caution" and use FormField.Hint to provide messages. See Form Field’s Error documentation for examples and accessibility guidance.

Caution

Use the alert state when a selection is valid but there is additional information.

Please choose a form of contact.

Selected value:
import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select} from '@workday/canvas-kit-react/select';
import {createStyles} from '@workday/canvas-kit-styling';

const parentContainerStyles = createStyles({
  flexDirection: 'column',
});

const options = [
  'E-mail',
  'Phone',
  'Fax',
  'Mail',
  'Mobile Phone',
  'The Ontologically Anthropocentric Sensory Immersive Simulation',
];

export default () => {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setValue(event.target.value);
  };
  return (
    <Flex cs={parentContainerStyles}>
      <FormField error="caution">
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select items={options}>
            <FormField.Input as={Select.Input} onChange={e => handleChange(e)} id="alert-select" />
            <Select.Popper>
              <Select.Card>
                <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List>
              </Select.Card>
            </Select.Popper>
            <FormField.Hint>Please choose a form of contact.</FormField.Hint>
          </Select>
        </FormField.Field>
      </FormField>
      Selected value: {value}
    </Flex>
  );
};

Error

Use the error state when the selection is no longer valid.

Fax is disabled. Please choose a different option.

Selected Value:
import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select} from '@workday/canvas-kit-react/select';
import {createStyles} from '@workday/canvas-kit-styling';

const parentContainerStyles = createStyles({
  flexDirection: 'column',
});

const options = [
  'E-mail',
  'Phone',
  'Fax (disabled)',
  'Mail',
  'Mobile Phone',
  'The Ontologically Anthropocentric Sensory Immersive Simulation',
];

export default () => {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setValue(event.target.value);
  };
  return (
    <Flex cs={parentContainerStyles}>
      <FormField error="error">
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select items={options} nonInteractiveIds={['Fax (disabled)']}>
            <FormField.Input as={Select.Input} onChange={e => handleChange(e)} />
            <Select.Popper>
              <Select.Card>
                <Select.List>
                  {item => (
                    <Select.Item aria-disabled={item === 'Fax (disabled)' ? true : undefined}>
                      {item}
                    </Select.Item>
                  )}
                </Select.List>
              </Select.Card>
            </Select.Popper>
            <FormField.Hint>Fax is disabled. Please choose a different option.</FormField.Hint>
          </Select>
        </FormField.Field>
      </FormField>
      Selected Value: {value}
    </Flex>
  );
};

Initial Selected Item

You can set initialSelectedIds to the value that you want initially selected.

Id: da594226446c11de98360015c5e6daf6

Value: English (United States)

import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select} from '@workday/canvas-kit-react/select';
import {createStyles} from '@workday/canvas-kit-styling';

const parentContainerStyles = createStyles({
  flexDirection: 'column',
});

const options = [
  {
    id: 'b310c757b2d341f99d40d76f4d563c5b',
    descriptor: 'Arabic',
    languageCode: 'ar',
    label: 'Arabic',
    nativeLanguageName: 'العربية',
  },
  {
    id: 'a675a6b6e22d100017d7fe2a784d1255',
    descriptor: 'Bulgarian (Bulgaria)',
    languageCode: 'bg_BG',
    label: 'Bulgarian (Bulgaria)',
    nativeLanguageName: 'български (Република България)',
  },
  {
    id: 'da594226446c11de98360015c5e6daf6',
    descriptor: 'English (United States)',
    languageCode: 'en_US',
    label: 'English (United States)',
    nativeLanguageName: 'English',
  },
];

export default () => {
  const [value, setValue] = React.useState('English (United States)');
  const [id, setId] = React.useState('da594226446c11de98360015c5e6daf6');

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setId(event.target.value);
    setValue(options.find(item => item.id === event.target.value).label);
  };

  return (
    <Flex cs={parentContainerStyles}>
      <FormField>
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select
            items={options}
            initialSelectedIds={['da594226446c11de98360015c5e6daf6']}
            getId={item => item.id}
            getTextValue={item => item.label}
          >
            <Select.Input onChange={e => handleChange(e)} />
            <Select.Popper>
              <Select.Card>
                <Select.List>{item => <Select.Item>{item.label}</Select.Item>}</Select.List>
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
      <p>Id: {id}</p>
      <p>Value: {value}</p>
    </Flex>
  );
};

Placeholder

You can change the placeholder text by passing a string to the placeholder prop on FormField.Input as={Select.Input}. Placeholder text is not a substitute for FormField.Label.

Selected Value:
import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select} from '@workday/canvas-kit-react/select';
import {createStyles} from '@workday/canvas-kit-styling';

const parentContainerStyles = createStyles({
  flexDirection: 'column',
});

const options = [
  'E-mail',
  'Phone',
  'Fax',
  'Mail',
  'Mobile Phone',
  'The Ontologically Anthropocentric Sensory Immersive Simulation',
];

export default () => {
  const [value, setValue] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setValue(event.target.value);
  };

  return (
    <Flex cs={parentContainerStyles}>
      <FormField>
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select items={options}>
            <Select.Input placeholder="Make a Selection" onChange={e => handleChange(e)} />
            <Select.Popper>
              <Select.Card>
                <Select.List>
                  {item => {
                    return <Select.Item>{item}</Select.Item>;
                  }}
                </Select.List>
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
      Selected Value: {value}
    </Flex>
  );
};

Fetching Dynamic Items

It’s common to load items from a server call. Hoisting the model and setting your items on state allows you to pass those items to your model. You can leverage React state to set your items on load as well as displaying a placeholder indicating when items are loaded.

Note: In this case we need to use getId and getTextValue because our data doesn’t have the properties of id or text. Using these helper functions sets the serverId to be id and label to be text.

Selected Id: 456
Selected value:
import React from 'react';

import {PrimaryButton} from '@workday/canvas-kit-react/button';
import {useMount} from '@workday/canvas-kit-react/common';
import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select, useSelectModel} from '@workday/canvas-kit-react/select';
import {createStyles, px2rem} from '@workday/canvas-kit-styling';

const parentContainerStyles = createStyles({
  flexDirection: 'column',
  maxWidth: px2rem(300),
});

const movieListItems = [
  {
    label: 'The Lion King',
    serverId: '123',
    Year: '2019',
    Runtime: '118 min',
  },
  {
    label: 'Mowgli: Legend of the Jungle',
    serverId: '234',
    Year: '2018',
    Runtime: '104 min',
  },
  {
    label: 'Doctor Strange',
    serverId: '345',
    Year: '2016',
    Runtime: '115 min',
  },
  {
    label: 'John Wick',
    Year: '2014',
    serverId: '456',
    Runtime: '101 min',
  },
  {
    label: 'The Notebook',
    serverId: '567',
    Year: '2004',
    Runtime: '123 min',
  },
];

export default () => {
  const [id, setId] = React.useState('456');
  const [moviesLists, setMoviesList] = React.useState<typeof movieListItems>([]);
  const [loadingStatus, setLoadingStatus] = React.useState<'idle' | 'loading' | 'success'>('idle');
  const loadingRef = React.useRef<ReturnType<typeof setTimeout>>();

  const model = useSelectModel({
    items: moviesLists,
    getTextValue: item => item.label,
    getId: item => item.serverId,
    initialSelectedIds: [id],
  });

  const stringValue = moviesLists.find(item => item.serverId === id)?.label || '';

  function loadItems() {
    setLoadingStatus('loading');
    loadingRef.current = setTimeout(() => {
      setLoadingStatus('success');
      setMoviesList(movieListItems);
    }, 1500);
  }

  useMount(() => {
    return () => {
      clearTimeout(loadingRef.current);
    };
  });

  return (
    <Flex cs={parentContainerStyles}>
      <FormField>
        <FormField.Label>Choose a Film</FormField.Label>
        <FormField.Field>
          <Select model={model}>
            <FormField.Input
              as={Select.Input}
              onChange={e => {
                setId(e.target.value);
              }}
              placeholder={loadingStatus}
            />
            <Select.Popper>
              <Select.Card>
                <Select.List>
                  {item => {
                    return <Select.Item>{item.label}</Select.Item>;
                  }}
                </Select.List>
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
      <div data-testid="selected-id">Selected Id: {id}</div>
      <div data-testid="selected-value">Selected value: {stringValue}</div>
      <PrimaryButton
        onClick={() => {
          loadItems();
        }}
      >
        Get Items
      </PrimaryButton>
    </Flex>
  );
};

Complex

When registering items in an array of objects, it’s common to have the text that is displayed to the user be different than an id. In this example, serverId and label properties need to be remapped to id and text hence the usage of getId and getTextValue. If your object has the properties text and id, there would be no need for this.

Id:

Value:

import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select} from '@workday/canvas-kit-react/select';
import {createStyles} from '@workday/canvas-kit-styling';

const parentContainerStyles = createStyles({
  flexDirection: 'column',
});

const options = [
  {serverId: 'email', label: 'E-mail'},
  {serverId: 'phone', label: 'Phone'},
  {serverId: 'fax', label: 'Fax'},
  {serverId: 'mail', label: 'Mail'},
  {serverId: 'mobile', label: 'Mobile Phone'},
  {
    serverId: 'oasis',
    label: 'The Ontologically Anthropocentric Sensory Immersive Simulation',
  },
];

export default () => {
  const [value, setValue] = React.useState('');
  const [id, setId] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setId(event.target.value);
    setValue(options.find(item => item.serverId === event.target.value)!.label);
  };

  return (
    <Flex cs={parentContainerStyles}>
      <FormField>
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select items={options} getId={item => item.serverId} getTextValue={item => item.label}>
            <FormField.Input as={Select.Input} onChange={e => handleChange(e)} />
            <Select.Popper>
              <Select.Card>
                <Select.List>{item => <Select.Item>{item.label}</Select.Item>}</Select.List>
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
      <p>Id: {id}</p>
      <p>Value: {value}</p>
    </Flex>
  );
};

Note: By default, the identifier and text value are id and text properties respectively. If your data object for each item is different, provide getId and/or getTextValue. If a custom getId does not return the display text, also pass getTextValue — otherwise the model uses getId for type-ahead and the selected value. For example:

const items = [ { serverId: '1', label: 'First Option', }, ]; <Select items={items} getId={item => item.serverId} getTextValue={item => item.label}> {/* etc */} </Select>;

Controlled

The Select can be a controlled input  component by passing the value and onChange to either the <Select> component or the <Select.Input> component. Internally, the Select.Input watches for changes on the value React prop as well as the value DOM property and will update the model accordingly.

Id:

Label:

import React from 'react';

import {SecondaryButton} from '@workday/canvas-kit-react/button';
import {FormField} from '@workday/canvas-kit-react/form-field';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Select} from '@workday/canvas-kit-react/select';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';

const parentContainerStyles = createStyles({
  flexDirection: 'column',
});

const options = [
  {serverId: 'email', label: 'E-mail'},
  {serverId: 'phone', label: 'Phone'},
  {serverId: 'fax', label: 'Fax'},
  {serverId: 'mail', label: 'Mail'},
  {serverId: 'mobile', label: 'Mobile Phone'},
  {
    serverId: 'oasis',
    label: 'The Ontologically Anthropocentric Sensory Immersive Simulation',
  },
];

export default () => {
  const [value, setValue] = React.useState('');
  const [label, setLabel] = React.useState('');

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setValue(event.currentTarget.value);
    setLabel(options.find(item => item.serverId === event.currentTarget.value)?.label || '');
  };

  return (
    <Flex cs={parentContainerStyles}>
      <FormField>
        <FormField.Label>Contact</FormField.Label>
        <FormField.Field>
          <Select items={options} getId={item => item.serverId} getTextValue={item => item.label}>
            <FormField.Input
              as={Select.Input}
              onChange={handleChange}
              value={value}
              name="contact"
            />
            <Select.Popper>
              <Select.Card>
                <Select.List>{item => <Select.Item>{item.label}</Select.Item>}</Select.List>
              </Select.Card>
            </Select.Popper>
          </Select>
        </FormField.Field>
      </FormField>
      <p>Id: {value}</p>
      <p>Label: {label}</p>
      <Flex cs={{gap: system.gap.md}}>
        <SecondaryButton
          onClick={e => {
            setValue('fax');
          }}
        >
          Set to "Fax"
        </SecondaryButton>
        <SecondaryButton
          onClick={e => {
            setValue('');
          }}
        >
          Clear
        </SecondaryButton>
      </Flex>
    </Flex>
  );
};

When to use getId, or getTextValue

  • getId: This is an optional function to return the id of an item. If not provided, the default function will return the id property from the object of each item. If you did not provide items, do not override this function. Instead provide static items via JSX. the list will create an internal array of items where id is the only property and the default getId will return the desired result. Note: If your array of objects has a different property for id, like serverId, use this function to set the id. If that function does not return the display text, also pass getTextValue.

    const options = [{text: 'Pizza', serverId: 'pizza-1'}, {text: 'Cheeseburger', serverId: 'cheeseburger'}] <FormField> <FormField.Label>Your Label</FormField.Label> <FormField.Field> <Select items={options} getId={(item) => item.serverId} getTextValue={(item) => item.text}> <FormField.Input as={Select.Input} onChange={e => handleChange(e)} /> <Select.Popper> <Select.Card> <Select.List>{item => <Select.Item>{item.text}</Select.Item>}</Select.List> </Select.Card> </Select.Popper> </Select> </FormField.Field> </FormField>
  • getTextValue: Optional function to return the text representation of an item. If not provided, the default function will return the text property of the object of each item or an empty string if there is no text property. If you did not provide items, do not override this function. Note: If your array of objects has a different property for text, like label, use this function to set the text.

    const options = [{label: 'Pizza', id: 'pizza-1'}, {label: 'Cheeseburger', id: 'cheeseburger'}] <FormField> <FormField.Label>Your Label</FormField.Label> <FormField.Field> <Select items={options} getTextValue={(item) => item.label}> <FormField.Input as={Select.Input} onChange={e => handleChange(e)} /> <Select.Popper> <Select.Card> <Select.List>{item => <Select.Item>{item.label}</Select.Item>}</Select.List> </Select.Card> </Select.Popper> </Select> </FormField.Field> </FormField>

Grouped Items

In order to group items, use the static item API with Menu.Group inside Select.List, and still pass items whose ids match each Select.Item data-id.

import React from 'react';

import {FormField} from '@workday/canvas-kit-react/form-field';
import {Menu} from '@workday/canvas-kit-react/menu';
import {Select} from '@workday/canvas-kit-react/select';

const items = [
  {
    id: 'first',
    text: 'First Item',
  },
  {
    id: 'second',
    text: 'Second Item',
  },
  {
    id: 'third',
    text: 'Third Item',
  },
  {
    id: 'fourth',
    text: 'Fourth Item',
  },
];

export default () => {
  return (
    <FormField>
      <FormField.Label>Contact</FormField.Label>
      <FormField.Field>
        <Select items={items} getId={item => item.id} getTextValue={item => item.text}>
          <FormField.Input as={Select.Input} />
          <Select.Popper>
            <Select.Card>
              <Select.List>
                <Menu.Group title="First Group">
                  <Select.Item data-id="first">First Item</Select.Item>
                  <Select.Item data-id="second">Second Item</Select.Item>
                </Menu.Group>
                <Menu.Group title="Second Group">
                  <Select.Item data-id="third">
                    Third Item (with a really, really, really long label)
                  </Select.Item>
                  <Select.Item data-id="fourth">Fourth Item</Select.Item>
                </Menu.Group>
              </Select.List>
            </Select.Card>
          </Select.Popper>
        </Select>
      </FormField.Field>
    </FormField>
  );
};

Custom Styles

Select and its subcomponents support custom styling via the cs prop. For more information, check our “How To Customize Styles” .

Accessibility

The primary accessibility goal for Select is a visible, persistent label and a single choice from a known list that assistive technology identifies as a combobox. Use Select when the user must pick one option. For multiple selections, use MultiSelect. For a value outside a fixed list, use Combobox. See FormField’s accessibility documentation for label, hint, error, and required wiring. This follows the WAI-ARIA Select-Only Combobox  pattern.

Minimum Accessible Structure

Build on the Basic Example: label first, then Select inside FormField.Field, with the combobox, popup, list, and items in this order.

import {FormField} from '@workday/canvas-kit-react/form-field'; import {Select} from '@workday/canvas-kit-react/select'; const options = ['E-mail', 'Phone', 'Fax']; <FormField> <FormField.Label>Contact</FormField.Label> <FormField.Field> <Select items={options}> <FormField.Input as={Select.Input} /> <Select.Popper> <Select.Card> <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List> </Select.Card> </Select.Popper> </Select> </FormField.Field> </FormField>;

Every Select requires FormField, a visible FormField.Label, and FormField.Input as={Select.Input} so the combobox has a programmatically determinable name, relationships, and instructions. See FormField’s accessibility documentation for hint, error, and required wiring.

Built-in Behaviors

Canvas Kit applies these automatically when you compose Select with FormField subcomponents. Do not duplicate them in consuming code.

ARIA and DOM (applied by subcomponents):

  • Select.Input: Visual <input> with role="combobox", aria-haspopup="listbox", aria-expanded from menu visibility, aria-autocomplete="list" (do not change to "none"), aria-controls pointing at the listbox id ({modelId}-list), and aria-activedescendant while the list is open (removed when the list is closed). autoComplete is "off". Keyboard characters are not inserted into the input; type-ahead is handled by the model. FormField.Label (via FormField.Input) is the accessible name of the combobox — do not add a second name on the listbox.
  • Hidden form input: A second input holds the selected id(s) for form submission. It is aria-hidden, has tabIndex={-1}, and is not in the tab order. onChange and name apply to this input. Focus and blur on a ref are forwarded to the visual combobox.
  • Select.List: role="listbox" with an id that matches the combobox aria-controls. Options are not in the tab order; keyboard focus stays on the combobox. Listbox labelling is library-owned — do not set aria-labelledby (or aria-label) on Select.List.
  • Select.Item: role="option" and aria-selected from selection state. Disabled options need aria-disabled from application code (see Accessibility Requirements).
  • Menu.Group (when used inside Select.List): role="group" with aria-labelledby referencing the group heading (title or Menu.Group.Heading).
  • Select.Item.Icon and the caret / start icons on Select.Input: Canvas Kit icons use role="presentation" and focusable="false". Decorative icons need no extra attributes.
  • disabled on Select.Input: Maps to the native disabled attribute on both inputs; the combobox is removed from the tab order.
  • ref: Forwards to the visual combobox (<input type="text" role="combobox">).

Keyboard (select-only combobox; focus remains on Select.Input):

  • Tab / Shift+Tab move to and from the combobox (native tab order). Other keys are prevented from editing the input.
  • Clicking FormField.Label moves focus to the combobox. Clicking the combobox opens or closes the list.
  • ArrowDown / ArrowUp open the list. While the list is open, those keys move the active option (skipping ids in nonInteractiveIds). Home / End move to the first or last option while the list is open.
  • Space opens the list when it is closed and no type-ahead string is in progress. While the list is open and type-ahead is empty, Space selects the active option and closes the list.
  • Printable characters type-ahead: with the list closed, matching options are selected; with the list open, assistive focus moves to the matching option. Consecutive keys within 500ms form a search string.
  • Enter while the list is open selects the active option (unless aria-disabled) and closes the list in single-select mode. It does not submit the form while the list is open.
  • Escape closes the list. Blur also hides the list. After close, aria-activedescendant is removed; the active option returns to the selected item when one is selected.
  • Activating an option with the pointer keeps focus on the combobox and closes the list.

Screen reader expectations (when built-in behaviors are used as intended):

  • On focus, assistive technology announces the field label and, when applicable: required state, invalid state (error="error"), hint or error text via aria-describedby, and the current selected text (or the placeholder when nothing is selected).
  • The control is announced as a combobox. Collapsed vs expanded follows aria-expanded. While the list is open, the active option is exposed through aria-activedescendant.
  • Options are announced with selected or not-selected state (aria-selected). Disabled options are announced as disabled when aria-disabled is set.
  • The Caution state is visual only — aria-invalid is not set for error="caution".
  • Disabled comboboxes may be announced as unavailable and are skipped in the tab order.
  • The hidden form input and decorative icons are not announced.

For rendered label, input, and hint association markup, see the DOM examples in FormField’s Built-in Behaviors.

Accessibility Requirements

Required in application code for an accessible Select. Rows marked (conditional) apply only when the situation matches—otherwise omit.

If no design spec is provided: use a visible FormField.Label, wrap Select with FormField, use FormField.Input as={Select.Input}, include Select.Popper, Select.Card, Select.List, and Select.Item, and pass items. Omit isHidden, omit a custom id unless testing or composition requires it, omit a ref unless programmatic focus is required, omit disabled, nonInteractiveIds, icons, grouped list items, and a custom placeholder unless the spec includes them.

Programmatic focus (conditional — omit by default):

Use a ref when the product needs to move focus to the combobox after an action. Do not attach a ref or call focus() unless the design or developer asks for it. See Ref Forwarding under Usage for a complete Storybook example (imports, ref on FormField.Input as={Select.Input}, and a button that calls focus()).

Disabled options (conditional):

When an option is unavailable, set nonInteractiveIds on Select and aria-disabled on those **Select.Item**s. See Disabled Items under Usage for a complete Storybook example. Do not use styling alone.

RequirementHow to satisfy
Input wiringFormField.Input as={Select.Input} for the combobox, with Select.Popper, Select.Card, Select.List, and Select.Item. See FormField accessibility for label, hint, error, and required wiring
Disabled combobox (conditional)disabled on FormField.Input as={Select.Input}. See Disabled
Disabled options (conditional)nonInteractiveIds on Select (ids skipped by keyboard and type-ahead) and aria-disabled on those **Select.Item**s. See Disabled Items
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 — not {item => …}. See Grouped Items
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
Custom placeholder (conditional)placeholder on FormField.Input as={Select.Input} only as short prompt text—never as the only name. Default is "Choose an option"
Programmatic focus (conditional)ref on FormField.Input as={Select.Input} and call focus() when moving focus to the field after an action—omit by default (see Programmatic focus above)

Summary for code generation:

  • REQUIRED: visible label, FormField.Input as={Select.Input}, popup list composition (Select.Popper, Select.Card, Select.List, Select.Item), items. Default list rendering is {item => <Select.Item>{item}</Select.Item>} (or item.text / getTextValue).
  • CONDITIONAL: disabled combobox, disabled options (nonInteractiveIds + aria-disabled), grouped list items (items plus static Menu.Group / data-id children — do not omit items), option icons, custom placeholder, programmatic focus via ref, getId and getTextValue when item shape is not {id, text} (always pass getTextValue if custom getId is not the display text), data-id on static JSX **Select.Item**s. See FormField accessibility for shared FormField conditionals (hint/error, required, stable id).

Anti-Patterns

Do not generate code that does the following (see Accessibility Requirements above for what to supply instead):

  • Missing FormField wiring: Do not use Select without FormField and FormField.Label, and do not render a bare Select.Input when a FormField is present. Use FormField.Input as={Select.Input} (see Minimum accessible structure). For shared FormField anti-patterns (manual ARIA, placeholder-only labels, color-only errors, broken ID references), see FormField Anti-Patterns.
  • Duplicating combobox or listbox ARIA: Do not set role, aria-haspopup, aria-expanded, aria-autocomplete (including "none"), aria-controls, aria-activedescendant, autoComplete, or listbox role / id / aria-labelledby / aria-label. Do not make Select.Item focusable — the active option is aria-activedescendant on the combobox.
  • Wrong component: Do not use a native <select>, Menu, Combobox, TextInput, or FormFieldGroup for a single submitted list value. Use MultiSelect when more than one option can be selected.
  • Item identity / grouping: Do not set data-id on {item => <Select.Item>}. Do not omit items when grouping, and do not group with a render callback alone — use Menu.Group and data-id (see Static item ids and Grouped list items).
  • Free-text keyboard on the combobox: Do not add onKeyDown that types into the input or calls preventDefault on Tab — Select is select-only.

Component API

Select

Use Select to allow users to choose an option from a list or type characters to select a matching option.

Note: Wrap Select with FormField and compose FormField.Input as={Select.Input} so the combobox receives the field label.

<FormField> <FormField.Label>Contact</FormField.Label> <FormField.Field> <Select items={options}> <FormField.Input as={Select.Input} onChange={e => handleChange(e)} /> <Select.Popper> <Select.Card> <Select.List>{item => <Select.Item>{item}</Select.Item>}</Select.List> </Select.Card> </Select.Popper> </Select> </FormField.Field> </FormField>

Props

Props extend from . If a model is passed, props from SelectModelConfig are ignored.

NameTypeDescriptionDefault
childrenReactNode

Children of the Combobox. Should contain a Combobox.Input and a Combobox.Menu

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

Select.Input

Select.Input renders a that handles keyboard navigation and interaction defined by WAI. This component can either be controlled or uncontrolled.

Compose it as FormField.Input as={Select.Input} so label, required, and error wiring apply.

<FormField> <FormField.Label>Contact</FormField.Label> <FormField.Field> <Select items={options}> <FormField.Input as={Select.Input} onChange={event => handleChange(event)} /> ... </Select> </FormField.Field> </FormField>

Props

Props extend from . Changing the as prop will change the element interface.

NameTypeDescriptionDefault
inputStartIcon

The Icon to render at the start of the input. Use this prop if your options include icons that you would like to render in the input when selected. Note:An option must be selected in order to render and icon.

error

The type of error associated with the TextInput (if applicable).

width number | string

The width of the TextInput.

growboolean

True if the component should grow to its container's width. False otherwise.

cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling'; import {mergeStyles} from '@workday/canvas-kit-react/layout'; // ... // `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same // function signature, but adds support for style props. return ( <Element {...handleCsProp(elemProps, [ myStyles, myModifiers({ size: 'medium' }), myVars({ backgroundColor: 'red' }) ])} > {children} </Element> )
childrenReact.ReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

refReact.Ref<R = >

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

useSelectInput

useSelectInput extends and and adds type ahead functionality and Select-specific keyboard support.

(
  (
    model: ,
    elemProps: {
      keySoFar: string;
      placeholder: string;
      value: string;
    },
    ref: React.Ref
  ) => {
    onKeyDown: (event: ) => void;
    autoComplete: 'off';
    keySoFar: null;
    ref: (instance:  | null) => void;
  },
  ,
  ,
  ,
  ,
  
)

Select.Card

Select.Card renders a . You have access to all Card props.

Note: The card will be the width of its corresponding Select.Input.

<FormField> <FormField.Label>Contact</FormField.Label> <FormField.Field> <Select items={options}> <FormField.Input as={Select.Input} onChange={event => handleChange(event)} /> <Select.Popper> <Select.Card>...</Select.Card> </Select.Popper> </Select> </FormField.Field> </FormField>

Layout Component

Select.Card supports all props from thelayout component.

Props

Props extend from div. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
variant 'alt' | 'tonal'

The variant of the Card. Can be alt, tonal or default.

'default'
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling'; import {mergeStyles} from '@workday/canvas-kit-react/layout'; // ... // `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same // function signature, but adds support for style props. return ( <Element {...handleCsProp(elemProps, [ myStyles, myModifiers({ size: 'medium' }), myVars({ backgroundColor: 'red' }) ])} > {children} </Element> )
childrenReact.ReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

div
refReact.Ref<R = div>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

useSelectCard

Sets the width of the SelectCard to the Select.Input width.

(
  model: ,
  elemProps: {},
  ref: React.Ref
) => {
  width: number;
}

Select.Item

Select.Item renders a with aria role of option. You can optionally render a Icon.

<FormField> <FormField.Label>Contact</FormField.Label> <FormField.Field> <Select items={options}> <FormField.Input as={Select.Input} onChange={event => handleChange(event)} /> <Select.Popper> <Select.Card> <Select.List> {item => ( <Select.Item> <Select.Item.Icon icon={icon} /> {item} </Select.Item> )} </Select.List> </Select.Card> </Select.Popper> </Select> </FormField.Field> </FormField>

Props

Props extend from li. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
indexnumber

Optionally pass index to menu item. This should be done if Menu.Item components were created via a Array::map function. This index will ensure keyboard navigation works even if items are inserted out of order.

childrenReactNode

The label text of the MenuItem.

data-idstring

The name of the menu item. This name will be used in the onSelect callback in the model. If this property is not provided, it will default to a string representation of the the zero-based index of the Tab when it was initialized.

aria-disabledboolean

aria-disabled is used for keyboard and screen reader users to discover disabled content with the keyboard or screen reader caret tool. For more information, see https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_disabled_controls

isDisabledboolean

If true, set the StyledMenuItem to the disabled state so it is not clickable.

false
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling'; import {mergeStyles} from '@workday/canvas-kit-react/layout'; // ... // `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same // function signature, but adds support for style props. return ( <Element {...handleCsProp(elemProps, [ myStyles, myModifiers({ size: 'medium' }), myVars({ backgroundColor: 'red' }) ])} > {children} </Element> )
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

li
refReact.Ref<R = li>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

Model

useSelectModel

SelectModel extends the . Selecting items from the menu will dispatch an input event on the input which should work with form libraries, automation and autofill.

const model = useSelectModel({items: ['Mobile', 'Phone', 'E-Mail']}) <Select model={model}> ... </Select>
useSelectModel (config: ):

Content Guidelines

  • The list of Menu items should be scannable, with concise labels written in title case. Don’t write sentences and omit articles (a, an, the) unless needed for clarity.
  • Placeholder text for a Select must begin with the verb “Select”.