@greypan/web-ui 4.0.0 → 5.0.0
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/README.CN.md +248 -139
- package/README.md +255 -139
- package/dist/assets/glass.js +1 -1
- package/dist/assets/glass.js.map +1 -1
- package/dist/assets/menu-portal.js +1 -1
- package/dist/assets/menu-portal.js.map +1 -1
- package/dist/components/autocomplete/index.d.ts +8 -0
- package/dist/components/autocomplete/index.js +108 -50
- package/dist/components/autocomplete/index.js.map +1 -1
- package/dist/components/autocomplete/style.js +1 -1
- package/dist/components/autocomplete/style.js.map +1 -1
- package/dist/components/back-top/index.js +1 -1
- package/dist/components/back-top/index.js.map +1 -1
- package/dist/components/back-top/style.js +1 -1
- package/dist/components/back-top/style.js.map +1 -1
- package/dist/components/button/index.js +33 -32
- package/dist/components/button/index.js.map +1 -1
- package/dist/components/button/style.js +1 -1
- package/dist/components/button/style.js.map +1 -1
- package/dist/components/button-group/index.js +14 -12
- package/dist/components/button-group/index.js.map +1 -1
- package/dist/components/button-group/style.js +1 -1
- package/dist/components/button-group/style.js.map +1 -1
- package/dist/components/checkbox/index.js +23 -16
- package/dist/components/checkbox/index.js.map +1 -1
- package/dist/components/checkbox/style.js +1 -1
- package/dist/components/checkbox/style.js.map +1 -1
- package/dist/components/collapse/index.d.ts +66 -0
- package/dist/components/collapse/index.js +159 -0
- package/dist/components/collapse/index.js.map +1 -0
- package/dist/components/collapse/style.js +6 -0
- package/dist/components/collapse/style.js.map +1 -0
- package/dist/components/context-menu/index.d.ts +29 -0
- package/dist/components/context-menu/index.js +167 -51
- package/dist/components/context-menu/index.js.map +1 -1
- package/dist/components/dialog/index.d.ts +6 -0
- package/dist/components/dialog/index.js +28 -7
- package/dist/components/dialog/index.js.map +1 -1
- package/dist/components/dialog/style.js +1 -1
- package/dist/components/dialog/style.js.map +1 -1
- package/dist/components/drawer/index.d.ts +32 -2
- package/dist/components/drawer/index.js +229 -39
- package/dist/components/drawer/index.js.map +1 -1
- package/dist/components/drawer/style.js +1 -1
- package/dist/components/drawer/style.js.map +1 -1
- package/dist/components/dropdown/index.d.ts +2 -0
- package/dist/components/dropdown/index.js +23 -13
- package/dist/components/dropdown/index.js.map +1 -1
- package/dist/components/dropdown-item/style.js +1 -1
- package/dist/components/dropdown-item/style.js.map +1 -1
- package/dist/components/empty/index.d.ts +1 -0
- package/dist/components/empty/index.js +23 -21
- package/dist/components/empty/index.js.map +1 -1
- package/dist/components/empty/style.js +1 -1
- package/dist/components/empty/style.js.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +28 -27
- package/dist/components/input/style.js +1 -1
- package/dist/components/input/style.js.map +1 -1
- package/dist/components/input-number/style.js +1 -1
- package/dist/components/input-number/style.js.map +1 -1
- package/dist/components/layout/index.d.ts +23 -0
- package/dist/components/layout/index.js +134 -30
- package/dist/components/layout/index.js.map +1 -1
- package/dist/components/layout/style.js +1 -1
- package/dist/components/layout/style.js.map +1 -1
- package/dist/components/option/style.js +1 -1
- package/dist/components/option/style.js.map +1 -1
- package/dist/components/popover/index.d.ts +2 -1
- package/dist/components/popover/index.js +8 -4
- package/dist/components/popover/index.js.map +1 -1
- package/dist/components/popover/style.js +1 -1
- package/dist/components/popover/style.js.map +1 -1
- package/dist/components/radio/index.js +18 -15
- package/dist/components/radio/index.js.map +1 -1
- package/dist/components/radio/style.js +1 -1
- package/dist/components/radio/style.js.map +1 -1
- package/dist/components/segmented/index.d.ts +8 -1
- package/dist/components/segmented/index.js +87 -21
- package/dist/components/segmented/index.js.map +1 -1
- package/dist/components/segmented/style.js +1 -1
- package/dist/components/segmented/style.js.map +1 -1
- package/dist/components/segmented-trigger/index.js +17 -14
- package/dist/components/segmented-trigger/index.js.map +1 -1
- package/dist/components/segmented-trigger/style.js +1 -1
- package/dist/components/segmented-trigger/style.js.map +1 -1
- package/dist/components/select/index.js +32 -28
- package/dist/components/select/index.js.map +1 -1
- package/dist/components/select/style.js +1 -1
- package/dist/components/select/style.js.map +1 -1
- package/dist/components/slider/index.d.ts +3 -2
- package/dist/components/slider/index.js +65 -47
- package/dist/components/slider/index.js.map +1 -1
- package/dist/components/slider/style.js +1 -1
- package/dist/components/slider/style.js.map +1 -1
- package/dist/components/spinner/index.js.map +1 -1
- package/dist/components/switch/index.d.ts +8 -0
- package/dist/components/switch/index.js +72 -25
- package/dist/components/switch/index.js.map +1 -1
- package/dist/components/switch/style.js +1 -1
- package/dist/components/switch/style.js.map +1 -1
- package/dist/components/textarea/index.js +1 -4
- package/dist/components/textarea/index.js.map +1 -1
- package/dist/components/textarea/style.js +1 -1
- package/dist/components/textarea/style.js.map +1 -1
- package/dist/components/theme/style.js +1 -1
- package/dist/components/theme/style.js.map +1 -1
- package/dist/components/toast/style.js +1 -1
- package/dist/components/toast/style.js.map +1 -1
- package/dist/components/toast/toast.js.map +1 -1
- package/dist/components/tooltip/index.js +2 -2
- package/dist/components/tooltip/index.js.map +1 -1
- package/dist/components/tooltip/style.js +1 -1
- package/dist/components/tooltip/style.js.map +1 -1
- package/dist/icons/generated/heroicons-arrow-down-16-solid.d.ts +6 -0
- package/dist/icons/generated/heroicons-arrow-up-16-solid.d.ts +6 -0
- package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.d.ts +6 -0
- package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.js +10 -0
- package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.js.map +1 -0
- package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.d.ts +6 -0
- package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.js +10 -0
- package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.js.map +1 -0
- package/dist/icons/generated/lucide-code.d.ts +6 -0
- package/dist/icons/generated/lucide-code.js +10 -0
- package/dist/icons/generated/lucide-code.js.map +1 -0
- package/dist/icons/generated/lucide-ellipsis-vertical.d.ts +6 -0
- package/dist/icons/generated/lucide-ellipsis-vertical.js +10 -0
- package/dist/icons/generated/lucide-ellipsis-vertical.js.map +1 -0
- package/dist/icons/generated/lucide-list-filter.d.ts +6 -0
- package/dist/icons/generated/lucide-list-filter.js +10 -0
- package/dist/icons/generated/lucide-list-filter.js.map +1 -0
- package/dist/icons/generated/lucide-list-restart.d.ts +6 -0
- package/dist/icons/generated/lucide-list-restart.js +10 -0
- package/dist/icons/generated/lucide-list-restart.js.map +1 -0
- package/dist/icons/generated/lucide-tag.d.ts +6 -0
- package/dist/icons/generated/lucide-tag.js +10 -0
- package/dist/icons/generated/lucide-tag.js.map +1 -0
- package/dist/icons/generated/tabler-sort-ascending-letters.d.ts +6 -0
- package/dist/icons/generated/tabler-sort-ascending-letters.js +10 -0
- package/dist/icons/generated/tabler-sort-ascending-letters.js.map +1 -0
- package/dist/icons/index.d.ts +8 -0
- package/dist/icons/index.js +18 -10
- package/dist/shared/gesture/drag-gesture.js +133 -0
- package/dist/shared/gesture/drag-gesture.js.map +1 -0
- package/dist/shared/gesture/physics.js +45 -0
- package/dist/shared/gesture/physics.js.map +1 -0
- package/dist/shared/group-management/index.js +49 -47
- package/dist/shared/group-management/index.js.map +1 -1
- package/dist/shared/menu-portal/menu-portal.js +22 -10
- package/dist/shared/menu-portal/menu-portal.js.map +1 -1
- package/dist/shared/menu-portal/menu-tree.js +4 -2
- package/dist/shared/menu-portal/menu-tree.js.map +1 -1
- package/dist/shared/overlay/native-dialog-presence.js.map +1 -1
- package/dist/shared/overlay/nested-drawer-layers.js +55 -0
- package/dist/shared/overlay/nested-drawer-layers.js.map +1 -0
- package/dist/shared/overlay/portal.js +44 -13
- package/dist/shared/overlay/portal.js.map +1 -1
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -187,49 +187,85 @@ Components own their role and interaction state. Browser-native composed events
|
|
|
187
187
|
remain the primary interaction API. Kebab-case custom events such as `open-change` describe user-originated component
|
|
188
188
|
state changes; assigning a property programmatically does not emit them.
|
|
189
189
|
|
|
190
|
+
### Cursor behavior
|
|
191
|
+
|
|
192
|
+
Interactive controls use the native arrow cursor instead of the hand cursor. Disabled controls use `not-allowed`.
|
|
193
|
+
Slider, switch, and segmented controls keep the arrow cursor during hover and press feedback, then switch to
|
|
194
|
+
`grabbing` only while a drag is active. Dedicated drag handles and resize controls keep their specialized cursors.
|
|
195
|
+
Cursor styles live inside Shadow DOM, so a plain document-level selector cannot override them.
|
|
196
|
+
|
|
197
|
+
### Controlled state semantics
|
|
198
|
+
|
|
199
|
+
`web-ui-*` elements do not use a single "controlled" contract; three distinct state models exist, chosen per component
|
|
200
|
+
family by the nature of the interaction. Do not assume `controlled` means the same thing across components.
|
|
201
|
+
|
|
202
|
+
**User-originated events only (all `open`-style components: collapse, popover, dropdown, tooltip, dialog, drawer, back-top).**
|
|
203
|
+
`*-change` events (`open-change`, etc.) fire only for user-originated toggles; assigning the property programmatically
|
|
204
|
+
(`el.open = true`) or calling an imperative method (`show()`, `close()`, `toggle()`) never emits. Components self-manage
|
|
205
|
+
their `open` value unless you coordinate externally — you may observe the event and write it back for your own state, but
|
|
206
|
+
the component does not require or wait for that write-back.
|
|
207
|
+
|
|
208
|
+
**Request-then-write-back (`controlled` on dialog and drawer only).**
|
|
209
|
+
With `controlled`, user close actions (Escape, backdrop, built-in close, drag-release) only _request_ `open=false`; the
|
|
210
|
+
component does not change its own state, and it stays open until the consumer writes `open=false`. This is the modal
|
|
211
|
+
confirmation semantics — closing a dialog or drawer is typically an operation that needs consumer approval (unsaved form,
|
|
212
|
+
confirmation), and unlike instantaneous open/close, it is not safe for the component to self-commit. Only these two modal
|
|
213
|
+
components use this mode; the instant open/close family (collapse, popover, dropdown, tooltip) does not need it.
|
|
214
|
+
|
|
215
|
+
**Native form-model (input, textarea, input-number, select, checkbox, radio, switch, autocomplete).**
|
|
216
|
+
The control manages its own value/checked state internally; user interaction flips it immediately and then dispatches
|
|
217
|
+
native `input`/`change` events. Assigning the property programmatically (`el.checked = true`) overrides the internal
|
|
218
|
+
state. This mirrors native `<input type="checkbox">` — there is no `controlled` prop because the value is always readable
|
|
219
|
+
and writable, and React/Vue layers provide their own controlled wrappers on top. For interactions that need an external
|
|
220
|
+
round-trip before the flip is durable (e.g. a switch that should only stay on after an API call succeeds), use the
|
|
221
|
+
optimistic-update path: flip immediately, observe `change`, set the control's `loading` during the request (this blocks
|
|
222
|
+
further interaction and shows a spinner), and on failure write the property back (`el.checked = false`) plus surface a
|
|
223
|
+
toast. The flip-before-approval window is accepted; there is no `controlled` prop for a reject-before-flip contract.
|
|
224
|
+
|
|
190
225
|
### Form-associated controls
|
|
191
226
|
|
|
192
227
|
All form controls participate in native `FormData`, constraint validation, `form.reset()` and browser form-state restoration. The control captures its reset default once, after declarative attributes have been applied on its first connection. Later runtime property updates do not redefine that default. A disabled ancestor `fieldset` disables validation and interaction without mutating the control's public `disabled` property. For checkbox/radio groups, the group is the single submission, reset and restoration owner; managed child controls do not submit or restore an independent state.
|
|
193
228
|
|
|
194
229
|
## All Components
|
|
195
230
|
|
|
196
|
-
| Category
|
|
197
|
-
|
|
|
198
|
-
| **Form Controls**
|
|
199
|
-
|
|
|
200
|
-
|
|
|
201
|
-
|
|
|
202
|
-
|
|
|
203
|
-
|
|
|
204
|
-
|
|
|
205
|
-
|
|
|
206
|
-
|
|
|
207
|
-
|
|
|
208
|
-
|
|
|
209
|
-
|
|
|
210
|
-
| **Buttons**
|
|
211
|
-
|
|
|
212
|
-
| **Overlay / Modal**
|
|
213
|
-
|
|
|
214
|
-
| **
|
|
215
|
-
|
|
|
216
|
-
|
|
|
217
|
-
|
|
|
218
|
-
|
|
|
219
|
-
|
|
|
220
|
-
|
|
|
221
|
-
|
|
|
222
|
-
|
|
|
223
|
-
|
|
|
224
|
-
|
|
|
225
|
-
|
|
|
226
|
-
|
|
|
227
|
-
|
|
|
228
|
-
|
|
|
229
|
-
|
|
|
230
|
-
|
|
|
231
|
-
| **
|
|
232
|
-
|
|
|
231
|
+
| Category | Component |
|
|
232
|
+
| ---------------------- | --------------------------------------------------------- |
|
|
233
|
+
| **Form Controls** | [`<web-ui-input>`](#web-ui-input) |
|
|
234
|
+
| | [`<web-ui-textarea>`](#web-ui-textarea) |
|
|
235
|
+
| | [`<web-ui-input-number>`](#web-ui-input-number) |
|
|
236
|
+
| | [`<web-ui-select>`](#web-ui-select) |
|
|
237
|
+
| | [`<web-ui-autocomplete>`](#web-ui-autocomplete) |
|
|
238
|
+
| | [`<web-ui-slider>`](#web-ui-slider) |
|
|
239
|
+
| | [`<web-ui-checkbox>`](#web-ui-checkbox) |
|
|
240
|
+
| | [`<web-ui-radio>`](#web-ui-radio) |
|
|
241
|
+
| | [`<web-ui-switch>`](#web-ui-switch) |
|
|
242
|
+
| | [`<web-ui-segmented>`](#web-ui-segmented) |
|
|
243
|
+
| | [`<web-ui-checkbox-group>`](#web-ui-checkbox-group) |
|
|
244
|
+
| | [`<web-ui-radio-group>`](#web-ui-radio-group) |
|
|
245
|
+
| **Buttons** | [`<web-ui-button>`](#web-ui-button) |
|
|
246
|
+
| | [`<web-ui-button-group>`](#web-ui-button-group) |
|
|
247
|
+
| **Overlay / Modal** | [`<web-ui-dialog>`](#web-ui-dialog) |
|
|
248
|
+
| | [`<web-ui-drawer>`](#web-ui-drawer) |
|
|
249
|
+
| **In-flow Disclosure** | [`<web-ui-collapse>`](#web-ui-collapse) |
|
|
250
|
+
| **Floating** | [`<web-ui-popover>`](#web-ui-popover) |
|
|
251
|
+
| | [`<web-ui-tooltip>`](#web-ui-tooltip) |
|
|
252
|
+
| | [`<web-ui-context-menu>`](#web-ui-context-menu) |
|
|
253
|
+
| **Menu** | [`<web-ui-dropdown>`](#web-ui-dropdown) |
|
|
254
|
+
| | [`<web-ui-dropdown-item>`](#web-ui-dropdown-item) |
|
|
255
|
+
| | [`<web-ui-dropdown-divider>`](#web-ui-dropdown-divider) |
|
|
256
|
+
| | [`<web-ui-dropdown-header>`](#web-ui-dropdown-header) |
|
|
257
|
+
| **Data Display** | [`<web-ui-avatar>`](#web-ui-avatar) |
|
|
258
|
+
| | [`<web-ui-badge>`](#web-ui-badge) |
|
|
259
|
+
| | [`<web-ui-empty>`](#web-ui-empty) |
|
|
260
|
+
| | [`<web-ui-icon>`](#web-ui-icon) |
|
|
261
|
+
| | [`<web-ui-spinner>`](#web-ui-spinner) |
|
|
262
|
+
| **Layout & Utility** | [`<web-ui-layout>`](#web-ui-layout) |
|
|
263
|
+
| | [`<web-ui-back-top>`](#web-ui-back-top) |
|
|
264
|
+
| | [`<web-ui-svg-draw-lines>`](#web-ui-svg-draw-lines) |
|
|
265
|
+
| | [`<web-ui-theme>`](#web-ui-theme) |
|
|
266
|
+
| **Notification** | [`<web-ui-toast>`](#web-ui-toast) |
|
|
267
|
+
| **Sub-items** | [`<web-ui-option>`](#web-ui-option) |
|
|
268
|
+
| | [`<web-ui-segmented-trigger>`](#web-ui-segmented-trigger) |
|
|
233
269
|
|
|
234
270
|
## API Reference
|
|
235
271
|
|
|
@@ -241,19 +277,19 @@ Form controls implement `static formAssociated = true` and integrate with native
|
|
|
241
277
|
|
|
242
278
|
Text input with clearable, prefix/suffix slots.
|
|
243
279
|
|
|
244
|
-
| Attribute | Type | Default | Description
|
|
245
|
-
| ------------- | --------- | -------- |
|
|
246
|
-
| `value` | `string` | `''` | Input value
|
|
247
|
-
| `type` | `string` | `'text'` | HTML input type
|
|
248
|
-
| `placeholder` | `string` | `''` | Placeholder text
|
|
249
|
-
| `name` | `string` | `''` | Form field name
|
|
250
|
-
| `disabled` | `boolean` | `false` | Disabled state
|
|
251
|
-
| `readonly` | `boolean` | `false` | Read-only state
|
|
252
|
-
| `required` | `boolean` | `false` | Required validation
|
|
253
|
-
| `clearable` | `boolean` | `false` | Show clear button
|
|
254
|
-
| `full` | `boolean` | `false` | Full width
|
|
255
|
-
| `borderless` | `boolean` | `false` |
|
|
256
|
-
| `aria-label` | `string` | — | Accessible label
|
|
280
|
+
| Attribute | Type | Default | Description |
|
|
281
|
+
| ------------- | --------- | -------- | ------------------------------------------------------------------------------------------------- |
|
|
282
|
+
| `value` | `string` | `''` | Input value |
|
|
283
|
+
| `type` | `string` | `'text'` | HTML input type |
|
|
284
|
+
| `placeholder` | `string` | `''` | Placeholder text |
|
|
285
|
+
| `name` | `string` | `''` | Form field name |
|
|
286
|
+
| `disabled` | `boolean` | `false` | Disabled state |
|
|
287
|
+
| `readonly` | `boolean` | `false` | Read-only state |
|
|
288
|
+
| `required` | `boolean` | `false` | Required validation |
|
|
289
|
+
| `clearable` | `boolean` | `false` | Show clear button |
|
|
290
|
+
| `full` | `boolean` | `false` | Full width |
|
|
291
|
+
| `borderless` | `boolean` | `false` | Ghost form: removes border, background, and shadow; keeps padding, height metrics, and focus ring |
|
|
292
|
+
| `aria-label` | `string` | — | Accessible label |
|
|
257
293
|
|
|
258
294
|
**Events:** `input`, `change`, `focus`, `blur`
|
|
259
295
|
|
|
@@ -269,24 +305,24 @@ Text input with clearable, prefix/suffix slots.
|
|
|
269
305
|
|
|
270
306
|
Multi-line text input with auto-resize.
|
|
271
307
|
|
|
272
|
-
| Attribute | Type | Default | Description
|
|
273
|
-
| ----------------- | --------- | ------- |
|
|
274
|
-
| `value` | `string` | `''` | Textarea value
|
|
275
|
-
| `placeholder` | `string` | `''` | Placeholder text
|
|
276
|
-
| `rows` | `number` | `3` | Visible rows
|
|
277
|
-
| `name` | `string` | `''` | Form field name
|
|
278
|
-
| `disabled` | `boolean` | `false` | Disabled state
|
|
279
|
-
| `readonly` | `boolean` | `false` | Read-only state
|
|
280
|
-
| `required` | `boolean` | `false` | Required validation
|
|
281
|
-
| `clearable` | `boolean` | `false` | Show clear button
|
|
282
|
-
| `full` | `boolean` | `false` | Full width
|
|
283
|
-
| `borderless` | `boolean` | `false` |
|
|
284
|
-
| `autosize` | `boolean` | `false` | Auto-resize height
|
|
285
|
-
| `max-height` | `number` | `0` | Autosize max height (px); `0` = unlimited
|
|
286
|
-
| `minlength` | `number` | — | Minimum length validation
|
|
287
|
-
| `maxlength` | `number` | — | Maximum length validation
|
|
288
|
-
| `aria-label` | `string` | — | Accessible label
|
|
289
|
-
| `aria-labelledby` | `string` | — | Accessible label reference
|
|
308
|
+
| Attribute | Type | Default | Description |
|
|
309
|
+
| ----------------- | --------- | ------- | ------------------------------------------------------------------------------------------------- |
|
|
310
|
+
| `value` | `string` | `''` | Textarea value |
|
|
311
|
+
| `placeholder` | `string` | `''` | Placeholder text |
|
|
312
|
+
| `rows` | `number` | `3` | Visible rows |
|
|
313
|
+
| `name` | `string` | `''` | Form field name |
|
|
314
|
+
| `disabled` | `boolean` | `false` | Disabled state |
|
|
315
|
+
| `readonly` | `boolean` | `false` | Read-only state |
|
|
316
|
+
| `required` | `boolean` | `false` | Required validation |
|
|
317
|
+
| `clearable` | `boolean` | `false` | Show clear button |
|
|
318
|
+
| `full` | `boolean` | `false` | Full width |
|
|
319
|
+
| `borderless` | `boolean` | `false` | Ghost form: removes border, background, and shadow; keeps padding, height metrics, and focus ring |
|
|
320
|
+
| `autosize` | `boolean` | `false` | Auto-resize height |
|
|
321
|
+
| `max-height` | `number` | `0` | Autosize max height (px); `0` = unlimited |
|
|
322
|
+
| `minlength` | `number` | — | Minimum length validation |
|
|
323
|
+
| `maxlength` | `number` | — | Maximum length validation |
|
|
324
|
+
| `aria-label` | `string` | — | Accessible label |
|
|
325
|
+
| `aria-labelledby` | `string` | — | Accessible label reference |
|
|
290
326
|
|
|
291
327
|
**Events:** `input`, `change`, `focus`, `blur`
|
|
292
328
|
|
|
@@ -347,43 +383,57 @@ Child `<web-ui-option>` elements register via `option-register` / `option-unregi
|
|
|
347
383
|
|
|
348
384
|
**CSS Custom Properties:**
|
|
349
385
|
|
|
350
|
-
| Property | Default
|
|
351
|
-
| ------------------------- |
|
|
352
|
-
| `--wui-select-max-width` | `500px`
|
|
353
|
-
| `--wui-
|
|
386
|
+
| Property | Default | Description |
|
|
387
|
+
| ------------------------- | ---------------------------------- | ------------------------------- |
|
|
388
|
+
| `--wui-select-max-width` | `500px` | Dropdown max width |
|
|
389
|
+
| `--wui-select-max-height` | `200px` | Dropdown scroll area max height |
|
|
390
|
+
| `--wui-overlay-min-width` | `200px` | Dropdown min width |
|
|
391
|
+
| `--wui-select-bg-hover` | `--wui-color-surface-glass-hover` | Trigger hover background |
|
|
392
|
+
| `--wui-select-bg-active` | `--wui-color-surface-glass-active` | Trigger pressed/open background |
|
|
393
|
+
|
|
394
|
+
Portal panels mirror these variables from the host element when created; change the host before opening a portal panel for a new value to apply.
|
|
354
395
|
|
|
355
396
|
#### `<web-ui-autocomplete>`
|
|
356
397
|
|
|
357
398
|
Editable combobox with input filtering and single option selection.
|
|
358
399
|
|
|
359
|
-
| Attribute
|
|
360
|
-
|
|
|
361
|
-
| `value`
|
|
362
|
-
| `selected-value`
|
|
363
|
-
| `placeholder`
|
|
364
|
-
| `
|
|
365
|
-
| `
|
|
366
|
-
| `
|
|
367
|
-
| `
|
|
368
|
-
| `
|
|
369
|
-
| `
|
|
370
|
-
| `
|
|
371
|
-
| `
|
|
372
|
-
| `
|
|
373
|
-
| `
|
|
400
|
+
| Attribute | Type | Default | Description |
|
|
401
|
+
| -------------------- | ---------------------------------- | ------------ | ------------------------------------------------------------------------------------------------- |
|
|
402
|
+
| `value` | `string` | `''` | Current input text (form value) |
|
|
403
|
+
| `selected-value` | `string` | `''` | Value of the enabled option exactly matching the input label (derived, read-only) |
|
|
404
|
+
| `placeholder` | `string` | `''` | Placeholder text |
|
|
405
|
+
| `borderless` | `boolean` | `false` | Ghost form: removes border, background, and shadow; keeps padding, height metrics, and focus ring |
|
|
406
|
+
| `filter` | `'none' \| 'prefix' \| 'contains'` | `'contains'` | Candidate filtering mode (matched against option label) |
|
|
407
|
+
| `name` | `string` | `''` | Form field name |
|
|
408
|
+
| `disabled` | `boolean` | `false` | Disabled state |
|
|
409
|
+
| `readonly` | `boolean` | `false` | Read-only state (no typing, no dropdown) |
|
|
410
|
+
| `required` | `boolean` | `false` | Required validation |
|
|
411
|
+
| `allow-custom-value` | `boolean` | `false` | Allow Enter to submit a custom value that is not among candidates |
|
|
412
|
+
| `portal` | `boolean` | `false` | Render dropdown in theme overlay |
|
|
413
|
+
| `no-scroll-lock` | `boolean` | `false` | Do not lock body scroll when open |
|
|
414
|
+
| `overlayContainer` | `HTMLElement \| () => HTMLElement` | — | Explicit portal container |
|
|
415
|
+
| `aria-label` | `string` | — | Accessible name |
|
|
416
|
+
| `aria-labelledby` | `string` | — | Accessible name references |
|
|
374
417
|
|
|
375
418
|
**Events:** `input`, `change`, `focus`, `blur`, `open-change` (`CustomEvent<{ open: boolean }>`)
|
|
376
419
|
|
|
377
|
-
**Slots:** `default` (project `<web-ui-option>` elements)
|
|
420
|
+
**Slots:** `default` (project `<web-ui-option>` elements), `empty` (replace the “no matches” state; falls back to “No matches”)
|
|
378
421
|
|
|
379
422
|
Typing filters the option list by label (`contains` or `prefix`, or `none` to disable filtering). Selecting an option fills the input with its label and exposes the option's value via `selected-value`; `change` fires on selection commit. Supports ArrowDown/ArrowUp/Enter/Escape keyboard navigation.
|
|
380
423
|
|
|
424
|
+
When `allow-custom-value` is enabled, pressing Enter with no active option and no matching candidate commits the raw input as a custom value and closes the panel. `change` fires and `selected-value` remains empty. The component does not create an option automatically or trim the raw value. Text matching a disabled option cannot bypass the disabled state or derive as a selected option.
|
|
425
|
+
|
|
426
|
+
Use `<div slot="empty">…</div>` for static, non-interactive empty-state content. Portal rendering moves this node into the floating panel and restores it to the host after close.
|
|
427
|
+
|
|
381
428
|
**CSS Custom Properties:**
|
|
382
429
|
|
|
383
|
-
| Property
|
|
384
|
-
|
|
|
385
|
-
| `--wui-autocomplete-max-width`
|
|
386
|
-
| `--wui-
|
|
430
|
+
| Property | Default | Description |
|
|
431
|
+
| ------------------------------- | ------- | ------------------------------- |
|
|
432
|
+
| `--wui-autocomplete-max-width` | `500px` | Dropdown max width |
|
|
433
|
+
| `--wui-autocomplete-max-height` | `200px` | Dropdown scroll area max height |
|
|
434
|
+
| `--wui-overlay-min-width` | `200px` | Dropdown minimum width |
|
|
435
|
+
|
|
436
|
+
Portal panels mirror these variables from the host element when created; change the host before opening a portal panel for a new value to apply.
|
|
387
437
|
|
|
388
438
|
#### `<web-ui-slider>`
|
|
389
439
|
|
|
@@ -415,8 +465,8 @@ Supports ArrowLeft/Right/Up/Down, Home/End, PageUp/PageDown keyboard navigation.
|
|
|
415
465
|
| `--wui-slider-vertical-height` | `200px` | Vertical slider height |
|
|
416
466
|
| `--wui-slider-height` | `var(--wui-slider-track-size, 6px)` | Track thickness |
|
|
417
467
|
| `--wui-slider-track-size` | `6px` | Track size |
|
|
418
|
-
| `--wui-slider-thumb-width` | `
|
|
419
|
-
| `--wui-slider-thumb-height` | `
|
|
468
|
+
| `--wui-slider-thumb-width` | `30px` | Thumb width |
|
|
469
|
+
| `--wui-slider-thumb-height` | `20px` | Thumb height |
|
|
420
470
|
| `--wui-slider-marks-inset` | `0` | Marks inset from edges |
|
|
421
471
|
|
|
422
472
|
#### `<web-ui-checkbox>`
|
|
@@ -538,7 +588,7 @@ Styled button with variants and loading state.
|
|
|
538
588
|
| `variant` | `'primary' \| 'secondary' \| 'ghost' \| 'danger' \| 'glass'` | `'glass'` | Button variant |
|
|
539
589
|
| `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | Inner-button type; invalid values become `button` |
|
|
540
590
|
| `disabled` | `boolean` | `false` | Disabled state |
|
|
541
|
-
| `loading` | `boolean` | `false` | Loading spinner
|
|
591
|
+
| `loading` | `boolean` | `false` | Loading spinner; with `icon`, the spinner replaces the icon content |
|
|
542
592
|
| `full` | `boolean` | `false` | Full width |
|
|
543
593
|
| `icon` | `boolean` | `false` | Icon-only mode |
|
|
544
594
|
| `size` | `string` | `''` | Button height in px (icon mode: also sets min-width for square default) |
|
|
@@ -553,6 +603,9 @@ form-associated control when external form submission behavior is required.
|
|
|
553
603
|
|
|
554
604
|
Disabled and loading states prevent `click` events.
|
|
555
605
|
|
|
606
|
+
When `icon` and `loading` are both set, the button renders only the spinner, and the default-slot icon is not
|
|
607
|
+
projected. The icon-mode geometry stays square by default, except for `full` or an explicit width.
|
|
608
|
+
|
|
556
609
|
**CSS Custom Properties:**
|
|
557
610
|
|
|
558
611
|
| Property | Default | Description |
|
|
@@ -585,31 +638,33 @@ Applies the direction to the grouped button layout without changing child button
|
|
|
585
638
|
|
|
586
639
|
Modal dialog using native `<dialog>` with `showModal()`.
|
|
587
640
|
|
|
588
|
-
| Attribute | Type | Default | Description
|
|
589
|
-
| ------------------- | --------- | ------- |
|
|
590
|
-
| `open` | `boolean` | `false` | Dialog visibility
|
|
591
|
-
| `no-scroll-lock` | `boolean` | `false` | Do not lock body scroll when open
|
|
592
|
-
| `no-backdrop-close` | `boolean` | `false` | Do not close on backdrop click
|
|
593
|
-
| `no-escape-close` | `boolean` | `false` | Do not close when Escape is pressed
|
|
641
|
+
| Attribute | Type | Default | Description |
|
|
642
|
+
| ------------------- | --------- | ------- | ------------------------------------------------------------------------------ |
|
|
643
|
+
| `open` | `boolean` | `false` | Dialog visibility |
|
|
644
|
+
| `no-scroll-lock` | `boolean` | `false` | Do not lock body scroll when open |
|
|
645
|
+
| `no-backdrop-close` | `boolean` | `false` | Do not close on backdrop click |
|
|
646
|
+
| `no-escape-close` | `boolean` | `false` | Do not close when Escape is pressed |
|
|
647
|
+
| `controlled` | `boolean` | `false` | Escape and backdrop only request `open=false`; the consumer must update `open` |
|
|
594
648
|
|
|
595
|
-
**Events:** `open-change` (`CustomEvent<{ open: boolean }>`)
|
|
649
|
+
**Events:** `open-change` (`CustomEvent<{ open: boolean }>`). With `controlled`, Escape and backdrop clicks only request `open=false` and the dialog stays open until the consumer writes `open=false`. Programmatic APIs (`showModal()`, `close()`, assigning `open`) stay direct and never emit. Native dialog closure (e.g. form `method="dialog"`) is restored to the controlled open state and re-emits the request.
|
|
596
650
|
|
|
597
651
|
**Slots:** `body`, `title`, `default`, `footer`
|
|
598
652
|
|
|
599
653
|
**Methods:** `showModal()`, `close()`
|
|
600
654
|
|
|
601
|
-
Uses native `<dialog>` with `@cancel` prevention. Escape calls `close()` unless `no-escape-close` is present. Click on backdrop closes dialog unless `no-backdrop-close` is present.
|
|
655
|
+
Uses native `<dialog>` with `@cancel` prevention. Escape calls `close()` unless `no-escape-close` is present. Click on backdrop closes dialog unless `no-backdrop-close` is present. With `controlled`, both only emit the close request instead.
|
|
602
656
|
|
|
603
657
|
**CSS Custom Properties:**
|
|
604
658
|
|
|
605
|
-
| Property | Default
|
|
606
|
-
| ------------------------- |
|
|
607
|
-
| `--wui-dialog-max-width` | `360px`
|
|
608
|
-
| `--wui-dialog-overlay-bg` | `var(--wui-color-backdrop)`
|
|
659
|
+
| Property | Default | Description |
|
|
660
|
+
| ------------------------- | ---------------------------------- | -------------------------------------------------------------- |
|
|
661
|
+
| `--wui-dialog-max-width` | `360px` | Dialog max width |
|
|
662
|
+
| `--wui-dialog-overlay-bg` | `var(--wui-color-backdrop)` | Backdrop background |
|
|
663
|
+
| `--wui-dialog-bg` | `var(--wui-color-surface-overlay)` | Glass card background, falls back to `rgb(246 246 246 / 0.88)` |
|
|
609
664
|
|
|
610
665
|
#### `<web-ui-drawer>`
|
|
611
666
|
|
|
612
|
-
Side drawer using native `<dialog>` with closing animation.
|
|
667
|
+
Side drawer using native `<dialog>` with closing animation. In non-headless mode the drawer renders as a floating rounded card inset from all viewport edges (matching the layout sidebar's card language), so elastic drag distances read as margin changes rather than gaps.
|
|
613
668
|
|
|
614
669
|
| Attribute | Type | Default | Description |
|
|
615
670
|
| ------------------- | ---------------------------------------- | --------- | --------------------------------------------------------------------------------- |
|
|
@@ -619,11 +674,12 @@ Side drawer using native `<dialog>` with closing animation.
|
|
|
619
674
|
| `closable` | `boolean` | `false` | Show close button |
|
|
620
675
|
| `no-scroll-lock` | `boolean` | `false` | Do not lock body scroll when open |
|
|
621
676
|
| `no-backdrop-close` | `boolean` | `false` | Do not close on backdrop click |
|
|
622
|
-
| `
|
|
677
|
+
| `controlled` | `boolean` | `false` | User close actions only request `open=false`; the consumer must update `open` |
|
|
623
678
|
| `headless` | `boolean` | `false` | Keep only overlay behavior and render the default slot without built-in drawer UI |
|
|
624
679
|
| `dialog-label` | `string` | `''` | Accessible name for the internal native dialog; required in headless mode |
|
|
680
|
+
| `draggable` | `boolean` | `false` | Show a drag bar on the inner edge for drag-to-close gestures |
|
|
625
681
|
|
|
626
|
-
**Events:** `open-change` (`CustomEvent<{ open: boolean }>`). With `
|
|
682
|
+
**Events:** `open-change` (`CustomEvent<{ open: boolean }>`). With `controlled`, Escape, backdrop, the built-in close button and drag-release only request `open=false`; the drawer remains open until the consumer writes `open=false`. Programmatic APIs (`show()`, `close()`, assigning `open`) stay direct and never emit. If native dialog closure occurs while a request is pending, the drawer restores its open top-layer state and emits the same request. With nested drawers, an inner `open-change` bubbles through the outer root (composed event); distinguish by `event.target`.
|
|
627
683
|
|
|
628
684
|
**Slots:** `header`, `default`, `footer` — with `headless`, only the `default` slot is rendered.
|
|
629
685
|
|
|
@@ -633,14 +689,54 @@ Side drawer using native `<dialog>` with closing animation.
|
|
|
633
689
|
|
|
634
690
|
Closing keeps the native dialog in the top layer until the `--wui-duration-drawer-exit` transition completes (240ms by default), then calls `dialog.close()`. Escape always follows this close path; `no-backdrop-close` controls backdrop clicks only.
|
|
635
691
|
|
|
692
|
+
**Drag to close:** With `draggable`, a gray capsule drag bar appears on the drawer's inner edge (left edge for `right`, right edge for `left`, bottom edge for `top`, top edge for `bottom`) while open. Dragging follows the pointer in real time (backdrop fades proportionally); releasing past ~1/3 of the drawer size or with a fast closing flick springs the drawer shut, otherwise it springs back open. The close direction is placement-aware. With `controlled`, release past the threshold only emits `open-change(false)`; the drawer holds at the closed position briefly (120ms write-back window) and springs back open if the consumer rejects or misses the write-back. Drag-to-open is not supported because the closed drawer renders nothing outside the native dialog. Under `prefers-reduced-motion`, release snaps instantly without spring animation.
|
|
693
|
+
|
|
636
694
|
**CSS Custom Properties:**
|
|
637
695
|
|
|
638
|
-
| Property | Default | Description
|
|
639
|
-
| ------------------------- | ---------------------------------- |
|
|
640
|
-
| `--wui-drawer-width` | `320px` | Drawer width
|
|
641
|
-
| `--wui-drawer-height` | `300px` | Drawer height (top/bottom)
|
|
642
|
-
| `--wui-drawer-bg` | `var(--wui-color-surface-overlay)` | Drawer body background
|
|
643
|
-
| `--wui-drawer-
|
|
696
|
+
| Property | Default | Description |
|
|
697
|
+
| ------------------------- | ---------------------------------- | ---------------------------------------------------------------------------- |
|
|
698
|
+
| `--wui-drawer-width` | `320px` | Drawer width |
|
|
699
|
+
| `--wui-drawer-height` | `300px` | Drawer height (top/bottom) |
|
|
700
|
+
| `--wui-drawer-bg` | `var(--wui-color-surface-overlay)` | Drawer body background |
|
|
701
|
+
| `--wui-drawer-radius` | `28px` | Floating card corner radius (non-headless) |
|
|
702
|
+
| `--wui-drawer-inset` | `8px` | Floating card viewport inset (non-headless); `0` gives edge-to-edge geometry |
|
|
703
|
+
| `--wui-drawer-overlay-bg` | `rgb(0 0 0 / 0.12)` | Backdrop background |
|
|
704
|
+
|
|
705
|
+
---
|
|
706
|
+
|
|
707
|
+
### In-flow Disclosure
|
|
708
|
+
|
|
709
|
+
#### `<web-ui-collapse>`
|
|
710
|
+
|
|
711
|
+
In-flow expand/collapse container with animated height (or width) transition. Single element with two slots; no portal, no scroll lock, no focus management.
|
|
712
|
+
|
|
713
|
+
| Attribute | Type | Default | Description |
|
|
714
|
+
| -------------- | --------- | ------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
715
|
+
| `open` | `boolean` | `false` | Expanded state; self-managed on interaction, `open-change` emits only for user-originated toggles |
|
|
716
|
+
| `disabled` | `boolean` | `false` | Ignores trigger clicks and sets `aria-disabled` on the trigger element; expanded content is kept |
|
|
717
|
+
| `horizontal` | `boolean` | `false` | Animate width instead of height |
|
|
718
|
+
| `keep-mounted` | `boolean` | `false` | Closed state keeps the content in the 0fr track with `inert` (scroll position and layout measurable) instead of `hidden` |
|
|
719
|
+
|
|
720
|
+
**Events:** `open-change` (`CustomEvent<{ open: boolean }>`). Emitted only for user-originated toggles (trigger click). Programmatic writes (`open`, `show()`, `close()`, `toggle()`) never emit. Nested collapses: an inner `open-change` bubbles through the outer root (composed event); distinguish by `event.target`.
|
|
721
|
+
|
|
722
|
+
**Slots:** `default` (trigger) + `content` (collapsible content)
|
|
723
|
+
|
|
724
|
+
**Methods:** `show()`, `close()`, `toggle()`
|
|
725
|
+
|
|
726
|
+
```html
|
|
727
|
+
<web-ui-collapse>
|
|
728
|
+
<button type="button">Toggle me</button>
|
|
729
|
+
<div slot="content">Collapsible content</div>
|
|
730
|
+
</web-ui-collapse>
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
The initial `open` attribute settles instantly without playing the animation. Nested collapses are supported.
|
|
734
|
+
|
|
735
|
+
**Trigger semantics:** interaction comes from the element you put in the default slot — a native `<button>`, `<web-ui-button>`, or any other interactive element supplies Enter/Space activation and focus natively. The collapse writes `aria-expanded` / `aria-controls` (pointing at its content track) and `aria-disabled` onto the first assigned element in the trigger slot. Use an interactive element as the trigger: a plain `<span>` is clickable but has no keyboard/focus semantics.
|
|
736
|
+
|
|
737
|
+
**Closed-state semantics:** the consumer's light DOM is never moved or unmounted. Default closed state applies `hidden` to the internal content container; with `keep-mounted` the inner container is marked `inert` while staying measurable inside the collapsed track.
|
|
738
|
+
|
|
739
|
+
**Known limitations:** the `horizontal` animation reflows content while width changes.
|
|
644
740
|
|
|
645
741
|
---
|
|
646
742
|
|
|
@@ -668,6 +764,8 @@ Popover overlay anchored to trigger element.
|
|
|
668
764
|
|
|
669
765
|
Hover mode uses `pointerenter`/`pointerleave` with delay. Click mode toggles on trigger click. Manual mode only responds to imperative `show()`/`close()`.
|
|
670
766
|
|
|
767
|
+
**Trigger ARIA:** open/close state is written back to the trigger element: `aria-expanded` and `aria-controls` (pointing at the panel) are set on the first assigned element in the `trigger` slot (the wrapper retains them for backward compatibility). Put an interactive element (native button, `web-ui-button`) in the trigger slot.
|
|
768
|
+
|
|
671
769
|
#### `<web-ui-tooltip>`
|
|
672
770
|
|
|
673
771
|
Tooltip overlay using pointer/focus triggers.
|
|
@@ -688,7 +786,7 @@ Tooltip overlay using pointer/focus triggers.
|
|
|
688
786
|
|
|
689
787
|
**Slots:** `default` (trigger), `content` (tooltip panel)
|
|
690
788
|
|
|
691
|
-
`open` is a
|
|
789
|
+
`open` is a self-managed visibility property. Pointer/focus triggers update it, and direct property writes synchronize the local or portal panel; `open-change` emits only for user-originated open/close. Adjacent tooltips open immediately after the first tooltip is visible; pointer/focus triggers otherwise use delay timers.
|
|
692
790
|
|
|
693
791
|
**CSS Custom Properties:**
|
|
694
792
|
|
|
@@ -714,6 +812,8 @@ Right-click context menu.
|
|
|
714
812
|
|
|
715
813
|
Opens on `contextmenu` event. Menu items: `<web-ui-dropdown-item>`, `<web-ui-dropdown-divider>`, `<web-ui-dropdown-header>`. Supports keyboard navigation (Arrow keys, Enter, Escape) and submenu hover with `pointerenter`.
|
|
716
814
|
|
|
815
|
+
While the menu is open, consumer code may conditionally render, move, or remove menu items (e.g. Vue `v-if`) without re-inserting them at the host element; changes inside the portal are reconciled automatically, and framework anchors are returned to the host on close so subsequent framework patches keep working.
|
|
816
|
+
|
|
717
817
|
---
|
|
718
818
|
|
|
719
819
|
### Menu
|
|
@@ -739,6 +839,8 @@ Dropdown menu with multi-level submenu support.
|
|
|
739
839
|
|
|
740
840
|
Items: `<web-ui-dropdown-item>`, `<web-ui-dropdown-divider>`, `<web-ui-dropdown-header>`. Submenus via `submenu` attribute on `<web-ui-dropdown-item>`. Full keyboard navigation (Arrow keys, Home, End, Enter, Space, Escape).
|
|
741
841
|
|
|
842
|
+
**Trigger ARIA:** `aria-haspopup="menu"`, `aria-expanded` and `aria-controls` (pointing at the root menu panel) are written back to the first assigned element in the `trigger` slot. Put an interactive element in the trigger slot.
|
|
843
|
+
|
|
742
844
|
#### `<web-ui-dropdown-item>`
|
|
743
845
|
|
|
744
846
|
Menu item for dropdown or context-menu.
|
|
@@ -878,15 +980,20 @@ WebUiSpinner.hide() // hide
|
|
|
878
980
|
|
|
879
981
|
Responsive page layout with an optional full-width banner, a collapsible desktop sidebar, and a headless-drawer mobile sidebar. The page itself scrolls; the desktop sidebar and header stick to the viewport after the banner scrolls away.
|
|
880
982
|
|
|
881
|
-
| Attribute | Type | Default | Description
|
|
882
|
-
| ------------------- | --------- | --------- |
|
|
883
|
-
| `sidebar-collapsed` | `boolean` | `false` | Controlled desktop sidebar collapsed state
|
|
884
|
-
| `sidebar-open` | `boolean` | `false` | Controlled mobile sidebar drawer open state
|
|
885
|
-
| `header-glow` | `boolean` | `false` | Decorative Header background glow behind slot content
|
|
886
|
-
| `sidebar-width` | `string` | `'240px'` | Expanded desktop and mobile sidebar width
|
|
887
|
-
| `collapsed-width` | `string` | `'72px'` | Collapsed desktop sidebar width
|
|
983
|
+
| Attribute | Type | Default | Description |
|
|
984
|
+
| ------------------- | --------- | --------- | -------------------------------------------------------------------------------------------------- |
|
|
985
|
+
| `sidebar-collapsed` | `boolean` | `false` | Controlled desktop sidebar collapsed state |
|
|
986
|
+
| `sidebar-open` | `boolean` | `false` | Controlled mobile sidebar drawer open state |
|
|
987
|
+
| `header-glow` | `boolean` | `false` | Decorative Header background glow behind slot content |
|
|
988
|
+
| `sidebar-width` | `string` | `'240px'` | Expanded desktop and mobile sidebar width |
|
|
989
|
+
| `collapsed-width` | `string` | `'72px'` | Collapsed desktop sidebar width |
|
|
990
|
+
| `sidebar-resizable` | `boolean` | `false` | Enable drag-to-resize on the desktop sidebar edge |
|
|
991
|
+
| `sidebar-min-width` | `string` | — | Resize lower bound (px); falls back to `collapsed-width` |
|
|
992
|
+
| `sidebar-max-width` | `string` | — | Resize upper bound (px); clamped to half the viewport, which always wins over the configured value |
|
|
993
|
+
|
|
994
|
+
**Events:** `sidebar-collapsed-change` (`CustomEvent<{ collapsed: boolean }>`) requests a desktop collapse-state update. `sidebar-open-change` (`CustomEvent<{ open: boolean }>`) requests a mobile drawer open-state update. `sidebar-width-change` (`CustomEvent<{ width: string }>`) requests a sidebar width update after a resize drag ends. Consumers must write the requested value back to the corresponding controlled property.
|
|
888
995
|
|
|
889
|
-
**
|
|
996
|
+
**Sidebar resize:** With `sidebar-resizable`, a resize handle appears on the desktop sidebar's right edge (hidden while collapsed). Hovering or dragging shows a 3px accent vertical line with a `col-resize` cursor. Dragging updates the width in real time (transition suppressed, clamped to `[min, max]` and the viewport); releasing emits `sidebar-width-change` with the final pixel width and returns control to the `sidebar-width` property once the consumer writes it back. `pointercancel` restores the property-controlled width without emitting. The handle is keyboard-operable (WAI-ARIA splitter pattern): focus it and use ←/→ to step by 16px (Shift for 64px), Home/End to jump to min/max, Enter to commit via the same `sidebar-width-change` request, and Escape to revert an uncommitted adjustment. The mobile drawer always supports drag-to-close via its built-in `draggable` drawer.
|
|
890
997
|
|
|
891
998
|
| Slot | Description |
|
|
892
999
|
| --------- | ----------------------------------------------------------------------------------------- |
|
|
@@ -898,15 +1005,16 @@ Responsive page layout with an optional full-width banner, a collapsible desktop
|
|
|
898
1005
|
|
|
899
1006
|
`web-ui-layout` constrains the sidebar card and owns the desktop toggle area, but does not create a sidebar scrollport. To make only part of the sidebar scroll, make the `sidebar` slot root a `height: 100%; min-height: 0` flex column and apply `overflow-y: auto` to the intended child. This keeps consumer-defined headers and footers fixed without adding extra public slots.
|
|
900
1007
|
|
|
901
|
-
At `640px` and below, the sidebar becomes a headless `web-ui-drawer`. The consumer content is rendered in the same rounded sidebar card; the mobile toggle appears in the header row.
|
|
1008
|
+
At `640px` and below, the sidebar becomes a headless `web-ui-drawer`. The consumer content is rendered in the same rounded sidebar card; the mobile toggle appears in the header row as a glass button. Its left inset defaults to `8px`; align it with your own header padding via `--wui-layout-mobile-toggle-inset`.
|
|
902
1009
|
|
|
903
1010
|
`header-glow` adds a pointer-transparent decorative glow behind header-slot content and the mobile toggle. It is a Header background rather than a foreground layer, so slotted content remains above it. Override its color with `--wui-layout-header-glow-color` (default: `--wui-color-page`). The glow concentration and spread are controlled by the internal variable `--wui-layout-header-glow-height` (default: `150%`); increase for stronger coverage, decrease for a subtler effect. Layout layers are ordered as Header (`10`) < Auxiliary (`20`) < Banner (`30`) < Tabbar (`40`) < Sidebar (`50`).
|
|
904
1011
|
|
|
905
1012
|
**CSS Custom Properties:**
|
|
906
1013
|
|
|
907
|
-
| Property
|
|
908
|
-
|
|
|
909
|
-
| `--wui-layout-sidebar-radius`
|
|
1014
|
+
| Property | Default | Description |
|
|
1015
|
+
| ---------------------------------- | ------- | ------------------------------------------------ |
|
|
1016
|
+
| `--wui-layout-sidebar-radius` | `24px` | Border radius of sidebar card (desktop & mobile) |
|
|
1017
|
+
| `--wui-layout-mobile-toggle-inset` | `8px` | Left inset of the mobile header toggle |
|
|
910
1018
|
|
|
911
1019
|
#### `<web-ui-back-top>`
|
|
912
1020
|
|
|
@@ -974,7 +1082,7 @@ Defines foundation, color, layer, shadow, and motion tokens for its subtree. `mo
|
|
|
974
1082
|
| ------------------------- | ------- | ------------------------------------------------ |
|
|
975
1083
|
| `--wui-font-size` | `14px` | Base font size for controls |
|
|
976
1084
|
| `--wui-input-width` | `200px` | Default width for compact form controls |
|
|
977
|
-
| `--wui-control-size` | `
|
|
1085
|
+
| `--wui-control-size` | `36px` | Default height and square min-width for controls |
|
|
978
1086
|
| `--wui-overlay-min-width` | `200px` | Minimum anchored overlay width |
|
|
979
1087
|
| `--wui-focus-ring-width` | `3px` | Focus indicator width |
|
|
980
1088
|
|
|
@@ -994,32 +1102,38 @@ Defines foundation, color, layer, shadow, and motion tokens for its subtree. `mo
|
|
|
994
1102
|
| `--wui-layer-toast` | `200` | Toasts |
|
|
995
1103
|
| `--wui-layer-loading` | `300` | Blocking loading surfaces |
|
|
996
1104
|
|
|
997
|
-
**Motion tokens:** duration defaults are `--wui-duration-press: 80ms`, `--wui-duration-feedback: 100ms`, `--wui-duration-trigger: 160ms`, `--wui-duration-focus: 200ms`, `--wui-duration-menu-enter: 140ms`, `--wui-duration-menu-exit: 100ms`, `--wui-duration-overlay-enter: 180ms`, `--wui-duration-overlay-exit: 140ms`, `--wui-duration-drawer-enter: 280ms`, `--wui-duration-drawer-exit: 240ms`, `--wui-duration-layout: 200ms`. Easing tokens are `--wui-ease-enter` and `--wui-ease-slide`; enter scale is `--wui-scale-enter: 0.97`.
|
|
1105
|
+
**Motion tokens:** duration defaults are `--wui-duration-press: 80ms`, `--wui-duration-feedback: 100ms`, `--wui-duration-trigger: 160ms`, `--wui-duration-focus: 200ms`, `--wui-duration-menu-enter: 140ms`, `--wui-duration-menu-exit: 100ms`, `--wui-duration-overlay-enter: 180ms`, `--wui-duration-overlay-exit: 140ms`, `--wui-duration-drawer-enter: 280ms`, `--wui-duration-drawer-exit: 240ms`, `--wui-duration-drawer-nested: 450ms`, `--wui-duration-collapse-enter: 200ms`, `--wui-duration-collapse-exit: 160ms`, `--wui-duration-layout: 200ms`. Easing tokens are `--wui-ease-enter` and `--wui-ease-slide`; enter scale is `--wui-scale-enter: 0.97`. Hover/active background feedback switches instantly with no transition; checked/pressed/focus and overlay enter/exit transitions are unaffected.
|
|
998
1106
|
|
|
999
1107
|
**Color tokens:**
|
|
1000
1108
|
|
|
1001
1109
|
| Property | Light default | Dark default | Description |
|
|
1002
1110
|
| ---------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------- |
|
|
1003
|
-
| `--wui-color-page` | `#fff` | `#
|
|
1111
|
+
| `--wui-color-page` | `#fff` | `#242628` | Page background |
|
|
1004
1112
|
| `--wui-color-surface` | `#fff` | `#2c2c2e` | Plain surface |
|
|
1005
1113
|
| `--wui-color-surface-raised` | `#f2f2f7` | `#2c2c2e` | Raised surface |
|
|
1006
1114
|
| `--wui-color-surface-control` | `#dfdfdf` | `#3a3a3c` | Neutral control surface |
|
|
1007
1115
|
| `--wui-color-surface-track` | `#e5e5ea` | `#444446` | Slider and switch track surface |
|
|
1116
|
+
| `--wui-color-surface-menu` | `rgb(246 246 246 / 0.82)` | `rgb(30 30 32 / 0.92)` | Menu and floating panel surface |
|
|
1008
1117
|
| `--wui-color-surface-glass` | `rgb(250 250 250 / 0.34)` | `rgb(44 44 46 / 0.42)` | Liquid glass surface |
|
|
1009
1118
|
| `--wui-color-surface-glass-hover` | `color-mix(... text 6%, surface-glass)` | `color-mix(... text 6%, surface-glass)` | Full glass hover background |
|
|
1010
1119
|
| `--wui-color-surface-glass-active` | `color-mix(... text 15%, surface-glass)` | `color-mix(... text 15%, surface-glass)` | Full glass pressed background |
|
|
1011
|
-
| `--wui-color-surface-overlay` | `rgb(246 246 246 / 0.82)` | `rgb(
|
|
1012
|
-
| `--wui-color-
|
|
1120
|
+
| `--wui-color-surface-overlay` | `rgb(246 246 246 / 0.82)` | `rgb(32 34 34 / 0.9)` | Translucent overlay surface |
|
|
1121
|
+
| `--wui-color-surface-segmented` | `#e5e5ea` | `#3a3a3c` | Segmented track surface |
|
|
1122
|
+
| `--wui-color-surface-selected` | `#fff` | `#5c5c5e` | Segmented selected indicator |
|
|
1123
|
+
| `--wui-color-text` | `#1b1b1b` | `#e9eaea` | Primary text |
|
|
1013
1124
|
| `--wui-color-text-secondary` | `#6a6a6a` | `#a1a1a6` | Secondary text |
|
|
1014
1125
|
| `--wui-color-text-tertiary` | `color-mix(in srgb, var(--wui-color-text) 35%, transparent)` | `color-mix(in srgb, var(--wui-color-text) 42%, transparent)` | Tertiary text and quiet icons |
|
|
1015
1126
|
| `--wui-color-text-disabled` | `color-mix(in srgb, var(--wui-color-text) 32%, transparent)` | `color-mix(in srgb, var(--wui-color-text) 38%, transparent)` | Disabled foreground text |
|
|
1016
1127
|
| `--wui-color-state-layer-hover` | `color-mix(in srgb, var(--wui-color-text) 6%, transparent)` | `color-mix(in srgb, var(--wui-color-text) 6%, transparent)` | Transparent hover overlay |
|
|
1017
1128
|
| `--wui-color-state-layer-active` | `color-mix(in srgb, var(--wui-color-text) 15%, transparent)` | `color-mix(in srgb, var(--wui-color-text) 15%, transparent)` | Transparent pressed overlay |
|
|
1018
1129
|
| `--wui-color-border` | `rgb(0 0 0 / 0.1)` | `rgb(255 255 255 / 0.14)` | Normal border and divider |
|
|
1019
|
-
| `--wui-color-glass-border` | `
|
|
1020
|
-
| `--wui-color-glass-highlight` | `rgb(255 255 255 / 0.9)` | `rgb(255 255 255 / 0.
|
|
1130
|
+
| `--wui-color-glass-border` | `transparent` | `rgb(255 255 255 / 0.05)` | Glass border tint |
|
|
1131
|
+
| `--wui-color-glass-highlight` | `rgb(255 255 255 / 0.9)` | `rgb(255 255 255 / 0.1)` | Glass edge highlight |
|
|
1132
|
+
| `--wui-color-glass-corner` | `rgb(255 255 255 / 0.08)` | `rgb(255 255 255 / 0.2)` | Glass corner sheen on border |
|
|
1133
|
+
| `--wui-color-glass-shade` | `rgb(0 0 0 / 0.06)` | `rgb(0 0 0 / 0.5)` | Glass corner shade on border |
|
|
1021
1134
|
| `--wui-color-accent` | `#08f` | `#0a84ff` | Accent and focused input border |
|
|
1022
1135
|
| `--wui-color-on-accent` | `#fff` | `#fff` | Foreground on accent |
|
|
1136
|
+
| `--wui-color-on-control` | `#fff` | `#f2f2f7` | Foreground on control inner |
|
|
1023
1137
|
| `--wui-color-success` | `#16a34a` | `#30d158` | Success |
|
|
1024
1138
|
| `--wui-color-warning` | `#d97706` | `#ff9f0a` | Warning |
|
|
1025
1139
|
| `--wui-color-danger` | `#dc2626` | `#ff453a` | Danger |
|
|
@@ -1031,9 +1145,11 @@ Defines foundation, color, layer, shadow, and motion tokens for its subtree. `mo
|
|
|
1031
1145
|
|
|
1032
1146
|
| Property | Light default | Dark default | Description |
|
|
1033
1147
|
| ---------------------- | -------------------------------- | ------------------------------- | --------------------------- |
|
|
1034
|
-
| `--wui-shadow-overlay` | `2px 16px 40px rgb(0 0 0 / 0.4)` | `0 18px 48px rgb(0 0 0 / 0.
|
|
1035
|
-
| `--wui-shadow-panel` | `0 3px 9px rgb(0 0 0 / 0.27)` | `0 4px 16px rgb(0 0 0 / 0.
|
|
1036
|
-
| `--wui-shadow-glass` | four-layer diffuse shadow | `0
|
|
1148
|
+
| `--wui-shadow-overlay` | `2px 16px 40px rgb(0 0 0 / 0.4)` | `0 18px 48px rgb(0 0 0 / 0.48)` | Modal and drawer shadow |
|
|
1149
|
+
| `--wui-shadow-panel` | `0 3px 9px rgb(0 0 0 / 0.27)` | `0 4px 16px rgb(0 0 0 / 0.32)` | Small floating panel shadow |
|
|
1150
|
+
| `--wui-shadow-glass` | four-layer diffuse shadow | `0 8px 24px rgb(0 0 0 / 0.08)` | Base liquid glass shadow |
|
|
1151
|
+
|
|
1152
|
+
**Glass effect tokens:** `--wui-glass-brightness` is `1.06` in light mode and `1.02` in dark mode. `--wui-glass-corner-radius` defaults to `32px`; glass components set it from their own corner radius so the diagonal border lighting aligns with their shape.
|
|
1037
1153
|
|
|
1038
1154
|
**Internal tokens:** variables prefixed `--wui-internal-*` are private wiring between shadow DOM parts; they are not part of the public token API and must not be overridden by consumers.
|
|
1039
1155
|
|