@greypan/web-ui 3.0.1 → 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 +495 -125
- package/README.md +504 -125
- package/dist/_virtual/{_@oxc-project_runtime@0.140.0 → _@oxc-project_runtime@0.146.0}/helpers/esm/decorate.js +1 -1
- 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/assets/overlay-motion.js +1 -1
- package/dist/assets/overlay-motion.js.map +1 -1
- package/dist/assets/toast-containers.js +1 -1
- package/dist/assets/toast-containers.js.map +1 -1
- package/dist/components/autocomplete/index.d.ts +12 -12
- package/dist/components/autocomplete/index.js +162 -111
- 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/avatar/index.d.ts +0 -1
- package/dist/components/avatar/index.js +8 -13
- package/dist/components/avatar/index.js.map +1 -1
- package/dist/components/back-top/index.js +2 -2
- 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/badge/index.d.ts +1 -0
- package/dist/components/badge/index.js +12 -14
- package/dist/components/badge/index.js.map +1 -1
- package/dist/components/button/index.d.ts +2 -0
- package/dist/components/button/index.js +52 -38
- 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.d.ts +1 -2
- package/dist/components/button-group/index.js +21 -23
- 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.d.ts +4 -7
- package/dist/components/checkbox/index.js +56 -38
- 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/checkbox-group/index.d.ts +4 -10
- package/dist/components/checkbox-group/index.js +74 -60
- package/dist/components/checkbox-group/index.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 +168 -53
- 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 +34 -13
- 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 +45 -0
- package/dist/components/drawer/index.js +270 -56
- 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 +24 -14
- package/dist/components/dropdown/index.js.map +1 -1
- package/dist/components/dropdown-divider/index.js +1 -1
- package/dist/components/dropdown-header/index.js +1 -1
- package/dist/components/dropdown-header/style.js +1 -1
- package/dist/components/dropdown-header/style.js.map +1 -1
- package/dist/components/dropdown-item/index.js +3 -2
- package/dist/components/dropdown-item/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 +24 -22
- 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/icon/index.js +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +21 -20
- package/dist/components/input/index.d.ts +2 -3
- package/dist/components/input/index.js +62 -52
- package/dist/components/input/index.js.map +1 -1
- package/dist/components/input/style.js +1 -1
- package/dist/components/input/style.js.map +1 -1
- package/dist/components/input-number/index.d.ts +2 -3
- package/dist/components/input-number/index.js +58 -38
- package/dist/components/input-number/index.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 +76 -3
- package/dist/components/layout/index.js +250 -39
- 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/index.js +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 +14 -8
- 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.d.ts +4 -7
- package/dist/components/radio/index.js +51 -37
- 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/radio-group/index.d.ts +4 -10
- package/dist/components/radio-group/index.js +70 -52
- package/dist/components/radio-group/index.js.map +1 -1
- package/dist/components/segmented/index.d.ts +14 -12
- package/dist/components/segmented/index.js +132 -54
- 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.d.ts +1 -2
- package/dist/components/segmented-trigger/index.js +23 -21
- 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.d.ts +13 -8
- package/dist/components/select/index.js +114 -75
- 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 +6 -7
- package/dist/components/slider/index.js +99 -64
- 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.d.ts +0 -2
- package/dist/components/spinner/index.js +14 -13
- package/dist/components/spinner/index.js.map +1 -1
- package/dist/components/spinner/style.js +1 -1
- package/dist/components/spinner/style.js.map +1 -1
- package/dist/components/svg-draw-lines/index.js +1 -1
- package/dist/components/switch/index.d.ts +13 -6
- package/dist/components/switch/index.js +102 -41
- 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.d.ts +5 -6
- package/dist/components/textarea/index.js +74 -67
- 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/index.js +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 +12 -12
- package/dist/components/toast/toast.js.map +1 -1
- package/dist/components/tooltip/index.js +3 -3
- 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-clapperboard.d.ts +6 -0
- package/dist/icons/generated/lucide-clapperboard.js +10 -0
- package/dist/icons/generated/lucide-clapperboard.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-eye.d.ts +6 -0
- package/dist/icons/generated/lucide-eye.js +10 -0
- package/dist/icons/generated/lucide-eye.js.map +1 -0
- package/dist/icons/generated/lucide-headphones.d.ts +6 -0
- package/dist/icons/generated/lucide-headphones.js +10 -0
- package/dist/icons/generated/lucide-headphones.js.map +1 -0
- package/dist/icons/generated/lucide-link.d.ts +6 -0
- package/dist/icons/generated/lucide-link.js +10 -0
- package/dist/icons/generated/lucide-link.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-pen-line.d.ts +6 -0
- package/dist/icons/generated/lucide-pen-line.js +10 -0
- package/dist/icons/generated/lucide-pen-line.js.map +1 -0
- package/dist/icons/generated/lucide-play.d.ts +6 -0
- package/dist/icons/generated/lucide-play.js +10 -0
- package/dist/icons/generated/lucide-play.js.map +1 -0
- package/dist/icons/generated/lucide-sliders-horizontal.d.ts +6 -0
- package/dist/icons/generated/lucide-sliders-horizontal.js +10 -0
- package/dist/icons/generated/lucide-sliders-horizontal.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 +15 -0
- package/dist/icons/index.js +18 -3
- package/dist/node_modules/.pnpm/@floating-ui_core@1.8.0/node_modules/@floating-ui/core/dist/floating-ui.core.js +1 -3
- package/dist/node_modules/.pnpm/@floating-ui_core@1.8.0/node_modules/@floating-ui/core/dist/floating-ui.core.js.map +1 -1
- package/dist/node_modules/.pnpm/@floating-ui_utils@0.2.12/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js +2 -1
- package/dist/node_modules/.pnpm/@floating-ui_utils@0.2.12/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js.map +1 -1
- package/dist/shared/events/user-change.js.map +1 -1
- package/dist/shared/form-association/index.js +41 -0
- package/dist/shared/form-association/index.js.map +1 -0
- 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 +111 -0
- package/dist/shared/group-management/index.js.map +1 -0
- 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 +22 -7
- package/dist/shared/menu-portal/menu-tree.js.map +1 -1
- package/dist/shared/option-portal/index.js +65 -0
- package/dist/shared/option-portal/index.js.map +1 -0
- 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/overlay.js +1 -1
- package/dist/shared/overlay/overlay.js.map +1 -1
- package/dist/shared/overlay/portal.js +47 -13
- package/dist/shared/overlay/portal.js.map +1 -1
- package/dist/shared/overlay/presence.js.map +1 -1
- package/dist/shared/visible-area/index.js +69 -0
- package/dist/shared/visible-area/index.js.map +1 -0
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -31,6 +31,30 @@ import '@greypan/web-ui'
|
|
|
31
31
|
|
|
32
32
|
## Framework Setup
|
|
33
33
|
|
|
34
|
+
### Cross-framework API conventions
|
|
35
|
+
|
|
36
|
+
`web-ui-*` elements expose three surfaces. The **DOM / JavaScript API is the source of truth**: Properties use
|
|
37
|
+
camelCase, Attributes use kebab-case, Events use kebab-case.
|
|
38
|
+
|
|
39
|
+
| Surface | Naming | Examples |
|
|
40
|
+
| --------- | ---------- | --------------------------------------------- |
|
|
41
|
+
| Property | camelCase | `open`, `sidebarCollapsed`, `noScrollLock` |
|
|
42
|
+
| Attribute | kebab-case | `open`, `sidebar-collapsed`, `no-scroll-lock` |
|
|
43
|
+
| Event | kebab-case | `open-change`, `sidebar-collapsed-change` |
|
|
44
|
+
|
|
45
|
+
- **Boolean attributes** follow native HTML presence semantics: absent → `false`, presence → `true`. A framework
|
|
46
|
+
binding that writes `disabled="false"` produces the string `"false"`, which is truthy — **bind dynamic booleans as
|
|
47
|
+
properties** (camelCase), not attributes, so `false` is written as a real property.
|
|
48
|
+
- **Vue**: dynamic binding must go to **Properties** with camelCase names (`:sidebarCollapsed="x"`, `:open="x"`).
|
|
49
|
+
A kebab-case binding like `:sidebar-collapsed="x"` is written as a string attribute and cannot express `false`;
|
|
50
|
+
use the camelCase property. The `.prop` modifier is only valid with the camelCase name
|
|
51
|
+
(`:sidebarCollapsed.prop="x"`). String/number values may stay on kebab-case attributes (`:max-height="120"`).
|
|
52
|
+
`v-model` is supported on value-bearing controls (`web-ui-input`, `web-ui-select`, `web-ui-autocomplete`, …) and
|
|
53
|
+
compiles to the element `value` property + `input` event.
|
|
54
|
+
- **React**: React 19 writes DOM properties for custom-element props, so use camelCase props (`open={open}`,
|
|
55
|
+
`noScrollLock`, `value={value}`). Never pass complex data (objects, arrays) through attribute strings — bind
|
|
56
|
+
them as properties. Kebab-case JSX props on a custom element are written as attributes.
|
|
57
|
+
|
|
34
58
|
### React
|
|
35
59
|
|
|
36
60
|
Requires `@types/react >= 19` as optional peer dependency.
|
|
@@ -129,6 +153,21 @@ import '@greypan/web-ui/types/vue'
|
|
|
129
153
|
</template>
|
|
130
154
|
```
|
|
131
155
|
|
|
156
|
+
Boolean properties must be bound with the **camelCase property name**, not the kebab-case attribute. Vue writes
|
|
157
|
+
attribute bindings as strings, and boolean attributes follow presence semantics — so `:sidebar-collapsed="false"`
|
|
158
|
+
produces the string `"false"`, which is truthy. Binding the camelCase name (`:sidebarCollapsed="false"`, or the
|
|
159
|
+
`.prop` modifier) makes Vue write the DOM property directly:
|
|
160
|
+
|
|
161
|
+
```vue
|
|
162
|
+
<web-ui-layout
|
|
163
|
+
header-glow
|
|
164
|
+
:sidebarCollapsed="sidebarCollapsed"
|
|
165
|
+
:sidebarOpen="sidebarOpen"
|
|
166
|
+
@sidebar-collapsed-change="sidebarCollapsed = $event.detail.collapsed"
|
|
167
|
+
@sidebar-open-change="sidebarOpen = $event.detail.open"
|
|
168
|
+
/>
|
|
169
|
+
```
|
|
170
|
+
|
|
132
171
|
Vue events are typed cast-free: `@input`/`@change` on value-bearing components resolve to the component emit, so
|
|
133
172
|
`$event.target` is the component instance and `value`/`checked` are read directly. `$event.detail` keeps the
|
|
134
173
|
`CustomEvent` payload type for kebab-case events like `open-change`. Named handlers annotate with
|
|
@@ -148,45 +187,85 @@ Components own their role and interaction state. Browser-native composed events
|
|
|
148
187
|
remain the primary interaction API. Kebab-case custom events such as `open-change` describe user-originated component
|
|
149
188
|
state changes; assigning a property programmatically does not emit them.
|
|
150
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
|
+
|
|
225
|
+
### Form-associated controls
|
|
226
|
+
|
|
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.
|
|
228
|
+
|
|
151
229
|
## All Components
|
|
152
230
|
|
|
153
|
-
| Category
|
|
154
|
-
|
|
|
155
|
-
| **Form Controls**
|
|
156
|
-
|
|
|
157
|
-
|
|
|
158
|
-
|
|
|
159
|
-
|
|
|
160
|
-
|
|
|
161
|
-
|
|
|
162
|
-
|
|
|
163
|
-
|
|
|
164
|
-
|
|
|
165
|
-
|
|
|
166
|
-
|
|
|
167
|
-
| **Buttons**
|
|
168
|
-
|
|
|
169
|
-
| **Overlay / Modal**
|
|
170
|
-
|
|
|
171
|
-
| **
|
|
172
|
-
|
|
|
173
|
-
|
|
|
174
|
-
|
|
|
175
|
-
|
|
|
176
|
-
|
|
|
177
|
-
|
|
|
178
|
-
|
|
|
179
|
-
|
|
|
180
|
-
|
|
|
181
|
-
|
|
|
182
|
-
|
|
|
183
|
-
|
|
|
184
|
-
|
|
|
185
|
-
|
|
|
186
|
-
|
|
|
187
|
-
|
|
|
188
|
-
| **
|
|
189
|
-
|
|
|
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) |
|
|
190
269
|
|
|
191
270
|
## API Reference
|
|
192
271
|
|
|
@@ -198,46 +277,52 @@ Form controls implement `static formAssociated = true` and integrate with native
|
|
|
198
277
|
|
|
199
278
|
Text input with clearable, prefix/suffix slots.
|
|
200
279
|
|
|
201
|
-
| Attribute | Type | Default | Description
|
|
202
|
-
| ------------- | --------- | -------- |
|
|
203
|
-
| `value` | `string` | `''` | Input value
|
|
204
|
-
| `type` | `string` | `'text'` | HTML input type
|
|
205
|
-
| `placeholder` | `string` | `''` | Placeholder text
|
|
206
|
-
| `name` | `string` | `''` | Form field name
|
|
207
|
-
| `disabled` | `boolean` | `false` | Disabled state
|
|
208
|
-
| `readonly` | `boolean` | `false` | Read-only state
|
|
209
|
-
| `required` | `boolean` | `false` | Required validation
|
|
210
|
-
| `clearable` | `boolean` | `false` | Show clear button
|
|
211
|
-
| `full` | `boolean` | `false` | Full width
|
|
212
|
-
| `borderless` | `boolean` | `false` |
|
|
213
|
-
| `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 |
|
|
214
293
|
|
|
215
294
|
**Events:** `input`, `change`, `focus`, `blur`
|
|
216
295
|
|
|
217
296
|
**Slots:** `prefix`, `default`, `suffix`
|
|
218
297
|
|
|
298
|
+
**CSS Custom Properties:**
|
|
299
|
+
|
|
300
|
+
| Property | Default | Description |
|
|
301
|
+
| ------------------------- | -------------------------------- | ------------------ |
|
|
302
|
+
| `--wui-input-clear-color` | `var(--wui-color-text-tertiary)` | Clear button color |
|
|
303
|
+
|
|
219
304
|
#### `<web-ui-textarea>`
|
|
220
305
|
|
|
221
306
|
Multi-line text input with auto-resize.
|
|
222
307
|
|
|
223
|
-
| Attribute | Type | Default | Description
|
|
224
|
-
| ----------------- | --------- | ------- |
|
|
225
|
-
| `value` | `string` | `''` | Textarea value
|
|
226
|
-
| `placeholder` | `string` | `''` | Placeholder text
|
|
227
|
-
| `rows` | `number` | `3` | Visible rows
|
|
228
|
-
| `name` | `string` | `''` | Form field name
|
|
229
|
-
| `disabled` | `boolean` | `false` | Disabled state
|
|
230
|
-
| `readonly` | `boolean` | `false` | Read-only state
|
|
231
|
-
| `required` | `boolean` | `false` | Required validation
|
|
232
|
-
| `clearable` | `boolean` | `false` | Show clear button
|
|
233
|
-
| `full` | `boolean` | `false` | Full width
|
|
234
|
-
| `borderless` | `boolean` | `false` |
|
|
235
|
-
| `autosize` | `boolean` | `false` | Auto-resize height
|
|
236
|
-
| `max-height` | `number` | `0` | Autosize max height (px); `0` = unlimited
|
|
237
|
-
| `minlength` | `number` | — | Minimum length validation
|
|
238
|
-
| `maxlength` | `number` | — | Maximum length validation
|
|
239
|
-
| `aria-label` | `string` | — | Accessible label
|
|
240
|
-
| `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 |
|
|
241
326
|
|
|
242
327
|
**Events:** `input`, `change`, `focus`, `blur`
|
|
243
328
|
|
|
@@ -245,6 +330,13 @@ Multi-line text input with auto-resize.
|
|
|
245
330
|
|
|
246
331
|
**Slots:** `prefix`, `suffix`
|
|
247
332
|
|
|
333
|
+
**CSS Custom Properties:**
|
|
334
|
+
|
|
335
|
+
| Property | Default | Description |
|
|
336
|
+
| ---------------------------- | -------------------------------- | ------------------ |
|
|
337
|
+
| `--wui-textarea-width` | `200px` | Textarea width |
|
|
338
|
+
| `--wui-textarea-clear-color` | `var(--wui-color-text-tertiary)` | Clear button color |
|
|
339
|
+
|
|
248
340
|
#### `<web-ui-input-number>`
|
|
249
341
|
|
|
250
342
|
Numeric input with step buttons and keyboard control.
|
|
@@ -289,32 +381,60 @@ Select dropdown with option items, keyboard navigation, and portal support.
|
|
|
289
381
|
|
|
290
382
|
Child `<web-ui-option>` elements register via `option-register` / `option-unregister` events. Supports ArrowDown/ArrowUp/Enter/Escape keyboard navigation.
|
|
291
383
|
|
|
384
|
+
**CSS Custom Properties:**
|
|
385
|
+
|
|
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.
|
|
395
|
+
|
|
292
396
|
#### `<web-ui-autocomplete>`
|
|
293
397
|
|
|
294
398
|
Editable combobox with input filtering and single option selection.
|
|
295
399
|
|
|
296
|
-
| Attribute
|
|
297
|
-
|
|
|
298
|
-
| `value`
|
|
299
|
-
| `selected-value`
|
|
300
|
-
| `placeholder`
|
|
301
|
-
| `
|
|
302
|
-
| `
|
|
303
|
-
| `
|
|
304
|
-
| `
|
|
305
|
-
| `
|
|
306
|
-
| `
|
|
307
|
-
| `
|
|
308
|
-
| `
|
|
309
|
-
| `
|
|
310
|
-
| `
|
|
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 |
|
|
311
417
|
|
|
312
418
|
**Events:** `input`, `change`, `focus`, `blur`, `open-change` (`CustomEvent<{ open: boolean }>`)
|
|
313
419
|
|
|
314
|
-
**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”)
|
|
315
421
|
|
|
316
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.
|
|
317
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
|
+
|
|
428
|
+
**CSS Custom Properties:**
|
|
429
|
+
|
|
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.
|
|
437
|
+
|
|
318
438
|
#### `<web-ui-slider>`
|
|
319
439
|
|
|
320
440
|
Range slider with marks and vertical orientation.
|
|
@@ -337,6 +457,18 @@ Range slider with marks and vertical orientation.
|
|
|
337
457
|
|
|
338
458
|
Supports ArrowLeft/Right/Up/Down, Home/End, PageUp/PageDown keyboard navigation. Uses pointer capture for drag interaction across mouse, touch, and pen.
|
|
339
459
|
|
|
460
|
+
**CSS Custom Properties:**
|
|
461
|
+
|
|
462
|
+
| Property | Default | Description |
|
|
463
|
+
| ------------------------------ | ----------------------------------- | ---------------------- |
|
|
464
|
+
| `--wui-slider-width` | `200px` | Slider width |
|
|
465
|
+
| `--wui-slider-vertical-height` | `200px` | Vertical slider height |
|
|
466
|
+
| `--wui-slider-height` | `var(--wui-slider-track-size, 6px)` | Track thickness |
|
|
467
|
+
| `--wui-slider-track-size` | `6px` | Track size |
|
|
468
|
+
| `--wui-slider-thumb-width` | `30px` | Thumb width |
|
|
469
|
+
| `--wui-slider-thumb-height` | `20px` | Thumb height |
|
|
470
|
+
| `--wui-slider-marks-inset` | `0` | Marks inset from edges |
|
|
471
|
+
|
|
340
472
|
#### `<web-ui-checkbox>`
|
|
341
473
|
|
|
342
474
|
Individual checkbox.
|
|
@@ -451,16 +583,16 @@ Radio group managing single selection.
|
|
|
451
583
|
|
|
452
584
|
Styled button with variants and loading state.
|
|
453
585
|
|
|
454
|
-
| Attribute | Type | Default | Description
|
|
455
|
-
| ------------ | ------------------------------------------------------------ | ---------- |
|
|
456
|
-
| `variant` | `'primary' \| 'secondary' \| 'ghost' \| 'danger' \| 'glass'` | `'glass'` | Button variant
|
|
457
|
-
| `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | Inner-button type; invalid values become `button`
|
|
458
|
-
| `disabled` | `boolean` | `false` | Disabled state
|
|
459
|
-
| `loading` | `boolean` | `false` | Loading spinner
|
|
460
|
-
| `full` | `boolean` | `false` | Full width
|
|
461
|
-
| `icon` | `boolean` | `false` | Icon-only mode
|
|
462
|
-
| `size` | `string` | `''` |
|
|
463
|
-
| `aria-label` | `string` | — | Accessible label (delegated to inner button)
|
|
586
|
+
| Attribute | Type | Default | Description |
|
|
587
|
+
| ------------ | ------------------------------------------------------------ | ---------- | ----------------------------------------------------------------------- |
|
|
588
|
+
| `variant` | `'primary' \| 'secondary' \| 'ghost' \| 'danger' \| 'glass'` | `'glass'` | Button variant |
|
|
589
|
+
| `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | Inner-button type; invalid values become `button` |
|
|
590
|
+
| `disabled` | `boolean` | `false` | Disabled state |
|
|
591
|
+
| `loading` | `boolean` | `false` | Loading spinner; with `icon`, the spinner replaces the icon content |
|
|
592
|
+
| `full` | `boolean` | `false` | Full width |
|
|
593
|
+
| `icon` | `boolean` | `false` | Icon-only mode |
|
|
594
|
+
| `size` | `string` | `''` | Button height in px (icon mode: also sets min-width for square default) |
|
|
595
|
+
| `aria-label` | `string` | — | Accessible label (delegated to inner button) |
|
|
464
596
|
|
|
465
597
|
**Events:** standard `click`
|
|
466
598
|
|
|
@@ -471,6 +603,21 @@ form-associated control when external form submission behavior is required.
|
|
|
471
603
|
|
|
472
604
|
Disabled and loading states prevent `click` events.
|
|
473
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
|
+
|
|
609
|
+
**CSS Custom Properties:**
|
|
610
|
+
|
|
611
|
+
| Property | Default | Description |
|
|
612
|
+
| ------------------------ | ------------- | --------------------------------------- |
|
|
613
|
+
| `--wui-button-width` | `max-content` | Button width |
|
|
614
|
+
| `--wui-button-px` | `12px` | Horizontal padding |
|
|
615
|
+
| `--wui-button-gap` | `8px` | Gap between prefix/default/suffix slots |
|
|
616
|
+
| `--wui-button-color` | variant-based | Button text color |
|
|
617
|
+
| `--wui-button-bg` | variant-based | Button background color |
|
|
618
|
+
| `--wui-button-bg-hover` | variant-based | Button hover background |
|
|
619
|
+
| `--wui-button-bg-active` | variant-based | Button active background |
|
|
620
|
+
|
|
474
621
|
#### `<web-ui-button-group>`
|
|
475
622
|
|
|
476
623
|
Button group that manages child button layout and direction.
|
|
@@ -481,7 +628,7 @@ Button group that manages child button layout and direction.
|
|
|
481
628
|
|
|
482
629
|
**Slots:** `default` (project `<web-ui-button>` elements)
|
|
483
630
|
|
|
484
|
-
|
|
631
|
+
Applies the direction to the grouped button layout without changing child button attributes.
|
|
485
632
|
|
|
486
633
|
---
|
|
487
634
|
|
|
@@ -491,41 +638,105 @@ Propagates `direction` attribute to child buttons.
|
|
|
491
638
|
|
|
492
639
|
Modal dialog using native `<dialog>` with `showModal()`.
|
|
493
640
|
|
|
494
|
-
| Attribute | Type | Default | Description
|
|
495
|
-
| ------------------- | --------- | ------- |
|
|
496
|
-
| `open` | `boolean` | `false` | Dialog visibility
|
|
497
|
-
| `no-scroll-lock` | `boolean` | `false` | Do not lock body scroll when open
|
|
498
|
-
| `no-backdrop-close` | `boolean` | `false` | Do not close on backdrop click
|
|
499
|
-
| `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` |
|
|
500
648
|
|
|
501
|
-
**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.
|
|
502
650
|
|
|
503
651
|
**Slots:** `body`, `title`, `default`, `footer`
|
|
504
652
|
|
|
505
653
|
**Methods:** `showModal()`, `close()`
|
|
506
654
|
|
|
507
|
-
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.
|
|
656
|
+
|
|
657
|
+
**CSS Custom Properties:**
|
|
658
|
+
|
|
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)` |
|
|
508
664
|
|
|
509
665
|
#### `<web-ui-drawer>`
|
|
510
666
|
|
|
511
|
-
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.
|
|
512
668
|
|
|
513
|
-
| Attribute | Type | Default | Description
|
|
514
|
-
| ------------------- | ---------------------------------------- | --------- |
|
|
515
|
-
| `open` | `boolean` | `false` | Drawer visibility
|
|
516
|
-
| `placement` | `'right' \| 'left' \| 'top' \| 'bottom'` | `'right'` | Slide-in direction
|
|
517
|
-
| `heading` | `string` | `''` | Title text (fallback when no header slot)
|
|
518
|
-
| `closable` | `boolean` | `false` | Show close button
|
|
519
|
-
| `no-scroll-lock` | `boolean` | `false` | Do not lock body scroll when open
|
|
520
|
-
| `no-backdrop-close` | `boolean` | `false` | Do not close on backdrop click
|
|
669
|
+
| Attribute | Type | Default | Description |
|
|
670
|
+
| ------------------- | ---------------------------------------- | --------- | --------------------------------------------------------------------------------- |
|
|
671
|
+
| `open` | `boolean` | `false` | Drawer visibility |
|
|
672
|
+
| `placement` | `'right' \| 'left' \| 'top' \| 'bottom'` | `'right'` | Slide-in direction |
|
|
673
|
+
| `heading` | `string` | `''` | Title text (fallback when no header slot) |
|
|
674
|
+
| `closable` | `boolean` | `false` | Show close button |
|
|
675
|
+
| `no-scroll-lock` | `boolean` | `false` | Do not lock body scroll when open |
|
|
676
|
+
| `no-backdrop-close` | `boolean` | `false` | Do not close on backdrop click |
|
|
677
|
+
| `controlled` | `boolean` | `false` | User close actions only request `open=false`; the consumer must update `open` |
|
|
678
|
+
| `headless` | `boolean` | `false` | Keep only overlay behavior and render the default slot without built-in drawer UI |
|
|
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 |
|
|
521
681
|
|
|
522
|
-
**Events:** `open-change` (`CustomEvent<{ open: boolean }>`)
|
|
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`.
|
|
523
683
|
|
|
524
|
-
**Slots:** `header`, `default`, `footer`
|
|
684
|
+
**Slots:** `header`, `default`, `footer` — with `headless`, only the `default` slot is rendered.
|
|
525
685
|
|
|
526
686
|
**Methods:** `show()`, `close()`
|
|
527
687
|
|
|
528
|
-
|
|
688
|
+
`headless` keeps the native dialog, backdrop, placement animation, Escape/backdrop close behavior, and scroll locking. It does not render the built-in glass body, header, close button, or footer; style the default-slot content completely in the consumer.
|
|
689
|
+
|
|
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.
|
|
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
|
+
|
|
694
|
+
**CSS Custom Properties:**
|
|
695
|
+
|
|
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.
|
|
529
740
|
|
|
530
741
|
---
|
|
531
742
|
|
|
@@ -553,6 +764,8 @@ Popover overlay anchored to trigger element.
|
|
|
553
764
|
|
|
554
765
|
Hover mode uses `pointerenter`/`pointerleave` with delay. Click mode toggles on trigger click. Manual mode only responds to imperative `show()`/`close()`.
|
|
555
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
|
+
|
|
556
769
|
#### `<web-ui-tooltip>`
|
|
557
770
|
|
|
558
771
|
Tooltip overlay using pointer/focus triggers.
|
|
@@ -573,7 +786,14 @@ Tooltip overlay using pointer/focus triggers.
|
|
|
573
786
|
|
|
574
787
|
**Slots:** `default` (trigger), `content` (tooltip panel)
|
|
575
788
|
|
|
576
|
-
`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.
|
|
790
|
+
|
|
791
|
+
**CSS Custom Properties:**
|
|
792
|
+
|
|
793
|
+
| Property | Default | Description |
|
|
794
|
+
| ------------------------- | ------- | ----------------- |
|
|
795
|
+
| `--wui-tooltip-max-width` | `240px` | Tooltip max width |
|
|
796
|
+
| `--wui-tooltip-font-size` | `13px` | Tooltip font size |
|
|
577
797
|
|
|
578
798
|
#### `<web-ui-context-menu>`
|
|
579
799
|
|
|
@@ -592,6 +812,8 @@ Right-click context menu.
|
|
|
592
812
|
|
|
593
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`.
|
|
594
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
|
+
|
|
595
817
|
---
|
|
596
818
|
|
|
597
819
|
### Menu
|
|
@@ -617,6 +839,8 @@ Dropdown menu with multi-level submenu support.
|
|
|
617
839
|
|
|
618
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).
|
|
619
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
|
+
|
|
620
844
|
#### `<web-ui-dropdown-item>`
|
|
621
845
|
|
|
622
846
|
Menu item for dropdown or context-menu.
|
|
@@ -687,6 +911,17 @@ Empty state placeholder.
|
|
|
687
911
|
|
|
688
912
|
**Slots:** `default` (title, overrides `title` prop), `icon`, `description`, `action`
|
|
689
913
|
|
|
914
|
+
**CSS Custom Properties:**
|
|
915
|
+
|
|
916
|
+
| Property | Default | Description |
|
|
917
|
+
| ----------------------------------- | ----------- | ------------------------------ |
|
|
918
|
+
| `--wui-empty-min-height` | `240px` | Min height (medium) |
|
|
919
|
+
| `--wui-empty-padding` | `32px 24px` | Padding (medium) |
|
|
920
|
+
| `--wui-empty-icon-size` | `56px` | Icon container size (medium) |
|
|
921
|
+
| `--wui-empty-content-width` | `480px` | Max width of title/description |
|
|
922
|
+
| `--wui-empty-title-font-size` | `16px` | Title font size (medium) |
|
|
923
|
+
| `--wui-empty-description-font-size` | `14px` | Description font size (medium) |
|
|
924
|
+
|
|
690
925
|
#### `<web-ui-icon>`
|
|
691
926
|
|
|
692
927
|
Icon renderer using Iconify data objects.
|
|
@@ -705,6 +940,12 @@ import { lucideLoaderCircle } from '@greypan/web-ui/icons'
|
|
|
705
940
|
html`<web-ui-icon .icon=${lucideLoaderCircle} spin />`
|
|
706
941
|
```
|
|
707
942
|
|
|
943
|
+
**CSS Custom Properties:**
|
|
944
|
+
|
|
945
|
+
| Property | Default | Description |
|
|
946
|
+
| ------------------ | --------- | ----------- |
|
|
947
|
+
| `--wui-icon-color` | `inherit` | Icon color |
|
|
948
|
+
|
|
708
949
|
#### `<web-ui-spinner>`
|
|
709
950
|
|
|
710
951
|
Loading spinner.
|
|
@@ -737,14 +978,43 @@ WebUiSpinner.hide() // hide
|
|
|
737
978
|
|
|
738
979
|
#### `<web-ui-layout>`
|
|
739
980
|
|
|
740
|
-
|
|
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.
|
|
982
|
+
|
|
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.
|
|
995
|
+
|
|
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.
|
|
997
|
+
|
|
998
|
+
| Slot | Description |
|
|
999
|
+
| --------- | ----------------------------------------------------------------------------------------- |
|
|
1000
|
+
| `banner` | Optional full-width banner above the layout body |
|
|
1001
|
+
| `header` | Sticky content-area header |
|
|
1002
|
+
| `sidebar` | Sidebar-card content. The consumer owns its internal fixed regions and scroll containers. |
|
|
1003
|
+
| `default` | Main content |
|
|
1004
|
+
| `tabbar` | Bottom tab bar |
|
|
1005
|
+
|
|
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.
|
|
1007
|
+
|
|
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`.
|
|
741
1009
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
|
747
|
-
|
|
|
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`).
|
|
1011
|
+
|
|
1012
|
+
**CSS Custom Properties:**
|
|
1013
|
+
|
|
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 |
|
|
748
1018
|
|
|
749
1019
|
#### `<web-ui-back-top>`
|
|
750
1020
|
|
|
@@ -761,10 +1031,21 @@ Scroll-to-top button.
|
|
|
761
1031
|
|
|
762
1032
|
**Methods:** `toTop()`
|
|
763
1033
|
|
|
764
|
-
**Positioning:** With `scrollTarget` as `window`, the button is fixed to the viewport corner. With `scrollTarget` as an `HTMLElement`, place the element inside that container and the button floats at the container's bottom corner via `position: sticky`. Offsets follow the `--
|
|
1034
|
+
**Positioning:** With `scrollTarget` as `window`, the button is fixed to the viewport corner. With `scrollTarget` as an `HTMLElement`, place the element inside that container and the button floats at the container's bottom corner via `position: sticky`. Offsets follow the `--wui-back-top-top/right/bottom/left` CSS variables.
|
|
765
1035
|
|
|
766
1036
|
Role: `button`, keyboard Enter scrolls to top.
|
|
767
1037
|
|
|
1038
|
+
**CSS Custom Properties:**
|
|
1039
|
+
|
|
1040
|
+
| Property | Default | Description |
|
|
1041
|
+
| ------------------------- | -------------------------------- | ------------- |
|
|
1042
|
+
| `--wui-back-top-position` | `fixed` | CSS position |
|
|
1043
|
+
| `--wui-back-top-z-index` | `var(--wui-layer-auxiliary, 20)` | Z-index |
|
|
1044
|
+
| `--wui-back-top-top` | `auto` | Top offset |
|
|
1045
|
+
| `--wui-back-top-right` | `20px` | Right offset |
|
|
1046
|
+
| `--wui-back-top-bottom` | `20px` | Bottom offset |
|
|
1047
|
+
| `--wui-back-top-left` | `auto` | Left offset |
|
|
1048
|
+
|
|
768
1049
|
#### `<web-ui-svg-draw-lines>`
|
|
769
1050
|
|
|
770
1051
|
SVG line drawing animation using `stroke-dashoffset`. Animates geometry in-place — no cloning, no DOM manipulation.
|
|
@@ -793,7 +1074,84 @@ Theme provider defining CSS custom property tokens.
|
|
|
793
1074
|
|
|
794
1075
|
**Methods:** `getOverlayRoot()` — returns the portal overlay container
|
|
795
1076
|
|
|
796
|
-
Defines
|
|
1077
|
+
Defines foundation, color, layer, shadow, and motion tokens for its subtree. `motion="system"` follows `prefers-reduced-motion`; use `motion="reduced"` to reduce animation in a scope or `motion="full"` in a nested theme to restore normal token values. System appearance follows `prefers-color-scheme`.
|
|
1078
|
+
|
|
1079
|
+
**Foundation tokens:**
|
|
1080
|
+
|
|
1081
|
+
| Property | Default | Description |
|
|
1082
|
+
| ------------------------- | ------- | ------------------------------------------------ |
|
|
1083
|
+
| `--wui-font-size` | `14px` | Base font size for controls |
|
|
1084
|
+
| `--wui-input-width` | `200px` | Default width for compact form controls |
|
|
1085
|
+
| `--wui-control-size` | `36px` | Default height and square min-width for controls |
|
|
1086
|
+
| `--wui-overlay-min-width` | `200px` | Minimum anchored overlay width |
|
|
1087
|
+
| `--wui-focus-ring-width` | `3px` | Focus indicator width |
|
|
1088
|
+
|
|
1089
|
+
**Layer tokens:**
|
|
1090
|
+
|
|
1091
|
+
| Property | Default | Description |
|
|
1092
|
+
| ---------------------------- | ------- | ---------------------------- |
|
|
1093
|
+
| `--wui-layer-base` | `0` | Base content |
|
|
1094
|
+
| `--wui-layer-inline-overlay` | `1` | Overlay local to a component |
|
|
1095
|
+
| `--wui-layer-header` | `10` | Page header |
|
|
1096
|
+
| `--wui-layer-auxiliary` | `20` | Floating utility controls |
|
|
1097
|
+
| `--wui-layer-banner` | `30` | Banners |
|
|
1098
|
+
| `--wui-layer-tabbar` | `40` | Tab bars |
|
|
1099
|
+
| `--wui-layer-sidebar` | `50` | Sidebars |
|
|
1100
|
+
| `--wui-layer-menu` | `100` | Menus and floating panels |
|
|
1101
|
+
| `--wui-layer-menu-nested` | `110` | Nested menus |
|
|
1102
|
+
| `--wui-layer-toast` | `200` | Toasts |
|
|
1103
|
+
| `--wui-layer-loading` | `300` | Blocking loading surfaces |
|
|
1104
|
+
|
|
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.
|
|
1106
|
+
|
|
1107
|
+
**Color tokens:**
|
|
1108
|
+
|
|
1109
|
+
| Property | Light default | Dark default | Description |
|
|
1110
|
+
| ---------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------- |
|
|
1111
|
+
| `--wui-color-page` | `#fff` | `#242628` | Page background |
|
|
1112
|
+
| `--wui-color-surface` | `#fff` | `#2c2c2e` | Plain surface |
|
|
1113
|
+
| `--wui-color-surface-raised` | `#f2f2f7` | `#2c2c2e` | Raised surface |
|
|
1114
|
+
| `--wui-color-surface-control` | `#dfdfdf` | `#3a3a3c` | Neutral control surface |
|
|
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 |
|
|
1117
|
+
| `--wui-color-surface-glass` | `rgb(250 250 250 / 0.34)` | `rgb(44 44 46 / 0.42)` | Liquid glass surface |
|
|
1118
|
+
| `--wui-color-surface-glass-hover` | `color-mix(... text 6%, surface-glass)` | `color-mix(... text 6%, surface-glass)` | Full glass hover background |
|
|
1119
|
+
| `--wui-color-surface-glass-active` | `color-mix(... text 15%, surface-glass)` | `color-mix(... text 15%, surface-glass)` | Full glass pressed background |
|
|
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 |
|
|
1124
|
+
| `--wui-color-text-secondary` | `#6a6a6a` | `#a1a1a6` | Secondary text |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
1129
|
+
| `--wui-color-border` | `rgb(0 0 0 / 0.1)` | `rgb(255 255 255 / 0.14)` | Normal border and divider |
|
|
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 |
|
|
1134
|
+
| `--wui-color-accent` | `#08f` | `#0a84ff` | Accent and focused input border |
|
|
1135
|
+
| `--wui-color-on-accent` | `#fff` | `#fff` | Foreground on accent |
|
|
1136
|
+
| `--wui-color-on-control` | `#fff` | `#f2f2f7` | Foreground on control inner |
|
|
1137
|
+
| `--wui-color-success` | `#16a34a` | `#30d158` | Success |
|
|
1138
|
+
| `--wui-color-warning` | `#d97706` | `#ff9f0a` | Warning |
|
|
1139
|
+
| `--wui-color-danger` | `#dc2626` | `#ff453a` | Danger |
|
|
1140
|
+
| `--wui-color-info` | `#2563eb` | `#64d2ff` | Info |
|
|
1141
|
+
| `--wui-color-backdrop` | `rgb(0 0 0 / 0.12)` | `rgb(0 0 0 / 0.48)` | Modal backdrop |
|
|
1142
|
+
| `--wui-color-focus-ring` | `rgb(0 136 255 / 0.4)` | `rgb(10 132 255 / 0.62)` | Focus indicator color |
|
|
1143
|
+
|
|
1144
|
+
**Shadow tokens:**
|
|
1145
|
+
|
|
1146
|
+
| Property | Light default | Dark default | Description |
|
|
1147
|
+
| ---------------------- | -------------------------------- | ------------------------------- | --------------------------- |
|
|
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.
|
|
1153
|
+
|
|
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.
|
|
797
1155
|
|
|
798
1156
|
---
|
|
799
1157
|
|
|
@@ -847,6 +1205,13 @@ toast.updateMessage(id, { message: 'Upload 60% complete', heading: 'Uploading' }
|
|
|
847
1205
|
|
|
848
1206
|
Hover pauses auto-close timer (uses `pointerenter`/`pointerleave`). Batch-mounts toasts created in the same microtask.
|
|
849
1207
|
|
|
1208
|
+
**CSS Custom Properties:**
|
|
1209
|
+
|
|
1210
|
+
| Property | Default | Description |
|
|
1211
|
+
| ------------------------------- | ------- | -------------------------------------------------- |
|
|
1212
|
+
| `--wui-toast-viewport-gap` | `16px` | Visible distance between toasts and viewport edges |
|
|
1213
|
+
| `--wui-toast-container-padding` | `40px` | Container padding reserved for diffuse shadows |
|
|
1214
|
+
|
|
850
1215
|
---
|
|
851
1216
|
|
|
852
1217
|
### Sub-items
|
|
@@ -866,6 +1231,12 @@ Selection option for `<web-ui-select>`.
|
|
|
866
1231
|
|
|
867
1232
|
Not form-associated (child of select, not independent submit).
|
|
868
1233
|
|
|
1234
|
+
**CSS Custom Properties:**
|
|
1235
|
+
|
|
1236
|
+
| Property | Default | Description |
|
|
1237
|
+
| ---------------------------- | ------- | --------------------------------------------- |
|
|
1238
|
+
| `--wui-option-check-display` | `block` | Display mode of the selection check indicator |
|
|
1239
|
+
|
|
869
1240
|
#### `<web-ui-segmented-trigger>`
|
|
870
1241
|
|
|
871
1242
|
Segment trigger for `<web-ui-segmented>`.
|
|
@@ -879,3 +1250,11 @@ Segment trigger for `<web-ui-segmented>`.
|
|
|
879
1250
|
**Events:** `change`
|
|
880
1251
|
|
|
881
1252
|
Not form-associated (child of segmented, not independent submit).
|
|
1253
|
+
|
|
1254
|
+
**CSS Custom Properties:**
|
|
1255
|
+
|
|
1256
|
+
| Property | Default | Description |
|
|
1257
|
+
| ----------------------------------- | -------------------------------- | ------------------------- |
|
|
1258
|
+
| `--wui-segmented-trigger-px` | `12px` | Horizontal padding |
|
|
1259
|
+
| `--wui-segmented-trigger-bg-hover` | `--wui-color-state-layer-hover` | Trigger hover background |
|
|
1260
|
+
| `--wui-segmented-trigger-bg-active` | `--wui-color-state-layer-active` | Trigger active background |
|