@kubex/zinc 1.0.25 → 1.0.98

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.
Files changed (198) hide show
  1. package/.claude/project.md +556 -0
  2. package/.github/workflows/js_build_and_deploy.yaml +9 -10
  3. package/dist/custom-elements.json +13431 -8728
  4. package/dist/vscode.html-custom-data.json +571 -37
  5. package/dist/web-types.json +1439 -181
  6. package/dist/zn.d.ts +1642 -661
  7. package/dist/zn.min.css +1 -1
  8. package/dist/zn.min.js +1406 -891
  9. package/docs/_utilities/code-previews.cjs +10 -1
  10. package/docs/assets/scripts/docs.js +42 -18
  11. package/docs/data/data-table.json +229 -66
  12. package/docs/data/empty.json +6 -0
  13. package/docs/data/products-table.json +41 -193
  14. package/docs/pages/components/action-bar.md +121 -6
  15. package/docs/pages/components/alert.md +118 -15
  16. package/docs/pages/components/animated-button.md +299 -0
  17. package/docs/pages/components/audio-select.md +534 -0
  18. package/docs/pages/components/bulk-actions.md +79 -5
  19. package/docs/pages/components/button-group.md +235 -27
  20. package/docs/pages/components/button.md +139 -1
  21. package/docs/pages/components/chart.md +365 -9
  22. package/docs/pages/components/checkbox.md +387 -58
  23. package/docs/pages/components/chip.md +253 -33
  24. package/docs/pages/components/collapsible.md +393 -46
  25. package/docs/pages/components/cols.md +152 -30
  26. package/docs/pages/components/confirm.md +182 -16
  27. package/docs/pages/components/copy-button.md +169 -6
  28. package/docs/pages/components/data-select.md +194 -15
  29. package/docs/pages/components/data-table-filter.md +96 -5
  30. package/docs/pages/components/data-table-search.md +451 -0
  31. package/docs/pages/components/data-table-sort.md +66 -5
  32. package/docs/pages/components/data-table.md +727 -66
  33. package/docs/pages/components/datepicker.md +402 -7
  34. package/docs/pages/components/defined-label.md +120 -5
  35. package/docs/pages/components/dialog.md +339 -59
  36. package/docs/pages/components/dropdown.md +366 -11
  37. package/docs/pages/components/editor.md +604 -7
  38. package/docs/pages/components/empty-state.md +315 -16
  39. package/docs/pages/components/expanding-action.md +212 -28
  40. package/docs/pages/components/file.md +421 -12
  41. package/docs/pages/components/filter-container.md +158 -5
  42. package/docs/pages/components/filter-wrapper.md +167 -6
  43. package/docs/pages/components/form-group.md +383 -6
  44. package/docs/pages/components/hover-container.md +237 -6
  45. package/docs/pages/components/icon-picker.md +121 -0
  46. package/docs/pages/components/icon.md +454 -48
  47. package/docs/pages/components/inline-edit.md +787 -19
  48. package/docs/pages/components/input-group.md +207 -13
  49. package/docs/pages/components/input.md +194 -0
  50. package/docs/pages/components/key-container.md +115 -0
  51. package/docs/pages/components/key.md +101 -0
  52. package/docs/pages/components/menu.md +512 -6
  53. package/docs/pages/components/note.md +239 -36
  54. package/docs/pages/components/opt-group.md +107 -0
  55. package/docs/pages/components/pagination.md +332 -6
  56. package/docs/pages/components/pane.md +222 -6
  57. package/docs/pages/components/panel.md +213 -26
  58. package/docs/pages/components/popup.md +1354 -6
  59. package/docs/pages/components/priority-list.md +233 -0
  60. package/docs/pages/components/progress-bar.md +387 -6
  61. package/docs/pages/components/radio-group.md +242 -5
  62. package/docs/pages/components/radio.md +474 -6
  63. package/docs/pages/components/rating.md +331 -7
  64. package/docs/pages/components/reveal.md +524 -6
  65. package/docs/pages/components/scroll-container.md +552 -6
  66. package/docs/pages/components/select.md +762 -160
  67. package/docs/pages/components/skeleton.md +473 -30
  68. package/docs/pages/components/slideout.md +261 -5
  69. package/docs/pages/components/sp.md +99 -41
  70. package/docs/pages/components/split-button.md +347 -9
  71. package/docs/pages/components/split-pane.md +445 -6
  72. package/docs/pages/components/stat.md +549 -9
  73. package/docs/pages/components/status-indicator.md +230 -1
  74. package/docs/pages/components/stepper.md +563 -6
  75. package/docs/pages/components/tabs.md +439 -13
  76. package/docs/pages/components/textarea.md +415 -17
  77. package/docs/pages/components/tile.md +385 -26
  78. package/docs/pages/components/toggle.md +424 -6
  79. package/docs/pages/components/tooltip.md +367 -0
  80. package/docs/pages/components/translation-group.md +210 -0
  81. package/docs/pages/components/translations.md +319 -19
  82. package/docs/pages/components/vertical-stepper.md +401 -8
  83. package/docs/pages/components/well.md +300 -3
  84. package/docs/pages/getting-started/form-controls.md +162 -0
  85. package/docs/pages/index.md +116 -15
  86. package/package.json +5 -6
  87. package/scss/_global-spacing.scss +4 -0
  88. package/scss/_root.scss +2 -2
  89. package/scss/boot.scss +19 -0
  90. package/scss/shared/layout.scss +5 -0
  91. package/scss/themes/_light.scss +3 -3
  92. package/src/components/alert/alert.scss +1 -0
  93. package/src/components/animated-button/README.md +306 -0
  94. package/src/components/animated-button/animated-button.component.ts +229 -0
  95. package/src/components/animated-button/animated-button.scss +228 -0
  96. package/src/components/animated-button/animated-button.test.ts +143 -0
  97. package/src/components/animated-button/index.ts +12 -0
  98. package/src/components/button/button.component.ts +5 -0
  99. package/src/components/button-group/button-group.component.ts +25 -13
  100. package/src/components/button-group/button-group.scss +6 -0
  101. package/src/components/checkbox/checkbox.component.ts +4 -0
  102. package/src/components/checkbox/checkbox.scss +7 -4
  103. package/src/components/checkbox-group/checkbox-group.scss +7 -0
  104. package/src/components/chip/chip.component.ts +7 -2
  105. package/src/components/chip/chip.scss +16 -2
  106. package/src/components/collapsible/collapsible.component.ts +27 -20
  107. package/src/components/cols/cols.component.ts +14 -2
  108. package/src/components/cols/cols.scss +6 -12
  109. package/src/components/confirm/confirm.component.ts +7 -0
  110. package/src/components/copy-button/copy-button.component.ts +12 -11
  111. package/src/components/data-select/data-select.component.ts +215 -44
  112. package/src/components/data-select/data-select.scss +66 -6
  113. package/src/components/data-select/providers/currency-data-provider.ts +20 -6
  114. package/src/components/data-select/providers/provider.ts +1 -0
  115. package/src/components/data-select/providers/us-state-data-provider.ts +68 -0
  116. package/src/components/data-table/data-table.component.ts +81 -22
  117. package/src/components/data-table-search/data-table-search.component.ts +184 -0
  118. package/src/components/data-table-search/data-table-search.scss +17 -0
  119. package/src/components/data-table-search/data-table-search.test.ts +11 -0
  120. package/src/components/data-table-search/index.ts +12 -0
  121. package/src/components/datepicker/datepicker.component.ts +347 -13
  122. package/src/components/dialog/dialog.component.ts +1 -1
  123. package/src/components/empty-state/empty-state.scss +6 -1
  124. package/src/components/header/header.scss +3 -3
  125. package/src/components/icon/icon.component.ts +23 -1
  126. package/src/components/icon/icon.scss +23 -0
  127. package/src/components/icon-picker/brand-icons.ts +24 -0
  128. package/src/components/icon-picker/icon-picker.component.ts +407 -0
  129. package/src/components/icon-picker/icon-picker.scss +205 -0
  130. package/src/components/icon-picker/index.ts +12 -0
  131. package/src/components/icon-picker/line-icons.ts +612 -0
  132. package/src/components/icon-picker/material-icons.ts +14543 -0
  133. package/src/components/inline-edit/inline-edit.component.ts +190 -46
  134. package/src/components/inline-edit/inline-edit.scss +29 -0
  135. package/src/components/inline-edit/inline-edit.test.ts +314 -1
  136. package/src/components/input/input.component.ts +324 -5
  137. package/src/components/input/input.scss +87 -0
  138. package/src/components/input-group/input-group.component.ts +28 -7
  139. package/src/components/input-group/input-group.scss +48 -10
  140. package/src/components/item/item.component.ts +11 -2
  141. package/src/components/item/item.scss +7 -0
  142. package/src/components/key/index.ts +12 -0
  143. package/src/components/key/key.component.ts +47 -0
  144. package/src/components/key/key.scss +38 -0
  145. package/src/components/key-container/index.ts +12 -0
  146. package/src/components/key-container/key-container.component.ts +142 -0
  147. package/src/components/key-container/key-container.scss +33 -0
  148. package/src/components/menu-item/menu-item.component.ts +20 -0
  149. package/src/components/menu-item/menu-item.scss +69 -2
  150. package/src/components/navbar/navbar.component.ts +103 -11
  151. package/src/components/navbar/navbar.scss +6 -1
  152. package/src/components/opt-group/index.ts +12 -0
  153. package/src/components/opt-group/opt-group.component.ts +74 -0
  154. package/src/components/opt-group/opt-group.scss +37 -0
  155. package/src/components/opt-group/opt-group.test.ts +27 -0
  156. package/src/components/option/option.component.ts +1 -16
  157. package/src/components/option/option.scss +4 -0
  158. package/src/components/panel/panel.component.ts +10 -8
  159. package/src/components/panel/panel.scss +20 -0
  160. package/src/components/priority-list/index.ts +12 -0
  161. package/src/components/priority-list/priority-list.component.ts +611 -0
  162. package/src/components/priority-list/priority-list.scss +185 -0
  163. package/src/components/priority-list/priority-list.test.ts +139 -0
  164. package/src/components/progress-bar/progress-bar.component.ts +22 -16
  165. package/src/components/radio/radio.scss +10 -3
  166. package/src/components/select/select.component.ts +812 -72
  167. package/src/components/select/select.scss +108 -2
  168. package/src/components/select/select.test.ts +147 -2
  169. package/src/components/settings-container/settings-container.component.ts +44 -19
  170. package/src/components/settings-container/settings-container.scss +1 -1
  171. package/src/components/skeleton/skeleton.component.ts +6 -1
  172. package/src/components/slideout/slideout.scss +8 -3
  173. package/src/components/sp/sp.component.ts +3 -1
  174. package/src/components/sp/sp.scss +19 -0
  175. package/src/components/stepper/stepper.component.ts +16 -10
  176. package/src/components/textarea/textarea.scss +0 -4
  177. package/src/components/tile/tile.component.ts +12 -3
  178. package/src/components/tile/tile.scss +1 -1
  179. package/src/components/timer/timer.component.ts +15 -2
  180. package/src/components/toggle/toggle.component.ts +29 -26
  181. package/src/components/toggle/toggle.scss +13 -1
  182. package/src/components/translation-group/index.ts +12 -0
  183. package/src/components/translation-group/translation-group.component.ts +207 -0
  184. package/src/components/translation-group/translation-group.scss +8 -0
  185. package/src/components/translations/translations.component.ts +90 -44
  186. package/src/components/translations/translations.scss +4 -0
  187. package/src/components/vertical-stepper/vertical-stepper.component.ts +14 -9
  188. package/src/events/events.ts +12 -7
  189. package/src/events/zn-language-change.ts +7 -0
  190. package/src/events/zn-purchase.ts +11 -0
  191. package/src/events/zn-redirect.ts +7 -0
  192. package/src/events/zn-reorder.ts +7 -0
  193. package/src/events/zn-search-change.ts +11 -0
  194. package/src/events/zn-submit.ts +1 -1
  195. package/src/form-control.scss +4 -0
  196. package/src/internal/form-navigation.ts +510 -0
  197. package/src/internal/form.ts +6 -0
  198. package/src/zinc.ts +91 -83
