@kubex/zinc 1.0.25 → 1.0.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/project.md +556 -0
- package/.github/workflows/js_build_and_deploy.yaml +9 -10
- package/dist/custom-elements.json +13575 -8856
- package/dist/vscode.html-custom-data.json +583 -48
- package/dist/web-types.json +1441 -181
- package/dist/zn.d.ts +1645 -660
- package/dist/zn.min.css +1 -1
- package/dist/zn.min.js +1412 -893
- package/docs/_utilities/code-previews.cjs +10 -1
- package/docs/assets/scripts/docs.js +42 -18
- package/docs/data/data-table.json +229 -66
- package/docs/data/empty.json +6 -0
- package/docs/data/products-table.json +41 -193
- package/docs/pages/components/action-bar.md +121 -6
- package/docs/pages/components/alert.md +118 -15
- package/docs/pages/components/animated-button.md +299 -0
- package/docs/pages/components/audio-select.md +534 -0
- package/docs/pages/components/bulk-actions.md +79 -5
- package/docs/pages/components/button-group.md +235 -27
- package/docs/pages/components/button.md +139 -1
- package/docs/pages/components/chart.md +365 -9
- package/docs/pages/components/checkbox.md +387 -58
- package/docs/pages/components/chip.md +253 -33
- package/docs/pages/components/collapsible.md +393 -46
- package/docs/pages/components/cols.md +152 -30
- package/docs/pages/components/confirm.md +182 -16
- package/docs/pages/components/copy-button.md +169 -6
- package/docs/pages/components/data-select.md +194 -15
- package/docs/pages/components/data-table-filter.md +96 -5
- package/docs/pages/components/data-table-search.md +451 -0
- package/docs/pages/components/data-table-sort.md +66 -5
- package/docs/pages/components/data-table.md +727 -66
- package/docs/pages/components/datepicker.md +402 -7
- package/docs/pages/components/defined-label.md +120 -5
- package/docs/pages/components/dialog.md +339 -59
- package/docs/pages/components/dropdown.md +366 -11
- package/docs/pages/components/editor.md +604 -7
- package/docs/pages/components/empty-state.md +315 -16
- package/docs/pages/components/expanding-action.md +212 -28
- package/docs/pages/components/file.md +421 -12
- package/docs/pages/components/filter-container.md +158 -5
- package/docs/pages/components/filter-wrapper.md +167 -6
- package/docs/pages/components/form-group.md +383 -6
- package/docs/pages/components/hover-container.md +237 -6
- package/docs/pages/components/icon-picker.md +121 -0
- package/docs/pages/components/icon.md +454 -48
- package/docs/pages/components/inline-edit.md +787 -19
- package/docs/pages/components/input-group.md +207 -13
- package/docs/pages/components/input.md +194 -0
- package/docs/pages/components/item.md +18 -0
- package/docs/pages/components/key-container.md +115 -0
- package/docs/pages/components/key.md +101 -0
- package/docs/pages/components/menu.md +512 -6
- package/docs/pages/components/note.md +239 -36
- package/docs/pages/components/opt-group.md +107 -0
- package/docs/pages/components/pagination.md +332 -6
- package/docs/pages/components/pane.md +222 -6
- package/docs/pages/components/panel.md +213 -26
- package/docs/pages/components/popup.md +1354 -6
- package/docs/pages/components/priority-list.md +233 -0
- package/docs/pages/components/progress-bar.md +387 -6
- package/docs/pages/components/radio-group.md +242 -5
- package/docs/pages/components/radio.md +474 -6
- package/docs/pages/components/rating.md +331 -7
- package/docs/pages/components/reveal.md +524 -6
- package/docs/pages/components/scroll-container.md +552 -6
- package/docs/pages/components/select.md +762 -160
- package/docs/pages/components/skeleton.md +473 -30
- package/docs/pages/components/slideout.md +261 -5
- package/docs/pages/components/sp.md +99 -41
- package/docs/pages/components/split-button.md +347 -9
- package/docs/pages/components/split-pane.md +445 -6
- package/docs/pages/components/stat.md +549 -9
- package/docs/pages/components/status-indicator.md +230 -1
- package/docs/pages/components/stepper.md +563 -6
- package/docs/pages/components/tabs.md +439 -13
- package/docs/pages/components/textarea.md +415 -17
- package/docs/pages/components/tile.md +385 -26
- package/docs/pages/components/toggle.md +424 -6
- package/docs/pages/components/tooltip.md +367 -0
- package/docs/pages/components/translation-group.md +210 -0
- package/docs/pages/components/translations.md +319 -19
- package/docs/pages/components/vertical-stepper.md +401 -8
- package/docs/pages/components/well.md +300 -3
- package/docs/pages/getting-started/form-controls.md +162 -0
- package/docs/pages/index.md +116 -15
- package/package.json +5 -6
- package/scss/_global-spacing.scss +4 -0
- package/scss/_root.scss +2 -2
- package/scss/boot.scss +19 -0
- package/scss/shared/layout.scss +5 -0
- package/scss/themes/_light.scss +3 -3
- package/src/components/alert/alert.scss +1 -0
- package/src/components/animated-button/README.md +306 -0
- package/src/components/animated-button/animated-button.component.ts +229 -0
- package/src/components/animated-button/animated-button.scss +228 -0
- package/src/components/animated-button/animated-button.test.ts +143 -0
- package/src/components/animated-button/index.ts +12 -0
- package/src/components/button/button.component.ts +5 -0
- package/src/components/button-group/button-group.component.ts +25 -13
- package/src/components/button-group/button-group.scss +6 -0
- package/src/components/checkbox/checkbox.component.ts +4 -0
- package/src/components/checkbox/checkbox.scss +7 -4
- package/src/components/checkbox-group/checkbox-group.scss +7 -0
- package/src/components/chip/chip.component.ts +7 -2
- package/src/components/chip/chip.scss +16 -2
- package/src/components/collapsible/collapsible.component.ts +27 -20
- package/src/components/cols/cols.component.ts +14 -2
- package/src/components/cols/cols.scss +6 -12
- package/src/components/confirm/confirm.component.ts +7 -0
- package/src/components/copy-button/copy-button.component.ts +12 -11
- package/src/components/data-select/data-select.component.ts +215 -44
- package/src/components/data-select/data-select.scss +66 -6
- package/src/components/data-select/providers/currency-data-provider.ts +20 -6
- package/src/components/data-select/providers/provider.ts +1 -0
- package/src/components/data-select/providers/us-state-data-provider.ts +68 -0
- package/src/components/data-table/data-table.component.ts +81 -22
- package/src/components/data-table-search/data-table-search.component.ts +184 -0
- package/src/components/data-table-search/data-table-search.scss +17 -0
- package/src/components/data-table-search/data-table-search.test.ts +11 -0
- package/src/components/data-table-search/index.ts +12 -0
- package/src/components/datepicker/datepicker.component.ts +347 -13
- package/src/components/dialog/dialog.component.ts +1 -1
- package/src/components/empty-state/empty-state.scss +6 -1
- package/src/components/header/header.scss +3 -3
- package/src/components/icon/icon.component.ts +23 -1
- package/src/components/icon/icon.scss +23 -0
- package/src/components/icon-picker/brand-icons.ts +24 -0
- package/src/components/icon-picker/icon-picker.component.ts +407 -0
- package/src/components/icon-picker/icon-picker.scss +205 -0
- package/src/components/icon-picker/index.ts +12 -0
- package/src/components/icon-picker/line-icons.ts +612 -0
- package/src/components/icon-picker/material-icons.ts +14543 -0
- package/src/components/inline-edit/inline-edit.component.ts +190 -46
- package/src/components/inline-edit/inline-edit.scss +29 -0
- package/src/components/inline-edit/inline-edit.test.ts +314 -1
- package/src/components/input/input.component.ts +324 -5
- package/src/components/input/input.scss +87 -0
- package/src/components/input-group/input-group.component.ts +28 -7
- package/src/components/input-group/input-group.scss +48 -10
- package/src/components/item/item.component.ts +24 -3
- package/src/components/item/item.scss +18 -0
- package/src/components/key/index.ts +12 -0
- package/src/components/key/key.component.ts +47 -0
- package/src/components/key/key.scss +38 -0
- package/src/components/key-container/index.ts +12 -0
- package/src/components/key-container/key-container.component.ts +142 -0
- package/src/components/key-container/key-container.scss +33 -0
- package/src/components/menu-item/menu-item.component.ts +20 -0
- package/src/components/menu-item/menu-item.scss +69 -2
- package/src/components/navbar/navbar.component.ts +103 -11
- package/src/components/navbar/navbar.scss +6 -1
- package/src/components/opt-group/index.ts +12 -0
- package/src/components/opt-group/opt-group.component.ts +74 -0
- package/src/components/opt-group/opt-group.scss +37 -0
- package/src/components/opt-group/opt-group.test.ts +27 -0
- package/src/components/option/option.component.ts +1 -16
- package/src/components/option/option.scss +4 -0
- package/src/components/panel/panel.component.ts +10 -8
- package/src/components/panel/panel.scss +20 -0
- package/src/components/priority-list/index.ts +12 -0
- package/src/components/priority-list/priority-list.component.ts +611 -0
- package/src/components/priority-list/priority-list.scss +185 -0
- package/src/components/priority-list/priority-list.test.ts +139 -0
- package/src/components/progress-bar/progress-bar.component.ts +22 -16
- package/src/components/radio/radio.scss +10 -3
- package/src/components/select/select.component.ts +812 -72
- package/src/components/select/select.scss +108 -2
- package/src/components/select/select.test.ts +147 -2
- package/src/components/settings-container/settings-container.component.ts +44 -19
- package/src/components/settings-container/settings-container.scss +1 -1
- package/src/components/skeleton/skeleton.component.ts +6 -1
- package/src/components/slideout/slideout.scss +8 -3
- package/src/components/sp/sp.component.ts +3 -1
- package/src/components/sp/sp.scss +19 -0
- package/src/components/stepper/stepper.component.ts +16 -10
- package/src/components/textarea/textarea.scss +0 -4
- package/src/components/tile/tile.component.ts +12 -3
- package/src/components/tile/tile.scss +1 -1
- package/src/components/timer/timer.component.ts +15 -2
- package/src/components/toggle/toggle.component.ts +29 -26
- package/src/components/toggle/toggle.scss +13 -1
- package/src/components/translation-group/index.ts +12 -0
- package/src/components/translation-group/translation-group.component.ts +207 -0
- package/src/components/translation-group/translation-group.scss +8 -0
- package/src/components/translations/translations.component.ts +90 -44
- package/src/components/translations/translations.scss +4 -0
- package/src/components/vertical-stepper/vertical-stepper.component.ts +14 -9
- package/src/events/events.ts +12 -7
- package/src/events/zn-language-change.ts +7 -0
- package/src/events/zn-purchase.ts +11 -0
- package/src/events/zn-redirect.ts +7 -0
- package/src/events/zn-reorder.ts +7 -0
- package/src/events/zn-search-change.ts +11 -0
- package/src/events/zn-submit.ts +1 -1
- package/src/form-control.scss +4 -0
- package/src/internal/form-navigation.ts +510 -0
- package/src/internal/form.ts +6 -0
- package/src/zinc.ts +91 -83
|
@@ -10,75 +10,48 @@ unusedProperties: |
|
|
|
10
10
|
|
|
11
11
|
## Examples
|
|
12
12
|
|
|
13
|
-
### Basic Select
|
|
13
|
+
### Basic Select
|
|
14
14
|
|
|
15
|
-
Use the `label` attribute to give the select an accessible label. For labels that contain HTML, use the `label` slot
|
|
16
|
-
instead.
|
|
15
|
+
Use the `label` attribute to give the select an accessible label. For labels that contain HTML, use the `label` slot instead.
|
|
17
16
|
|
|
18
17
|
```html:preview
|
|
19
|
-
|
|
20
|
-
<
|
|
21
|
-
<zn-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
<zn-option value="5">Option 5</zn-option>
|
|
28
|
-
<zn-option value="6">Option 6</zn-option>
|
|
29
|
-
</zn-select>
|
|
30
|
-
|
|
31
|
-
<br>
|
|
32
|
-
|
|
33
|
-
<zn-button type="submit">Submit</zn-button>
|
|
34
|
-
</form>
|
|
18
|
+
<zn-select label="Select one option">
|
|
19
|
+
<zn-option value="option-1">Option 1</zn-option>
|
|
20
|
+
<zn-option value="option-2">Option 2</zn-option>
|
|
21
|
+
<zn-option value="option-3">Option 3</zn-option>
|
|
22
|
+
<zn-option value="option-4">Option 4</zn-option>
|
|
23
|
+
<zn-option value="option-5">Option 5</zn-option>
|
|
24
|
+
<zn-option value="option-6">Option 6</zn-option>
|
|
25
|
+
</zn-select>
|
|
35
26
|
```
|
|
36
27
|
|
|
37
28
|
:::tip
|
|
38
|
-
This component works with standard `<form>` elements. Please refer to the section
|
|
39
|
-
on [form controls](/getting-started/form-controls) to learn more about form submission and client-side validation.
|
|
29
|
+
This component works with standard `<form>` elements. Please refer to the section on [form controls](/getting-started/form-controls) to learn more about form submission and client-side validation.
|
|
40
30
|
:::
|
|
41
31
|
|
|
42
|
-
###
|
|
43
|
-
|
|
44
|
-
```html:preview
|
|
45
|
-
|
|
46
|
-
<div class="form-spacing">
|
|
47
|
-
<zn-select provider="country" multiple name="country-one" id="country-one" distinct="country-two">
|
|
48
|
-
<zn-option value="0">Option 0</zn-option>
|
|
49
|
-
<zn-option value="1">Option 1</zn-option>
|
|
50
|
-
<zn-option value="2">Option 2</zn-option>
|
|
51
|
-
</zn-select>
|
|
52
|
-
<zn-select provider="country" multiple name="country-two" id="country-two" distinct="country-one">
|
|
53
|
-
<zn-option value="0">Option 0</zn-option>
|
|
54
|
-
<zn-option value="1">Option 1</zn-option>
|
|
55
|
-
<zn-option value="2">Option 2</zn-option>
|
|
56
|
-
</zn-select>
|
|
57
|
-
</div>
|
|
58
|
-
```
|
|
32
|
+
### Initial Values
|
|
59
33
|
|
|
60
|
-
|
|
34
|
+
Use the `value` attribute to set the initial selection. You can also use the `selected` attribute on individual options.
|
|
61
35
|
|
|
62
36
|
```html:preview
|
|
63
|
-
|
|
64
|
-
<
|
|
65
|
-
<zn-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
<zn-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
</zn-select>
|
|
75
|
-
</div>
|
|
37
|
+
<zn-select label="Select with initial value" value="option-2">
|
|
38
|
+
<zn-option value="option-1">Option 1</zn-option>
|
|
39
|
+
<zn-option value="option-2">Option 2</zn-option>
|
|
40
|
+
<zn-option value="option-3">Option 3</zn-option>
|
|
41
|
+
</zn-select>
|
|
42
|
+
<br />
|
|
43
|
+
<zn-select label="Using selected attribute">
|
|
44
|
+
<zn-option value="option-1">Option 1</zn-option>
|
|
45
|
+
<zn-option value="option-2" selected>Option 2</zn-option>
|
|
46
|
+
<zn-option value="option-3">Option 3</zn-option>
|
|
47
|
+
</zn-select>
|
|
76
48
|
```
|
|
77
49
|
|
|
50
|
+
When using `multiple`, the `value` attribute uses space-delimited values to select more than one option. Because of this, `<zn-option>` values cannot contain spaces. If you're accessing the `value` property through JavaScript, it will be an array.
|
|
51
|
+
|
|
78
52
|
### Help Text
|
|
79
53
|
|
|
80
|
-
Add descriptive help text to a select with the `help-text` attribute. For help texts that contain HTML, use the
|
|
81
|
-
`help-text` slot instead.
|
|
54
|
+
Add descriptive help text to a select with the `help-text` attribute. For help texts that contain HTML, use the `help-text` slot instead.
|
|
82
55
|
|
|
83
56
|
```html:preview
|
|
84
57
|
<zn-select label="Skill level" help-text="Select one option that best describes your current skill level">
|
|
@@ -102,9 +75,7 @@ Add descriptive help text to a select with the `help-text` attribute. For help t
|
|
|
102
75
|
Use the `label-tooltip` attribute to add text that appears in a tooltip triggered by an info icon next to the label.
|
|
103
76
|
|
|
104
77
|
:::tip
|
|
105
|
-
**Usage:** Use a **label tooltip** to provide helpful but non-essential instructions or examples to guide people when
|
|
106
|
-
selecting an option. Use **help text** to communicate instructions or requirements for choosing an option without
|
|
107
|
-
errors.
|
|
78
|
+
**Usage:** Use a **label tooltip** to provide helpful but non-essential instructions or examples to guide people when selecting an option. Use **help text** to communicate instructions or requirements for choosing an option without errors.
|
|
108
79
|
:::
|
|
109
80
|
|
|
110
81
|
```html:preview
|
|
@@ -118,14 +89,10 @@ errors.
|
|
|
118
89
|
|
|
119
90
|
### Label with Context Note
|
|
120
91
|
|
|
121
|
-
Use the `context-note` attribute to add text that provides additional context or reference. For text that contains HTML,
|
|
122
|
-
use the `context-note` slot. **Note:** On small screens the context note will wrap below the label if there isn't enough
|
|
123
|
-
room next to the label.
|
|
92
|
+
Use the `context-note` attribute to add text that provides additional context or reference. For text that contains HTML, use the `context-note` slot. **Note:** On small screens the context note will wrap below the label if there isn't enough room next to the label.
|
|
124
93
|
|
|
125
94
|
:::tip
|
|
126
|
-
**Usage:** Use a **context note** to provide secondary contextual data, especially dynamic data, that would help people
|
|
127
|
-
when choosing an option. Use **help text** to communicate instructions or requirements for choosing an option without
|
|
128
|
-
errors.
|
|
95
|
+
**Usage:** Use a **context note** to provide secondary contextual data, especially dynamic data, that would help people when choosing an option. Use **help text** to communicate instructions or requirements for choosing an option without errors.
|
|
129
96
|
:::
|
|
130
97
|
|
|
131
98
|
```html:preview
|
|
@@ -155,8 +122,7 @@ Use the `placeholder` attribute to add a placeholder.
|
|
|
155
122
|
Use the `clearable` attribute to make the control clearable. The clear button only appears when an option is selected.
|
|
156
123
|
|
|
157
124
|
:::tip
|
|
158
|
-
**Usage:** Add a clear button only when **multiple** options can be selected. For the default single-choice use case (
|
|
159
|
-
the most common for selects), include an empty option that people can select to "clear" the current selection.
|
|
125
|
+
**Usage:** Add a clear button only when **multiple** options can be selected. For the default single-choice use case (the most common for selects), include an empty option that people can select to "clear" the current selection.
|
|
160
126
|
:::
|
|
161
127
|
|
|
162
128
|
```html:preview
|
|
@@ -180,39 +146,322 @@ the most common for selects), include an empty option that people can select to
|
|
|
180
146
|
</zn-select>
|
|
181
147
|
```
|
|
182
148
|
|
|
183
|
-
###
|
|
149
|
+
### Search
|
|
184
150
|
|
|
185
|
-
Use the `
|
|
186
|
-
|
|
187
|
-
:::warning
|
|
188
|
-
**Note:** Pill-shaped selects are not a standard pattern in our Design System, and there is no Figma component for this
|
|
189
|
-
option. Please check with the design team before using this option.
|
|
190
|
-
:::
|
|
151
|
+
Use the `search` attribute to allow users to type into the select to filter the list of options. When the dropdown opens, the input becomes editable and options are filtered as you type using case-insensitive substring matching against labels and values.
|
|
191
152
|
|
|
192
153
|
```html:preview
|
|
193
|
-
<zn-select label="
|
|
194
|
-
<zn-option value="
|
|
195
|
-
<zn-option value="
|
|
196
|
-
<zn-option value="
|
|
197
|
-
<zn-option value="
|
|
198
|
-
<zn-option value="
|
|
199
|
-
<zn-option value="
|
|
154
|
+
<zn-select label="Search for a country" search placeholder="Type to search...">
|
|
155
|
+
<zn-option value="au">Australia</zn-option>
|
|
156
|
+
<zn-option value="br">Brazil</zn-option>
|
|
157
|
+
<zn-option value="ca">Canada</zn-option>
|
|
158
|
+
<zn-option value="cn">China</zn-option>
|
|
159
|
+
<zn-option value="fr">France</zn-option>
|
|
160
|
+
<zn-option value="de">Germany</zn-option>
|
|
161
|
+
<zn-option value="in">India</zn-option>
|
|
162
|
+
<zn-option value="jp">Japan</zn-option>
|
|
163
|
+
<zn-option value="mx">Mexico</zn-option>
|
|
164
|
+
<zn-option value="uk">United Kingdom</zn-option>
|
|
165
|
+
<zn-option value="us">United States</zn-option>
|
|
200
166
|
</zn-select>
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Search with Multiple Selection
|
|
170
|
+
|
|
171
|
+
Combine `search` with `multiple` to allow users to search and select multiple options. The search clears automatically after each selection so you can continue searching.
|
|
172
|
+
|
|
173
|
+
```html:preview
|
|
174
|
+
<zn-select label="Select your skills" search multiple clearable placeholder="Search skills...">
|
|
175
|
+
<zn-option value="html">HTML</zn-option>
|
|
176
|
+
<zn-option value="css">CSS</zn-option>
|
|
177
|
+
<zn-option value="js">JavaScript</zn-option>
|
|
178
|
+
<zn-option value="ts">TypeScript</zn-option>
|
|
179
|
+
<zn-option value="react">React</zn-option>
|
|
180
|
+
<zn-option value="vue">Vue</zn-option>
|
|
181
|
+
<zn-option value="angular">Angular</zn-option>
|
|
182
|
+
<zn-option value="node">Node.js</zn-option>
|
|
183
|
+
<zn-option value="python">Python</zn-option>
|
|
184
|
+
<zn-option value="go">Go</zn-option>
|
|
209
185
|
</zn-select>
|
|
210
186
|
```
|
|
211
187
|
|
|
188
|
+
### Remote Search
|
|
189
|
+
|
|
190
|
+
When `search` and `data-uri` are used together, typing in the select sends debounced requests to the server instead of filtering locally. The search term is appended as a query parameter (default `q`). Use `search-param` to customise the parameter name, `search-debounce` to control the delay, and `max-results` to cap displayed results.
|
|
191
|
+
|
|
192
|
+
If the server returns fewer results than `max-results`, further refinements of the same query are filtered client-side automatically — no extra requests are made. When results are truncated, a message at the bottom of the dropdown shows how many results are displayed out of the total, prompting the user to refine their search.
|
|
193
|
+
|
|
194
|
+
```html:preview
|
|
195
|
+
<div class="remote-search-demo">
|
|
196
|
+
<zn-select
|
|
197
|
+
id="remote-search-example"
|
|
198
|
+
label="Search users"
|
|
199
|
+
search
|
|
200
|
+
search-debounce="300"
|
|
201
|
+
max-results="5"
|
|
202
|
+
placeholder="Type a name to search..."
|
|
203
|
+
help-text="Try typing 'a' then narrowing to 'al' — the second query filters locally."
|
|
204
|
+
></zn-select>
|
|
205
|
+
|
|
206
|
+
<div id="remote-search-log" style="margin-top: 1rem; padding: 0.75rem 1rem; background: var(--zn-color-neutral-100); border-radius: var(--zn-border-radius-medium); font-family: var(--zn-font-mono); font-size: var(--zn-font-size-small); max-height: 8rem; overflow-y: auto;">
|
|
207
|
+
<strong>Request log:</strong>
|
|
208
|
+
</div>
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
<script type="module">
|
|
212
|
+
// -- Mock user database --
|
|
213
|
+
const allUsers = [
|
|
214
|
+
{ key: 'alice', value: 'Alice Johnson' },
|
|
215
|
+
{ key: 'alex', value: 'Alex Thompson' },
|
|
216
|
+
{ key: 'amanda', value: 'Amanda Garcia' },
|
|
217
|
+
{ key: 'bob', value: 'Bob Williams' },
|
|
218
|
+
{ key: 'beth', value: 'Beth Davis' },
|
|
219
|
+
{ key: 'charlie', value: 'Charlie Brown' },
|
|
220
|
+
{ key: 'carol', value: 'Carol Martinez' },
|
|
221
|
+
{ key: 'david', value: 'David Lee' },
|
|
222
|
+
{ key: 'diana', value: 'Diana Wilson' },
|
|
223
|
+
{ key: 'emma', value: 'Emma Taylor' },
|
|
224
|
+
{ key: 'elena', value: 'Elena Rodriguez' },
|
|
225
|
+
{ key: 'frank', value: 'Frank Anderson' },
|
|
226
|
+
{ key: 'fiona', value: 'Fiona Clark' },
|
|
227
|
+
{ key: 'george', value: 'George Hall' },
|
|
228
|
+
{ key: 'grace', value: 'Grace Lewis' },
|
|
229
|
+
];
|
|
230
|
+
|
|
231
|
+
// -- Intercept fetch for the demo endpoint --
|
|
232
|
+
const realFetch = window.fetch;
|
|
233
|
+
const DEMO_URL = '/_demo/api/users';
|
|
234
|
+
const log = document.getElementById('remote-search-log');
|
|
235
|
+
|
|
236
|
+
window.fetch = function(url, opts) {
|
|
237
|
+
const urlStr = typeof url === 'string' ? url : url.toString();
|
|
238
|
+
if (!urlStr.startsWith(DEMO_URL)) {
|
|
239
|
+
return realFetch.call(this, url, opts);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const params = new URL(urlStr, location.origin).searchParams;
|
|
243
|
+
const q = (params.get('q') || '').toLowerCase();
|
|
244
|
+
const time = new Date().toLocaleTimeString();
|
|
245
|
+
log.innerHTML += `<br>[${time}] GET ${urlStr.replace(location.origin, '')}`;
|
|
246
|
+
log.scrollTop = log.scrollHeight;
|
|
247
|
+
|
|
248
|
+
// Simulate network latency
|
|
249
|
+
return new Promise(resolve => {
|
|
250
|
+
setTimeout(() => {
|
|
251
|
+
const filtered = allUsers.filter(u =>
|
|
252
|
+
u.value.toLowerCase().includes(q) || u.key.includes(q)
|
|
253
|
+
);
|
|
254
|
+
resolve(new Response(JSON.stringify(filtered), {
|
|
255
|
+
status: 200,
|
|
256
|
+
headers: { 'Content-Type': 'application/json' }
|
|
257
|
+
}));
|
|
258
|
+
}, 200 + Math.random() * 300);
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// Wire up the select
|
|
263
|
+
document.getElementById('remote-search-example').setAttribute('data-uri', DEMO_URL);
|
|
264
|
+
</script>
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Remote Search with Custom Parameter
|
|
268
|
+
|
|
269
|
+
Use `search-param` to change the query parameter name sent to the server.
|
|
270
|
+
|
|
271
|
+
```html:preview
|
|
272
|
+
<zn-select
|
|
273
|
+
id="custom-param-example"
|
|
274
|
+
label="Search products"
|
|
275
|
+
search
|
|
276
|
+
search-param="filter"
|
|
277
|
+
search-debounce="500"
|
|
278
|
+
placeholder="Search with custom param..."
|
|
279
|
+
help-text='Sends requests like /api?filter=term instead of /api?q=term'
|
|
280
|
+
></zn-select>
|
|
281
|
+
|
|
282
|
+
<script type="module">
|
|
283
|
+
const products = [
|
|
284
|
+
{ key: 'laptop', value: 'Laptop' },
|
|
285
|
+
{ key: 'phone', value: 'Phone' },
|
|
286
|
+
{ key: 'tablet', value: 'Tablet' },
|
|
287
|
+
{ key: 'monitor', value: 'Monitor' },
|
|
288
|
+
{ key: 'keyboard', value: 'Keyboard' },
|
|
289
|
+
{ key: 'mouse', value: 'Mouse' },
|
|
290
|
+
{ key: 'headset', value: 'Headset' },
|
|
291
|
+
{ key: 'webcam', value: 'Webcam' },
|
|
292
|
+
];
|
|
293
|
+
|
|
294
|
+
const realFetch = window.fetch;
|
|
295
|
+
const DEMO_URL = '/_demo/api/products';
|
|
296
|
+
|
|
297
|
+
window.fetch = function(url, opts) {
|
|
298
|
+
const urlStr = typeof url === 'string' ? url : url.toString();
|
|
299
|
+
if (!urlStr.startsWith(DEMO_URL)) {
|
|
300
|
+
return realFetch.call(this, url, opts);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const params = new URL(urlStr, location.origin).searchParams;
|
|
304
|
+
const q = (params.get('filter') || '').toLowerCase();
|
|
305
|
+
|
|
306
|
+
return new Promise(resolve => {
|
|
307
|
+
setTimeout(() => {
|
|
308
|
+
const filtered = products.filter(p =>
|
|
309
|
+
p.value.toLowerCase().includes(q) || p.key.includes(q)
|
|
310
|
+
);
|
|
311
|
+
resolve(new Response(JSON.stringify(filtered), {
|
|
312
|
+
status: 200,
|
|
313
|
+
headers: { 'Content-Type': 'application/json' }
|
|
314
|
+
}));
|
|
315
|
+
}, 150 + Math.random() * 200);
|
|
316
|
+
});
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
document.getElementById('custom-param-example').setAttribute('data-uri', DEMO_URL);
|
|
320
|
+
</script>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Remote Search with Multiple Selection
|
|
324
|
+
|
|
325
|
+
Combine remote search with `multiple` to search and pick several results.
|
|
326
|
+
|
|
327
|
+
```html:preview
|
|
328
|
+
<div class="remote-search-multi-demo">
|
|
329
|
+
<zn-select
|
|
330
|
+
id="remote-search-multi"
|
|
331
|
+
label="Assign team members"
|
|
332
|
+
search
|
|
333
|
+
multiple
|
|
334
|
+
clearable
|
|
335
|
+
search-debounce="300"
|
|
336
|
+
max-results="8"
|
|
337
|
+
max-options-visible="3"
|
|
338
|
+
placeholder="Search team members..."
|
|
339
|
+
></zn-select>
|
|
340
|
+
</div>
|
|
341
|
+
|
|
342
|
+
<script type="module">
|
|
343
|
+
const allUsers = [
|
|
344
|
+
{ key: 'alice', value: 'Alice Johnson' },
|
|
345
|
+
{ key: 'alex', value: 'Alex Thompson' },
|
|
346
|
+
{ key: 'amanda', value: 'Amanda Garcia' },
|
|
347
|
+
{ key: 'bob', value: 'Bob Williams' },
|
|
348
|
+
{ key: 'beth', value: 'Beth Davis' },
|
|
349
|
+
{ key: 'charlie', value: 'Charlie Brown' },
|
|
350
|
+
{ key: 'carol', value: 'Carol Martinez' },
|
|
351
|
+
{ key: 'david', value: 'David Lee' },
|
|
352
|
+
{ key: 'diana', value: 'Diana Wilson' },
|
|
353
|
+
{ key: 'emma', value: 'Emma Taylor' },
|
|
354
|
+
];
|
|
355
|
+
|
|
356
|
+
const realFetch = window.fetch;
|
|
357
|
+
const DEMO_URL = '/_demo/api/team';
|
|
358
|
+
|
|
359
|
+
window.fetch = function(url, opts) {
|
|
360
|
+
const urlStr = typeof url === 'string' ? url : url.toString();
|
|
361
|
+
if (!urlStr.startsWith(DEMO_URL)) {
|
|
362
|
+
return realFetch.call(this, url, opts);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const q = new URL(urlStr, location.origin).searchParams.get('q') || '';
|
|
366
|
+
return new Promise(resolve => {
|
|
367
|
+
setTimeout(() => {
|
|
368
|
+
const filtered = allUsers.filter(u =>
|
|
369
|
+
u.value.toLowerCase().includes(q.toLowerCase()) || u.key.includes(q.toLowerCase())
|
|
370
|
+
);
|
|
371
|
+
resolve(new Response(JSON.stringify(filtered), {
|
|
372
|
+
status: 200,
|
|
373
|
+
headers: { 'Content-Type': 'application/json' }
|
|
374
|
+
}));
|
|
375
|
+
}, 150 + Math.random() * 200);
|
|
376
|
+
});
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
document.getElementById('remote-search-multi').setAttribute('data-uri', DEMO_URL);
|
|
380
|
+
</script>
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Search Only (No Initial Load)
|
|
384
|
+
|
|
385
|
+
Use `search-only` with `search` and `data-uri` to defer all fetching until the user types. No request is made on page load — the dropdown shows a "Type to search..." prompt until a query is entered. This is ideal for large datasets where preloading all options isn't practical.
|
|
386
|
+
|
|
387
|
+
```html:preview
|
|
388
|
+
<div class="search-only-demo">
|
|
389
|
+
<zn-select
|
|
390
|
+
id="search-only-example"
|
|
391
|
+
label="Find a city"
|
|
392
|
+
search
|
|
393
|
+
search-only
|
|
394
|
+
search-debounce="300"
|
|
395
|
+
max-results="10"
|
|
396
|
+
placeholder="Start typing a city name..."
|
|
397
|
+
></zn-select>
|
|
398
|
+
|
|
399
|
+
<div id="search-only-log" style="margin-top: 1rem; padding: 0.75rem 1rem; background: var(--zn-color-neutral-100); border-radius: var(--zn-border-radius-medium); font-family: var(--zn-font-mono); font-size: var(--zn-font-size-small); max-height: 8rem; overflow-y: auto;">
|
|
400
|
+
<strong>Request log:</strong>
|
|
401
|
+
</div>
|
|
402
|
+
</div>
|
|
403
|
+
|
|
404
|
+
<script type="module">
|
|
405
|
+
const cities = [
|
|
406
|
+
{ key: 'london', value: 'London' },
|
|
407
|
+
{ key: 'los-angeles', value: 'Los Angeles' },
|
|
408
|
+
{ key: 'lisbon', value: 'Lisbon' },
|
|
409
|
+
{ key: 'lima', value: 'Lima' },
|
|
410
|
+
{ key: 'lagos', value: 'Lagos' },
|
|
411
|
+
{ key: 'lyon', value: 'Lyon' },
|
|
412
|
+
{ key: 'new-york', value: 'New York' },
|
|
413
|
+
{ key: 'nairobi', value: 'Nairobi' },
|
|
414
|
+
{ key: 'nice', value: 'Nice' },
|
|
415
|
+
{ key: 'paris', value: 'Paris' },
|
|
416
|
+
{ key: 'prague', value: 'Prague' },
|
|
417
|
+
{ key: 'porto', value: 'Porto' },
|
|
418
|
+
{ key: 'perth', value: 'Perth' },
|
|
419
|
+
{ key: 'sydney', value: 'Sydney' },
|
|
420
|
+
{ key: 'seoul', value: 'Seoul' },
|
|
421
|
+
{ key: 'shanghai', value: 'Shanghai' },
|
|
422
|
+
{ key: 'singapore', value: 'Singapore' },
|
|
423
|
+
{ key: 'stockholm', value: 'Stockholm' },
|
|
424
|
+
{ key: 'tokyo', value: 'Tokyo' },
|
|
425
|
+
{ key: 'toronto', value: 'Toronto' },
|
|
426
|
+
{ key: 'taipei', value: 'Taipei' },
|
|
427
|
+
];
|
|
428
|
+
|
|
429
|
+
const realFetch = window.fetch;
|
|
430
|
+
const DEMO_URL = '/_demo/api/cities';
|
|
431
|
+
const log = document.getElementById('search-only-log');
|
|
432
|
+
|
|
433
|
+
window.fetch = function(url, opts) {
|
|
434
|
+
const urlStr = typeof url === 'string' ? url : url.toString();
|
|
435
|
+
if (!urlStr.startsWith(DEMO_URL)) {
|
|
436
|
+
return realFetch.call(this, url, opts);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const params = new URL(urlStr, location.origin).searchParams;
|
|
440
|
+
const q = (params.get('q') || '').toLowerCase();
|
|
441
|
+
const time = new Date().toLocaleTimeString();
|
|
442
|
+
log.innerHTML += `<br>[${time}] GET ...?q=${q}`;
|
|
443
|
+
log.scrollTop = log.scrollHeight;
|
|
444
|
+
|
|
445
|
+
return new Promise(resolve => {
|
|
446
|
+
setTimeout(() => {
|
|
447
|
+
const filtered = cities.filter(c =>
|
|
448
|
+
c.value.toLowerCase().includes(q) || c.key.includes(q)
|
|
449
|
+
);
|
|
450
|
+
resolve(new Response(JSON.stringify(filtered), {
|
|
451
|
+
status: 200,
|
|
452
|
+
headers: { 'Content-Type': 'application/json' }
|
|
453
|
+
}));
|
|
454
|
+
}, 200 + Math.random() * 300);
|
|
455
|
+
});
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
document.getElementById('search-only-example').setAttribute('data-uri', DEMO_URL);
|
|
459
|
+
</script>
|
|
460
|
+
```
|
|
461
|
+
|
|
212
462
|
### Disabled
|
|
213
463
|
|
|
214
|
-
Use the `disabled` attribute to disable the entire select. To disable just one option, put `disabled` on the
|
|
215
|
-
`zn-option`.
|
|
464
|
+
Use the `disabled` attribute to disable the entire select. To disable just one option, put `disabled` on the `zn-option`.
|
|
216
465
|
|
|
217
466
|
```html:preview
|
|
218
467
|
<zn-select label="Disabled select" disabled>
|
|
@@ -235,14 +484,12 @@ Use the `disabled` attribute to disable the entire select. To disable just one o
|
|
|
235
484
|
|
|
236
485
|
```
|
|
237
486
|
|
|
238
|
-
###
|
|
487
|
+
### Sizes
|
|
239
488
|
|
|
240
|
-
|
|
241
|
-
the `clearable` attribute to display a clear button. To set multiple values at once, set `value` to a space-delimited
|
|
242
|
-
list of values.
|
|
489
|
+
Use the `size` attribute to change a select's size. Note that size does not apply to listbox options. Size `medium` is the selects default.
|
|
243
490
|
|
|
244
491
|
```html:preview
|
|
245
|
-
<zn-select label="
|
|
492
|
+
<zn-select label="Medium input">
|
|
246
493
|
<zn-option value="option-1">Option 1</zn-option>
|
|
247
494
|
<zn-option value="option-2">Option 2</zn-option>
|
|
248
495
|
<zn-option value="option-3">Option 3</zn-option>
|
|
@@ -250,19 +497,8 @@ list of values.
|
|
|
250
497
|
<zn-option value="option-5">Option 5</zn-option>
|
|
251
498
|
<zn-option value="option-6">Option 6</zn-option>
|
|
252
499
|
</zn-select>
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
:::tip
|
|
256
|
-
Note that multi-select options may wrap, causing the control to expand vertically. You can use the `max-options-visible`
|
|
257
|
-
attribute to control the maximum number of selected options to show at once.
|
|
258
|
-
:::
|
|
259
|
-
|
|
260
|
-
### Multiple with a limit
|
|
261
|
-
|
|
262
|
-
To limit the number of options that can be selected, use the `max-options` attribute.
|
|
263
|
-
|
|
264
|
-
```html:preview
|
|
265
|
-
<zn-select label="Select one or more" value="option-1 option-2" multiple clearable max-options="3">
|
|
500
|
+
<br />
|
|
501
|
+
<zn-select label="Medium input" size="medium">
|
|
266
502
|
<zn-option value="option-1">Option 1</zn-option>
|
|
267
503
|
<zn-option value="option-2">Option 2</zn-option>
|
|
268
504
|
<zn-option value="option-3">Option 3</zn-option>
|
|
@@ -270,56 +506,51 @@ To limit the number of options that can be selected, use the `max-options` attri
|
|
|
270
506
|
<zn-option value="option-5">Option 5</zn-option>
|
|
271
507
|
<zn-option value="option-6">Option 6</zn-option>
|
|
272
508
|
</zn-select>
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
### Setting Initial Values
|
|
276
|
-
|
|
277
|
-
Use the `value` attribute to set the initial selection.
|
|
278
|
-
|
|
279
|
-
When using `multiple`, the `value` _attribute_ uses space-delimited values to select more than one option. Because of
|
|
280
|
-
this, `<zn-option>` values cannot contain spaces. If you're accessing the `value` _property_ through Javascript, it will
|
|
281
|
-
be an array.
|
|
282
|
-
|
|
283
|
-
```html:preview
|
|
284
|
-
<zn-select label="Select one or more" value="option-1 option-2" multiple clearable>
|
|
509
|
+
<br />
|
|
510
|
+
<zn-select label="Large input" size="large">
|
|
285
511
|
<zn-option value="option-1">Option 1</zn-option>
|
|
286
512
|
<zn-option value="option-2">Option 2</zn-option>
|
|
287
513
|
<zn-option value="option-3">Option 3</zn-option>
|
|
288
514
|
<zn-option value="option-4">Option 4</zn-option>
|
|
515
|
+
<zn-option value="option-5">Option 5</zn-option>
|
|
516
|
+
<zn-option value="option-6">Option 6</zn-option>
|
|
289
517
|
</zn-select>
|
|
290
518
|
```
|
|
291
519
|
|
|
292
|
-
###
|
|
520
|
+
### Pill
|
|
293
521
|
|
|
294
|
-
Use
|
|
295
|
-
they won't be announced by most assistive devices.
|
|
522
|
+
Use the `pill` attribute to give selects rounded edges.
|
|
296
523
|
|
|
297
524
|
:::warning
|
|
298
|
-
**Note:**
|
|
525
|
+
**Note:** Pill-shaped selects are not a standard pattern in our Design System, and there is no Figma component for this option. Please check with the design team before using this option.
|
|
299
526
|
:::
|
|
300
527
|
|
|
301
528
|
```html:preview
|
|
302
|
-
<zn-select label="
|
|
303
|
-
<zn-option value=""
|
|
304
|
-
<
|
|
529
|
+
<zn-select label="Medium pill" pill>
|
|
530
|
+
<zn-option value="option-1">Option 1</zn-option>
|
|
531
|
+
<zn-option value="option-2">Option 2</zn-option>
|
|
532
|
+
<zn-option value="option-3">Option 3</zn-option>
|
|
533
|
+
<zn-option value="option-4">Option 4</zn-option>
|
|
534
|
+
<zn-option value="option-5">Option 5</zn-option>
|
|
535
|
+
<zn-option value="option-6">Option 6</zn-option>
|
|
536
|
+
</zn-select>
|
|
537
|
+
<br />
|
|
538
|
+
<zn-select label="Large pill" size="large" pill>
|
|
305
539
|
<zn-option value="option-1">Option 1</zn-option>
|
|
306
540
|
<zn-option value="option-2">Option 2</zn-option>
|
|
307
541
|
<zn-option value="option-3">Option 3</zn-option>
|
|
308
|
-
<zn-divider></zn-divider>
|
|
309
|
-
<small>Section 2</small>
|
|
310
542
|
<zn-option value="option-4">Option 4</zn-option>
|
|
311
543
|
<zn-option value="option-5">Option 5</zn-option>
|
|
312
544
|
<zn-option value="option-6">Option 6</zn-option>
|
|
313
545
|
</zn-select>
|
|
314
546
|
```
|
|
315
547
|
|
|
316
|
-
###
|
|
548
|
+
### Multiple Selection
|
|
317
549
|
|
|
318
|
-
|
|
319
|
-
the selects default.
|
|
550
|
+
To allow multiple options to be selected, use the `multiple` attribute. When this option is enabled, be sure to also add the `clearable` attribute to display a clear button. To set multiple values at once, set `value` to a space-delimited list of values.
|
|
320
551
|
|
|
321
552
|
```html:preview
|
|
322
|
-
<zn-select label="
|
|
553
|
+
<zn-select label="Select one or more" value="option-1 option-2 option-3" multiple clearable>
|
|
323
554
|
<zn-option value="option-1">Option 1</zn-option>
|
|
324
555
|
<zn-option value="option-2">Option 2</zn-option>
|
|
325
556
|
<zn-option value="option-3">Option 3</zn-option>
|
|
@@ -327,8 +558,18 @@ the selects default.
|
|
|
327
558
|
<zn-option value="option-5">Option 5</zn-option>
|
|
328
559
|
<zn-option value="option-6">Option 6</zn-option>
|
|
329
560
|
</zn-select>
|
|
330
|
-
|
|
331
|
-
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
:::tip
|
|
564
|
+
Note that multi-select options may wrap, causing the control to expand vertically. You can use the `max-options-visible` attribute to control the maximum number of selected options to show at once.
|
|
565
|
+
:::
|
|
566
|
+
|
|
567
|
+
### Multiple with Limit
|
|
568
|
+
|
|
569
|
+
To limit the number of options that can be selected, use the `max-options` attribute.
|
|
570
|
+
|
|
571
|
+
```html:preview
|
|
572
|
+
<zn-select label="Select up to 3 options" value="option-1 option-2" multiple clearable max-options="3">
|
|
332
573
|
<zn-option value="option-1">Option 1</zn-option>
|
|
333
574
|
<zn-option value="option-2">Option 2</zn-option>
|
|
334
575
|
<zn-option value="option-3">Option 3</zn-option>
|
|
@@ -336,8 +577,14 @@ the selects default.
|
|
|
336
577
|
<zn-option value="option-5">Option 5</zn-option>
|
|
337
578
|
<zn-option value="option-6">Option 6</zn-option>
|
|
338
579
|
</zn-select>
|
|
339
|
-
|
|
340
|
-
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
### Maximum Visible Options
|
|
583
|
+
|
|
584
|
+
When using `multiple`, you can control how many selected options are displayed before showing a "+n" indicator using the `max-options-visible` attribute. Set to 0 to remove the limit.
|
|
585
|
+
|
|
586
|
+
```html:preview
|
|
587
|
+
<zn-select label="Show max 2 options" value="option-1 option-2 option-3 option-4" multiple clearable max-options-visible="2">
|
|
341
588
|
<zn-option value="option-1">Option 1</zn-option>
|
|
342
589
|
<zn-option value="option-2">Option 2</zn-option>
|
|
343
590
|
<zn-option value="option-3">Option 3</zn-option>
|
|
@@ -347,13 +594,90 @@ the selects default.
|
|
|
347
594
|
</zn-select>
|
|
348
595
|
```
|
|
349
596
|
|
|
597
|
+
### Grouping Options
|
|
598
|
+
|
|
599
|
+
Use `<zn-opt-group>` to group options under labeled headers, similar to `<optgroup>` in native HTML. Each group displays a non-selectable label above its options. Groups are also accessible, using `role="group"` and `aria-label`.
|
|
600
|
+
|
|
601
|
+
```html:preview
|
|
602
|
+
<zn-select label="Select a fruit">
|
|
603
|
+
<zn-opt-group label="Citrus">
|
|
604
|
+
<zn-option value="orange">Orange</zn-option>
|
|
605
|
+
<zn-option value="lemon">Lemon</zn-option>
|
|
606
|
+
<zn-option value="lime">Lime</zn-option>
|
|
607
|
+
</zn-opt-group>
|
|
608
|
+
<zn-opt-group label="Berries">
|
|
609
|
+
<zn-option value="strawberry">Strawberry</zn-option>
|
|
610
|
+
<zn-option value="blueberry">Blueberry</zn-option>
|
|
611
|
+
<zn-option value="raspberry">Raspberry</zn-option>
|
|
612
|
+
</zn-opt-group>
|
|
613
|
+
</zn-select>
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
### Grouping with Search
|
|
617
|
+
|
|
618
|
+
When `search` is enabled, group headers automatically hide when all of their child options are filtered out.
|
|
619
|
+
|
|
620
|
+
```html:preview
|
|
621
|
+
<zn-select label="Select a country" search placeholder="Type to search...">
|
|
622
|
+
<zn-opt-group label="North America">
|
|
623
|
+
<zn-option value="us">United States</zn-option>
|
|
624
|
+
<zn-option value="ca">Canada</zn-option>
|
|
625
|
+
<zn-option value="mx">Mexico</zn-option>
|
|
626
|
+
</zn-opt-group>
|
|
627
|
+
<zn-opt-group label="Europe">
|
|
628
|
+
<zn-option value="gb">United Kingdom</zn-option>
|
|
629
|
+
<zn-option value="de">Germany</zn-option>
|
|
630
|
+
<zn-option value="fr">France</zn-option>
|
|
631
|
+
</zn-opt-group>
|
|
632
|
+
<zn-opt-group label="Asia">
|
|
633
|
+
<zn-option value="jp">Japan</zn-option>
|
|
634
|
+
<zn-option value="cn">China</zn-option>
|
|
635
|
+
<zn-option value="in">India</zn-option>
|
|
636
|
+
</zn-opt-group>
|
|
637
|
+
</zn-select>
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
### Disabled Groups
|
|
641
|
+
|
|
642
|
+
Use the `disabled` attribute on `<zn-opt-group>` to disable all options within a group.
|
|
643
|
+
|
|
644
|
+
```html:preview
|
|
645
|
+
<zn-select label="Select a plan">
|
|
646
|
+
<zn-opt-group label="Available">
|
|
647
|
+
<zn-option value="basic">Basic</zn-option>
|
|
648
|
+
<zn-option value="pro">Pro</zn-option>
|
|
649
|
+
</zn-opt-group>
|
|
650
|
+
<zn-opt-group label="Coming Soon" disabled>
|
|
651
|
+
<zn-option value="enterprise">Enterprise</zn-option>
|
|
652
|
+
<zn-option value="unlimited">Unlimited</zn-option>
|
|
653
|
+
</zn-opt-group>
|
|
654
|
+
</zn-select>
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
### Mixed Grouped and Ungrouped Options
|
|
658
|
+
|
|
659
|
+
You can mix ungrouped options alongside `<zn-opt-group>` elements.
|
|
660
|
+
|
|
661
|
+
```html:preview
|
|
662
|
+
<zn-select label="Select an option">
|
|
663
|
+
<zn-option value="none">None</zn-option>
|
|
664
|
+
<zn-opt-group label="Group A">
|
|
665
|
+
<zn-option value="a1">Option A1</zn-option>
|
|
666
|
+
<zn-option value="a2">Option A2</zn-option>
|
|
667
|
+
</zn-opt-group>
|
|
668
|
+
<zn-opt-group label="Group B">
|
|
669
|
+
<zn-option value="b1">Option B1</zn-option>
|
|
670
|
+
<zn-option value="b2">Option B2</zn-option>
|
|
671
|
+
</zn-opt-group>
|
|
672
|
+
</zn-select>
|
|
673
|
+
```
|
|
674
|
+
|
|
350
675
|
### Placement
|
|
351
676
|
|
|
352
|
-
The preferred placement of the select's listbox can be set with the `placement` attribute. Note that the actual position
|
|
353
|
-
may vary to ensure the panel remains in the viewport. Valid placements are `top` and `bottom`.
|
|
677
|
+
The preferred placement of the select's listbox can be set with the `placement` attribute. Note that the actual position may vary to ensure the panel remains in the viewport. Valid placements are `top` and `bottom`.
|
|
354
678
|
|
|
355
679
|
```html:preview
|
|
356
|
-
<zn-select label="Select an option" placement="top" help-text="This select
|
|
680
|
+
<zn-select label="Select an option" placement="top" help-text="This select's panel of options will try to open on top first if there is room">
|
|
357
681
|
<zn-option value="option-1">Option 1</zn-option>
|
|
358
682
|
<zn-option value="option-2">Option 2</zn-option>
|
|
359
683
|
<zn-option value="option-3">Option 3</zn-option>
|
|
@@ -363,6 +687,23 @@ may vary to ensure the panel remains in the viewport. Valid placements are `top`
|
|
|
363
687
|
</zn-select>
|
|
364
688
|
```
|
|
365
689
|
|
|
690
|
+
### Hoisting
|
|
691
|
+
|
|
692
|
+
Enable this option to prevent the listbox from being clipped when the component is placed inside a container with `overflow: auto|scroll`. Hoisting uses a fixed positioning strategy that works in many, but not all, scenarios.
|
|
693
|
+
|
|
694
|
+
```html:preview
|
|
695
|
+
<div style="overflow: auto; height: 150px; border: 1px solid var(--zn-color-neutral-200); padding: 1rem;">
|
|
696
|
+
<zn-select label="With hoisting enabled" hoist>
|
|
697
|
+
<zn-option value="option-1">Option 1</zn-option>
|
|
698
|
+
<zn-option value="option-2">Option 2</zn-option>
|
|
699
|
+
<zn-option value="option-3">Option 3</zn-option>
|
|
700
|
+
<zn-option value="option-4">Option 4</zn-option>
|
|
701
|
+
<zn-option value="option-5">Option 5</zn-option>
|
|
702
|
+
<zn-option value="option-6">Option 6</zn-option>
|
|
703
|
+
</zn-select>
|
|
704
|
+
</div>
|
|
705
|
+
```
|
|
706
|
+
|
|
366
707
|
### Prefix Icons
|
|
367
708
|
|
|
368
709
|
Use the `prefix` slot to prepend an icon to the select.
|
|
@@ -376,12 +717,10 @@ Follow these general guidelines when adding prefix icons to the select:
|
|
|
376
717
|
- In general **don't** resize icons or change their color from the default already set by the `zn-select` component
|
|
377
718
|
|
|
378
719
|
:::warning
|
|
379
|
-
**Note:** If you find your use case requires a different size or color from the default, bring it up to the Design Team
|
|
380
|
-
so that we can consider whether the pattern needs to be updated.
|
|
720
|
+
**Note:** If you find your use case requires a different size or color from the default, bring it up to the Design Team so that we can consider whether the pattern needs to be updated.
|
|
381
721
|
:::
|
|
382
722
|
:::warning
|
|
383
|
-
**Note:** `ts_form_for` doesn't support slots. Prefix icons cannot be added when rendering `zn-select` with
|
|
384
|
-
`ts_form_for`.
|
|
723
|
+
**Note:** `ts_form_for` doesn't support slots. Prefix icons cannot be added when rendering `zn-select` with `ts_form_for`.
|
|
385
724
|
:::
|
|
386
725
|
|
|
387
726
|
```html:preview
|
|
@@ -423,8 +762,7 @@ so that we can consider whether the pattern needs to be updated.
|
|
|
423
762
|
|
|
424
763
|
### Checkbox Prefix
|
|
425
764
|
|
|
426
|
-
You can place a checkbox in the `prefix` slot to visually join it to the select. The checkbox will match the height of
|
|
427
|
-
the control and can be interacted with independently (clicking or toggling it won’t open the select).
|
|
765
|
+
You can place a checkbox in the `prefix` slot to visually join it to the select. The checkbox will match the height of the control and can be interacted with independently (clicking or toggling it won't open the select).
|
|
428
766
|
|
|
429
767
|
```html:preview
|
|
430
768
|
<zn-select label="Notify me about" help-text="Use the checkbox to enable/disable notifications; choose a channel with the select">
|
|
@@ -446,23 +784,15 @@ the control and can be interacted with independently (clicking or toggling it wo
|
|
|
446
784
|
|
|
447
785
|
### Custom Tags
|
|
448
786
|
|
|
449
|
-
When multiple options can be selected, you can provide custom tags by passing a function to the `getTag` property. Your
|
|
450
|
-
function can return a string of HTML, a <a href="https://lit.dev/docs/templates/overview/">Lit Template</a>, or an [
|
|
451
|
-
`HTMLElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement). The `getTag()` function will be called for
|
|
452
|
-
each option. The first argument is an `<zn-option>` element and the second argument is the tag's index (its position in
|
|
453
|
-
the tag list).
|
|
787
|
+
When multiple options can be selected, you can provide custom tags by passing a function to the `getTag` property. Your function can return a string of HTML, a <a href="https://lit.dev/docs/templates/overview/">Lit Template</a>, or an [`HTMLElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement). The `getTag()` function will be called for each option. The first argument is an `<zn-option>` element and the second argument is the tag's index (its position in the tag list).
|
|
454
788
|
|
|
455
|
-
Remember that custom tags are rendered in a shadow root. To style them, you can use the `style` attribute in your
|
|
456
|
-
template or you can add your own [parts](/getting-started/customizing/#css-parts) and target them with the [
|
|
457
|
-
`::part()`](https://developer.mozilla.org/en-US/docs/Web/CSS/::part) selector.
|
|
789
|
+
Remember that custom tags are rendered in a shadow root. To style them, you can use the `style` attribute in your template or you can add your own [parts](/getting-started/customizing/#css-parts) and target them with the [`::part()`](https://developer.mozilla.org/en-US/docs/Web/CSS/::part) selector.
|
|
458
790
|
|
|
459
791
|
:::warning
|
|
460
|
-
**Note:** In general, you shouldn't need to do this. If you are working on a design that requires custom styling for the
|
|
461
|
-
tag, please ensure that there's not a standard tag in the design system that would work instead.
|
|
792
|
+
**Note:** In general, you shouldn't need to do this. If you are working on a design that requires custom styling for the tag, please ensure that there's not a standard tag in the design system that would work instead.
|
|
462
793
|
:::
|
|
463
794
|
:::warning
|
|
464
|
-
**Note:** `ts_form_for` doesn't support slots. Custom tags cannot be added when rendering `zn-select` with
|
|
465
|
-
`ts_form_for`.
|
|
795
|
+
**Note:** `ts_form_for` doesn't support slots. Custom tags cannot be added when rendering `zn-select` with `ts_form_for`.
|
|
466
796
|
:::
|
|
467
797
|
|
|
468
798
|
```html:preview
|
|
@@ -506,6 +836,278 @@ tag, please ensure that there's not a standard tag in the design system that wou
|
|
|
506
836
|
```
|
|
507
837
|
|
|
508
838
|
:::warning
|
|
509
|
-
Be sure you trust the content you are outputting! Passing unsanitized user input to `getTag()` can result in XSS
|
|
510
|
-
|
|
511
|
-
|
|
839
|
+
Be sure you trust the content you are outputting! Passing unsanitized user input to `getTag()` can result in XSS vulnerabilities.
|
|
840
|
+
:::
|
|
841
|
+
|
|
842
|
+
### Form Integration
|
|
843
|
+
|
|
844
|
+
Select components work seamlessly with standard HTML forms. The select's `name` attribute determines the key in the form data.
|
|
845
|
+
|
|
846
|
+
```html:preview
|
|
847
|
+
<form id="select-form">
|
|
848
|
+
<zn-select name="favoriteColor" label="Favorite color" required>
|
|
849
|
+
<zn-option value="red">Red</zn-option>
|
|
850
|
+
<zn-option value="blue">Blue</zn-option>
|
|
851
|
+
<zn-option value="green">Green</zn-option>
|
|
852
|
+
<zn-option value="yellow">Yellow</zn-option>
|
|
853
|
+
</zn-select>
|
|
854
|
+
<br />
|
|
855
|
+
<zn-select name="hobbies" label="Hobbies" multiple clearable>
|
|
856
|
+
<zn-option value="reading">Reading</zn-option>
|
|
857
|
+
<zn-option value="gaming">Gaming</zn-option>
|
|
858
|
+
<zn-option value="cooking">Cooking</zn-option>
|
|
859
|
+
<zn-option value="sports">Sports</zn-option>
|
|
860
|
+
</zn-select>
|
|
861
|
+
<br />
|
|
862
|
+
<zn-button type="submit" variant="primary">Submit</zn-button>
|
|
863
|
+
<zn-button type="reset">Reset</zn-button>
|
|
864
|
+
</form>
|
|
865
|
+
|
|
866
|
+
<script type="module">
|
|
867
|
+
const form = document.getElementById('select-form');
|
|
868
|
+
|
|
869
|
+
form.addEventListener('submit', (e) => {
|
|
870
|
+
e.preventDefault();
|
|
871
|
+
const formData = new FormData(form);
|
|
872
|
+
const data = Object.fromEntries(formData);
|
|
873
|
+
alert('Form submitted!\n\n' + JSON.stringify(data, null, 2));
|
|
874
|
+
});
|
|
875
|
+
</script>
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
### Validation
|
|
879
|
+
|
|
880
|
+
Select components support native HTML validation attributes like `required`. The component will show validation states and messages automatically.
|
|
881
|
+
|
|
882
|
+
```html:preview
|
|
883
|
+
<form id="validation-form" class="form-spacing">
|
|
884
|
+
<zn-select name="country" label="Country" required help-text="This field is required">
|
|
885
|
+
<zn-option value=""></zn-option>
|
|
886
|
+
<zn-option value="us">United States</zn-option>
|
|
887
|
+
<zn-option value="ca">Canada</zn-option>
|
|
888
|
+
<zn-option value="uk">United Kingdom</zn-option>
|
|
889
|
+
<zn-option value="au">Australia</zn-option>
|
|
890
|
+
</zn-select>
|
|
891
|
+
|
|
892
|
+
<zn-select name="interests" label="Select at least one interest" multiple clearable required help-text="Please select at least one option">
|
|
893
|
+
<zn-option value="tech">Technology</zn-option>
|
|
894
|
+
<zn-option value="art">Art</zn-option>
|
|
895
|
+
<zn-option value="science">Science</zn-option>
|
|
896
|
+
<zn-option value="music">Music</zn-option>
|
|
897
|
+
</zn-select>
|
|
898
|
+
|
|
899
|
+
<zn-button type="submit" variant="primary">Submit</zn-button>
|
|
900
|
+
</form>
|
|
901
|
+
|
|
902
|
+
<script type="module">
|
|
903
|
+
const validationForm = document.getElementById('validation-form');
|
|
904
|
+
|
|
905
|
+
validationForm.addEventListener('submit', (e) => {
|
|
906
|
+
e.preventDefault();
|
|
907
|
+
const formData = new FormData(validationForm);
|
|
908
|
+
const data = Object.fromEntries(formData);
|
|
909
|
+
alert('Form is valid!\n\n' + JSON.stringify(data, null, 2));
|
|
910
|
+
});
|
|
911
|
+
</script>
|
|
912
|
+
```
|
|
913
|
+
|
|
914
|
+
You can also use custom validation with the `setCustomValidity()` method:
|
|
915
|
+
|
|
916
|
+
```html:preview
|
|
917
|
+
<form id="custom-validation-form">
|
|
918
|
+
<zn-select id="age-range" name="ageRange" label="Age range">
|
|
919
|
+
<zn-option value="under-18">Under 18</zn-option>
|
|
920
|
+
<zn-option value="18-25">18-25</zn-option>
|
|
921
|
+
<zn-option value="26-35">26-35</zn-option>
|
|
922
|
+
<zn-option value="over-35">Over 35</zn-option>
|
|
923
|
+
</zn-select>
|
|
924
|
+
<br />
|
|
925
|
+
<zn-button type="submit" variant="primary">Submit</zn-button>
|
|
926
|
+
</form>
|
|
927
|
+
|
|
928
|
+
<script type="module">
|
|
929
|
+
const customValidationForm = document.getElementById('custom-validation-form');
|
|
930
|
+
const ageRange = document.getElementById('age-range');
|
|
931
|
+
|
|
932
|
+
ageRange.addEventListener('zn-change', () => {
|
|
933
|
+
if (ageRange.value === 'under-18') {
|
|
934
|
+
ageRange.setCustomValidity('You must be 18 or older to continue');
|
|
935
|
+
} else {
|
|
936
|
+
ageRange.setCustomValidity('');
|
|
937
|
+
}
|
|
938
|
+
});
|
|
939
|
+
|
|
940
|
+
customValidationForm.addEventListener('submit', (e) => {
|
|
941
|
+
e.preventDefault();
|
|
942
|
+
if (customValidationForm.reportValidity()) {
|
|
943
|
+
alert('Form is valid!');
|
|
944
|
+
}
|
|
945
|
+
});
|
|
946
|
+
</script>
|
|
947
|
+
```
|
|
948
|
+
|
|
949
|
+
### Events
|
|
950
|
+
|
|
951
|
+
The select component emits several events you can listen to:
|
|
952
|
+
|
|
953
|
+
```html:preview
|
|
954
|
+
<div class="form-spacing">
|
|
955
|
+
<zn-select id="event-example" label="Select an option" multiple clearable>
|
|
956
|
+
<zn-option value="option-1">Option 1</zn-option>
|
|
957
|
+
<zn-option value="option-2">Option 2</zn-option>
|
|
958
|
+
<zn-option value="option-3">Option 3</zn-option>
|
|
959
|
+
</zn-select>
|
|
960
|
+
|
|
961
|
+
<div style="margin-top: 1rem; padding: 1rem; background: var(--zn-color-neutral-100); border-radius: 4px;">
|
|
962
|
+
<strong>Event Log:</strong>
|
|
963
|
+
<div id="event-log" style="margin-top: 0.5rem; font-family: monospace; font-size: 0.875rem;"></div>
|
|
964
|
+
</div>
|
|
965
|
+
</div>
|
|
966
|
+
|
|
967
|
+
<script type="module">
|
|
968
|
+
const select = document.getElementById('event-example');
|
|
969
|
+
const eventLog = document.getElementById('event-log');
|
|
970
|
+
|
|
971
|
+
function logEvent(eventName, detail) {
|
|
972
|
+
const time = new Date().toLocaleTimeString();
|
|
973
|
+
const message = `[${time}] ${eventName}${detail ? ': ' + JSON.stringify(detail) : ''}`;
|
|
974
|
+
eventLog.innerHTML = message + '<br>' + eventLog.innerHTML;
|
|
975
|
+
// Keep only last 5 events
|
|
976
|
+
const lines = eventLog.innerHTML.split('<br>');
|
|
977
|
+
if (lines.length > 5) {
|
|
978
|
+
eventLog.innerHTML = lines.slice(0, 5).join('<br>');
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
select.addEventListener('zn-change', (e) => logEvent('zn-change', { value: e.target.value }));
|
|
983
|
+
select.addEventListener('zn-input', (e) => logEvent('zn-input'));
|
|
984
|
+
select.addEventListener('zn-focus', (e) => logEvent('zn-focus'));
|
|
985
|
+
select.addEventListener('zn-blur', (e) => logEvent('zn-blur'));
|
|
986
|
+
select.addEventListener('zn-clear', (e) => logEvent('zn-clear'));
|
|
987
|
+
select.addEventListener('zn-show', (e) => logEvent('zn-show'));
|
|
988
|
+
select.addEventListener('zn-hide', (e) => logEvent('zn-hide'));
|
|
989
|
+
</script>
|
|
990
|
+
```
|
|
991
|
+
|
|
992
|
+
### Distinct Selects
|
|
993
|
+
|
|
994
|
+
Use the `distinct` attribute to link two selects so that selected values in one are hidden from the other. This is useful for scenarios where you want to prevent duplicate selections across multiple select controls.
|
|
995
|
+
|
|
996
|
+
```html:preview
|
|
997
|
+
<div class="form-spacing">
|
|
998
|
+
<zn-select label="First select" multiple name="country-one" id="country-one" distinct="country-two">
|
|
999
|
+
<zn-option value="option-1">Option 1</zn-option>
|
|
1000
|
+
<zn-option value="option-2">Option 2</zn-option>
|
|
1001
|
+
<zn-option value="option-3">Option 3</zn-option>
|
|
1002
|
+
<zn-option value="option-4">Option 4</zn-option>
|
|
1003
|
+
</zn-select>
|
|
1004
|
+
<zn-select label="Second select" multiple name="country-two" id="country-two" distinct="country-one">
|
|
1005
|
+
<zn-option value="option-1">Option 1</zn-option>
|
|
1006
|
+
<zn-option value="option-2">Option 2</zn-option>
|
|
1007
|
+
<zn-option value="option-3">Option 3</zn-option>
|
|
1008
|
+
<zn-option value="option-4">Option 4</zn-option>
|
|
1009
|
+
</zn-select>
|
|
1010
|
+
</div>
|
|
1011
|
+
```
|
|
1012
|
+
|
|
1013
|
+
### Conditional Selects
|
|
1014
|
+
|
|
1015
|
+
Use the `conditional` attribute to disable a select based on whether another select has a value. You can specify multiple select IDs separated by commas.
|
|
1016
|
+
|
|
1017
|
+
```html:preview
|
|
1018
|
+
<div class="form-spacing">
|
|
1019
|
+
<zn-select label="Enable/disable the second select" multiple name="conditional-one" id="conditional-one" conditional="conditional-two">
|
|
1020
|
+
<zn-option value="option-1">Option 1</zn-option>
|
|
1021
|
+
<zn-option value="option-2">Option 2</zn-option>
|
|
1022
|
+
<zn-option value="option-3">Option 3</zn-option>
|
|
1023
|
+
</zn-select>
|
|
1024
|
+
<zn-select label="This is disabled when first has value" multiple name="conditional-two" id="conditional-two" conditional="conditional-one">
|
|
1025
|
+
<zn-option value="option-1">Option 1</zn-option>
|
|
1026
|
+
<zn-option value="option-2">Option 2</zn-option>
|
|
1027
|
+
<zn-option value="option-3">Option 3</zn-option>
|
|
1028
|
+
</zn-select>
|
|
1029
|
+
</div>
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
### Programmatic Control
|
|
1033
|
+
|
|
1034
|
+
You can control the select programmatically using its methods:
|
|
1035
|
+
|
|
1036
|
+
```html:preview
|
|
1037
|
+
<div class="form-spacing">
|
|
1038
|
+
<zn-select id="programmatic-select" label="Programmatic control" multiple clearable>
|
|
1039
|
+
<zn-option value="option-1">Option 1</zn-option>
|
|
1040
|
+
<zn-option value="option-2">Option 2</zn-option>
|
|
1041
|
+
<zn-option value="option-3">Option 3</zn-option>
|
|
1042
|
+
<zn-option value="option-4">Option 4</zn-option>
|
|
1043
|
+
</zn-select>
|
|
1044
|
+
|
|
1045
|
+
<div style="margin-top: 1rem; display: flex; gap: 0.5rem; flex-wrap: wrap;">
|
|
1046
|
+
<zn-button id="show-btn" size="small">Show</zn-button>
|
|
1047
|
+
<zn-button id="hide-btn" size="small">Hide</zn-button>
|
|
1048
|
+
<zn-button id="focus-btn" size="small">Focus</zn-button>
|
|
1049
|
+
<zn-button id="set-value-btn" size="small">Set Value</zn-button>
|
|
1050
|
+
<zn-button id="check-validity-btn" size="small">Check Validity</zn-button>
|
|
1051
|
+
</div>
|
|
1052
|
+
</div>
|
|
1053
|
+
|
|
1054
|
+
<script type="module">
|
|
1055
|
+
const select = document.getElementById('programmatic-select');
|
|
1056
|
+
|
|
1057
|
+
document.getElementById('show-btn').addEventListener('click', () => select.show());
|
|
1058
|
+
document.getElementById('hide-btn').addEventListener('click', () => select.hide());
|
|
1059
|
+
document.getElementById('focus-btn').addEventListener('click', () => select.focus());
|
|
1060
|
+
document.getElementById('set-value-btn').addEventListener('click', () => {
|
|
1061
|
+
select.value = ['option-2', 'option-3'];
|
|
1062
|
+
});
|
|
1063
|
+
document.getElementById('check-validity-btn').addEventListener('click', () => {
|
|
1064
|
+
alert('Valid: ' + select.checkValidity());
|
|
1065
|
+
});
|
|
1066
|
+
</script>
|
|
1067
|
+
```
|
|
1068
|
+
|
|
1069
|
+
### Keyboard Navigation
|
|
1070
|
+
|
|
1071
|
+
The select component supports comprehensive keyboard navigation:
|
|
1072
|
+
|
|
1073
|
+
- **Tab** - Move focus to/from the select
|
|
1074
|
+
- **Enter** or **Space** - Open the dropdown (when closed) or select the current option (when open)
|
|
1075
|
+
- **Escape** - Close the dropdown
|
|
1076
|
+
- **Arrow Up/Down** - Navigate through options
|
|
1077
|
+
- **Home/End** - Jump to first/last option
|
|
1078
|
+
- **Type characters** - Jump to options starting with typed characters (type-to-select)
|
|
1079
|
+
|
|
1080
|
+
When `search` is enabled, **Space** types into the input instead of toggling the dropdown, and **Arrow Up/Down** skips filtered (hidden) options.
|
|
1081
|
+
|
|
1082
|
+
### Customizing Label Position
|
|
1083
|
+
|
|
1084
|
+
Use [CSS parts](#css-parts) to customize the way form controls are drawn. This example uses CSS grid to position the label to the left of the control.
|
|
1085
|
+
|
|
1086
|
+
```html:preview
|
|
1087
|
+
<zn-select class="label-on-left" label="Country">
|
|
1088
|
+
<zn-option value="us">United States</zn-option>
|
|
1089
|
+
<zn-option value="ca">Canada</zn-option>
|
|
1090
|
+
<zn-option value="uk">United Kingdom</zn-option>
|
|
1091
|
+
</zn-select>
|
|
1092
|
+
|
|
1093
|
+
<style>
|
|
1094
|
+
.label-on-left {
|
|
1095
|
+
--label-width: 5rem;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
.label-on-left::part(form-control) {
|
|
1099
|
+
display: grid;
|
|
1100
|
+
grid: auto / var(--label-width) 1fr;
|
|
1101
|
+
gap: var(--zn-spacing-3x-small) var(--zn-spacing-medium);
|
|
1102
|
+
align-items: center;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
.label-on-left::part(form-control-label) {
|
|
1106
|
+
text-align: right;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
.label-on-left::part(form-control-help-text) {
|
|
1110
|
+
grid-column-start: 2;
|
|
1111
|
+
}
|
|
1112
|
+
</style>
|
|
1113
|
+
```
|