Skip to content

Commit 43d0410

Browse files
authored
feat: add refactored Combobox component (#1559)
1 parent e1a2f86 commit 43d0410

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+4706
-23
lines changed

README.md

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,30 @@ single repository.
1919
See the individual package README for the React component you would like
2020
to install.
2121

22-
| Package | Version | Size |
23-
| -------------------------------------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------- |
24-
| [`@zendeskgarden/react-accordions`](packages/accordions) | [![npm version][accordions npm version]][accordions npm link] | [![Bundle Size][accordions size bundle]][accordions size link] |
25-
| [`@zendeskgarden/react-avatars`](packages/avatars) | [![npm version][avatars npm version]][avatars npm link] | [![Bundle Size][avatars size bundle]][avatars size link] |
26-
| [`@zendeskgarden/react-breadcrumbs`](packages/breadcrumbs) | [![npm version][breadcrumbs npm version]][breadcrumbs npm link] | [![Bundle Size][breadcrumbs size bundle]][breadcrumbs size link] |
27-
| [`@zendeskgarden/react-buttons`](packages/buttons) | [![npm version][buttons npm version]][buttons npm link] | [![Bundle Size][buttons size bundle]][buttons size link] |
28-
| [`@zendeskgarden/react-chrome`](packages/chrome) | [![npm version][chrome npm version]][chrome npm link] | [![Bundle Size][chrome size bundle]][chrome size link] |
29-
| [`@zendeskgarden/react-colorpickers`](packages/colorpickers) | [![npm version][colorpickers npm version]][colorpickers npm link] | [![Bundle Size][colorpickers size bundle]][colorpickers size link] |
30-
| [`@zendeskgarden/react-datepickers`](packages/datepickers) | [![npm version][datepickers npm version]][datepickers npm link] | [![Bundle Size][datepickers size bundle]][datepickers size link] |
31-
| [`@zendeskgarden/react-drag-drop`](packages/drag-drop) | [![npm version][drag-drop npm version]][drag-drop npm link] | [![Bundle Size][drag-drop size bundle]][drag-drop size link] |
32-
| [`@zendeskgarden/react-dropdowns`](packages/dropdowns) | [![npm version][dropdowns npm version]][dropdowns npm link] | [![Bundle Size][dropdowns size bundle]][dropdowns size link] |
33-
| [`@zendeskgarden/react-forms`](packages/forms) | [![npm version][forms npm version]][forms npm link] | [![Bundle Size][forms size bundle]][forms size link] |
34-
| [`@zendeskgarden/react-grid`](packages/grid) | [![npm version][grid npm version]][grid npm link] | [![Bundle Size][grid size bundle]][grid size link] |
35-
| [`@zendeskgarden/react-loaders`](packages/loaders) | [![npm version][loaders npm version]][loaders npm link] | [![Bundle Size][loaders size bundle]][loaders size link] |
36-
| [`@zendeskgarden/react-modals`](packages/modals) | [![npm version][modals npm version]][modals npm link] | [![Bundle Size][modals size bundle]][modals size link] |
37-
| [`@zendeskgarden/react-notifications`](packages/notifications) | [![npm version][notifications npm version]][notifications npm link] | [![Bundle Size][notifications size bundle]][notifications size link] |
38-
| [`@zendeskgarden/react-pagination`](packages/pagination) | [![npm version][pagination npm version]][pagination npm link] | [![Bundle Size][pagination size bundle]][pagination size link] |
39-
| [`@zendeskgarden/react-tabs`](packages/tabs) | [![npm version][tabs npm version]][tabs npm link] | [![Bundle Size][tabs size bundle]][tabs size link] |
40-
| [`@zendeskgarden/react-tables`](packages/tables) | [![npm version][tables npm version]][tables npm link] | [![Bundle Size][tables size bundle]][tables size link] |
41-
| [`@zendeskgarden/react-tags`](packages/tags) | [![npm version][tags npm version]][tags npm link] | [![Bundle Size][tags size bundle]][tags size link] |
42-
| [`@zendeskgarden/react-theming`](packages/theming) | [![npm version][theming npm version]][theming npm link] | [![Bundle Size][theming size bundle]][theming size link] |
43-
| [`@zendeskgarden/react-tooltips`](packages/tooltips) | [![npm version][tooltips npm version]][tooltips npm link] | [![Bundle Size][tooltips size bundle]][tooltips size link] |
44-
| [`@zendeskgarden/react-typography`](packages/typography) | [![npm version][typography npm version]][typography npm link] | [![Bundle Size][typography size bundle]][typography size link] |
22+
| Package | Version | Size |
23+
| ---------------------------------------------------------------- | --------------------------------------------------------------------- | ---------------------------------------------------------------------- |
24+
| [`@zendeskgarden/react-accordions`](packages/accordions) | [![npm version][accordions npm version]][accordions npm link] | [![Bundle Size][accordions size bundle]][accordions size link] |
25+
| [`@zendeskgarden/react-avatars`](packages/avatars) | [![npm version][avatars npm version]][avatars npm link] | [![Bundle Size][avatars size bundle]][avatars size link] |
26+
| [`@zendeskgarden/react-breadcrumbs`](packages/breadcrumbs) | [![npm version][breadcrumbs npm version]][breadcrumbs npm link] | [![Bundle Size][breadcrumbs size bundle]][breadcrumbs size link] |
27+
| [`@zendeskgarden/react-buttons`](packages/buttons) | [![npm version][buttons npm version]][buttons npm link] | [![Bundle Size][buttons size bundle]][buttons size link] |
28+
| [`@zendeskgarden/react-chrome`](packages/chrome) | [![npm version][chrome npm version]][chrome npm link] | [![Bundle Size][chrome size bundle]][chrome size link] |
29+
| [`@zendeskgarden/react-colorpickers`](packages/colorpickers) | [![npm version][colorpickers npm version]][colorpickers npm link] | [![Bundle Size][colorpickers size bundle]][colorpickers size link] |
30+
| [`@zendeskgarden/react-datepickers`](packages/datepickers) | [![npm version][datepickers npm version]][datepickers npm link] | [![Bundle Size][datepickers size bundle]][datepickers size link] |
31+
| [`@zendeskgarden/react-drag-drop`](packages/drag-drop) | [![npm version][drag-drop npm version]][drag-drop npm link] | [![Bundle Size][drag-drop size bundle]][drag-drop size link] |
32+
| [`@zendeskgarden/react-dropdowns`](packages/dropdowns) | [![npm version][dropdowns npm version]][dropdowns npm link] | [![Bundle Size][dropdowns size bundle]][dropdowns size link] |
33+
| [`@zendeskgarden/react-dropdowns.next`](packages/dropdowns.next) | [![npm version][dropdowns.next npm version]][dropdowns.next npm link] | [![Bundle Size][dropdowns.next size bundle]][dropdowns.next size link] |
34+
| [`@zendeskgarden/react-forms`](packages/forms) | [![npm version][forms npm version]][forms npm link] | [![Bundle Size][forms size bundle]][forms size link] |
35+
| [`@zendeskgarden/react-grid`](packages/grid) | [![npm version][grid npm version]][grid npm link] | [![Bundle Size][grid size bundle]][grid size link] |
36+
| [`@zendeskgarden/react-loaders`](packages/loaders) | [![npm version][loaders npm version]][loaders npm link] | [![Bundle Size][loaders size bundle]][loaders size link] |
37+
| [`@zendeskgarden/react-modals`](packages/modals) | [![npm version][modals npm version]][modals npm link] | [![Bundle Size][modals size bundle]][modals size link] |
38+
| [`@zendeskgarden/react-notifications`](packages/notifications) | [![npm version][notifications npm version]][notifications npm link] | [![Bundle Size][notifications size bundle]][notifications size link] |
39+
| [`@zendeskgarden/react-pagination`](packages/pagination) | [![npm version][pagination npm version]][pagination npm link] | [![Bundle Size][pagination size bundle]][pagination size link] |
40+
| [`@zendeskgarden/react-tabs`](packages/tabs) | [![npm version][tabs npm version]][tabs npm link] | [![Bundle Size][tabs size bundle]][tabs size link] |
41+
| [`@zendeskgarden/react-tables`](packages/tables) | [![npm version][tables npm version]][tables npm link] | [![Bundle Size][tables size bundle]][tables size link] |
42+
| [`@zendeskgarden/react-tags`](packages/tags) | [![npm version][tags npm version]][tags npm link] | [![Bundle Size][tags size bundle]][tags size link] |
43+
| [`@zendeskgarden/react-theming`](packages/theming) | [![npm version][theming npm version]][theming npm link] | [![Bundle Size][theming size bundle]][theming size link] |
44+
| [`@zendeskgarden/react-tooltips`](packages/tooltips) | [![npm version][tooltips npm version]][tooltips npm link] | [![Bundle Size][tooltips size bundle]][tooltips size link] |
45+
| [`@zendeskgarden/react-typography`](packages/typography) | [![npm version][typography npm version]][typography npm link] | [![Bundle Size][typography size bundle]][typography size link] |
4546

4647
[accordions npm version]: https://flat.badgen.net/npm/v/@zendeskgarden/react-accordions
4748
[accordions npm link]: https://www.npmjs.com/package/@zendeskgarden/react-accordions
@@ -79,6 +80,10 @@ to install.
7980
[dropdowns npm link]: https://www.npmjs.com/package/@zendeskgarden/react-dropdowns
8081
[dropdowns size bundle]: https://flat.badgen.net/bundlephobia/minzip/@zendeskgarden/react-dropdowns
8182
[dropdowns size link]: https://bundlephobia.com/result?p=@zendeskgarden/react-dropdowns
83+
[dropdowns.next npm version]: https://flat.badgen.net/npm/v/@zendeskgarden/react-dropdowns.next
84+
[dropdowns.next npm link]: https://www.npmjs.com/package/@zendeskgarden/react-dropdowns.next
85+
[dropdowns.next size bundle]: https://flat.badgen.net/bundlephobia/minzip/@zendeskgarden/react-dropdowns.next
86+
[dropdowns.next size link]: https://bundlephobia.com/result?p=@zendeskgarden/react-dropdowns.next
8287
[forms npm version]: https://flat.badgen.net/npm/v/@zendeskgarden/react-forms
8388
[forms npm link]: https://www.npmjs.com/package/@zendeskgarden/react-forms
8489
[forms size bundle]: https://flat.badgen.net/bundlephobia/minzip/@zendeskgarden/react-forms
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"index.cjs.js": {
3+
"bundled": 51272,
4+
"minified": 36664,
5+
"gzipped": 8496
6+
},
7+
"index.esm.js": {
8+
"bundled": 46953,
9+
"minified": 32590,
10+
"gzipped": 8196,
11+
"treeshaked": {
12+
"rollup": {
13+
"code": 26040,
14+
"import_statements": 1047
15+
},
16+
"webpack": {
17+
"code": 28543
18+
}
19+
}
20+
}
21+
}