@@ -5,7 +5,7 @@ meta:
5
5
  layout: component
6
6
  ---
7
7
 
8
- Input Groups allow you to group multiple form controls together into a single visual unit.
8
+ Input Groups allow you to group multiple form controls together into a single visual unit. They are ideal for creating compound inputs where multiple fields are related and should be visually connected, such as address fields, URL builders, or search interfaces with action buttons.
9
9
 
10
10
  ```html:preview
11
11
  <zn-input-group>
@@ -14,24 +14,27 @@ Input Groups allow you to group multiple form controls together into a single vi
14
14
  </zn-input-group>
15
15
  ```
16
16
 
17
+ :::tip
18
+ Input Groups support `zn-input`, `zn-select`, and `zn-button` components. The component automatically styles the borders and corners to create a seamless visual connection between controls.
19
+ :::
20
+
17
21
  ## Examples
18
22
 
19
- ### Mixed Inputs and Selects
23
+ ### Basic Input Group
20
24
 
21
- You can combine inputs and selects.
25
+ The simplest input group combines two or more inputs. Borders between controls are merged, and corner radii are adjusted automatically to create a unified appearance.
22
26
 
23
27
  ```html:preview
24
28
  <zn-input-group>
25
- <zn-select value="http://" style="width: 125px;">
26
- <zn-option value="http://">http://</zn-option>
27
- <zn-option value="https://">https://</zn-option>
28
- </zn-select>
29
- <zn-input placeholder="example.com"></zn-input>
29
+ <zn-input placeholder="First Name"></zn-input>
30
+ <zn-input placeholder="Last Name"></zn-input>
30
31
  </zn-input-group>
31
32
  ```
