Dropdown
A form input for making a single selection from a list of items.
- Install
npm install @pluralsight/ps-design-system-dropdown
- Import
import Dropdown from '@pluralsight/ps-design-system-dropdown'
Examples
Controlling with value
import React from 'react'import Dropdown from '@pluralsight/ps-design-system-dropdown'import Button from '@pluralsight/ps-design-system-button'function Example() {const options = [{ value: 'beg', label: 'Beginner' },{ value: 'int', label: 'Intermediate' },{ value: 'adv', label: 'Advanced' }]const [value, setValue] = React.useState(options[1].value)return (<div className="example-flex-column"><Dropdownlabel="Level"placeholder="Select"onChange={(evt, value, label) => setValue(value)}menu={options.map(opt => (<Dropdown.Item key={opt.value} value={opt.value}>{opt.label}</Dropdown.Item>))}value={value}/><div>Selected: {value}</div><div><Buttonappearance="secondary"size="xSmall"onClick={() => setValue('beg')}>Set Beginner</Button></div></div>)}export default Example
Label
Primary identification of a dropdown comes through the label. Usage hints are given in the placeholder. Supporting text and error messaging is set in the subLabel.
import React from 'react'import Dropdown from '@pluralsight/ps-design-system-dropdown'const Comp = () => (<div className="example-flex-column"><Dropdownlabel="Level"placeholder="Select level"subLabel="Which audience is this course aimed at?"menu={<><Dropdown.Item>Beginner</Dropdown.Item><Dropdown.Item>Intermediate</Dropdown.Item><Dropdown.Item>Advanced</Dropdown.Item></>}/></div>)export default Comp
Appearance
When using the dark theme, a subtle
appearance is available. (Switch theme to dark)
import React from 'react'import Dropdown from '@pluralsight/ps-design-system-dropdown'const Comp = () => (<Dropdownappearance={Dropdown.appearances.subtle}label="Level"placeholder="Select level"menu={<React.Fragment><Dropdown.Item>Beginner</Dropdown.Item><Dropdown.Item>Intermediate</Dropdown.Item><Dropdown.Item>Advanced</Dropdown.Item></React.Fragment>}/>)export default Comp
Sizes
For table rows, step down to the small
size.
import React from 'react'import Dropdown from '@pluralsight/ps-design-system-dropdown'const Comp = () => (<div className="example-flex-column"><Dropdownplaceholder="Medium dropdown"menu={<><Dropdown.Item>Beginner</Dropdown.Item><Dropdown.Item>Intermediate</Dropdown.Item><Dropdown.Item>Advanced</Dropdown.Item></>}/><Dropdownsize={Dropdown.sizes.small}placeholder="Small dropdown"menu={<><Dropdown.Item>Beginner</Dropdown.Item><Dropdown.Item>Intermediate</Dropdown.Item><Dropdown.Item>Advanced</Dropdown.Item></>}/></div>)export default Comp
Disabled
Disabled dropdowns are unmodifiable, not interactive, and diminished visually.
import React from 'react'import Dropdown from '@pluralsight/ps-design-system-dropdown'const Comp = () => (<Dropdown disabled label="Can't touch this" placeholder="Just try it" />)export default Comp
Error
Error states are engaged with the error
flag. Error-related messaging is sent to the subLabel
prop.
import React from 'react'import Dropdown from '@pluralsight/ps-design-system-dropdown'const Comp = () => (<Dropdownerrorlabel="Level"placeholder="Select level"menu={<><Dropdown.Item>Beginner</Dropdown.Item><Dropdown.Item>Intermediate</Dropdown.Item><Dropdown.Item>Advanced</Dropdown.Item></>}/>)export default Comp
Customizing with icon
import React from 'react'import Dropdown, { useDropdown } from '@pluralsight/ps-design-system-dropdown'import { CalendarIcon } from '@pluralsight/ps-design-system-icon'interface DropdownWithIconProps extends HTMLAttributes<HTMLButtonElement> {icon: React.ReactNodemenu: React.ReactNode}const DropdownWithIcon = React.forwardRef<HTMLButtonElement,DropdownWithIconProps>(({ icon, ...props }, forwardedRef) => {const allProps = useDropdown(props, forwardedRef)return (<Dropdown.Layout{...allProps.layout}label={<Dropdown.Label {...allProps.label} />}menu={<DropdownContext.Provider {...allProps.value}><Dropdown.Menu {...allProps.menu} /></DropdownContext.Provider>}subLabel={<Dropdown.SubLabel {...allProps.subLabel} />}button={<Dropdown.Button {...allProps.button}>{icon}<div style={{ height: '100%', position: 'relative', flex: 1 }}><Dropdown.Selected {...allProps.selected} /></div></Dropdown.Button>}/>)})function Example() {return (<DropdownWithIconicon={<CalendarIcon style={{ marginRight: 8 }} />}menu={<><Dropdown.Item>Trailing 14 Days</Dropdown.Item><Dropdown.Item>Last Month</Dropdown.Item><Dropdown.Item>Trailing 30 Days</Dropdown.Item><Dropdown.Item>Last Quater</Dropdown.Item><Dropdown.Item>Trailing 90 Days</Dropdown.Item><Dropdown.Item>Custom</Dropdown.Item></>}/>)}export default Example
Customizing with dynamic icon
import React, { HTMLAttributes } from 'react'import Dropdown, { useDropdown } from '@pluralsight/ps-design-system-dropdown'import { CalendarIcon } from '@pluralsight/ps-design-system-icon'interface DropdownWithIconPropsextends Omit<HTMLAttributes<HTMLButtonElement>, 'onChange'> {icon: React.ReactNodeonChange?: (e: React.MouseEvent, value: React.ReactText) => voidmenu: React.ReactNode}const DropdownWithIcon = React.forwardRef<HTMLButtonElement,DropdownWithIconProps>(({ icon, ...props }, forwardedRef) => {const allProps = useDropdown(props, forwardedRef)return (<Dropdown.Layout{...allProps.layout}label={<Dropdown.Label {...allProps.label} />}menu={<DropdownContext.Provider {...allProps.value}><Dropdown.Menu {...allProps.menu} /></DropdownContext.Provider>}subLabel={<Dropdown.SubLabel {...allProps.subLabel} />}button={<Dropdown.Button {...allProps.button}>{icon}<div style={{ height: '100%', position: 'relative', flex: 1 }}><Dropdown.Selected {...allProps.selected} /></div></Dropdown.Button>}/>)})function Example() {const [selected, setSelected] = React.useState<null | string>()const values = {channel: {value: 'channel',icon: <ChannelIcon style={{ marginRight: 8 }} />,label: 'Channel'},analytics: {value: 'analytics',icon: <AnalyticsIcon style={{ marginRight: 8 }} />,label: 'Analytics'},authorKit: {value: 'authorKit',icon: <AuthorKitIcon style={{ marginRight: 8 }} />,label: 'Author Kit'},labs: {value: 'labs',icon: <LabsIcon style={{ marginRight: 8 }} />,label: 'Labs'}}const handleChange = (e: React.MouseEvent, value: React.ReactText) => {setSelected(value)}const icon = values[selected] ? (values[selected].icon) : (<div style={{ width: 24, height: 24, marginRight: 8 }} />)return (<DropdownWithIconicon={icon}onChange={handleChange}menu={Object.values(values).map(({ value, icon, label }) => (<Dropdown.Item value={value} key={value} icon={icon}>{label}</Dropdown.Item>))}/>)}export default Example
Menu scrolling
The dropdown component menu has a max height of 400px and will scroll for content needing more vertical space.
import React from 'react'import Dropdown from '@pluralsight/ps-design-system-dropdown'const Example = () => (<Dropdownlabel="Max height example"menu={<><Dropdown.Item>One item</Dropdown.Item><Dropdown.Item>Two item</Dropdown.Item><Dropdown.Item>Three item</Dropdown.Item><Dropdown.Item>Four item</Dropdown.Item><Dropdown.Item>Five item</Dropdown.Item><Dropdown.Item>Six item</Dropdown.Item><Dropdown.Item>Seven item</Dropdown.Item><Dropdown.Item>Eight item</Dropdown.Item><Dropdown.Item>Nine item</Dropdown.Item><Dropdown.Item>Ten item</Dropdown.Item><Dropdown.Item>Eleven item</Dropdown.Item><Dropdown.Item>Twelve item</Dropdown.Item><Dropdown.Item>Thirteen item</Dropdown.Item><Dropdown.Item>Fourteen item</Dropdown.Item><Dropdown.Item>Fifteen item</Dropdown.Item></>}/>)export default Example
Accessibility
WCAG 2.1 AA Compliance
100% axe-core testsNo manual audit
WAI-ARIA Patterns: Listbox
Props
Dropdown
Name | Type | Description | Default |
---|---|---|---|
appearance |
| visual style (from Dropdown.appearances) | default |
disabled | boolean | standard input disabled flag |
|
error | boolean | error state flag |
|
label | string | identifying string for dropdown |
|
menu | Dropdown.Item(s) | menu items for dropdown | <span></span> |
onChange | (Event, value, label) => void | triggered when an item selected |
|
placeholder | string | in-field usage hint |
|
size |
| sets dropdown size (from Dropdown.sizes) | medium |
subLabel | string | supporting text or error messaging |
|
uniqueId | (prefix: string) => string | override internal id generation for test stability |
|
Dropdown.Item
Name | Type | Description | Default |
---|---|---|---|
disabled | boolean | visually disabled, non-interactive |
|
icon | *Icon | An Icon component |
|
onClick | (Event, value) => void | override default onClick behavior passed to Dropdown.props.onChange |
|
value | string | number | value sent to ActionMenu#onChange |
|