packages/dropdowns.next/README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# @zendeskgarden/react-dropdowns.next [![npm version][npm version badge]][npm version link]
2+
3+
[npm version badge]: https://flat.badgen.net/npm/v/@zendeskgarden/react-dropdowns.next
4+
[npm version link]: https://www.npmjs.com/package/@zendeskgarden/react-dropdowns.next
5+
6+
This package includes components related to dropdowns in the
7+
[Garden Design System](https://zendeskgarden.github.io/).
8+
9+
## Installation
10+
11+
```sh
12+
npm install @zendeskgarden/react-dropdowns.next
13+
14+
# Peer Dependencies - Also Required
15+
npm install react react-dom styled-components @zendeskgarden/react-theming
16+
```
17+
18+
## Usage
19+
20+
### Combobox
21+
22+
```jsx
23+
import { ThemeProvider } from '@zendeskgarden/react-theming';
24+
import { Field, Label, Combobox, Option } from '@zendeskgarden/react-dropdowns.next';
25+
26+
/**
27+
* Place a `ThemeProvider` at the root of your React application
28+
*/
29+
<ThemeProvider>
30+
<Field>
31+
<Label>Combobox</Label>
32+
<Combobox>
33+
<Option value="One" />
34+
<Option value="Two" />
35+
<Option value="Three" />
36+
</Combobox>
37+
</Field>
38+
</ThemeProvider>;
39+
```
40+
41+
Beyond this basic example, Garden's `Combobox` offers a comprehensive set of
42+
WAI-ARIA compliant combobox features. Key capabilities include:
43+
44+
- **Controllable**: The `Combobox` functions in both [uncontrolled and
45+
controlled](https://react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components)
46+
modes. Controlled mode enables aspects, such as input value, selection value(s),
47+
listbox expansion, and current option active index, to share and adapt to the
48+
surrounding UI.
49+
- **Autocomplete-able**: Denotes the `Combobox` with [list
50+
autocomplete](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-autocomplete-list/).
51+
Filtering implementation is left to the API consumer.
52+
- **Selectable**: The `Combobox` API ensures the selection of one or more
53+
listbox option values, while also supporting the W3C [no autocomplete
54+
example](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-autocomplete-none/)
55+
for use cases like search.
56+
- **Multi-selectable**: This feature enables the `Combobox` to provide WAI-ARIA
57+
[multi-select
58+
listbox](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/examples/listbox-rearrangeable/#ex2_label)
59+
functionality with option-as-tag value rendering.
60+
- **Non-editable**: The `Combobox` supports [select-only
61+
mode](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/),
62+
where the user cannot modify the `<input>`.
63+
- **Filterable**: The `Combobox` offers various filtering methods for listbox
64+
options. Details of the filtering implementation are left to the API consumer.
65+
- **Markup-able**: The `Combobox` can convert input value text to rich HTML
66+
markup on blur in single-selection mode.
67+
- **Decorate-able**: The `Combobox` allows adding start and end media (SVG icons).
68+
Certain features will replace end media with Garden's standard dropdown chevron
69+
treatment.
70+
- **Group-able**: The `Combobox` API utilizes fully accessible `<OptGroup>`
71+
components for grouping, similar to the corresponding HTML element.
72+
- **Compactible**: Like other form elements, the `Combobox` supports compact
73+
sizing.
74+
- **Field-able**: The `Combobox` builds on Garden’s Field API context to
75+
establish accessible relationships with corresponding Label, Hint, and Message
76+
components.
77+
- **Validate-able**: The `Combobox` provides validation styling and
78+
accessibility comparable to other Garden form components.
79+
- **RTL theme-able**: Functionality displays and operates correctly for
80+
left-to-right and right-to-left layouts.
81+
82+
Visit [storybook](https://zendeskgarden.github.io/react-components) for live examples.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { Meta, Description } from '@storybook/addon-docs';
2+
import README from '../README.md';
3+
4+
<Meta title="Packages/Dropdowns.Next/README" />
5+
6+
<Description>{README}</Description>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { Meta, ArgsTable, Canvas, Story } from '@storybook/addon-docs';
2+
import { useArgs } from '@storybook/client-api';
3+
import {
4+
Combobox,
5+
Hint,
6+
Label,
7+
Message,
8+
Option,
9+
OptGroup,
10+
Tag
11+
} from '@zendeskgarden/react-dropdowns.next';
12+
import { ComboboxStory } from './stories/ComboboxStory';
13+
import { OPTIONS } from './stories/data';
14+
15+
<Meta
16+
title="Packages/Dropdowns.Next/Combobox"
17+
component={Combobox}
18+
subcomponents={{
19+
Hint,
20+
Label,
21+
Message,
22+
Option,
23+
'Option.Meta': Option.Meta,
24+
OptGroup,
25+
Tag,
26+
'Tag.Avatar': Tag.Avatar
27+
}}
28+
args={{
29+
label: 'Label',
30+
isLabelRegular: false,
31+
isLabelHidden: false,
32+
hint: 'Hint',
33+
startIcon: false,
34+
renderValue: false,
35+
endIcon: false,
36+
listboxAriaLabel: 'Label',
37+
message: 'Message',
38+
validationLabel: 'Label',
39+
isEditable: true,
40+
listboxMaxHeight: Combobox.defaultProps.listboxMaxHeight,
41+
listboxZIndex: Combobox.defaultProps.listboxZIndex,
42+
options: OPTIONS
43+
}}
44+
argTypes={{
45+
label: { name: 'children', table: { category: 'Label' } },
46+
hint: { name: 'children', table: { category: 'Hint' } },
47+
startIcon: { control: 'boolean' },
48+
renderValue: { control: 'boolean' },
49+
endIcon: { control: 'boolean' },
50+
appendListboxToNode: { control: false },
51+
message: { name: 'children', table: { category: 'Message' } },
52+
validationLabel: { table: { category: 'Message' } },
53+
isLabelRegular: { name: 'isRegular', table: { category: 'Label' } },
54+
isLabelHidden: { name: 'hidden', table: { category: 'Label' } }
55+
}}
56+
parameters={{
57+
design: {
58+
allowFullscreen: true,
59+
type: 'figma',
60+
url: 'https://www.figma.com/file/6g87L4FdKZTA3knt3Rsfdx/Garden?node-id=103%3A24482'
61+
}
62+
}}
63+
/>
64+
65+
# API
66+
67+
<ArgsTable />
68+
69+
# Demo
70+
71+
## Uncontrolled
72+
73+
<Canvas>
74+
<Story
75+
name="Uncontrolled"
76+
argTypes={{
77+
activeIndex: { control: false },
78+
inputValue: { control: false },
79+
isExpanded: { control: false },
80+
selectionValue: { control: false }
81+
}}
82+
>
83+
{args => <ComboboxStory {...args} />}
84+
</Story>
85+
</Canvas>
86+
87+
## Controlled
88+
89+
<Canvas>
90+
<Story
91+
name="Controlled"
92+
args={{
93+
isExpanded: false,
94+
inputValue: '',
95+
activeIndex: -1,
96+
selectionValue: null
97+
}}
98+
argTypes={{
99+
defaultExpanded: { control: false },
100+
defaultSelectionValue: { control: false }
101+
}}
102+
>
103+
{args => {
104+
const updateArgs = useArgs()[1];
105+
const handleChange = changes => {
106+
const { type, ...args } = changes;
107+
updateArgs(args);
108+
};
109+
return <ComboboxStory {...args} onChange={handleChange} />;
110+
}}
111+
</Story>
112+
</Canvas>

0 commit comments

Comments
 (0)