32
33
 
33
34
  ### Multiple Inputs
34
35
 
36
+ You can group three or more inputs together. Middle inputs will have no border radius, creating a continuous flow.
37
+
35
38
  ```html:preview
36
39
  <zn-input-group>
37
40
  <zn-input placeholder="City"></zn-input>
@@ -40,22 +43,213 @@ You can combine inputs and selects.
40
43
  </zn-input-group>
41
44
  ```
42
45
 
43
- ### Labeled Group
46
+ ### Label
44
47
 
45
- Use the `label` attribute to add a label to the input group.
48
+ Use the `label` attribute to give the input group an accessible label. For labels that contain HTML, use the `label` slot instead.
46
49
 
47
50
  ```html:preview
48
51
  <zn-input-group label="Personal Information">
49
52
  <zn-input placeholder="First Name"></zn-input>
50
53
  <zn-input placeholder="Last Name"></zn-input>
51
54
  </zn-input-group>
55
+ <br />
56
+ <zn-input-group>
57
+ <span slot="label">Mailing Address</span>
58
+ <zn-input placeholder="Street Address"></zn-input>
59
+ <zn-input placeholder="City"></zn-input>
60
+ <zn-input placeholder="State"></zn-input>
61
+ <zn-input placeholder="Zip Code"></zn-input>
62
+ </zn-input-group>
52
63
  ```
53
64
 
