For Developers

Combobox

Combobox is an abstract compound component - it should not be used on its own, but used as a base to create combobox components. The Combobox system provides components, models, loaders, and elemProps hooks.

The term "Combobox" is based on the Combobox Pattern as defined in the ARIA Authoring Practices Guide (APG):

A combobox is an input widget with an associated popup that enables users to select a value for the combobox from a collection of possible values.

Examples of a "combobox" would be date pickers, autocomplete, and select components.

Examples

Autocomplete

This example shows an Autocomplete example using FormField, InputGroup, and the Combobox components to make an autocomplete form field. It uses useComboboxLoader to make mock API calls using setTimeout. Your application may use fetch, WebSockets, or other means of communicating with a server.

Component API

Combobox

Props

Props extend from . If a model is passed, props from ComboboxModelConfig 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.

Combobox.Input

The input of the Combobox. This element will have role="combobox" applied, along with aria-haspopup="true"

Props

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

NameTypeDescriptionDefault
error

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

width number | string

The width of the TextInput.

theme
growboolean

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

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.

useComboboxInput

Adds all attributes necessary to start with a . It opens the menu with arrow keys, uses , and handles keyboard arrows to navigate items of the menu. You may also compose this hook to add more specific behaviors for your .

(
  (
    model: ,
    elemProps: {},
    ref: React.Ref
  ) => {
    onKeyDown: (event: ) => void;
    onBlur: (event: ) => void;
    onChange: (event: <>) => void;
    onClick: (event: ) => void;
    value:  string | undefined;
    role: 'combobox';
    aria-haspopup: true;
    aria-expanded: boolean;
    aria-autocomplete: 'list';
    aria-controls: any;
    id: string;
    ref: (instance:  | null) => void;
  },
  ,
  ,
  ,
  
)

Combobox.Menu

A custom component that uses aria-activedescendant instead of roving tab index to keep the focus on the .

Props

NameTypeDescriptionDefault
childrenReactNode

Children of the .

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.

Combobox.Menu.List

The combobox menu list follows the Collections API. A list can either contain static items or a render prop and items to the model.

const MyComponent = () => {
const model = useComboboxModel({
items: ['First Item', 'Second Item']
})
return (
<Combobox model={model}>
// other combobox subcomponents
<Combobox.Menu.List>
{(item) => <Combobox.Menu.Item>{item}</Combobox.Menu.Item>}
</Combobox.Menu.List>
</Combobox>
)
}

Layout Component

Combobox.Menu.List supports all props from thelayout component.

Props

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

NameTypeDescriptionDefault
children ReactNode | ((
    item: T,
    index: number
  ) => 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.

ul
refReact.Ref<R = ul>

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.

useComboboxMenuList

The listbox uses aria-labelledby pointing to the . This input should be labelled by a form field label for proper accessibility. Use to ensure proper accessibility.

(
  model: ,
  elemProps: {},
  ref: React.Ref
) => {
  role: 'listbox';
  aria-labelledby: string;
  id: any;
  flexDirection:  'column' | 'row';
}

Combobox.Menu.Item

Combobox.Menu.Item has an optional data-id prop that identifies the item in the Combobox.Menu.List and will be passed to the optional onSelect callback of the ComboboxModel. Combobox.Menu.Item can contain any HTML.

Props

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

NameTypeDescriptionDefault
childrenReactNode
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.

useComboboxMenuItem

This hook sets up accessibility and behavior of a component. It prevents focus when clicking so the focus stays on the component and selects an item when the user clicks on it. It also prevents items with an aria-disabled attribute from being selected. A focus CSS class is added when the item has "focus" (when the cursor is on the item).

(
  (
    model: ,
    elemProps: {
      data-id: string;
    },
    ref: React.Ref
  ) => {
    role: 'option';
    aria-selected:  true | undefined;
    onMouseDown: (event: <>) => void;
    className:  '' | 'focus';
  },
  ,
  
)

Combobox.Menu.Card

Combobox.Menu.Card is a non-semantic element used to give the dropdown menu its distinct visual cue that the dropdown menu is floating above other content. Combobox.Menu.Card usually contains a Combobox.Menu.List, but it can also contain other elements like a header or footer.

Layout Component

Combobox.Menu.Card supports all props from thelayout component.

Props

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

NameTypeDescriptionDefault
childrenReactNode

Children of the Card. Should contain a <Card.Body> and an optional <Card.Heading>

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.

useComboboxCard

This hook sets the minWidth style attribute to match the width of the component.

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

Model

useComboboxModel

ComboboxModel extends the and 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 = useComboboxModel()
<Combobox model={model}>{Combobox child components}</Combobox>
useComboboxModel (config: ):

Hooks

useComboboxLoader

Creates a Combobox data loader and a model. The Combobox loader extends the and connects a to the filter of the data loader. A simple loader using fetch could look like the following:

const {model, loader} = useComboboxLoader(
{
total: 0,
pageSize: 20,
async load({pageNumber, pageSize, filter}) {
// `filter` will be a `string`
return fetch(`/myUrl?filter=${filter}`)
.then(response => response.json())
.then(response => {
return {total: response.total, items: response.items};
});
},
},
useComboboxModel
);

Can't Find What You Need?

Check out our FAQ section which may help you find the information you're looking for. For further information, contact the #canvas or #canvas-kitchannels on Slack.

FAQ Section