@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,227 @@
|
|
|
1
|
+
# cv-button
|
|
2
|
+
|
|
3
|
+
Interactive element that triggers an action or toggles a pressed state.
|
|
4
|
+
|
|
5
|
+
**Headless:** [`createButton`](https://github.com/chromvoid/headless-ui/blob/main/specs/components/button.md)
|
|
6
|
+
|
|
7
|
+
## Anatomy
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
<cv-button> (host)
|
|
11
|
+
└── <button part="base" type="button" role="button">
|
|
12
|
+
├── <span part="spinner" aria-hidden="true"> ← only when [loading]
|
|
13
|
+
├── <span part="prefix">
|
|
14
|
+
│ └── <slot name="prefix">
|
|
15
|
+
├── <span part="label">
|
|
16
|
+
│ └── <slot>
|
|
17
|
+
└── <span part="suffix">
|
|
18
|
+
└── <slot name="suffix">
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Attributes
|
|
22
|
+
|
|
23
|
+
| Attribute | Type | Default | Description |
|
|
24
|
+
| ---------- | ------- | ----------- | ------------------------------------------------------------- |
|
|
25
|
+
| `disabled` | Boolean | `false` | Prevents interaction |
|
|
26
|
+
| `toggle` | Boolean | `false` | Enables toggle (pressed) behavior |
|
|
27
|
+
| `pressed` | Boolean | `false` | Pressed state (only meaningful when `toggle` is `true`) |
|
|
28
|
+
| `loading` | Boolean | `false` | Shows spinner and blocks interaction |
|
|
29
|
+
| `variant` | String | `"default"` | Visual variant: `default` \| `primary` \| `danger` \| `ghost` |
|
|
30
|
+
| `outline` | Boolean | `false` | Outlined appearance (transparent background, visible border) |
|
|
31
|
+
| `pill` | Boolean | `false` | Fully rounded edges (`border-radius: 999px`) |
|
|
32
|
+
| `size` | String | `"medium"` | Size: `small` \| `medium` \| `large` |
|
|
33
|
+
| `type` | String | `"button"` | Form action type: `button` \| `submit` \| `reset` |
|
|
34
|
+
|
|
35
|
+
## Form Behavior
|
|
36
|
+
|
|
37
|
+
- `type="button"`: no form action.
|
|
38
|
+
- `type="submit"`: triggers form submission for nearest form owner.
|
|
39
|
+
- `type="reset"`: triggers form reset for nearest form owner.
|
|
40
|
+
- Form owner resolution order:
|
|
41
|
+
1. host `[form="..."]` attribute by element id
|
|
42
|
+
2. nearest ancestor `form` via `closest('form')`
|
|
43
|
+
- If `disabled` or `loading` is active, submit/reset actions are blocked.
|
|
44
|
+
|
|
45
|
+
## Variants
|
|
46
|
+
|
|
47
|
+
| Variant | Description |
|
|
48
|
+
| --------- | --------------------------------------------------------------- |
|
|
49
|
+
| `default` | Default filled style with surface background and border |
|
|
50
|
+
| `primary` | Primary-tinted background and border using `--cv-color-primary` |
|
|
51
|
+
| `danger` | Danger-tinted background and border using `--cv-color-danger` |
|
|
52
|
+
| `ghost` | Transparent background and border |
|
|
53
|
+
|
|
54
|
+
The `outline` boolean modifier can be combined with any variant to produce an outlined appearance (transparent background, visible border tinted by variant color).
|
|
55
|
+
|
|
56
|
+
## Sizes
|
|
57
|
+
|
|
58
|
+
| Size | `--cv-button-min-height` | `--cv-button-padding-inline` | `--cv-button-padding-block` | `--cv-button-font-size` |
|
|
59
|
+
| -------- | ------------------------ | ---------------------------- | --------------------------- | -------------------------------- |
|
|
60
|
+
| `small` | `30px` | `var(--cv-space-2, 8px)` | `var(--cv-space-1, 4px)` | `var(--cv-font-size-sm, 13px)` |
|
|
61
|
+
| `medium` | `36px` | `var(--cv-space-3, 12px)` | `var(--cv-space-2, 8px)` | `var(--cv-font-size-base, 14px)` |
|
|
62
|
+
| `large` | `42px` | `var(--cv-space-4, 16px)` | `var(--cv-space-2, 8px)` | `var(--cv-font-size-md, 16px)` |
|
|
63
|
+
|
|
64
|
+
## Slots
|
|
65
|
+
|
|
66
|
+
| Slot | Description |
|
|
67
|
+
| ----------- | ---------------------------- |
|
|
68
|
+
| `(default)` | Button label |
|
|
69
|
+
| `prefix` | Icon or element before label |
|
|
70
|
+
| `suffix` | Icon or element after label |
|
|
71
|
+
|
|
72
|
+
## CSS Parts
|
|
73
|
+
|
|
74
|
+
| Part | Element | Description |
|
|
75
|
+
| --------- | ---------- | -------------------------------------------------------- |
|
|
76
|
+
| `base` | `<button>` | Root interactive element with `role="button"` |
|
|
77
|
+
| `label` | `<span>` | Wrapper around the default slot |
|
|
78
|
+
| `prefix` | `<span>` | Wrapper around the `prefix` slot |
|
|
79
|
+
| `suffix` | `<span>` | Wrapper around the `suffix` slot |
|
|
80
|
+
| `spinner` | `<span>` | Loading spinner (rendered only when `loading` is `true`) |
|
|
81
|
+
|
|
82
|
+
## CSS Custom Properties
|
|
83
|
+
|
|
84
|
+
| Property | Default | Description |
|
|
85
|
+
| ---------------------------- | -------------------------------- | ------------------------------------ |
|
|
86
|
+
| `--cv-button-min-height` | `36px` | Minimum block size of the button |
|
|
87
|
+
| `--cv-button-padding-inline` | `var(--cv-space-3, 12px)` | Horizontal padding |
|
|
88
|
+
| `--cv-button-padding-block` | `var(--cv-space-2, 8px)` | Vertical padding |
|
|
89
|
+
| `--cv-button-border-radius` | `var(--cv-radius-sm, 6px)` | Border radius for button shape |
|
|
90
|
+
| `--cv-button-gap` | `var(--cv-space-2, 8px)` | Spacing between button content parts |
|
|
91
|
+
| `--cv-button-font-size` | `var(--cv-font-size-base, 14px)` | Font size of button content |
|
|
92
|
+
|
|
93
|
+
Additionally, component styles depend on theme tokens through fallback values:
|
|
94
|
+
|
|
95
|
+
| Theme Property | Default | Description |
|
|
96
|
+
| ---------------------- | --------- | ------------------------------------ |
|
|
97
|
+
| `--cv-color-border` | `#2a3245` | Base border color |
|
|
98
|
+
| `--cv-color-surface` | `#141923` | Surface background color |
|
|
99
|
+
| `--cv-color-text` | `#e8ecf6` | Default text color |
|
|
100
|
+
| `--cv-color-primary` | `#65d7ff` | Primary accent color |
|
|
101
|
+
| `--cv-color-danger` | `#ff7d86` | Danger accent color |
|
|
102
|
+
| `--cv-duration-fast` | `120ms` | Transition duration |
|
|
103
|
+
| `--cv-easing-standard` | `ease` | Transition timing function |
|
|
104
|
+
| `--cv-radius-sm` | `6px` | Base radius used for button fallback |
|
|
105
|
+
| `--cv-space-1` | `4px` | Small spacing scale fallback |
|
|
106
|
+
| `--cv-space-2` | `8px` | Medium spacing scale fallback |
|
|
107
|
+
| `--cv-space-3` | `12px` | Medium-large spacing scale fallback |
|
|
108
|
+
| `--cv-space-4` | `16px` | Large spacing scale fallback |
|
|
109
|
+
|
|
110
|
+
## Visual States
|
|
111
|
+
|
|
112
|
+
| Host selector | Description |
|
|
113
|
+
| ---------------------------- | ----------------------------------------------------------------- |
|
|
114
|
+
| `:host([disabled])` | Reduced opacity (`0.55`), `cursor: not-allowed` |
|
|
115
|
+
| `:host([pressed])` | Primary-tinted background (per variant) |
|
|
116
|
+
| `:host([loading])` | Shows spinner, label reduced opacity (`0.72`), `cursor: progress` |
|
|
117
|
+
| `:host([variant="default"])` | Default surface background with border |
|
|
118
|
+
| `:host([variant="primary"])` | Primary-tinted background and border |
|
|
119
|
+
| `:host([variant="danger"])` | Danger-tinted background and border |
|
|
120
|
+
| `:host([variant="ghost"])` | Transparent background and border |
|
|
121
|
+
| `:host([outline])` | Transparent background, visible border (tinted by variant) |
|
|
122
|
+
| `:host([pill])` | Fully rounded edges |
|
|
123
|
+
| `:host([size="small"])` | Small size overrides |
|
|
124
|
+
| `:host([size="large"])` | Large size overrides |
|
|
125
|
+
|
|
126
|
+
## Reactive State Mapping
|
|
127
|
+
|
|
128
|
+
`cv-button` is a visual adapter over headless `createButton`.
|
|
129
|
+
|
|
130
|
+
| UIKit Property | Direction | Headless Binding |
|
|
131
|
+
| -------------- | ------------- | --------------------------------------------------------- |
|
|
132
|
+
| `disabled` | attr → action | `actions.setDisabled(value)` |
|
|
133
|
+
| `loading` | attr → action | `actions.setLoading(value)` |
|
|
134
|
+
| `pressed` | attr → action | `actions.setPressed(value)` |
|
|
135
|
+
| `toggle` | attr → option | passed as `isPressed` presence in `createButton(options)` |
|
|
136
|
+
|
|
137
|
+
| Headless State | Direction | DOM Reflection |
|
|
138
|
+
| -------------------- | ------------ | --------------------------- |
|
|
139
|
+
| `state.isDisabled()` | state → attr | `[disabled]` host attribute |
|
|
140
|
+
| `state.isLoading()` | state → attr | `[loading]` host attribute |
|
|
141
|
+
| `state.isPressed()` | state → attr | `[pressed]` host attribute |
|
|
142
|
+
|
|
143
|
+
- `contracts.getButtonProps()` is spread onto the inner `[part="base"]` element to apply `role`, `aria-disabled`, `aria-busy`, `aria-pressed`, `tabindex`, and keyboard/click handlers.
|
|
144
|
+
- UIKit dispatches `cv-input` and `cv-change` events by observing `isPressed` changes triggered by user activation (not by controlled `setPressed`).
|
|
145
|
+
- UIKit does not own activation or toggle logic; headless state is the source of truth.
|
|
146
|
+
|
|
147
|
+
## Events
|
|
148
|
+
|
|
149
|
+
| Event | Detail | Description |
|
|
150
|
+
| ----------- | ------------------------------------- | ----------------------------------------------------- |
|
|
151
|
+
| `cv-input` | `{pressed: boolean, toggle: boolean}` | Fires on activation in toggle mode only |
|
|
152
|
+
| `cv-change` | `{pressed: boolean}` | Fires when `pressed` state changes (toggle mode only) |
|
|
153
|
+
|
|
154
|
+
Normal (non-toggle) buttons rely on the native `click` event.
|
|
155
|
+
|
|
156
|
+
## Legacy Button Migration Mapping
|
|
157
|
+
|
|
158
|
+
### Variant mapping
|
|
159
|
+
|
|
160
|
+
- `brand` -> `primary`
|
|
161
|
+
- `neutral` -> `default`
|
|
162
|
+
- `secondary` -> `default`
|
|
163
|
+
- `plain` -> `ghost`
|
|
164
|
+
- `text` -> `ghost`
|
|
165
|
+
- `primary` -> `primary`
|
|
166
|
+
- `danger` -> `danger`
|
|
167
|
+
- `ghost` -> `ghost`
|
|
168
|
+
|
|
169
|
+
### Slot mapping
|
|
170
|
+
|
|
171
|
+
- `slot="start"` -> `slot="prefix"`
|
|
172
|
+
- `slot="end"` -> `slot="suffix"`
|
|
173
|
+
|
|
174
|
+
## Usage
|
|
175
|
+
|
|
176
|
+
```html
|
|
177
|
+
<cv-button>Click me</cv-button>
|
|
178
|
+
|
|
179
|
+
<cv-button variant="primary">Save</cv-button>
|
|
180
|
+
|
|
181
|
+
<cv-button variant="danger" outline>Delete</cv-button>
|
|
182
|
+
|
|
183
|
+
<cv-button variant="primary" outline size="small">Small outline</cv-button>
|
|
184
|
+
|
|
185
|
+
<cv-button pill>Rounded</cv-button>
|
|
186
|
+
|
|
187
|
+
<cv-button variant="danger" loading>Deleting…</cv-button>
|
|
188
|
+
|
|
189
|
+
<cv-button toggle pressed>Bold</cv-button>
|
|
190
|
+
|
|
191
|
+
<cv-button>
|
|
192
|
+
<svg
|
|
193
|
+
slot="prefix"
|
|
194
|
+
width="16"
|
|
195
|
+
height="16"
|
|
196
|
+
viewBox="0 0 24 24"
|
|
197
|
+
fill="none"
|
|
198
|
+
stroke="currentColor"
|
|
199
|
+
stroke-width="2"
|
|
200
|
+
stroke-linecap="round"
|
|
201
|
+
stroke-linejoin="round"
|
|
202
|
+
aria-hidden="true"
|
|
203
|
+
>
|
|
204
|
+
<path d="M12 5v14"></path>
|
|
205
|
+
<path d="M5 12h14"></path>
|
|
206
|
+
</svg>
|
|
207
|
+
Add item
|
|
208
|
+
</cv-button>
|
|
209
|
+
|
|
210
|
+
<cv-button>
|
|
211
|
+
Settings
|
|
212
|
+
<svg
|
|
213
|
+
slot="suffix"
|
|
214
|
+
width="16"
|
|
215
|
+
height="16"
|
|
216
|
+
viewBox="0 0 24 24"
|
|
217
|
+
fill="none"
|
|
218
|
+
stroke="currentColor"
|
|
219
|
+
stroke-width="2"
|
|
220
|
+
stroke-linecap="round"
|
|
221
|
+
stroke-linejoin="round"
|
|
222
|
+
aria-hidden="true"
|
|
223
|
+
>
|
|
224
|
+
<path d="m9 18 6-6-6-6"></path>
|
|
225
|
+
</svg>
|
|
226
|
+
</cv-button>
|
|
227
|
+
```
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# cv-callout
|
|
2
|
+
|
|
3
|
+
Static supplementary content block that highlights important information using `role="note"`. Unlike `cv-alert`, a callout is not a live region and does not announce dynamically.
|
|
4
|
+
|
|
5
|
+
**Headless:** [`createCallout`](https://github.com/chromvoid/headless-ui/blob/main/specs/components/callout.md)
|
|
6
|
+
|
|
7
|
+
## Anatomy
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
<cv-callout> (host)
|
|
11
|
+
└── <div part="base" role="note">
|
|
12
|
+
├── <span part="icon">
|
|
13
|
+
│ └── <slot name="icon">
|
|
14
|
+
├── <span part="message">
|
|
15
|
+
│ └── <slot>
|
|
16
|
+
└── <button part="close-button" aria-label="Dismiss"> ← only when [closable]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Attributes
|
|
20
|
+
|
|
21
|
+
| Attribute | Type | Default | Description |
|
|
22
|
+
| ---------- | ------- | -------- | ----------------------------------------------------------------------------------- |
|
|
23
|
+
| `variant` | String | `"info"` | Visual variant: `"info"` \| `"success"` \| `"warning"` \| `"danger"` \| `"neutral"` |
|
|
24
|
+
| `closable` | Boolean | `false` | Renders a dismiss button and enables the `cv-close` event |
|
|
25
|
+
| `open` | Boolean | `true` | Controls visibility of the callout |
|
|
26
|
+
|
|
27
|
+
## Variants
|
|
28
|
+
|
|
29
|
+
| Variant | Description |
|
|
30
|
+
| --------- | --------------------------------------------------------------- |
|
|
31
|
+
| `info` | Default informational style using `--cv-color-info` |
|
|
32
|
+
| `success` | Success-tinted background and border using `--cv-color-success` |
|
|
33
|
+
| `warning` | Warning-tinted background and border using `--cv-color-warning` |
|
|
34
|
+
| `danger` | Danger-tinted background and border using `--cv-color-danger` |
|
|
35
|
+
| `neutral` | Muted style with surface background and border |
|
|
36
|
+
|
|
37
|
+
## Slots
|
|
38
|
+
|
|
39
|
+
| Slot | Description |
|
|
40
|
+
| ----------- | ---------------------------------------------- |
|
|
41
|
+
| `(default)` | Main content (projected into the message area) |
|
|
42
|
+
| `icon` | Leading icon area before the message content |
|
|
43
|
+
|
|
44
|
+
## CSS Parts
|
|
45
|
+
|
|
46
|
+
| Part | Element | Description |
|
|
47
|
+
| -------------- | ---------- | ------------------------------------------------------------------------------------ |
|
|
48
|
+
| `base` | `<div>` | Outer container with `role="note"`; receives headless `getCalloutProps()` attributes |
|
|
49
|
+
| `icon` | `<span>` | Wrapper around the `icon` slot |
|
|
50
|
+
| `message` | `<span>` | Wrapper around the default slot |
|
|
51
|
+
| `close-button` | `<button>` | Dismiss button (rendered only when `closable` is `true`) |
|
|
52
|
+
|
|
53
|
+
## CSS Custom Properties
|
|
54
|
+
|
|
55
|
+
| Property | Default | Description |
|
|
56
|
+
| ---------------------------------- | ------------------------------------------- | ------------------------------------------- |
|
|
57
|
+
| `--cv-callout-padding-inline` | `var(--cv-space-3, 12px)` | Horizontal padding |
|
|
58
|
+
| `--cv-callout-padding-block` | `var(--cv-space-3, 12px)` | Vertical padding |
|
|
59
|
+
| `--cv-callout-gap` | `var(--cv-space-2, 8px)` | Gap between icon, message, and close button |
|
|
60
|
+
| `--cv-callout-border-radius` | `var(--cv-radius-sm, 6px)` | Border radius |
|
|
61
|
+
| `--cv-callout-border-color` | `var(--cv-color-border, #2a3245)` | Border color (overridden per variant) |
|
|
62
|
+
| `--cv-callout-background` | `var(--cv-color-surface-elevated, #1d2432)` | Background color (overridden per variant) |
|
|
63
|
+
| `--cv-callout-color` | `var(--cv-color-text, #e8ecf6)` | Text color |
|
|
64
|
+
| `--cv-callout-icon-color` | `currentColor` | Icon slot color (overridden per variant) |
|
|
65
|
+
| `--cv-callout-font-size` | `var(--cv-font-size-base, 14px)` | Font size of callout content |
|
|
66
|
+
| `--cv-callout-transition-duration` | `var(--cv-duration-fast, 120ms)` | Transition duration for show/hide |
|
|
67
|
+
| `--cv-callout-transition-easing` | `var(--cv-easing-standard, ease)` | Transition timing function |
|
|
68
|
+
|
|
69
|
+
Additionally, component styles depend on theme tokens through fallback values:
|
|
70
|
+
|
|
71
|
+
| Theme Property | Default | Description |
|
|
72
|
+
| ----------------------------- | --------- | ----------------------------------- |
|
|
73
|
+
| `--cv-color-border` | `#2a3245` | Base border color |
|
|
74
|
+
| `--cv-color-surface-elevated` | `#1d2432` | Elevated surface background color |
|
|
75
|
+
| `--cv-color-text` | `#e8ecf6` | Default text color |
|
|
76
|
+
| `--cv-color-info` | `#65d7ff` | Info accent color |
|
|
77
|
+
| `--cv-color-success` | `#5beba0` | Success accent color |
|
|
78
|
+
| `--cv-color-warning` | `#ffc857` | Warning accent color |
|
|
79
|
+
| `--cv-color-danger` | `#ff7d86` | Danger accent color |
|
|
80
|
+
| `--cv-duration-fast` | `120ms` | Transition duration |
|
|
81
|
+
| `--cv-easing-standard` | `ease` | Transition timing function |
|
|
82
|
+
| `--cv-radius-sm` | `6px` | Base radius fallback |
|
|
83
|
+
| `--cv-space-2` | `8px` | Medium spacing scale fallback |
|
|
84
|
+
| `--cv-space-3` | `12px` | Medium-large spacing scale fallback |
|
|
85
|
+
|
|
86
|
+
## Visual States
|
|
87
|
+
|
|
88
|
+
| Host selector | Description |
|
|
89
|
+
| ---------------------------- | ------------------------------------------------------------------------------ |
|
|
90
|
+
| `:host([open])` | Visible state; callout is rendered and visible |
|
|
91
|
+
| `:host(:not([open]))` | Hidden state; callout is hidden (e.g., `display: none` or fade-out transition) |
|
|
92
|
+
| `:host([variant="info"])` | Info-tinted background and border (default) |
|
|
93
|
+
| `:host([variant="success"])` | Success-tinted background and border |
|
|
94
|
+
| `:host([variant="warning"])` | Warning-tinted background and border |
|
|
95
|
+
| `:host([variant="danger"])` | Danger-tinted background and border |
|
|
96
|
+
| `:host([variant="neutral"])` | Muted surface background with border |
|
|
97
|
+
| `:host([closable])` | Close button is rendered in the template |
|
|
98
|
+
|
|
99
|
+
## Reactive State Mapping
|
|
100
|
+
|
|
101
|
+
`cv-callout` is a visual adapter over headless `createCallout`.
|
|
102
|
+
|
|
103
|
+
| UIKit Property | Direction | Headless Binding |
|
|
104
|
+
| -------------- | -------------- | -------------------------------------------------- |
|
|
105
|
+
| `variant` | attr -> action | `actions.setVariant(value)` |
|
|
106
|
+
| `closable` | attr -> action | `actions.setClosable(value)` |
|
|
107
|
+
| `open` | attr -> action | `actions.show()` / programmatic visibility control |
|
|
108
|
+
|
|
109
|
+
| Headless State | Direction | DOM Reflection |
|
|
110
|
+
| ------------------ | ------------- | --------------------------- |
|
|
111
|
+
| `state.variant()` | state -> attr | `[variant]` host attribute |
|
|
112
|
+
| `state.closable()` | state -> attr | `[closable]` host attribute |
|
|
113
|
+
| `state.open()` | state -> attr | `[open]` host attribute |
|
|
114
|
+
|
|
115
|
+
- `contracts.getCalloutProps()` is spread onto the inner `[part="base"]` element to apply `id`, `role="note"`, and `data-variant`.
|
|
116
|
+
- `contracts.getCloseButtonProps()` is spread onto the inner `[part="close-button"]` element to apply `id`, `role="button"`, `tabindex="0"`, `aria-label="Dismiss"`, and `onClick` handler. The close button is only rendered when `closable` is `true`.
|
|
117
|
+
- UIKit dispatches `cv-close` when the headless `actions.close()` transitions `open` from `true` to `false`.
|
|
118
|
+
- UIKit does not own ARIA logic or close behavior; headless state is the source of truth.
|
|
119
|
+
- The callout root is not focusable; no `tabindex` is applied to the root element.
|
|
120
|
+
|
|
121
|
+
## Events
|
|
122
|
+
|
|
123
|
+
| Event | Detail | Description |
|
|
124
|
+
| ---------- | ----------- | ------------------------------------------------------------------------------------ |
|
|
125
|
+
| `cv-close` | `undefined` | Fires when the callout is dismissed via the close button (`closable` must be `true`) |
|
|
126
|
+
|
|
127
|
+
No `cv-input` or `cv-change` events are emitted. The callout has no user-modifiable state; closing is a one-way action.
|
|
128
|
+
|
|
129
|
+
## Usage
|
|
130
|
+
|
|
131
|
+
```html
|
|
132
|
+
<cv-callout>This is an informational callout.</cv-callout>
|
|
133
|
+
|
|
134
|
+
<cv-callout variant="success">Operation completed successfully.</cv-callout>
|
|
135
|
+
|
|
136
|
+
<cv-callout variant="warning">Please review before continuing.</cv-callout>
|
|
137
|
+
|
|
138
|
+
<cv-callout variant="danger">This action cannot be undone.</cv-callout>
|
|
139
|
+
|
|
140
|
+
<cv-callout variant="neutral">Additional context for this section.</cv-callout>
|
|
141
|
+
|
|
142
|
+
<cv-callout variant="warning" closable> This warning can be dismissed. </cv-callout>
|
|
143
|
+
|
|
144
|
+
<cv-callout variant="info">
|
|
145
|
+
<icon-info slot="icon"></icon-info>
|
|
146
|
+
Callout with a leading icon.
|
|
147
|
+
</cv-callout>
|
|
148
|
+
|
|
149
|
+
<cv-callout variant="danger" closable>
|
|
150
|
+
<icon-alert-triangle slot="icon"></icon-alert-triangle>
|
|
151
|
+
Critical issue detected. Please take action.
|
|
152
|
+
</cv-callout>
|
|
153
|
+
```
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# cv-card
|
|
2
|
+
|
|
3
|
+
Visual container that groups related content into a cohesive unit, with an optional expandable variant that follows the disclosure pattern to show/hide body content.
|
|
4
|
+
|
|
5
|
+
**Headless:** [`createCard`](https://github.com/chromvoid/headless-ui/blob/main/specs/components/card.md)
|
|
6
|
+
|
|
7
|
+
## Anatomy
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
<cv-card> (host)
|
|
11
|
+
└── <div part="base">
|
|
12
|
+
├── <div part="image">
|
|
13
|
+
│ └── <slot name="image">
|
|
14
|
+
├── <div part="header"> ← trigger when [expandable]
|
|
15
|
+
│ ├── <slot name="header">
|
|
16
|
+
│ └── <span part="indicator"> ← only when [expandable], chevron/arrow
|
|
17
|
+
├── <div part="body"> ← collapsible when [expandable]
|
|
18
|
+
│ └── <slot>
|
|
19
|
+
└── <div part="footer">
|
|
20
|
+
└── <slot name="footer">
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Attributes
|
|
24
|
+
|
|
25
|
+
| Attribute | Type | Default | Description |
|
|
26
|
+
| ------------ | ------- | ------------ | ------------------------------------------------------------------ |
|
|
27
|
+
| `variant` | String | `"elevated"` | Visual variant: `elevated` \| `outlined` \| `filled` |
|
|
28
|
+
| `expandable` | Boolean | `false` | Enables disclosure behavior (expand/collapse body) |
|
|
29
|
+
| `expanded` | Boolean | `false` | Expanded state (only meaningful when `expandable` is `true`) |
|
|
30
|
+
| `disabled` | Boolean | `false` | Prevents interaction (only meaningful when `expandable` is `true`) |
|
|
31
|
+
|
|
32
|
+
## Variants
|
|
33
|
+
|
|
34
|
+
| Variant | Description |
|
|
35
|
+
| ---------- | ----------------------------------------------------------- |
|
|
36
|
+
| `elevated` | Default style with box shadow for a raised appearance |
|
|
37
|
+
| `outlined` | Transparent background with a visible border |
|
|
38
|
+
| `filled` | Solid surface background without shadow or prominent border |
|
|
39
|
+
|
|
40
|
+
Variants are CSS-only concerns and carry no headless state. They are mutually exclusive and selected via the `variant` attribute.
|
|
41
|
+
|
|
42
|
+
## Slots
|
|
43
|
+
|
|
44
|
+
| Slot | Description |
|
|
45
|
+
| ----------- | -------------------------------------------------------- |
|
|
46
|
+
| `image` | Optional image or media displayed at the top of the card |
|
|
47
|
+
| `header` | Card header content (title, subtitle, actions) |
|
|
48
|
+
| `(default)` | Main body content of the card |
|
|
49
|
+
| `footer` | Card footer content (actions, metadata) |
|
|
50
|
+
|
|
51
|
+
## CSS Parts
|
|
52
|
+
|
|
53
|
+
| Part | Element | Description |
|
|
54
|
+
| ----------- | -------- | ------------------------------------------------------------------------- |
|
|
55
|
+
| `base` | `<div>` | Root wrapper element |
|
|
56
|
+
| `image` | `<div>` | Container for the `image` slot |
|
|
57
|
+
| `header` | `<div>` | Header area; acts as the disclosure trigger when `expandable` is `true` |
|
|
58
|
+
| `indicator` | `<span>` | Expand/collapse indicator icon; rendered only when `expandable` is `true` |
|
|
59
|
+
| `body` | `<div>` | Body content area; collapsible region when `expandable` is `true` |
|
|
60
|
+
| `footer` | `<div>` | Footer area |
|
|
61
|
+
|
|
62
|
+
## CSS Custom Properties
|
|
63
|
+
|
|
64
|
+
| Property | Default | Description |
|
|
65
|
+
| -------------------------------- | ---------------------------------------------------------------- | ------------------------------------------------------ |
|
|
66
|
+
| `--cv-card-padding` | `var(--cv-space-4, 16px)` | Inner padding for card sections (header, body, footer) |
|
|
67
|
+
| `--cv-card-border-radius` | `var(--cv-radius-md, 8px)` | Border radius of the card |
|
|
68
|
+
| `--cv-card-border-color` | `var(--cv-color-border, #2a3245)` | Border color (primarily for `outlined` variant) |
|
|
69
|
+
| `--cv-card-background` | `var(--cv-color-surface, #141923)` | Background color of the card |
|
|
70
|
+
| `--cv-card-shadow` | `0 1px 3px rgba(0, 0, 0, 0.24)` | Box shadow (primarily for `elevated` variant) |
|
|
71
|
+
| `--cv-card-gap` | `var(--cv-space-0, 0px)` | Spacing between card sections |
|
|
72
|
+
| `--cv-card-indicator-size` | `var(--cv-space-4, 16px)` | Size of the expand/collapse indicator icon |
|
|
73
|
+
| `--cv-card-indicator-transition` | `var(--cv-duration-fast, 120ms) var(--cv-easing-standard, ease)` | Transition for indicator rotation |
|
|
74
|
+
|
|
75
|
+
Additionally, component styles depend on theme tokens through fallback values:
|
|
76
|
+
|
|
77
|
+
| Theme Property | Default | Description |
|
|
78
|
+
| ---------------------- | --------- | ---------------------------------- |
|
|
79
|
+
| `--cv-color-border` | `#2a3245` | Base border color |
|
|
80
|
+
| `--cv-color-surface` | `#141923` | Surface background color |
|
|
81
|
+
| `--cv-color-text` | `#e8ecf6` | Default text color |
|
|
82
|
+
| `--cv-duration-fast` | `120ms` | Transition duration |
|
|
83
|
+
| `--cv-easing-standard` | `ease` | Transition timing function |
|
|
84
|
+
| `--cv-radius-md` | `8px` | Base radius used for card fallback |
|
|
85
|
+
| `--cv-space-0` | `0px` | Zero spacing scale fallback |
|
|
86
|
+
| `--cv-space-4` | `16px` | Large spacing scale fallback |
|
|
87
|
+
|
|
88
|
+
## Visual States
|
|
89
|
+
|
|
90
|
+
| Host selector | Description |
|
|
91
|
+
| ----------------------------- | ------------------------------------------------------------------------------- |
|
|
92
|
+
| `:host([variant="elevated"])` | Applies box shadow via `--cv-card-shadow`; no visible border |
|
|
93
|
+
| `:host([variant="outlined"])` | Applies visible border via `--cv-card-border-color`; no shadow |
|
|
94
|
+
| `:host([variant="filled"])` | Solid background; no shadow, subtle or no border |
|
|
95
|
+
| `:host([expandable])` | Renders indicator in header; header becomes interactive trigger |
|
|
96
|
+
| `:host([expanded])` | Body content visible; indicator rotated to open position |
|
|
97
|
+
| `:host([disabled])` | Reduced opacity (`0.55`), `cursor: not-allowed` on trigger; interaction blocked |
|
|
98
|
+
|
|
99
|
+
## Reactive State Mapping
|
|
100
|
+
|
|
101
|
+
`cv-card` is a visual adapter over headless `createCard`.
|
|
102
|
+
|
|
103
|
+
### UIKit Property -> Headless Binding (input direction)
|
|
104
|
+
|
|
105
|
+
| UIKit Property | Direction | Headless Binding |
|
|
106
|
+
| -------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
107
|
+
| `expandable` | attr -> option | passed as `isExpandable` in `createCard(options)` |
|
|
108
|
+
| `expanded` | attr -> option | passed as `isExpanded` in `createCard(options)`; updates via `actions.toggle()` / `actions.expand()` / `actions.collapse()` |
|
|
109
|
+
| `disabled` | attr -> action | `actions.setDisabled(value)` |
|
|
110
|
+
|
|
111
|
+
### Headless State -> DOM Reflection (output direction)
|
|
112
|
+
|
|
113
|
+
| Headless State | Direction | DOM Reflection |
|
|
114
|
+
| ---------------------- | ------------- | ----------------------------- |
|
|
115
|
+
| `state.isExpandable()` | state -> attr | `[expandable]` host attribute |
|
|
116
|
+
| `state.isExpanded()` | state -> attr | `[expanded]` host attribute |
|
|
117
|
+
| `state.isDisabled()` | state -> attr | `[disabled]` host attribute |
|
|
118
|
+
|
|
119
|
+
### Contract Spreading
|
|
120
|
+
|
|
121
|
+
| Contract | Target Element | Notes |
|
|
122
|
+
| ----------------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
123
|
+
| `contracts.getCardProps()` | `[part="base"]` | Spread as attributes on the card root element |
|
|
124
|
+
| `contracts.getTriggerProps()` | `[part="header"]` | Spread onto the header element when `isExpandable` is `true`; provides `role="button"`, `aria-expanded`, `aria-controls`, `tabindex`, and event handlers |
|
|
125
|
+
| `contracts.getContentProps()` | `[part="body"]` | Spread onto the body element when `isExpandable` is `true`; provides `id`, `role="region"`, `aria-labelledby`, `hidden` |
|
|
126
|
+
|
|
127
|
+
### Boundary
|
|
128
|
+
|
|
129
|
+
- UIKit dispatches `cv-input` and `cv-change` events by observing `isExpanded` changes triggered by user activation (not by controlled attribute updates).
|
|
130
|
+
- UIKit does not own toggle, expand/collapse, or keyboard logic; headless state is the source of truth.
|
|
131
|
+
- Visual variants (`elevated`, `outlined`, `filled`) are CSS-only; no headless state involved.
|
|
132
|
+
- Slot layout, image positioning, indicator rendering, and CSS transitions are UIKit rendering concerns.
|
|
133
|
+
|
|
134
|
+
## Events
|
|
135
|
+
|
|
136
|
+
| Event | Detail | Description |
|
|
137
|
+
| ----------- | --------------------- | ------------------------------------------------------------------------- |
|
|
138
|
+
| `cv-input` | `{expanded: boolean}` | Fires when user toggles the expanded state (click or keyboard on trigger) |
|
|
139
|
+
| `cv-change` | `{expanded: boolean}` | Fires when the expanded state commits after user interaction |
|
|
140
|
+
|
|
141
|
+
Events only fire when `expandable` is `true` and the state change is triggered by user action (not programmatic attribute changes). Normal (non-expandable) cards do not emit these events.
|
|
142
|
+
|
|
143
|
+
## Usage
|
|
144
|
+
|
|
145
|
+
```html
|
|
146
|
+
<!-- Static elevated card (default) -->
|
|
147
|
+
<cv-card>
|
|
148
|
+
<span slot="header">Card Title</span>
|
|
149
|
+
Main body content goes here.
|
|
150
|
+
<span slot="footer">Footer actions</span>
|
|
151
|
+
</cv-card>
|
|
152
|
+
|
|
153
|
+
<!-- Outlined card with image -->
|
|
154
|
+
<cv-card variant="outlined">
|
|
155
|
+
<img slot="image" src="hero.jpg" alt="Hero image" />
|
|
156
|
+
<span slot="header">Article Title</span>
|
|
157
|
+
Article preview text.
|
|
158
|
+
</cv-card>
|
|
159
|
+
|
|
160
|
+
<!-- Filled card -->
|
|
161
|
+
<cv-card variant="filled">
|
|
162
|
+
<span slot="header">Settings</span>
|
|
163
|
+
Configuration content.
|
|
164
|
+
</cv-card>
|
|
165
|
+
|
|
166
|
+
<!-- Expandable card (collapsed by default) -->
|
|
167
|
+
<cv-card expandable>
|
|
168
|
+
<span slot="header">Expandable Section</span>
|
|
169
|
+
This content is hidden until the header is clicked.
|
|
170
|
+
</cv-card>
|
|
171
|
+
|
|
172
|
+
<!-- Expandable card (expanded by default) -->
|
|
173
|
+
<cv-card expandable expanded>
|
|
174
|
+
<span slot="header">Details</span>
|
|
175
|
+
This content is visible on initial render.
|
|
176
|
+
<span slot="footer">Last updated: today</span>
|
|
177
|
+
</cv-card>
|
|
178
|
+
|
|
179
|
+
<!-- Expandable card (disabled) -->
|
|
180
|
+
<cv-card expandable disabled>
|
|
181
|
+
<span slot="header">Locked Section</span>
|
|
182
|
+
This content cannot be toggled by the user.
|
|
183
|
+
</cv-card>
|
|
184
|
+
|
|
185
|
+
<!-- Expandable card with image and all slots -->
|
|
186
|
+
<cv-card expandable variant="outlined">
|
|
187
|
+
<img slot="image" src="preview.jpg" alt="Preview" />
|
|
188
|
+
<span slot="header">Full Example</span>
|
|
189
|
+
Body content with detailed information.
|
|
190
|
+
<span slot="footer">Action buttons here</span>
|
|
191
|
+
</cv-card>
|
|
192
|
+
```
|