54
- ### Input with Submit Button
65
+ ### Mixed Inputs and Selects
66
+
67
+ Combine inputs and selects to create powerful compound controls. This is useful for URL builders, phone number inputs with country codes, or any scenario where a predefined option needs to be paired with user input.
55
68
 
56
69
  ```html:preview
57
- <zn-input-group>
58
- <zn-input placeholder="Email Address" type="email"></zn-input>
70
+ <zn-input-group label="Website URL">
71
+ <zn-select value="https://" style="width: 125px;">
72
+ <zn-option value="http://">http://</zn-option>
73
+ <zn-option value="https://">https://</zn-option>
74
+ </zn-select>
75
+ <zn-input placeholder="example.com"></zn-input>
76
+ </zn-input-group>
77
+ <br />
78
+ <zn-input-group label="Phone Number">
79
+ <zn-select value="+1" style="width: 100px;">
80
+ <zn-option value="+1">+1</zn-option>
81
+ <zn-option value="+44">+44</zn-option>
82
+ <zn-option value="+86">+86</zn-option>
83
+ <zn-option value="+91">+91</zn-option>
84
+ </zn-select>
85
+ <zn-input type="tel" placeholder="(555) 123-4567"></zn-input>
86
+ </zn-input-group>
87
+ ```
88
+
89
+ ### Input with Button
90
+
91
+ Add a button to create search interfaces, newsletter signups, or any input that requires immediate action. Buttons integrate seamlessly with the grouped styling.
92
+
93
+ ```html:preview
94
+ <zn-input-group label="Email Newsletter">
95
+ <zn-input placeholder="Enter your email" type="email"></zn-input>
59
96
  <zn-button>Subscribe</zn-button>
60
97
  </zn-input-group>
98
+ <br />
99
+ <zn-input-group label="Search Products">
100
+ <zn-input placeholder="Search..." type="search"></zn-input>
101
+ <zn-button color="secondary">Search</zn-button>
102
+ </zn-input-group>
103
+ ```
104
+
105
+ ### Button at the Start
106
+
107
+ Place a button at the beginning of the group for actions that should precede the input.
108
+
109
+ ```html:preview
110
+ <zn-input-group label="Quick Search">
111
+ <zn-button icon="search"></zn-button>
112
+ <zn-input placeholder="Type to search..."></zn-input>
113
+ </zn-input-group>
114
+ ```
115
+
116
+ ### Multiple Controls with Buttons
117
+
118
+ Create more complex interfaces by combining multiple inputs, selects, and buttons in a single group.
119
+
120
+ ```html:preview
121
+ <zn-input-group label="Transfer Funds">
122
+ <zn-select value="USD" style="width: 100px;">
123
+ <zn-option value="USD">USD</zn-option>
124
+ <zn-option value="EUR">EUR</zn-option>
125
+ <zn-option value="GBP">GBP</zn-option>
126
+ </zn-select>
127
+ <zn-input type="currency" placeholder="0.00"></zn-input>
128
+ <zn-button color="success">Transfer</zn-button>
129
+ </zn-input-group>
130
+ <br />
131
+ <zn-input-group label="Date Range Filter">
132
+ <zn-input type="date" placeholder="Start Date"></zn-input>
133
+ <zn-input type="date" placeholder="End Date"></zn-input>
134
+ <zn-button color="secondary">Apply</zn-button>
135
+ </zn-input-group>
136
+ ```
137
+
138
+ ### Flexible Width Distribution
139
+
140
+ Use the `span` attribute on individual controls to control their relative widths within the group. The span attribute accepts values from 1 to 12 and works similarly to CSS grid column spans. This is particularly useful when one field should be larger than others.
141
+
142
+ ```html:preview
143
+ <zn-input-group label="Address">
144
+ <zn-input span="8" placeholder="Street Address"></zn-input>
145
+ <zn-input span="4" placeholder="Apt/Unit"></zn-input>
146
+ </zn-input-group>
147
+ <br />
148
+ <zn-input-group label="Contact Information">
149
+ <zn-input span="6" placeholder="First Name"></zn-input>
150
+ <zn-input span="6" placeholder="Last Name"></zn-input>
151
+ </zn-input-group>
152
+ <br />
153
+ <zn-input-group label="Location">
154
+ <zn-input span="6" placeholder="City"></zn-input>
155
+ <zn-input span="3" placeholder="State"></zn-input>
156
+ <zn-input span="3" placeholder="Zip"></zn-input>
157
+ </zn-input-group>
158
+ ```
159
+
160
+ :::tip
161
+ **Usage:** The `span` attribute only takes effect on medium screens and above. On smaller screens, all inputs will be equal width to ensure proper mobile usability.
162
+ :::
163
+
164
+ ### Different Input Types
165
+
166
+ Input groups work with all input types, allowing you to create diverse compound controls.
167
+
168
+ ```html:preview
169
+ <zn-input-group label="Payment Information">
170
+ <zn-input type="text" placeholder="Cardholder Name" span="12"></zn-input>
171
+ </zn-input-group>
172
+ <br />
173
+ <zn-input-group>
174
+ <zn-input type="text" placeholder="Card Number" span="8"></zn-input>
175
+ <zn-input type="text" placeholder="CVV" span="4"></zn-input>
176
+ </zn-input-group>
177
+ <br />
178
+ <zn-input-group label="Price Range">
179
+ <zn-input type="currency" placeholder="Min"></zn-input>
180
+ <zn-input type="currency" placeholder="Max"></zn-input>
181
+ </zn-input-group>
182
+ ```
183
+
184
+ ### Form Integration
185
+
186
+ Input groups work seamlessly within forms. Each control maintains its individual `name` attribute for form submission.
187
+
188
+ ```html:preview
189
+ <form class="input-group-form">
190
+ <zn-input-group label="Full Name">
191
+ <zn-input name="firstName" placeholder="First Name" required></zn-input>
192
+ <zn-input name="lastName" placeholder="Last Name" required></zn-input>
193
+ </zn-input-group>
194
+ <br />
195
+ <zn-input-group label="Contact">
196
+ <zn-select name="countryCode" value="+1" style="width: 100px;">
197
+ <zn-option value="+1">+1</zn-option>
198
+ <zn-option value="+44">+44</zn-option>
199
+ </zn-select>
200
+ <zn-input name="phone" type="tel" placeholder="Phone Number" required></zn-input>
201
+ </zn-input-group>
202
+ <br />
203
+ <zn-button type="submit" color="success">Submit</zn-button>
204
+ </form>
205
+
206
+ <script type="module">
207
+ const form = document.querySelector('.input-group-form');
208
+
209
+ await Promise.all([
210
+ customElements.whenDefined('zn-input'),
211
+ customElements.whenDefined('zn-select'),
212
+ customElements.whenDefined('zn-button')
213
+ ]).then(() => {
214
+ form.addEventListener('submit', (e) => {
215
+ e.preventDefault();
216
+ const formData = new FormData(form);
217
+ const data = Object.fromEntries(formData);
218
+ alert('Form submitted!\n\n' + JSON.stringify(data, null, 2));
219
+ });
220
+ });
221
+ </script>
61
222
  ```
