@chromvoid/uikit 0.1.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/LICENSE +8 -0
- package/README.md +96 -0
- package/dist/components/cv-accordion-item.d.ts +69 -0
- package/dist/components/cv-accordion-item.js +176 -0
- package/dist/components/cv-accordion.d.ts +79 -0
- package/dist/components/cv-accordion.js +310 -0
- package/dist/components/cv-alert-dialog.d.ts +86 -0
- package/dist/components/cv-alert-dialog.js +393 -0
- package/dist/components/cv-alert.d.ts +48 -0
- package/dist/components/cv-alert.js +156 -0
- package/dist/components/cv-badge.d.ts +56 -0
- package/dist/components/cv-badge.js +280 -0
- package/dist/components/cv-breadcrumb-item.d.ts +35 -0
- package/dist/components/cv-breadcrumb-item.js +64 -0
- package/dist/components/cv-breadcrumb.d.ts +39 -0
- package/dist/components/cv-breadcrumb.js +160 -0
- package/dist/components/cv-button.d.ts +83 -0
- package/dist/components/cv-button.js +541 -0
- package/dist/components/cv-callout.d.ts +32 -0
- package/dist/components/cv-callout.js +221 -0
- package/dist/components/cv-card.d.ts +48 -0
- package/dist/components/cv-card.js +269 -0
- package/dist/components/cv-carousel-slide.d.ts +25 -0
- package/dist/components/cv-carousel-slide.js +51 -0
- package/dist/components/cv-carousel.d.ts +96 -0
- package/dist/components/cv-carousel.js +457 -0
- package/dist/components/cv-checkbox.d.ts +84 -0
- package/dist/components/cv-checkbox.js +274 -0
- package/dist/components/cv-combobox-group.d.ts +15 -0
- package/dist/components/cv-combobox-group.js +34 -0
- package/dist/components/cv-combobox-option.d.ts +30 -0
- package/dist/components/cv-combobox-option.js +66 -0
- package/dist/components/cv-combobox.d.ts +135 -0
- package/dist/components/cv-combobox.js +834 -0
- package/dist/components/cv-command-item.d.ts +30 -0
- package/dist/components/cv-command-item.js +68 -0
- package/dist/components/cv-command-palette.d.ts +105 -0
- package/dist/components/cv-command-palette.js +578 -0
- package/dist/components/cv-context-menu.d.ts +98 -0
- package/dist/components/cv-context-menu.js +515 -0
- package/dist/components/cv-copy-button.d.ts +61 -0
- package/dist/components/cv-copy-button.js +318 -0
- package/dist/components/cv-date-picker.d.ts +161 -0
- package/dist/components/cv-date-picker.js +803 -0
- package/dist/components/cv-dialog.d.ts +89 -0
- package/dist/components/cv-dialog.js +459 -0
- package/dist/components/cv-disclosure.d.ts +57 -0
- package/dist/components/cv-disclosure.js +241 -0
- package/dist/components/cv-drawer.d.ts +102 -0
- package/dist/components/cv-drawer.js +595 -0
- package/dist/components/cv-feed-article.d.ts +26 -0
- package/dist/components/cv-feed-article.js +52 -0
- package/dist/components/cv-feed.d.ts +62 -0
- package/dist/components/cv-feed.js +310 -0
- package/dist/components/cv-grid-cell.d.ts +30 -0
- package/dist/components/cv-grid-cell.js +57 -0
- package/dist/components/cv-grid-column.d.ts +30 -0
- package/dist/components/cv-grid-column.js +43 -0
- package/dist/components/cv-grid-row.d.ts +30 -0
- package/dist/components/cv-grid-row.js +42 -0
- package/dist/components/cv-grid.d.ts +119 -0
- package/dist/components/cv-grid.js +567 -0
- package/dist/components/cv-icon.d.ts +57 -0
- package/dist/components/cv-icon.js +352 -0
- package/dist/components/cv-input.d.ts +127 -0
- package/dist/components/cv-input.js +482 -0
- package/dist/components/cv-landmark.d.ts +32 -0
- package/dist/components/cv-landmark.js +62 -0
- package/dist/components/cv-link.d.ts +22 -0
- package/dist/components/cv-link.js +99 -0
- package/dist/components/cv-listbox-group.d.ts +15 -0
- package/dist/components/cv-listbox-group.js +42 -0
- package/dist/components/cv-listbox.d.ts +81 -0
- package/dist/components/cv-listbox.js +388 -0
- package/dist/components/cv-menu-button.d.ts +118 -0
- package/dist/components/cv-menu-button.js +822 -0
- package/dist/components/cv-menu-group.d.ts +20 -0
- package/dist/components/cv-menu-group.js +48 -0
- package/dist/components/cv-menu-item.d.ts +52 -0
- package/dist/components/cv-menu-item.js +105 -0
- package/dist/components/cv-menu.d.ts +62 -0
- package/dist/components/cv-menu.js +414 -0
- package/dist/components/cv-meter.d.ts +66 -0
- package/dist/components/cv-meter.js +154 -0
- package/dist/components/cv-number.d.ts +139 -0
- package/dist/components/cv-number.js +553 -0
- package/dist/components/cv-option.d.ts +30 -0
- package/dist/components/cv-option.js +84 -0
- package/dist/components/cv-popover.d.ts +87 -0
- package/dist/components/cv-popover.js +373 -0
- package/dist/components/cv-progress-ring.d.ts +45 -0
- package/dist/components/cv-progress-ring.js +169 -0
- package/dist/components/cv-progress.d.ts +45 -0
- package/dist/components/cv-progress.js +148 -0
- package/dist/components/cv-radio-group.d.ts +79 -0
- package/dist/components/cv-radio-group.js +398 -0
- package/dist/components/cv-radio.d.ts +36 -0
- package/dist/components/cv-radio.js +123 -0
- package/dist/components/cv-select-group.d.ts +15 -0
- package/dist/components/cv-select-group.js +44 -0
- package/dist/components/cv-select-option.d.ts +30 -0
- package/dist/components/cv-select-option.js +66 -0
- package/dist/components/cv-select.d.ts +128 -0
- package/dist/components/cv-select.js +666 -0
- package/dist/components/cv-sidebar-item.d.ts +26 -0
- package/dist/components/cv-sidebar-item.js +142 -0
- package/dist/components/cv-sidebar.d.ts +171 -0
- package/dist/components/cv-sidebar.js +767 -0
- package/dist/components/cv-slider-multi-thumb.d.ts +73 -0
- package/dist/components/cv-slider-multi-thumb.js +374 -0
- package/dist/components/cv-slider.d.ts +84 -0
- package/dist/components/cv-slider.js +328 -0
- package/dist/components/cv-spinbutton.d.ts +121 -0
- package/dist/components/cv-spinbutton.js +486 -0
- package/dist/components/cv-spinner.d.ts +18 -0
- package/dist/components/cv-spinner.js +95 -0
- package/dist/components/cv-switch.d.ts +81 -0
- package/dist/components/cv-switch.js +285 -0
- package/dist/components/cv-tab-panel.d.ts +20 -0
- package/dist/components/cv-tab-panel.js +37 -0
- package/dist/components/cv-tab.d.ts +40 -0
- package/dist/components/cv-tab.js +132 -0
- package/dist/components/cv-table-cell.d.ts +31 -0
- package/dist/components/cv-table-cell.js +49 -0
- package/dist/components/cv-table-column.d.ts +37 -0
- package/dist/components/cv-table-column.js +63 -0
- package/dist/components/cv-table-row.d.ts +30 -0
- package/dist/components/cv-table-row.js +45 -0
- package/dist/components/cv-table.d.ts +147 -0
- package/dist/components/cv-table.js +607 -0
- package/dist/components/cv-tabs.d.ts +70 -0
- package/dist/components/cv-tabs.js +524 -0
- package/dist/components/cv-textarea.d.ts +108 -0
- package/dist/components/cv-textarea.js +328 -0
- package/dist/components/cv-toast-region.d.ts +39 -0
- package/dist/components/cv-toast-region.js +162 -0
- package/dist/components/cv-toast.d.ts +67 -0
- package/dist/components/cv-toast.js +315 -0
- package/dist/components/cv-toolbar-item.d.ts +25 -0
- package/dist/components/cv-toolbar-item.js +72 -0
- package/dist/components/cv-toolbar-separator.d.ts +25 -0
- package/dist/components/cv-toolbar-separator.js +45 -0
- package/dist/components/cv-toolbar.d.ts +63 -0
- package/dist/components/cv-toolbar.js +295 -0
- package/dist/components/cv-tooltip.d.ts +83 -0
- package/dist/components/cv-tooltip.js +455 -0
- package/dist/components/cv-treegrid-cell.d.ts +30 -0
- package/dist/components/cv-treegrid-cell.js +57 -0
- package/dist/components/cv-treegrid-column.d.ts +37 -0
- package/dist/components/cv-treegrid-column.js +53 -0
- package/dist/components/cv-treegrid-row.d.ts +55 -0
- package/dist/components/cv-treegrid-row.js +90 -0
- package/dist/components/cv-treegrid.d.ts +96 -0
- package/dist/components/cv-treegrid.js +632 -0
- package/dist/components/cv-treeitem.d.ts +58 -0
- package/dist/components/cv-treeitem.js +144 -0
- package/dist/components/cv-treeview.d.ts +70 -0
- package/dist/components/cv-treeview.js +396 -0
- package/dist/components/cv-window-splitter.d.ts +79 -0
- package/dist/components/cv-window-splitter.js +316 -0
- package/dist/components/index.d.ts +94 -0
- package/dist/components/index.js +79 -0
- package/dist/dialog/create-dialog-controller.d.ts +31 -0
- package/dist/dialog/create-dialog-controller.js +320 -0
- package/dist/dialog/index.d.ts +2 -0
- package/dist/dialog/index.js +1 -0
- package/dist/form-associated/FormAssociatedReatomElement.d.ts +25 -0
- package/dist/form-associated/FormAssociatedReatomElement.js +70 -0
- package/dist/form-associated/withFormAssociated.d.ts +5 -0
- package/dist/form-associated/withFormAssociated.js +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +9 -0
- package/dist/reatom-lit/ReatomLitElement.d.ts +27 -0
- package/dist/reatom-lit/ReatomLitElement.js +118 -0
- package/dist/reatom-lit/html.d.ts +4 -0
- package/dist/reatom-lit/html.js +10 -0
- package/dist/reatom-lit/index.d.ts +4 -0
- package/dist/reatom-lit/index.js +4 -0
- package/dist/reatom-lit/watch.d.ts +15 -0
- package/dist/reatom-lit/watch.js +40 -0
- package/dist/reatom-lit/withReatomElement.d.ts +4 -0
- package/dist/reatom-lit/withReatomElement.js +57 -0
- package/dist/register.d.ts +1 -0
- package/dist/register.js +84 -0
- package/dist/styles/component-styles.d.ts +4 -0
- package/dist/styles/component-styles.js +78 -0
- package/dist/theme/cv-theme-provider.d.ts +32 -0
- package/dist/theme/cv-theme-provider.js +110 -0
- package/dist/theme/index.d.ts +4 -0
- package/dist/theme/index.js +2 -0
- package/dist/theme/theme-engine.d.ts +4 -0
- package/dist/theme/theme-engine.js +67 -0
- package/dist/theme/tokens.css +265 -0
- package/dist/theme/types.d.ts +7 -0
- package/dist/theme/types.js +1 -0
- package/dist/toast/create-toast-controller.d.ts +12 -0
- package/dist/toast/create-toast-controller.js +12 -0
- package/dist/toast/index.d.ts +2 -0
- package/dist/toast/index.js +1 -0
- package/package.json +146 -0
- package/specs/_template.md +110 -0
- package/specs/components/accordion.md +207 -0
- package/specs/components/alert.md +83 -0
- package/specs/components/badge.md +183 -0
- package/specs/components/breadcrumb.md +152 -0
- package/specs/components/button.md +227 -0
- package/specs/components/callout.md +153 -0
- package/specs/components/card.md +192 -0
- package/specs/components/carousel.md +232 -0
- package/specs/components/checkbox.md +141 -0
- package/specs/components/combobox.md +427 -0
- package/specs/components/context-menu.md +375 -0
- package/specs/components/copy-button.md +236 -0
- package/specs/components/date-picker.md +290 -0
- package/specs/components/dialog.md +184 -0
- package/specs/components/disclosure.md +151 -0
- package/specs/components/drawer.md +216 -0
- package/specs/components/feed.md +266 -0
- package/specs/components/grid.md +423 -0
- package/specs/components/input.md +237 -0
- package/specs/components/landmark.md +92 -0
- package/specs/components/link.md +117 -0
- package/specs/components/listbox.md +327 -0
- package/specs/components/menu.md +508 -0
- package/specs/components/meter.md +148 -0
- package/specs/components/number.md +268 -0
- package/specs/components/option.md +167 -0
- package/specs/components/popover.md +207 -0
- package/specs/components/progress-ring.md +134 -0
- package/specs/components/progress.md +110 -0
- package/specs/components/radio.md +208 -0
- package/specs/components/select.md +305 -0
- package/specs/components/sidebar.md +204 -0
- package/specs/components/spinbutton.md +157 -0
- package/specs/components/spinner.md +83 -0
- package/specs/components/switch.md +145 -0
- package/specs/components/table.md +372 -0
- package/specs/components/tabs.md +242 -0
- package/specs/components/textarea.md +166 -0
- package/specs/components/theme.md +364 -0
- package/specs/components/toast.md +198 -0
- package/specs/components/toolbar.md +258 -0
- package/specs/components/tooltip.md +152 -0
- package/specs/components/treegrid.md +363 -0
- package/specs/components/treeview.md +263 -0
- package/specs/components/window-splitter.md +225 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# cv-number
|
|
2
|
+
|
|
3
|
+
Numeric input field with optional stepper controls, clearable behavior, and form-field chrome (label, help-text, prefix/suffix slots).
|
|
4
|
+
|
|
5
|
+
**Headless:** [`createNumber`](https://github.com/chromvoid/headless-ui/blob/main/specs/components/number.md)
|
|
6
|
+
|
|
7
|
+
## Anatomy
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
<cv-number> (host)
|
|
11
|
+
├── <span part="form-control-label">
|
|
12
|
+
│ └── <slot name="label">
|
|
13
|
+
├── <div part="base">
|
|
14
|
+
│ ├── <span part="prefix">
|
|
15
|
+
│ │ └── <slot name="prefix">
|
|
16
|
+
│ ├── <input part="input" role="spinbutton" inputmode="decimal">
|
|
17
|
+
│ ├── <span part="clear-button" role="button"> ← conditional on showClearButton
|
|
18
|
+
│ │ └── <slot name="clear-icon">×</slot>
|
|
19
|
+
│ ├── <span part="stepper"> ← conditional on stepper
|
|
20
|
+
│ │ ├── <button part="increment" type="button">
|
|
21
|
+
│ │ └── <button part="decrement" type="button">
|
|
22
|
+
│ └── <span part="suffix">
|
|
23
|
+
│ └── <slot name="suffix">
|
|
24
|
+
└── <span part="form-control-help-text">
|
|
25
|
+
└── <slot name="help-text">
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Attributes
|
|
29
|
+
|
|
30
|
+
| Attribute | Type | Default | Reflects | Description |
|
|
31
|
+
| ------------------ | ------- | ------------ | -------- | -------------------------------------------------------- |
|
|
32
|
+
| `value` | Number | `0` | no | Current numeric value |
|
|
33
|
+
| `default-value` | Number | `min ?? 0` | no | Value to reset to on clear |
|
|
34
|
+
| `min` | Number | — | no | Optional minimum boundary |
|
|
35
|
+
| `max` | Number | — | no | Optional maximum boundary |
|
|
36
|
+
| `step` | Number | `1` | no | Small increment/decrement step |
|
|
37
|
+
| `large-step` | Number | `10` | no | Large increment/decrement step (`PageUp`/`PageDown`) |
|
|
38
|
+
| `name` | String | `""` | no | Form field name for submit serialization |
|
|
39
|
+
| `disabled` | Boolean | `false` | yes | Prevents interaction and dims the component |
|
|
40
|
+
| `read-only` | Boolean | `false` | yes | Keeps focusable/announced but blocks user mutation |
|
|
41
|
+
| `required` | Boolean | `false` | yes | Marks the field as required for form validation |
|
|
42
|
+
| `clearable` | Boolean | `false` | yes | Shows a clear button when the value differs from default |
|
|
43
|
+
| `stepper` | Boolean | `false` | yes | Shows increment/decrement stepper buttons |
|
|
44
|
+
| `placeholder` | String | `""` | no | Placeholder text displayed when the input is empty |
|
|
45
|
+
| `size` | String | `"medium"` | yes | Component size: `small` \| `medium` \| `large` |
|
|
46
|
+
| `variant` | String | `"outlined"` | yes | Visual variant: `outlined` \| `filled` |
|
|
47
|
+
| `aria-label` | String | `""` | no | Accessible label |
|
|
48
|
+
| `aria-labelledby` | String | `""` | no | ID reference to visible label |
|
|
49
|
+
| `aria-describedby` | String | `""` | no | ID reference to description |
|
|
50
|
+
|
|
51
|
+
## Variants
|
|
52
|
+
|
|
53
|
+
| Variant | Description |
|
|
54
|
+
| ---------- | ------------------------------------------------------------ |
|
|
55
|
+
| `outlined` | Default style with visible border and transparent background |
|
|
56
|
+
| `filled` | Subtle background fill with no visible border |
|
|
57
|
+
|
|
58
|
+
## Sizes
|
|
59
|
+
|
|
60
|
+
| Size | `--cv-number-height` | `--cv-number-padding-inline` | `--cv-number-font-size` |
|
|
61
|
+
| -------- | -------------------- | ---------------------------- | -------------------------------- |
|
|
62
|
+
| `small` | `30px` | `var(--cv-space-2, 8px)` | `var(--cv-font-size-sm, 13px)` |
|
|
63
|
+
| `medium` | `36px` | `var(--cv-space-3, 12px)` | `var(--cv-font-size-base, 14px)` |
|
|
64
|
+
| `large` | `42px` | `var(--cv-space-4, 16px)` | `var(--cv-font-size-md, 16px)` |
|
|
65
|
+
|
|
66
|
+
## Slots
|
|
67
|
+
|
|
68
|
+
| Slot | Description |
|
|
69
|
+
| ------------ | -------------------------------------------------------------- |
|
|
70
|
+
| `prefix` | Content rendered before the input (e.g., currency symbol icon) |
|
|
71
|
+
| `suffix` | Content rendered after the stepper controls (e.g., unit label) |
|
|
72
|
+
| `clear-icon` | Custom icon for the clear button (default: `×`) |
|
|
73
|
+
| `label` | Label text displayed above the input |
|
|
74
|
+
| `help-text` | Help or description text displayed below the input |
|
|
75
|
+
|
|
76
|
+
> **Note:** The native `<input>` element is not slottable. There is no default slot.
|
|
77
|
+
|
|
78
|
+
## CSS Parts
|
|
79
|
+
|
|
80
|
+
| Part | Element | Description |
|
|
81
|
+
| ------------------------ | ---------- | ------------------------------------------------------------------ |
|
|
82
|
+
| `base` | `<div>` | Outermost wrapper element containing input and controls |
|
|
83
|
+
| `input` | `<input>` | The native input element with `role="spinbutton"` |
|
|
84
|
+
| `prefix` | `<span>` | Wrapper around the `prefix` slot |
|
|
85
|
+
| `suffix` | `<span>` | Wrapper around the `suffix` slot |
|
|
86
|
+
| `clear-button` | `<span>` | The clear button wrapper (conditionally visible) |
|
|
87
|
+
| `stepper` | `<span>` | Wrapper around increment/decrement buttons (conditionally visible) |
|
|
88
|
+
| `increment` | `<button>` | Increment stepper button |
|
|
89
|
+
| `decrement` | `<button>` | Decrement stepper button |
|
|
90
|
+
| `form-control-label` | `<span>` | Wrapper around the `label` slot |
|
|
91
|
+
| `form-control-help-text` | `<span>` | Wrapper around the `help-text` slot |
|
|
92
|
+
|
|
93
|
+
## CSS Custom Properties
|
|
94
|
+
|
|
95
|
+
| Property | Default | Description |
|
|
96
|
+
| --------------------------------- | -------------------------------------------- | --------------------------------------------------------------- |
|
|
97
|
+
| `--cv-number-height` | `36px` | Component block size |
|
|
98
|
+
| `--cv-number-padding-inline` | `var(--cv-space-3, 12px)` | Horizontal padding inside the input container |
|
|
99
|
+
| `--cv-number-font-size` | `var(--cv-font-size-base, 14px)` | Font size of the input text |
|
|
100
|
+
| `--cv-number-border-radius` | `var(--cv-radius-sm, 6px)` | Border radius of the input container |
|
|
101
|
+
| `--cv-number-border-color` | `var(--cv-color-border, #2a3245)` | Border color in default state |
|
|
102
|
+
| `--cv-number-background` | `transparent` | Background color of the input container |
|
|
103
|
+
| `--cv-number-color` | `var(--cv-color-text, #e8ecf6)` | Text color of the input value |
|
|
104
|
+
| `--cv-number-placeholder-color` | `var(--cv-color-text-muted, #6b7a99)` | Placeholder text color |
|
|
105
|
+
| `--cv-number-focus-ring` | `0 0 0 2px var(--cv-color-primary, #65d7ff)` | Box-shadow applied on focus |
|
|
106
|
+
| `--cv-number-icon-size` | `1em` | Size of prefix/suffix/clear icons |
|
|
107
|
+
| `--cv-number-gap` | `var(--cv-space-2, 8px)` | Spacing between inner elements (prefix, input, buttons, suffix) |
|
|
108
|
+
| `--cv-number-transition-duration` | `var(--cv-duration-fast, 120ms)` | Transition duration for state changes |
|
|
109
|
+
| `--cv-number-stepper-width` | `24px` | Width of each stepper button |
|
|
110
|
+
|
|
111
|
+
Additionally, component styles depend on theme tokens through fallback values:
|
|
112
|
+
|
|
113
|
+
| Theme Property | Default | Description |
|
|
114
|
+
| ----------------------------- | --------- | --------------------------------------------------- |
|
|
115
|
+
| `--cv-color-border` | `#2a3245` | Base border color |
|
|
116
|
+
| `--cv-color-surface` | `#141923` | Surface background color (used by `filled` variant) |
|
|
117
|
+
| `--cv-color-surface-elevated` | `#1d2432` | Stepper button background |
|
|
118
|
+
| `--cv-color-text` | `#e8ecf6` | Default text color |
|
|
119
|
+
| `--cv-color-text-muted` | `#6b7a99` | Muted text color for placeholder |
|
|
120
|
+
| `--cv-color-primary` | `#65d7ff` | Primary accent color for focus ring |
|
|
121
|
+
| `--cv-duration-fast` | `120ms` | Transition duration |
|
|
122
|
+
| `--cv-easing-standard` | `ease` | Transition timing function |
|
|
123
|
+
| `--cv-radius-sm` | `6px` | Base border radius fallback |
|
|
124
|
+
| `--cv-font-size-sm` | `13px` | Small font size |
|
|
125
|
+
| `--cv-font-size-base` | `14px` | Base font size |
|
|
126
|
+
| `--cv-font-size-md` | `16px` | Medium font size |
|
|
127
|
+
| `--cv-space-2` | `8px` | Spacing scale: small |
|
|
128
|
+
| `--cv-space-3` | `12px` | Spacing scale: medium |
|
|
129
|
+
| `--cv-space-4` | `16px` | Spacing scale: large |
|
|
130
|
+
|
|
131
|
+
## Visual States
|
|
132
|
+
|
|
133
|
+
| Host selector | Description |
|
|
134
|
+
| ----------------------------- | --------------------------------------------------------------------------- |
|
|
135
|
+
| `:host([disabled])` | Reduced opacity (`0.55`), `cursor: not-allowed`, no interaction |
|
|
136
|
+
| `:host([read-only])` | Normal opacity, `cursor: default`, input text not editable |
|
|
137
|
+
| `:host([required])` | No visual change by default (can be styled via part selectors) |
|
|
138
|
+
| `:host([focused])` | Focus ring applied via `--cv-number-focus-ring` |
|
|
139
|
+
| `:host([filled])` | Indicates value differs from default (e.g., for floating label transitions) |
|
|
140
|
+
| `:host([clearable])` | Clear button space reserved in layout |
|
|
141
|
+
| `:host([stepper])` | Stepper buttons rendered and visible |
|
|
142
|
+
| `:host([size="small"])` | Small size overrides |
|
|
143
|
+
| `:host([size="large"])` | Large size overrides |
|
|
144
|
+
| `:host([variant="outlined"])` | Visible border, transparent background |
|
|
145
|
+
| `:host([variant="filled"])` | Subtle background (`--cv-color-surface`), no visible border |
|
|
146
|
+
|
|
147
|
+
## Reactive State Mapping
|
|
148
|
+
|
|
149
|
+
`cv-number` is a visual adapter over headless `createNumber`.
|
|
150
|
+
|
|
151
|
+
### UIKit properties to headless actions
|
|
152
|
+
|
|
153
|
+
| UIKit Property | Direction | Headless Binding |
|
|
154
|
+
| ------------------ | ------------------- | ------------------------------------------------------ |
|
|
155
|
+
| `value` | attr/prop -> action | `actions.setValue(value)` |
|
|
156
|
+
| `disabled` | attr -> action | `actions.setDisabled(value)` |
|
|
157
|
+
| `read-only` | attr -> action | `actions.setReadOnly(value)` |
|
|
158
|
+
| `required` | attr -> action | `actions.setRequired(value)` |
|
|
159
|
+
| `placeholder` | attr -> action | `actions.setPlaceholder(value)` |
|
|
160
|
+
| `clearable` | attr -> action | `actions.setClearable(value)` |
|
|
161
|
+
| `stepper` | attr -> action | `actions.setStepper(value)` |
|
|
162
|
+
| `min` | attr -> option | passed to `createNumber(options)` |
|
|
163
|
+
| `max` | attr -> option | passed to `createNumber(options)` |
|
|
164
|
+
| `step` | attr -> option | passed to `createNumber(options)` |
|
|
165
|
+
| `large-step` | attr -> option | passed to `createNumber(options)` |
|
|
166
|
+
| `default-value` | attr -> option | passed as `defaultValue` to `createNumber(options)` |
|
|
167
|
+
| `aria-label` | attr -> option | passed as `ariaLabel` to `createNumber(options)` |
|
|
168
|
+
| `aria-labelledby` | attr -> option | passed as `ariaLabelledBy` to `createNumber(options)` |
|
|
169
|
+
| `aria-describedby` | attr -> option | passed as `ariaDescribedBy` to `createNumber(options)` |
|
|
170
|
+
|
|
171
|
+
### Headless state to DOM reflection
|
|
172
|
+
|
|
173
|
+
| Headless State | Direction | DOM Reflection |
|
|
174
|
+
| ----------------------------------- | ------------- | ------------------------------------------------------------------------------------ |
|
|
175
|
+
| `state.isDisabled()` | state -> attr | `[disabled]` host attribute |
|
|
176
|
+
| `state.isReadOnly()` | state -> attr | `[read-only]` host attribute |
|
|
177
|
+
| `state.required()` | state -> attr | `[required]` host attribute |
|
|
178
|
+
| `state.focused()` | state -> attr | `[focused]` host attribute |
|
|
179
|
+
| `state.filled()` | state -> attr | `[filled]` host attribute |
|
|
180
|
+
| `state.showClearButton()` | state -> DOM | shows/hides the clear button element |
|
|
181
|
+
| `state.stepper()` | state -> DOM | shows/hides the stepper buttons |
|
|
182
|
+
| `state.draftText()` | state -> DOM | when non-null, displayed in the input; when null, displays formatted `String(value)` |
|
|
183
|
+
| `state.value()` | state -> DOM | displayed in the input when `draftText` is null |
|
|
184
|
+
| `state.placeholder()` | state -> DOM | applied as placeholder on the native input |
|
|
185
|
+
| `state.hasMin()` / `state.hasMax()` | state -> DOM | for conditional styling or rendering hints |
|
|
186
|
+
|
|
187
|
+
### Contract props spreading
|
|
188
|
+
|
|
189
|
+
- `contracts.getInputProps()` is spread onto the `[part="input"]` native `<input>` element to apply `id`, `role`, `tabindex`, `inputmode`, `aria-valuenow`, `aria-valuemin`, `aria-valuemax`, `aria-valuetext`, `aria-disabled`, `aria-readonly`, `aria-required`, `aria-label`, `aria-labelledby`, `aria-describedby`, `placeholder`, and `autocomplete`.
|
|
190
|
+
- `contracts.getIncrementButtonProps()` is spread onto the `[part="increment"]` button to apply `id`, `tabindex`, `aria-label`, `aria-disabled`, `hidden`, `aria-hidden`, and `onClick`.
|
|
191
|
+
- `contracts.getDecrementButtonProps()` is spread onto the `[part="decrement"]` button to apply `id`, `tabindex`, `aria-label`, `aria-disabled`, `hidden`, `aria-hidden`, and `onClick`.
|
|
192
|
+
- `contracts.getClearButtonProps()` is spread onto the `[part="clear-button"]` element to apply `role`, `aria-label`, `tabindex`, `hidden`, `aria-hidden`, and `onClick`.
|
|
193
|
+
|
|
194
|
+
### Event wiring
|
|
195
|
+
|
|
196
|
+
- Native `<input>` `input` event -> `actions.handleInput(e.target.value)` (updates draft text)
|
|
197
|
+
- Native `<input>` `keydown` event -> `actions.handleKeyDown(e)` (handles ArrowUp/Down, PageUp/Down, Home/End, Enter, Escape)
|
|
198
|
+
- Native `<input>` `focus` event -> `actions.setFocused(true)` -> dispatches `cv-focus` CustomEvent
|
|
199
|
+
- Native `<input>` `blur` event -> `actions.setFocused(false)` (triggers draft commit) -> dispatches `cv-blur` CustomEvent; if value changed since focus, dispatches `cv-change` CustomEvent
|
|
200
|
+
- Clear button `click` -> `actions.clear()` -> dispatches `cv-clear` CustomEvent
|
|
201
|
+
- Increment button `click` -> `actions.increment()` -> dispatches `cv-change` CustomEvent
|
|
202
|
+
- Decrement button `click` -> `actions.decrement()` -> dispatches `cv-change` CustomEvent
|
|
203
|
+
|
|
204
|
+
### Input display logic (UIKit responsibility)
|
|
205
|
+
|
|
206
|
+
UIKit reads `state.draftText()` and `state.value()` to determine what to display in the native `<input>`:
|
|
207
|
+
|
|
208
|
+
- When `draftText !== null`: display `draftText` (user is actively editing)
|
|
209
|
+
- When `draftText === null`: display formatted `String(value)` (committed state)
|
|
210
|
+
|
|
211
|
+
UIKit does not own value management, clamping, snapping, draft commit logic, or ARIA computation; headless state is the source of truth.
|
|
212
|
+
|
|
213
|
+
## Events
|
|
214
|
+
|
|
215
|
+
| Event | Detail | Description |
|
|
216
|
+
| ----------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
217
|
+
| `cv-change` | `{ value: number }` | Fires on committed value change from user interaction (stepper click, keyboard step, draft commit on blur/Enter). Does not fire from programmatic `setValue`. |
|
|
218
|
+
| `cv-clear` | `{ }` | Fires when the value is cleared via the clear button or `Escape` key |
|
|
219
|
+
| `cv-focus` | `{ }` | Fires when the input receives focus |
|
|
220
|
+
| `cv-blur` | `{ }` | Fires when the input loses focus |
|
|
221
|
+
|
|
222
|
+
## Usage
|
|
223
|
+
|
|
224
|
+
```html
|
|
225
|
+
<!-- Basic number input -->
|
|
226
|
+
<cv-number value="0" placeholder="Enter a number"></cv-number>
|
|
227
|
+
|
|
228
|
+
<!-- With label and help text -->
|
|
229
|
+
<cv-number>
|
|
230
|
+
<span slot="label">Quantity</span>
|
|
231
|
+
<span slot="help-text">Enter a value between 1 and 100</span>
|
|
232
|
+
</cv-number>
|
|
233
|
+
|
|
234
|
+
<!-- With min, max, and step -->
|
|
235
|
+
<cv-number value="5" min="0" max="100" step="5" large-step="25"></cv-number>
|
|
236
|
+
|
|
237
|
+
<!-- Stepper buttons visible -->
|
|
238
|
+
<cv-number value="1" min="0" max="10" stepper></cv-number>
|
|
239
|
+
|
|
240
|
+
<!-- Clearable -->
|
|
241
|
+
<cv-number value="42" clearable></cv-number>
|
|
242
|
+
|
|
243
|
+
<!-- With prefix (currency symbol) and suffix (unit) -->
|
|
244
|
+
<cv-number>
|
|
245
|
+
<span slot="prefix">$</span>
|
|
246
|
+
<span slot="suffix">.00</span>
|
|
247
|
+
</cv-number>
|
|
248
|
+
|
|
249
|
+
<!-- Filled variant, small size -->
|
|
250
|
+
<cv-number variant="filled" size="small" placeholder="0"></cv-number>
|
|
251
|
+
|
|
252
|
+
<!-- Large size, outlined variant with stepper and clearable -->
|
|
253
|
+
<cv-number size="large" stepper clearable value="10" min="0" max="99"></cv-number>
|
|
254
|
+
|
|
255
|
+
<!-- Disabled -->
|
|
256
|
+
<cv-number disabled value="50"></cv-number>
|
|
257
|
+
|
|
258
|
+
<!-- Read-only -->
|
|
259
|
+
<cv-number read-only value="100"></cv-number>
|
|
260
|
+
|
|
261
|
+
<!-- Required with label -->
|
|
262
|
+
<cv-number required>
|
|
263
|
+
<span slot="label">Age</span>
|
|
264
|
+
</cv-number>
|
|
265
|
+
|
|
266
|
+
<!-- With accessible label -->
|
|
267
|
+
<cv-number aria-label="Quantity" value="1" min="1" max="99" stepper></cv-number>
|
|
268
|
+
```
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# cv-option
|
|
2
|
+
|
|
3
|
+
Individual selectable option for use as a direct child of `cv-listbox` or `cv-listbox-group`. All ARIA attributes are managed exclusively by the parent `cv-listbox` via headless `contracts.getOptionProps(id)`; `cv-option` itself sets no ARIA.
|
|
4
|
+
|
|
5
|
+
> **Note:** `cv-option` has no headless module of its own. It is a purely presentational element. See the [Parent-managed ARIA Contract](#parent-managed-aria-contract) section for the full attribute contract imposed by the parent.
|
|
6
|
+
|
|
7
|
+
## Anatomy
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
<cv-option> (host)
|
|
11
|
+
└── <div part="base">
|
|
12
|
+
├── <span part="prefix">
|
|
13
|
+
│ └── <slot name="prefix">
|
|
14
|
+
├── <span part="label">
|
|
15
|
+
│ └── <slot>
|
|
16
|
+
└── <span part="suffix">
|
|
17
|
+
└── <slot name="suffix">
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Attributes
|
|
21
|
+
|
|
22
|
+
| Attribute | Type | Default | Description |
|
|
23
|
+
| ---------- | ------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
24
|
+
| `value` | String | `""` | Unique identifier for this option. The parent `cv-listbox` reads this to register the option in the headless model. Auto-generated as `option-{n}` if omitted. |
|
|
25
|
+
| `disabled` | Boolean | `false` | Whether the option is disabled. Prevents selection and keyboard activation. Also reflected as `aria-disabled` by the parent via `getOptionProps`. |
|
|
26
|
+
| `selected` | Boolean | `false` | Whether the option is currently selected. Set by the parent `cv-listbox` as part of state synchronisation. |
|
|
27
|
+
| `active` | Boolean | `false` | Whether the option is the active (highlighted) option. Set by the parent `cv-listbox` as part of state synchronisation. |
|
|
28
|
+
|
|
29
|
+
## Slots
|
|
30
|
+
|
|
31
|
+
| Slot | Description |
|
|
32
|
+
| ----------- | -------------------------------------------------------------------------------------------------- |
|
|
33
|
+
| `(default)` | Option label text. Also used as the source text for typeahead matching by the parent `cv-listbox`. |
|
|
34
|
+
| `prefix` | Icon or element placed before the label. |
|
|
35
|
+
| `suffix` | Icon or element placed after the label. |
|
|
36
|
+
|
|
37
|
+
## CSS Parts
|
|
38
|
+
|
|
39
|
+
| Part | Element | Description |
|
|
40
|
+
| -------- | -------- | ----------------------------------------------------------------- |
|
|
41
|
+
| `base` | `<div>` | Root wrapper; receives layout, background, and transition styles. |
|
|
42
|
+
| `label` | `<span>` | Wrapper around the default slot (label text). |
|
|
43
|
+
| `prefix` | `<span>` | Wrapper around the `prefix` named slot. |
|
|
44
|
+
| `suffix` | `<span>` | Wrapper around the `suffix` named slot. |
|
|
45
|
+
|
|
46
|
+
## CSS Custom Properties
|
|
47
|
+
|
|
48
|
+
| Property | Default | Description |
|
|
49
|
+
| --------------------------------- | ------------------------------------------------------------------------ | -------------------------------------------------------------------- |
|
|
50
|
+
| `--cv-option-padding-block` | `var(--cv-space-2, 8px)` | Vertical padding inside `[part="base"]`. |
|
|
51
|
+
| `--cv-option-padding-inline` | `var(--cv-space-3, 12px)` | Horizontal padding inside `[part="base"]`. |
|
|
52
|
+
| `--cv-option-border-radius` | `var(--cv-radius-sm, 6px)` | Border radius of `[part="base"]`. |
|
|
53
|
+
| `--cv-option-active-background` | `color-mix(in oklab, var(--cv-color-primary, #65d7ff) 22%, transparent)` | Background applied when the option is active (highlighted). |
|
|
54
|
+
| `--cv-option-selected-background` | `color-mix(in oklab, var(--cv-color-primary, #65d7ff) 34%, transparent)` | Background applied when the option is selected. |
|
|
55
|
+
| `--cv-option-disabled-opacity` | `0.55` | Opacity applied when the option is disabled. |
|
|
56
|
+
| `--cv-option-focus-outline-color` | `var(--cv-color-primary, #65d7ff)` | Outline color for `:focus-visible` (roving-tabindex focus strategy). |
|
|
57
|
+
|
|
58
|
+
Additionally, component styles depend on theme tokens through fallback values:
|
|
59
|
+
|
|
60
|
+
| Theme Property | Default | Description |
|
|
61
|
+
| ---------------------- | --------- | ---------------------------------------------------------------------------- |
|
|
62
|
+
| `--cv-color-text` | `#e8ecf6` | Default text color. |
|
|
63
|
+
| `--cv-color-primary` | `#65d7ff` | Primary accent color used for active/selected backgrounds and focus outline. |
|
|
64
|
+
| `--cv-duration-fast` | `120ms` | Background and color transition duration. |
|
|
65
|
+
| `--cv-easing-standard` | `ease` | Transition timing function. |
|
|
66
|
+
| `--cv-space-2` | `8px` | Fallback for vertical padding. |
|
|
67
|
+
| `--cv-space-3` | `12px` | Fallback for horizontal padding. |
|
|
68
|
+
| `--cv-radius-sm` | `6px` | Fallback for border radius. |
|
|
69
|
+
|
|
70
|
+
## Visual States
|
|
71
|
+
|
|
72
|
+
| Host selector | Description |
|
|
73
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
74
|
+
| `:host([active])` | Active/highlighted option; applies `--cv-option-active-background` to `[part="base"]`. |
|
|
75
|
+
| `:host([selected])` | Selected option; applies `--cv-option-selected-background` to `[part="base"]`. |
|
|
76
|
+
| `:host([disabled])` | Disabled option; applies `--cv-option-disabled-opacity` to `[part="base"]`. |
|
|
77
|
+
| `:host([hidden])` | Hidden option; `display: none` on the host. |
|
|
78
|
+
| `:host(:focus-visible)` | Focus ring when the option receives DOM focus (roving-tabindex strategy); 2px solid outline using `--cv-option-focus-outline-color`. |
|
|
79
|
+
|
|
80
|
+
## Events
|
|
81
|
+
|
|
82
|
+
`cv-option` emits no events. All interaction events (`input`, `change`) are dispatched by the parent `cv-listbox`.
|
|
83
|
+
|
|
84
|
+
## Parent-managed ARIA Contract
|
|
85
|
+
|
|
86
|
+
`cv-option` sets no ARIA attributes itself. The parent `cv-listbox` spreads `contracts.getOptionProps(id)` directly onto each `cv-option` host element. The following attributes are applied by the parent:
|
|
87
|
+
|
|
88
|
+
| Attribute | Source | Description |
|
|
89
|
+
| --------------- | -------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
90
|
+
| `id` | `getOptionProps(id)` | Unique DOM id used by `aria-activedescendant` on the listbox root. |
|
|
91
|
+
| `role` | `getOptionProps(id)` | Always `"option"`. |
|
|
92
|
+
| `tabindex` | `getOptionProps(id)` | `"0"` for the active option (roving-tabindex) or `"-1"` for all options (aria-activedescendant strategy). |
|
|
93
|
+
| `aria-selected` | `getOptionProps(id)` | `"true"` when the option is selected; `"false"` otherwise. |
|
|
94
|
+
| `aria-disabled` | `getOptionProps(id)` | `"true"` when `[disabled]` is present; omitted otherwise. |
|
|
95
|
+
| `aria-setsize` | `getOptionProps(id)` | Total number of options in the listbox (supports virtual scrolling). |
|
|
96
|
+
| `aria-posinset` | `getOptionProps(id)` | 1-based position of this option within the full option list. |
|
|
97
|
+
| `data-active` | `getOptionProps(id)` | Present when the option is the active option; used as a CSS hook. |
|
|
98
|
+
|
|
99
|
+
These attributes must not be set directly on `cv-option` by the consumer. They are owned entirely by the parent and will be overwritten on each render cycle.
|
|
100
|
+
|
|
101
|
+
## Usage
|
|
102
|
+
|
|
103
|
+
```html
|
|
104
|
+
<!-- Basic usage inside a listbox -->
|
|
105
|
+
<cv-listbox aria-label="Fruits">
|
|
106
|
+
<cv-option value="apple">Apple</cv-option>
|
|
107
|
+
<cv-option value="banana">Banana</cv-option>
|
|
108
|
+
<cv-option value="cherry" disabled>Cherry (unavailable)</cv-option>
|
|
109
|
+
</cv-listbox>
|
|
110
|
+
|
|
111
|
+
<!-- With prefix icon -->
|
|
112
|
+
<cv-listbox aria-label="Connections">
|
|
113
|
+
<cv-option value="wifi">
|
|
114
|
+
<icon-wifi slot="prefix"></icon-wifi>
|
|
115
|
+
Wi-Fi
|
|
116
|
+
</cv-option>
|
|
117
|
+
<cv-option value="ethernet">
|
|
118
|
+
<icon-ethernet slot="prefix"></icon-ethernet>
|
|
119
|
+
Ethernet
|
|
120
|
+
</cv-option>
|
|
121
|
+
</cv-listbox>
|
|
122
|
+
|
|
123
|
+
<!-- With suffix badge -->
|
|
124
|
+
<cv-listbox aria-label="Plans">
|
|
125
|
+
<cv-option value="free">
|
|
126
|
+
Free
|
|
127
|
+
<cv-badge slot="suffix">current</cv-badge>
|
|
128
|
+
</cv-option>
|
|
129
|
+
<cv-option value="pro">
|
|
130
|
+
Pro
|
|
131
|
+
<cv-badge slot="suffix" variant="primary">upgrade</cv-badge>
|
|
132
|
+
</cv-option>
|
|
133
|
+
</cv-listbox>
|
|
134
|
+
|
|
135
|
+
<!-- With both prefix and suffix -->
|
|
136
|
+
<cv-listbox aria-label="Files">
|
|
137
|
+
<cv-option value="doc">
|
|
138
|
+
<icon-file slot="prefix"></icon-file>
|
|
139
|
+
document.pdf
|
|
140
|
+
<span slot="suffix">12 KB</span>
|
|
141
|
+
</cv-option>
|
|
142
|
+
<cv-option value="img">
|
|
143
|
+
<icon-image slot="prefix"></icon-image>
|
|
144
|
+
photo.png
|
|
145
|
+
<span slot="suffix">4.2 MB</span>
|
|
146
|
+
</cv-option>
|
|
147
|
+
</cv-listbox>
|
|
148
|
+
|
|
149
|
+
<!-- Pre-selected option -->
|
|
150
|
+
<cv-listbox aria-label="Theme">
|
|
151
|
+
<cv-option value="light">Light</cv-option>
|
|
152
|
+
<cv-option value="dark" selected>Dark</cv-option>
|
|
153
|
+
<cv-option value="system">System</cv-option>
|
|
154
|
+
</cv-listbox>
|
|
155
|
+
|
|
156
|
+
<!-- Inside a group -->
|
|
157
|
+
<cv-listbox aria-label="City">
|
|
158
|
+
<cv-listbox-group label="North America">
|
|
159
|
+
<cv-option value="nyc">New York</cv-option>
|
|
160
|
+
<cv-option value="la">Los Angeles</cv-option>
|
|
161
|
+
</cv-listbox-group>
|
|
162
|
+
<cv-listbox-group label="Europe">
|
|
163
|
+
<cv-option value="lon">London</cv-option>
|
|
164
|
+
<cv-option value="par">Paris</cv-option>
|
|
165
|
+
</cv-listbox-group>
|
|
166
|
+
</cv-listbox>
|
|
167
|
+
```
|