223
+
224
+ ### Focus Behavior
225
+
226
+ When a control within the group receives focus, its z-index increases to ensure the focus ring displays properly over adjacent controls.
227
+
228
+ ```html:preview
229
+ <zn-input-group label="Try clicking into each field">
230
+ <zn-input placeholder="First Name"></zn-input>
231
+ <zn-input placeholder="Last Name"></zn-input>
232
+ <zn-input placeholder="Email"></zn-input>
233
+ </zn-input-group>
234
+ ```
235
+
236
+ ### Styling Individual Controls
237
+
238
+ You can still apply individual styling to controls within a group. However, note that border-radius is controlled by the input group and will be overridden.
239
+
240
+ ```html:preview
241
+ <zn-input-group label="Custom Styled Controls">
242
+ <zn-input placeholder="Normal" span="4"></zn-input>
243
+ <zn-input placeholder="Disabled" disabled span="4"></zn-input>
244
+ <zn-input placeholder="With Value" value="Prefilled" span="4"></zn-input>
245
+ </zn-input-group>
246
+ <br />
247
+ <zn-input-group label="Different Sizes">
248
+ <zn-input placeholder="Medium (default)" size="medium"></zn-input>
249
+ <zn-input placeholder="Large" size="large"></zn-input>
250
+ </zn-input-group>
251
+ ```
252
+
253
+ :::warning
254
+ **Note:** While controls within a group can have different sizes, it's recommended to use consistent sizes for better visual harmony. The component adjusts alignment automatically, but mixed sizes may not look as polished.
255
+ :::
@@ -134,6 +134,33 @@ The `type` attribute controls the type of input the browser renders. As shown in
134
134
  have default prefix and suffix elements. Not all available types are shown below. See
135
135
  the [Properties table](#properties) for the full list of options.
136
136
 
137
+ #### Color Input
138
+
139
+ The color input type displays a clickable color swatch on the left that opens the browser's native color picker. The color value is shown as editable text in the input field, allowing users to either pick a color visually or enter a color value directly.
140
+
141
+ Use the `color-format` attribute to specify the format: `hex` (default), `rgb`, or `oklch`.
142
+
143
+ ```html:preview
144
+ <zn-input type="color" label="Hex Format (default)" value="#3b82f6">
145
+ <div slot="help-text">Default format. Click the swatch to pick a color, or type a hex value like #3b82f6.</div>
146
+ </zn-input>
147
+ <br />
148
+ <zn-input type="color" label="RGB Format" color-format="rgb" value="rgb(139, 92, 246)">
149
+ <div slot="help-text">Type RGB values like rgb(139, 92, 246). The picker converts to/from hex automatically.</div>
150
+ </zn-input>
151
+ <br />
152
+ <zn-input type="color" label="OKLCH Format" color-format="oklch" value="oklch(0.628 0.225 292.6)">
153
+ <div slot="help-text">Type OKLCH values like oklch(0.628 0.225 292.6). The picker converts to/from hex automatically.</div>
154
+ </zn-input>
155
+ <br />
156
+ <zn-input type="color" label="Background Color" value="#f59e0b" clearable>
157
+ <div slot="help-text">Use the <code>clearable</code> attribute to allow clearing the color value.</div>
158
+ </zn-input>
159
+ <br />
160
+ ```
161
+
162
+ #### Other Input Types
163
+
137
164
  ```html:preview
138
165
  <zn-input type="currency" label="Input type: Currency"><div slot="help-text">Has <code>$</code> prefix and <code>USD</code> suffix by default and native input type set to <code>number</code>. The currency input does <strong>NOT</strong> have input masking at this time.</div></zn-input>
139
166
  <br />
@@ -222,6 +249,173 @@ Or as a Prefix
222
249
  </zn-input>
223
250
  ```
224
251
 
252
+ ### Form Navigation with Enter Key
253
+
254
+ Add the `data-enter-navigation` attribute to a form to enable Enter key navigation through form inputs. When enabled, pressing Enter will move focus to the next input field, and submit the form when all named fields are filled and valid.
255
+
256
+ :::tip
257
+ **Usage:** This feature is useful for forms where users naturally want to press Enter to move between fields, such as data entry forms, registration forms, or checkout flows.
258
+ :::
259
+
260
+ #### Basic Example
261
+
262
+ ```html:preview
263
+ <form class="form-nav-basic" data-enter-navigation>
264
+ <zn-input name="firstName" label="First Name" required></zn-input>
265
+ <br />
266
+ <zn-input name="lastName" label="Last Name" required></zn-input>
267
+ <br />
268
+ <zn-input name="email" type="email" label="Email" required></zn-input>
269
+ <br />
270
+ <zn-input name="phone" type="tel" label="Phone"></zn-input>
271
+ <br />
272
+ <zn-button type="submit" variant="primary">Submit</zn-button>
273
+ </form>
274
+
275
+ <script type="module">
276
+ const form = document.querySelector('.form-nav-basic');
277
+
278
+ // Wait for controls to be defined before attaching form listeners
279
+ await Promise.all([
280
+ customElements.whenDefined('zn-button'),
281
+ customElements.whenDefined('zn-input')
282
+ ]).then(() => {
283
+ form.addEventListener('submit', (e) => {
284
+ e.preventDefault();
285
+ const formData = new FormData(form);
286
+ const data = Object.fromEntries(formData);
287
+ alert('Form submitted!\n\n' + JSON.stringify(data, null, 2));
288
+ });
289
+ });
290
+ </script>
291
+ ```
292
+
293
+ #### All Input Types Example
294
+
295
+ This example demonstrates Enter key navigation with various input types including text, email, phone, number, currency, and date inputs:
296
+
297
+ ```html:preview
298
+ <form class="form-nav-all-types" data-enter-navigation>
299
+ <zn-input name="fullName" label="Full Name" required></zn-input>
300
+ <br />
301
+ <zn-input name="email" type="email" label="Email Address" required></zn-input>
302
+ <br />
303
+ <zn-input name="phone" type="tel" label="Phone Number" required></zn-input>
304
+ <br />
305
+ <zn-input name="age" type="number" label="Age" min="18" max="100" required></zn-input>
306
+ <br />
307
+ <zn-input name="salary" type="currency" label="Expected Salary" required></zn-input>
308
+ <br />
309
+ <zn-datepicker name="availableDate" label="Available Start Date" required></zn-datepicker>
310
+ <br />
311
+ <zn-input name="website" type="url" label="Portfolio Website"></zn-input>
312
+ <br />
313
+ <zn-button type="submit" variant="primary">Continue</zn-button>
314
+ </form>
315
+
316
+ <script type="module">
317
+ const allTypesForm = document.querySelector('.form-nav-all-types');
318
+
319
+ // Wait for controls to be defined before attaching form listeners
320
+ await Promise.all([
321
+ customElements.whenDefined('zn-button'),
322
+ customElements.whenDefined('zn-datepicker'),
323
+ customElements.whenDefined('zn-input')
324
+ ]).then(() => {
325
+ allTypesForm.addEventListener('submit', (e) => {
326
+ e.preventDefault();
327
+ const formData = new FormData(allTypesForm);
328
+ const data = Object.fromEntries(formData);
329
+ alert('Form submitted!\n\n' + JSON.stringify(data, null, 2));
330
+ });
331
+ });
332
+ </script>
333
+ ```
334
+
335
+ **Navigation flow:** Press Enter to move through each field. The form submits when all named fields are filled and valid.
336
+
337
+ #### Mixed Form Controls
338
+
339
+ Form navigation works with all Zinc form controls including selects, radios, checkboxes, toggles, and textareas. Textareas are excluded from navigation since they need Enter for their own functionality.
340
+
341
+ ```html:preview
342
+ <form class="form-nav-mixed" data-enter-navigation>
343
+ <zn-input name="productName" label="Product Name" required></zn-input>
344
+ <br />
345
+ <zn-input name="sku" label="SKU" required></zn-input>
346
+ <br />
347
+ <zn-input name="price" type="currency" label="Price" required></zn-input>
348
+ <br />
349
+ <zn-input name="quantity" type="number" label="Quantity" required min="1"></zn-input>
350
+ <br />
351
+ <zn-select name="category" label="Category" required clearable>
352
+ <zn-option value="electronics">Electronics</zn-option>
353
+ <zn-option value="clothing">Clothing</zn-option>
354
+ <zn-option value="books">Books</zn-option>
355
+ <zn-option value="home">Home & Garden</zn-option>
356
+ </zn-select>
357
+ <br />
358
+ <zn-radio-group name="condition" label="Condition" required>
359
+ <zn-radio value="new">New</zn-radio>
360
+ <zn-radio value="used">Used</zn-radio>
361
+ <zn-radio value="refurbished">Refurbished</zn-radio>
362
+ </zn-radio-group>
363
+ <br /><br />
364
+ <zn-checkbox name="featured" value="yes">Feature this product</zn-checkbox>
365
+ <br /><br />
366
+ <zn-toggle name="available" value="yes">Available for purchase</zn-toggle>
367
+ <br /><br />
368
+ <zn-textarea name="description" label="Description (Press Tab to navigate, Enter for new lines)"></zn-textarea>
369
+ <br />
370
+ <zn-button type="submit" variant="primary">Add Product</zn-button>
371
+ </form>
372
+
373
+ <script type="module">
374
+ const mixedForm = document.querySelector('.form-nav-mixed');
375
+
376
+ // Wait for controls to be defined before attaching form listeners
377
+ await Promise.all([
378
+ customElements.whenDefined('zn-button'),
379
+ customElements.whenDefined('zn-checkbox'),
380
+ customElements.whenDefined('zn-input'),
381
+ customElements.whenDefined('zn-option'),
382
+ customElements.whenDefined('zn-radio'),
383
+ customElements.whenDefined('zn-radio-group'),
384
+ customElements.whenDefined('zn-select'),
385
+ customElements.whenDefined('zn-textarea'),
386
+ customElements.whenDefined('zn-toggle')
387
+ ]).then(() => {
388
+ mixedForm.addEventListener('submit', (e) => {
389
+ e.preventDefault();
390
+ const formData = new FormData(mixedForm);
391
+ const data = Object.fromEntries(formData);
392
+ alert('Product added!\n\n' + JSON.stringify(data, null, 2));
393
+ });
394
+ });
395
+ </script>
396
+ ```
397
+
398
+ **Navigation behavior by control type:**
399
+ - **Text inputs:** Enter moves to next field
400
+ - **Number/Currency inputs:** Enter moves to next field
401
+ - **Datepicker:** Enter moves to next field
402
+ - **Select dropdowns:** Automatically opens when navigated to. Enter on an option selects it and moves to next field.
403
+ - **Radio buttons:** Arrow keys select different options within the radio group. Space or Enter selects the current option. Press Enter to move to next field.
404
+ - **Checkboxes:** Space toggles the checkbox. Enter, Arrow Down, or Arrow Up moves to next/previous field.
405
+ - **Toggles:** Space toggles the toggle. Enter, Arrow Down, or Arrow Up moves to next/previous field.
406
+ - **Textareas:** You can navigate TO a textarea with Enter, but pressing Enter inside a textarea adds newlines. Use Tab to navigate away from textareas.
407
+ - **Search inputs:** You can navigate TO a search input with Enter, but pressing Enter inside a search input triggers search. Use Tab to navigate away from search inputs.
408
+
409
+ **Keyboard shortcuts:**
410
+ - **Enter** - Move to next field (or submit form if all fields complete)
411
+ - **Arrow Down/Up** - On checkboxes and toggles, moves to next/previous field. On radios, selects next/previous option in group.
412
+ - **Space** - Toggle checkboxes and toggles. Select current radio option.
413
+ - **Tab** - Standard browser tab navigation
414
+
415
+ :::warning
416
+ **Note:** While you can navigate TO textareas and search inputs using Enter, pressing Enter while inside these controls uses the Enter key for their own functionality (new lines and search triggers, respectively). Use Tab to navigate away from these controls.
417
+ :::
418
+
225
419
  ### Customizing Label Position
226
420
 
227
421
  Use [CSS parts](#css-parts) to customize the way form controls are drawn. This example uses CSS grid to position the
@@ -0,0 +1,115 @@
1
+ ---
2
+ meta:
3
+ title: Key Container
4
+ description: A legend container that manages key items, typically used alongside charts to toggle visibility of data series by category.
5
+ layout: component
6
+ ---
7
+
8
+ ```html:preview
9
+ <zn-key-container filter-attribute="data-type">
10
+ <zn-key icon="circle" color="primary" attribute="sale" active>Sales</zn-key>
11
+ <zn-key icon="circle" color="success" attribute="refund" active>Refunds</zn-key>
12
+ <zn-key icon="circle" color="warning" attribute="pending" active>Pending</zn-key>
13
+
14
+ <div style="margin-top: 16px; display: flex; flex-direction: column; gap: 4px;">
15
+ <zn-chip data-type="sale" type="primary">Sale #1001</zn-chip>
16
+ <zn-chip data-type="refund" type="success">Refund #2001</zn-chip>
17
+ <zn-chip data-type="sale" type="primary">Sale #1002</zn-chip>
18
+ <zn-chip data-type="pending" type="warning">Pending #3001</zn-chip>
19
+ <zn-chip data-type="refund" type="success">Refund #2002</zn-chip>
20
+ </div>
21
+ </zn-key-container>
22
+ ```
23
+
24
+ ## Examples
25
+
26
+ ### Basic Usage
27
+
28
+ Place `zn-key` elements and filterable content inside a `zn-key-container`. Use `filter-attribute` to specify which attribute on content items should be matched against each key's `attribute` value. Deactivating a key hides items that match it.
29
+
30
+ ```html:preview
31
+ <zn-key-container filter-attribute="data-category">
32
+ <zn-key icon="circle" color="primary" attribute="frontend" active>Frontend</zn-key>
33
+ <zn-key icon="circle" color="success" attribute="backend" active>Backend</zn-key>
34
+ <zn-key icon="circle" color="info" attribute="devops" active>DevOps</zn-key>
35
+
36
+ <div style="margin-top: 16px; display: flex; flex-direction: column; gap: 4px;">
37
+ <zn-chip data-category="frontend" type="primary">React component</zn-chip>
38
+ <zn-chip data-category="backend" type="success">API endpoint</zn-chip>
39
+ <zn-chip data-category="devops" type="info">CI pipeline</zn-chip>
40
+ <zn-chip data-category="frontend" type="primary">CSS update</zn-chip>
41
+ <zn-chip data-category="backend" type="success">Database migration</zn-chip>
42
+ </div>
43
+ </zn-key-container>
44
+ ```
45
+
46
+ ### Using Attribute and Value
47
+
48
+ When keys specify both `attribute` and `value`, items are matched by checking if the given attribute contains the given value.
49
+
50
+ ```html:preview
51
+ <zn-key-container>
52
+ <zn-key icon="circle" color="success" attribute="data-status" value="active" active>Active</zn-key>
53
+ <zn-key icon="circle" color="warning" attribute="data-status" value="pending" active>Pending</zn-key>
54
+ <zn-key icon="circle" color="error" attribute="data-status" value="closed" active>Closed</zn-key>
55
+
56
+ <div style="margin-top: 16px; display: flex; flex-direction: column; gap: 4px;">
57
+ <zn-chip data-status="active" type="success">Ticket #101 - Active</zn-chip>
58
+ <zn-chip data-status="pending" type="warning">Ticket #102 - Pending</zn-chip>
59
+ <zn-chip data-status="closed" type="error">Ticket #103 - Closed</zn-chip>
60
+ <zn-chip data-status="active" type="success">Ticket #104 - Active</zn-chip>
61
+ <zn-chip data-status="pending" type="warning">Ticket #105 - Pending</zn-chip>
62
+ </div>
63
+ </zn-key-container>
64
+ ```
65
+
66
+ ### External Target
67
+
68
+ Use the `target` attribute to filter content in a separate element by its ID, instead of filtering slotted content.
69
+
70
+ ```html:preview
71
+ <zn-key-container target="target-list" filter-attribute="data-type">
72
+ <zn-key icon="circle" color="primary" attribute="order" active>Orders</zn-key>
73
+ <zn-key icon="circle" color="success" attribute="payment" active>Payments</zn-key>
74
+ </zn-key-container>
75
+
76
+ <div id="target-list" style="margin-top: 16px; display: flex; flex-direction: column; gap: 4px;">
77
+ <zn-chip data-type="order" type="primary">Order #5001</zn-chip>
78
+ <zn-chip data-type="payment" type="success">Payment #6001</zn-chip>
79
+ <zn-chip data-type="order" type="primary">Order #5002</zn-chip>
80
+ <zn-chip data-type="payment" type="success">Payment #6002</zn-chip>
81
+ </div>
82
+ ```
83
+
84
+ ### No Scroll
85
+
86
+ By default, the container allows its content to scroll. Use the `no-scroll` attribute to disable this behaviour.
87
+
88
+ ```html:preview
89
+ <zn-key-container filter-attribute="data-type" no-scroll>
90
+ <zn-key icon="circle" color="primary" attribute="alpha" active>Alpha</zn-key>
91
+ <zn-key icon="circle" color="error" attribute="beta" active>Beta</zn-key>
92
+
93
+ <div style="margin-top: 16px; display: flex; flex-direction: column; gap: 4px;">
94
+ <zn-chip data-type="alpha" type="primary">Alpha item 1</zn-chip>
95
+ <zn-chip data-type="beta" type="error">Beta item 1</zn-chip>
96
+ <zn-chip data-type="alpha" type="primary">Alpha item 2</zn-chip>
97
+ </div>
98
+ </zn-key-container>
99
+ ```
100
+
101
+ ### Custom Item Selector
102
+
103
+ Use the `item-selector` attribute to change the CSS selector used to find filterable items. The default is `[data-type]`.
104
+
105
+ ```html:preview
106
+ <zn-key-container item-selector=".filterable">
107
+ <zn-key icon="circle" color="info" attribute="class" value="filterable" active>Show items</zn-key>
108
+
109
+ <div style="margin-top: 16px; display: flex; flex-direction: column; gap: 4px;">
110
+ <zn-chip class="filterable" type="info">Filterable item</zn-chip>
111
+ <zn-chip type="neutral">Always visible (no class)</zn-chip>
112
+ <zn-chip class="filterable" type="info">Another filterable item</zn-chip>
113
+ </div>
114
+ </zn-key-container>
115
+ ```