@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.
Files changed (246) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +96 -0
  3. package/dist/components/cv-accordion-item.d.ts +69 -0
  4. package/dist/components/cv-accordion-item.js +176 -0
  5. package/dist/components/cv-accordion.d.ts +79 -0
  6. package/dist/components/cv-accordion.js +310 -0
  7. package/dist/components/cv-alert-dialog.d.ts +86 -0
  8. package/dist/components/cv-alert-dialog.js +393 -0
  9. package/dist/components/cv-alert.d.ts +48 -0
  10. package/dist/components/cv-alert.js +156 -0
  11. package/dist/components/cv-badge.d.ts +56 -0
  12. package/dist/components/cv-badge.js +280 -0
  13. package/dist/components/cv-breadcrumb-item.d.ts +35 -0
  14. package/dist/components/cv-breadcrumb-item.js +64 -0
  15. package/dist/components/cv-breadcrumb.d.ts +39 -0
  16. package/dist/components/cv-breadcrumb.js +160 -0
  17. package/dist/components/cv-button.d.ts +83 -0
  18. package/dist/components/cv-button.js +541 -0
  19. package/dist/components/cv-callout.d.ts +32 -0
  20. package/dist/components/cv-callout.js +221 -0
  21. package/dist/components/cv-card.d.ts +48 -0
  22. package/dist/components/cv-card.js +269 -0
  23. package/dist/components/cv-carousel-slide.d.ts +25 -0
  24. package/dist/components/cv-carousel-slide.js +51 -0
  25. package/dist/components/cv-carousel.d.ts +96 -0
  26. package/dist/components/cv-carousel.js +457 -0
  27. package/dist/components/cv-checkbox.d.ts +84 -0
  28. package/dist/components/cv-checkbox.js +274 -0
  29. package/dist/components/cv-combobox-group.d.ts +15 -0
  30. package/dist/components/cv-combobox-group.js +34 -0
  31. package/dist/components/cv-combobox-option.d.ts +30 -0
  32. package/dist/components/cv-combobox-option.js +66 -0
  33. package/dist/components/cv-combobox.d.ts +135 -0
  34. package/dist/components/cv-combobox.js +834 -0
  35. package/dist/components/cv-command-item.d.ts +30 -0
  36. package/dist/components/cv-command-item.js +68 -0
  37. package/dist/components/cv-command-palette.d.ts +105 -0
  38. package/dist/components/cv-command-palette.js +578 -0
  39. package/dist/components/cv-context-menu.d.ts +98 -0
  40. package/dist/components/cv-context-menu.js +515 -0
  41. package/dist/components/cv-copy-button.d.ts +61 -0
  42. package/dist/components/cv-copy-button.js +318 -0
  43. package/dist/components/cv-date-picker.d.ts +161 -0
  44. package/dist/components/cv-date-picker.js +803 -0
  45. package/dist/components/cv-dialog.d.ts +89 -0
  46. package/dist/components/cv-dialog.js +459 -0
  47. package/dist/components/cv-disclosure.d.ts +57 -0
  48. package/dist/components/cv-disclosure.js +241 -0
  49. package/dist/components/cv-drawer.d.ts +102 -0
  50. package/dist/components/cv-drawer.js +595 -0
  51. package/dist/components/cv-feed-article.d.ts +26 -0
  52. package/dist/components/cv-feed-article.js +52 -0
  53. package/dist/components/cv-feed.d.ts +62 -0
  54. package/dist/components/cv-feed.js +310 -0
  55. package/dist/components/cv-grid-cell.d.ts +30 -0
  56. package/dist/components/cv-grid-cell.js +57 -0
  57. package/dist/components/cv-grid-column.d.ts +30 -0
  58. package/dist/components/cv-grid-column.js +43 -0
  59. package/dist/components/cv-grid-row.d.ts +30 -0
  60. package/dist/components/cv-grid-row.js +42 -0
  61. package/dist/components/cv-grid.d.ts +119 -0
  62. package/dist/components/cv-grid.js +567 -0
  63. package/dist/components/cv-icon.d.ts +57 -0
  64. package/dist/components/cv-icon.js +352 -0
  65. package/dist/components/cv-input.d.ts +127 -0
  66. package/dist/components/cv-input.js +482 -0
  67. package/dist/components/cv-landmark.d.ts +32 -0
  68. package/dist/components/cv-landmark.js +62 -0
  69. package/dist/components/cv-link.d.ts +22 -0
  70. package/dist/components/cv-link.js +99 -0
  71. package/dist/components/cv-listbox-group.d.ts +15 -0
  72. package/dist/components/cv-listbox-group.js +42 -0
  73. package/dist/components/cv-listbox.d.ts +81 -0
  74. package/dist/components/cv-listbox.js +388 -0
  75. package/dist/components/cv-menu-button.d.ts +118 -0
  76. package/dist/components/cv-menu-button.js +822 -0
  77. package/dist/components/cv-menu-group.d.ts +20 -0
  78. package/dist/components/cv-menu-group.js +48 -0
  79. package/dist/components/cv-menu-item.d.ts +52 -0
  80. package/dist/components/cv-menu-item.js +105 -0
  81. package/dist/components/cv-menu.d.ts +62 -0
  82. package/dist/components/cv-menu.js +414 -0
  83. package/dist/components/cv-meter.d.ts +66 -0
  84. package/dist/components/cv-meter.js +154 -0
  85. package/dist/components/cv-number.d.ts +139 -0
  86. package/dist/components/cv-number.js +553 -0
  87. package/dist/components/cv-option.d.ts +30 -0
  88. package/dist/components/cv-option.js +84 -0
  89. package/dist/components/cv-popover.d.ts +87 -0
  90. package/dist/components/cv-popover.js +373 -0
  91. package/dist/components/cv-progress-ring.d.ts +45 -0
  92. package/dist/components/cv-progress-ring.js +169 -0
  93. package/dist/components/cv-progress.d.ts +45 -0
  94. package/dist/components/cv-progress.js +148 -0
  95. package/dist/components/cv-radio-group.d.ts +79 -0
  96. package/dist/components/cv-radio-group.js +398 -0
  97. package/dist/components/cv-radio.d.ts +36 -0
  98. package/dist/components/cv-radio.js +123 -0
  99. package/dist/components/cv-select-group.d.ts +15 -0
  100. package/dist/components/cv-select-group.js +44 -0
  101. package/dist/components/cv-select-option.d.ts +30 -0
  102. package/dist/components/cv-select-option.js +66 -0
  103. package/dist/components/cv-select.d.ts +128 -0
  104. package/dist/components/cv-select.js +666 -0
  105. package/dist/components/cv-sidebar-item.d.ts +26 -0
  106. package/dist/components/cv-sidebar-item.js +142 -0
  107. package/dist/components/cv-sidebar.d.ts +171 -0
  108. package/dist/components/cv-sidebar.js +767 -0
  109. package/dist/components/cv-slider-multi-thumb.d.ts +73 -0
  110. package/dist/components/cv-slider-multi-thumb.js +374 -0
  111. package/dist/components/cv-slider.d.ts +84 -0
  112. package/dist/components/cv-slider.js +328 -0
  113. package/dist/components/cv-spinbutton.d.ts +121 -0
  114. package/dist/components/cv-spinbutton.js +486 -0
  115. package/dist/components/cv-spinner.d.ts +18 -0
  116. package/dist/components/cv-spinner.js +95 -0
  117. package/dist/components/cv-switch.d.ts +81 -0
  118. package/dist/components/cv-switch.js +285 -0
  119. package/dist/components/cv-tab-panel.d.ts +20 -0
  120. package/dist/components/cv-tab-panel.js +37 -0
  121. package/dist/components/cv-tab.d.ts +40 -0
  122. package/dist/components/cv-tab.js +132 -0
  123. package/dist/components/cv-table-cell.d.ts +31 -0
  124. package/dist/components/cv-table-cell.js +49 -0
  125. package/dist/components/cv-table-column.d.ts +37 -0
  126. package/dist/components/cv-table-column.js +63 -0
  127. package/dist/components/cv-table-row.d.ts +30 -0
  128. package/dist/components/cv-table-row.js +45 -0
  129. package/dist/components/cv-table.d.ts +147 -0
  130. package/dist/components/cv-table.js +607 -0
  131. package/dist/components/cv-tabs.d.ts +70 -0
  132. package/dist/components/cv-tabs.js +524 -0
  133. package/dist/components/cv-textarea.d.ts +108 -0
  134. package/dist/components/cv-textarea.js +328 -0
  135. package/dist/components/cv-toast-region.d.ts +39 -0
  136. package/dist/components/cv-toast-region.js +162 -0
  137. package/dist/components/cv-toast.d.ts +67 -0
  138. package/dist/components/cv-toast.js +315 -0
  139. package/dist/components/cv-toolbar-item.d.ts +25 -0
  140. package/dist/components/cv-toolbar-item.js +72 -0
  141. package/dist/components/cv-toolbar-separator.d.ts +25 -0
  142. package/dist/components/cv-toolbar-separator.js +45 -0
  143. package/dist/components/cv-toolbar.d.ts +63 -0
  144. package/dist/components/cv-toolbar.js +295 -0
  145. package/dist/components/cv-tooltip.d.ts +83 -0
  146. package/dist/components/cv-tooltip.js +455 -0
  147. package/dist/components/cv-treegrid-cell.d.ts +30 -0
  148. package/dist/components/cv-treegrid-cell.js +57 -0
  149. package/dist/components/cv-treegrid-column.d.ts +37 -0
  150. package/dist/components/cv-treegrid-column.js +53 -0
  151. package/dist/components/cv-treegrid-row.d.ts +55 -0
  152. package/dist/components/cv-treegrid-row.js +90 -0
  153. package/dist/components/cv-treegrid.d.ts +96 -0
  154. package/dist/components/cv-treegrid.js +632 -0
  155. package/dist/components/cv-treeitem.d.ts +58 -0
  156. package/dist/components/cv-treeitem.js +144 -0
  157. package/dist/components/cv-treeview.d.ts +70 -0
  158. package/dist/components/cv-treeview.js +396 -0
  159. package/dist/components/cv-window-splitter.d.ts +79 -0
  160. package/dist/components/cv-window-splitter.js +316 -0
  161. package/dist/components/index.d.ts +94 -0
  162. package/dist/components/index.js +79 -0
  163. package/dist/dialog/create-dialog-controller.d.ts +31 -0
  164. package/dist/dialog/create-dialog-controller.js +320 -0
  165. package/dist/dialog/index.d.ts +2 -0
  166. package/dist/dialog/index.js +1 -0
  167. package/dist/form-associated/FormAssociatedReatomElement.d.ts +25 -0
  168. package/dist/form-associated/FormAssociatedReatomElement.js +70 -0
  169. package/dist/form-associated/withFormAssociated.d.ts +5 -0
  170. package/dist/form-associated/withFormAssociated.js +1 -0
  171. package/dist/index.d.ts +10 -0
  172. package/dist/index.js +9 -0
  173. package/dist/reatom-lit/ReatomLitElement.d.ts +27 -0
  174. package/dist/reatom-lit/ReatomLitElement.js +118 -0
  175. package/dist/reatom-lit/html.d.ts +4 -0
  176. package/dist/reatom-lit/html.js +10 -0
  177. package/dist/reatom-lit/index.d.ts +4 -0
  178. package/dist/reatom-lit/index.js +4 -0
  179. package/dist/reatom-lit/watch.d.ts +15 -0
  180. package/dist/reatom-lit/watch.js +40 -0
  181. package/dist/reatom-lit/withReatomElement.d.ts +4 -0
  182. package/dist/reatom-lit/withReatomElement.js +57 -0
  183. package/dist/register.d.ts +1 -0
  184. package/dist/register.js +84 -0
  185. package/dist/styles/component-styles.d.ts +4 -0
  186. package/dist/styles/component-styles.js +78 -0
  187. package/dist/theme/cv-theme-provider.d.ts +32 -0
  188. package/dist/theme/cv-theme-provider.js +110 -0
  189. package/dist/theme/index.d.ts +4 -0
  190. package/dist/theme/index.js +2 -0
  191. package/dist/theme/theme-engine.d.ts +4 -0
  192. package/dist/theme/theme-engine.js +67 -0
  193. package/dist/theme/tokens.css +265 -0
  194. package/dist/theme/types.d.ts +7 -0
  195. package/dist/theme/types.js +1 -0
  196. package/dist/toast/create-toast-controller.d.ts +12 -0
  197. package/dist/toast/create-toast-controller.js +12 -0
  198. package/dist/toast/index.d.ts +2 -0
  199. package/dist/toast/index.js +1 -0
  200. package/package.json +146 -0
  201. package/specs/_template.md +110 -0
  202. package/specs/components/accordion.md +207 -0
  203. package/specs/components/alert.md +83 -0
  204. package/specs/components/badge.md +183 -0
  205. package/specs/components/breadcrumb.md +152 -0
  206. package/specs/components/button.md +227 -0
  207. package/specs/components/callout.md +153 -0
  208. package/specs/components/card.md +192 -0
  209. package/specs/components/carousel.md +232 -0
  210. package/specs/components/checkbox.md +141 -0
  211. package/specs/components/combobox.md +427 -0
  212. package/specs/components/context-menu.md +375 -0
  213. package/specs/components/copy-button.md +236 -0
  214. package/specs/components/date-picker.md +290 -0
  215. package/specs/components/dialog.md +184 -0
  216. package/specs/components/disclosure.md +151 -0
  217. package/specs/components/drawer.md +216 -0
  218. package/specs/components/feed.md +266 -0
  219. package/specs/components/grid.md +423 -0
  220. package/specs/components/input.md +237 -0
  221. package/specs/components/landmark.md +92 -0
  222. package/specs/components/link.md +117 -0
  223. package/specs/components/listbox.md +327 -0
  224. package/specs/components/menu.md +508 -0
  225. package/specs/components/meter.md +148 -0
  226. package/specs/components/number.md +268 -0
  227. package/specs/components/option.md +167 -0
  228. package/specs/components/popover.md +207 -0
  229. package/specs/components/progress-ring.md +134 -0
  230. package/specs/components/progress.md +110 -0
  231. package/specs/components/radio.md +208 -0
  232. package/specs/components/select.md +305 -0
  233. package/specs/components/sidebar.md +204 -0
  234. package/specs/components/spinbutton.md +157 -0
  235. package/specs/components/spinner.md +83 -0
  236. package/specs/components/switch.md +145 -0
  237. package/specs/components/table.md +372 -0
  238. package/specs/components/tabs.md +242 -0
  239. package/specs/components/textarea.md +166 -0
  240. package/specs/components/theme.md +364 -0
  241. package/specs/components/toast.md +198 -0
  242. package/specs/components/toolbar.md +258 -0
  243. package/specs/components/tooltip.md +152 -0
  244. package/specs/components/treegrid.md +363 -0
  245. package/specs/components/treeview.md +263 -0
  246. package/specs/components/window-splitter.md +225 -0
@@ -0,0 +1,237 @@
1
+ # cv-input
2
+
3
+ Single-line text input control supporting text-like types, clearable behavior, and password visibility toggling.
4
+
5
+ **Headless:** [`createInput`](https://github.com/chromvoid/headless-ui/blob/main/specs/components/input.md)
6
+
7
+ ## Anatomy
8
+
9
+ ```
10
+ <cv-input> (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" />
17
+ │ ├── <span part="clear-button">
18
+ │ │ └── <slot name="clear-icon">×</slot>
19
+ │ ├── <span part="password-toggle">
20
+ │ │ └── <slot name="show-password-icon|hide-password-icon">
21
+ │ └── <span part="suffix">
22
+ │ └── <slot name="suffix">
23
+ └── <span part="form-control-help-text">
24
+ └── <slot name="help-text">
25
+ ```
26
+
27
+ ## Attributes
28
+
29
+ | Attribute | Type | Default | Reflects | Description |
30
+ | ----------------- | ----------- | ------------ | -------- | -------------------------------------------------------------------------- |
31
+ | `value` | String | `""` | no | Current input value |
32
+ | `type` | `InputType` | `"text"` | no | Input type: `text` \| `password` \| `email` \| `url` \| `tel` \| `search` |
33
+ | `placeholder` | String | `""` | no | Placeholder text displayed when the input is empty |
34
+ | `disabled` | Boolean | `false` | yes | Prevents interaction and dims the component |
35
+ | `readonly` | Boolean | `false` | yes | Prevents editing while keeping the input focusable |
36
+ | `required` | Boolean | `false` | yes | Marks the input as required for form validation |
37
+ | `clearable` | Boolean | `false` | yes | Shows a clear button when the input has a value |
38
+ | `password-toggle` | Boolean | `false` | yes | Shows a password visibility toggle (only effective when `type="password"`) |
39
+ | `size` | String | `"medium"` | yes | Component size: `small` \| `medium` \| `large` |
40
+ | `variant` | String | `"outlined"` | yes | Visual variant: `outlined` \| `filled` |
41
+ | `name` | String | `""` | no | Name for form association |
42
+
43
+ ## Variants
44
+
45
+ | Variant | Description |
46
+ | ---------- | ------------------------------------------------------------ |
47
+ | `outlined` | Default style with visible border and transparent background |
48
+ | `filled` | Subtle background fill with no visible border |
49
+
50
+ ## Sizes
51
+
52
+ | Size | `--cv-input-height` | `--cv-input-padding-inline` | `--cv-input-font-size` |
53
+ | -------- | ------------------- | --------------------------- | -------------------------------- |
54
+ | `small` | `30px` | `var(--cv-space-2, 8px)` | `var(--cv-font-size-sm, 13px)` |
55
+ | `medium` | `36px` | `var(--cv-space-3, 12px)` | `var(--cv-font-size-base, 14px)` |
56
+ | `large` | `42px` | `var(--cv-space-4, 16px)` | `var(--cv-font-size-md, 16px)` |
57
+
58
+ ## Slots
59
+
60
+ | Slot | Description |
61
+ | -------------------- | -------------------------------------------------- |
62
+ | `prefix` | Content rendered before the input (e.g., icon) |
63
+ | `suffix` | Content rendered after the input (e.g., icon) |
64
+ | `clear-icon` | Custom icon for the clear button (default: `×`) |
65
+ | `show-password-icon` | Custom icon for the "show password" state |
66
+ | `hide-password-icon` | Custom icon for the "hide password" state |
67
+ | `label` | Label text displayed above or beside the input |
68
+ | `help-text` | Help or description text displayed below the input |
69
+
70
+ > **Note:** The native `<input>` element is not slottable. There is no default slot.
71
+
72
+ ## CSS Parts
73
+
74
+ | Part | Element | Description |
75
+ | ------------------------ | --------- | ----------------------------------- |
76
+ | `base` | `<div>` | Outermost wrapper element |
77
+ | `input` | `<input>` | The native input element |
78
+ | `prefix` | `<span>` | Wrapper around the `prefix` slot |
79
+ | `suffix` | `<span>` | Wrapper around the `suffix` slot |
80
+ | `clear-button` | `<span>` | The clear button wrapper |
81
+ | `password-toggle` | `<span>` | The password toggle button wrapper |
82
+ | `form-control-label` | `<span>` | Wrapper around the `label` slot |
83
+ | `form-control-help-text` | `<span>` | Wrapper around the `help-text` slot |
84
+
85
+ ## CSS Custom Properties
86
+
87
+ | Property | Default | Description |
88
+ | -------------------------------- | -------------------------------------------- | --------------------------------------------------------------- |
89
+ | `--cv-input-height` | `36px` | Component block size |
90
+ | `--cv-input-padding-inline` | `var(--cv-space-3, 12px)` | Horizontal padding inside the input |
91
+ | `--cv-input-font-size` | `var(--cv-font-size-base, 14px)` | Font size of the input text |
92
+ | `--cv-input-border-radius` | `var(--cv-radius-sm, 6px)` | Border radius of the input container |
93
+ | `--cv-input-border-color` | `var(--cv-color-border, #2a3245)` | Border color in default state |
94
+ | `--cv-input-background` | `transparent` | Background color of the input container |
95
+ | `--cv-input-color` | `var(--cv-color-text, #e8ecf6)` | Text color of the input value |
96
+ | `--cv-input-placeholder-color` | `var(--cv-color-text-muted, #6b7a99)` | Placeholder text color |
97
+ | `--cv-input-focus-ring` | `0 0 0 2px var(--cv-color-primary, #65d7ff)` | Box-shadow applied on focus |
98
+ | `--cv-input-icon-size` | `1em` | Size of prefix/suffix/clear/toggle icons |
99
+ | `--cv-input-gap` | `var(--cv-space-2, 8px)` | Spacing between inner elements (prefix, input, suffix, buttons) |
100
+ | `--cv-input-transition-duration` | `var(--cv-duration-fast, 120ms)` | Transition duration for state changes |
101
+
102
+ Additionally, component styles depend on theme tokens through fallback values:
103
+
104
+ | Theme Property | Default | Description |
105
+ | ----------------------- | --------- | --------------------------------------------------- |
106
+ | `--cv-color-border` | `#2a3245` | Base border color |
107
+ | `--cv-color-surface` | `#141923` | Surface background color (used by `filled` variant) |
108
+ | `--cv-color-text` | `#e8ecf6` | Default text color |
109
+ | `--cv-color-text-muted` | `#6b7a99` | Muted text color for placeholder |
110
+ | `--cv-color-primary` | `#65d7ff` | Primary accent color for focus ring |
111
+ | `--cv-duration-fast` | `120ms` | Transition duration |
112
+ | `--cv-easing-standard` | `ease` | Transition timing function |
113
+ | `--cv-radius-sm` | `6px` | Base border radius fallback |
114
+ | `--cv-font-size-sm` | `13px` | Small font size |
115
+ | `--cv-font-size-base` | `14px` | Base font size |
116
+ | `--cv-font-size-md` | `16px` | Medium font size |
117
+ | `--cv-space-2` | `8px` | Spacing scale: small |
118
+ | `--cv-space-3` | `12px` | Spacing scale: medium |
119
+ | `--cv-space-4` | `16px` | Spacing scale: large |
120
+
121
+ ## Visual States
122
+
123
+ | Host selector | Description |
124
+ | ----------------------------- | ---------------------------------------------------------------- |
125
+ | `:host([disabled])` | Reduced opacity (`0.55`), `cursor: not-allowed`, no interaction |
126
+ | `:host([readonly])` | Normal opacity, `cursor: default`, input text not editable |
127
+ | `:host([required])` | No visual change by default (can be styled via part selectors) |
128
+ | `:host([focused])` | Focus ring applied via `--cv-input-focus-ring` |
129
+ | `:host([filled])` | Indicates non-empty value (e.g., for floating label transitions) |
130
+ | `:host([clearable])` | Clear button space reserved in layout |
131
+ | `:host([password-toggle])` | Password toggle button space reserved in layout |
132
+ | `:host([size="small"])` | Small size overrides |
133
+ | `:host([size="large"])` | Large size overrides |
134
+ | `:host([variant="outlined"])` | Visible border, transparent background |
135
+ | `:host([variant="filled"])` | Subtle background (`--cv-color-surface`), no visible border |
136
+
137
+ ## Reactive State Mapping
138
+
139
+ `cv-input` is a visual adapter over headless `createInput`.
140
+
141
+ ### UIKit properties to headless actions
142
+
143
+ | UIKit Property | Direction | Headless Binding |
144
+ | ----------------- | ------------------- | ---------------------------------- |
145
+ | `value` | attr/prop -> action | `actions.setValue(value)` |
146
+ | `type` | attr -> action | `actions.setType(type)` |
147
+ | `disabled` | attr -> action | `actions.setDisabled(value)` |
148
+ | `readonly` | attr -> action | `actions.setReadonly(value)` |
149
+ | `required` | attr -> action | `actions.setRequired(value)` |
150
+ | `placeholder` | attr -> action | `actions.setPlaceholder(value)` |
151
+ | `clearable` | attr -> action | `actions.setClearable(value)` |
152
+ | `password-toggle` | attr -> action | `actions.setPasswordToggle(value)` |
153
+
154
+ ### Headless state to DOM reflection
155
+
156
+ | Headless State | Direction | DOM Reflection |
157
+ | ---------------------------- | ------------- | ----------------------------------------------------------------- |
158
+ | `state.disabled()` | state -> attr | `[disabled]` host attribute |
159
+ | `state.readonly()` | state -> attr | `[readonly]` host attribute |
160
+ | `state.required()` | state -> attr | `[required]` host attribute |
161
+ | `state.focused()` | state -> attr | `[focused]` host attribute |
162
+ | `state.filled()` | state -> attr | `[filled]` host attribute |
163
+ | `state.passwordVisible()` | state -> DOM | toggles between `show-password-icon` / `hide-password-icon` slots |
164
+ | `state.showClearButton()` | state -> DOM | shows/hides the clear button element |
165
+ | `state.showPasswordToggle()` | state -> DOM | shows/hides the password toggle element |
166
+ | `state.resolvedType()` | state -> DOM | applied as `type` attribute on the native `<input>` |
167
+
168
+ ### Contract props spreading
169
+
170
+ - `contracts.getInputProps()` is spread onto the `[part="input"]` native `<input>` element to apply `id`, `type`, `aria-disabled`, `aria-readonly`, `aria-required`, `placeholder`, `disabled`, `readonly`, `tabindex`, and `autocomplete`.
171
+ - `contracts.getClearButtonProps()` is spread onto the `[part="clear-button"]` element to apply `role`, `aria-label`, `tabindex`, `hidden`, and `aria-hidden`.
172
+ - `contracts.getPasswordToggleProps()` is spread onto the `[part="password-toggle"]` element to apply `role`, `aria-label`, `aria-pressed`, `tabindex`, `hidden`, and `aria-hidden`.
173
+
174
+ ### Event wiring
175
+
176
+ - Native `<input>` `input` event -> `actions.handleInput(e.target.value)` -> dispatches `cv-input` CustomEvent
177
+ - Native `<input>` `keydown` event -> `actions.handleKeyDown(e)` -> may trigger `actions.clear()` -> dispatches `cv-clear` CustomEvent
178
+ - Native `<input>` `focus` event -> `actions.setFocused(true)` -> dispatches `cv-focus` CustomEvent
179
+ - Native `<input>` `blur` event -> `actions.setFocused(false)` -> dispatches `cv-blur` CustomEvent; if value changed since focus, dispatches `cv-change` CustomEvent
180
+ - Clear button `click` -> `actions.clear()` -> dispatches `cv-clear` CustomEvent
181
+ - Password toggle `click` -> `actions.togglePasswordVisibility()`
182
+
183
+ UIKit does not own value management, type resolution, clearable logic, or password toggle logic; headless state is the source of truth.
184
+
185
+ ## Events
186
+
187
+ | Event | Detail | Description |
188
+ | ----------- | ------------------- | -------------------------------------------------------------------------------------------------- |
189
+ | `cv-input` | `{ value: string }` | Fires on value change from user interaction (native input event), not from programmatic `setValue` |
190
+ | `cv-change` | `{ value: string }` | Fires on value commit (blur after the value changed since focus) |
191
+ | `cv-clear` | `{ }` | Fires when the value is cleared via the clear button or `Escape` key |
192
+ | `cv-focus` | `{ }` | Fires when the input receives focus |
193
+ | `cv-blur` | `{ }` | Fires when the input loses focus |
194
+
195
+ ## Usage
196
+
197
+ ```html
198
+ <!-- Basic text input -->
199
+ <cv-input placeholder="Enter text"></cv-input>
200
+
201
+ <!-- With label and help text -->
202
+ <cv-input>
203
+ <span slot="label">Username</span>
204
+ <span slot="help-text">Enter your username</span>
205
+ </cv-input>
206
+
207
+ <!-- Clearable -->
208
+ <cv-input clearable value="Hello world"></cv-input>
209
+
210
+ <!-- Password with toggle -->
211
+ <cv-input type="password" password-toggle placeholder="Password"></cv-input>
212
+
213
+ <!-- Filled variant, small size -->
214
+ <cv-input variant="filled" size="small" placeholder="Search..."></cv-input>
215
+
216
+ <!-- With prefix and suffix icons -->
217
+ <cv-input>
218
+ <icon-search slot="prefix"></icon-search>
219
+ <icon-arrow slot="suffix"></icon-arrow>
220
+ </cv-input>
221
+
222
+ <!-- Disabled -->
223
+ <cv-input disabled value="Cannot edit"></cv-input>
224
+
225
+ <!-- Readonly -->
226
+ <cv-input readonly value="Read only value"></cv-input>
227
+
228
+ <!-- Email type, required -->
229
+ <cv-input type="email" required placeholder="Email address">
230
+ <span slot="label">Email</span>
231
+ </cv-input>
232
+
233
+ <!-- Large size, outlined variant with custom clear icon -->
234
+ <cv-input size="large" clearable>
235
+ <icon-x slot="clear-icon"></icon-x>
236
+ </cv-input>
237
+ ```
@@ -0,0 +1,92 @@
1
+ # cv-landmark
2
+
3
+ Semantic wrapper that identifies a page region as an ARIA landmark for assistive technology navigation.
4
+
5
+ **Headless:** [`createLandmark`](https://github.com/chromvoid/headless-ui/blob/main/specs/components/landmarks.md)
6
+
7
+ ## Anatomy
8
+
9
+ ```
10
+ <cv-landmark> (host)
11
+ └── <section part="base" role="…">
12
+ └── <slot>
13
+ ```
14
+
15
+ ## Attributes
16
+
17
+ | Attribute | Type | Default | Description |
18
+ | ---------- | ------ | ---------- | ----------------------------------------------------------------------------------------------------------------------- |
19
+ | `type` | String | `"region"` | Landmark role: `banner` \| `main` \| `navigation` \| `complementary` \| `contentinfo` \| `search` \| `form` \| `region` |
20
+ | `label` | String | `""` | Accessible label applied via `aria-label` |
21
+ | `label-id` | String | `""` | ID of the external labelling element, applied via `aria-labelledby` (takes precedence over `label`) |
22
+
23
+ ## Slots
24
+
25
+ | Slot | Description |
26
+ | ----------- | ---------------- |
27
+ | `(default)` | Landmark content |
28
+
29
+ ## CSS Parts
30
+
31
+ | Part | Element | Description |
32
+ | ------ | ----------- | ------------------------------------ |
33
+ | `base` | `<section>` | Root landmark element with ARIA role |
34
+
35
+ ## CSS Custom Properties
36
+
37
+ None. `cv-landmark` is a pure semantic wrapper with `display: block` only.
38
+
39
+ ## Visual States
40
+
41
+ | Host selector | Description |
42
+ | ------------- | ---------------------------------------------- |
43
+ | `:host` | `display: block`; no additional visual styling |
44
+
45
+ ## Events
46
+
47
+ None. Landmark has no user-driven interactions.
48
+
49
+ ## Reactive State Mapping
50
+
51
+ `cv-landmark` is a visual adapter over headless `createLandmark`.
52
+
53
+ | UIKit Property | Direction | Headless Binding |
54
+ | -------------- | ------------- | ------------------------------------------------ |
55
+ | `type` | attr → option | passed as `type` in `createLandmark(options)` |
56
+ | `label` | attr → option | passed as `label` in `createLandmark(options)` |
57
+ | `label-id` | attr → option | passed as `labelId` in `createLandmark(options)` |
58
+
59
+ | Headless State | Direction | DOM Reflection |
60
+ | ----------------- | ------------ | --------------------------- |
61
+ | `state.type()` | state → attr | `[type]` host attribute |
62
+ | `state.label()` | state → attr | `[label]` host attribute |
63
+ | `state.labelId()` | state → attr | `[label-id]` host attribute |
64
+
65
+ - `contracts.getLandmarkProps()` is spread onto the inner `[part="base"]` element to apply `role`, `aria-label`, and `aria-labelledby`.
66
+ - When any of `type`, `label`, or `label-id` attributes change, the headless model is recreated with updated options.
67
+ - UIKit does not own labeling precedence logic; headless `getLandmarkProps()` determines whether `aria-label` or `aria-labelledby` is emitted.
68
+
69
+ ## Usage
70
+
71
+ ```html
72
+ <cv-landmark type="navigation" label="Main navigation">
73
+ <nav-links></nav-links>
74
+ </cv-landmark>
75
+
76
+ <cv-landmark type="main">
77
+ <page-content></page-content>
78
+ </cv-landmark>
79
+
80
+ <cv-landmark type="complementary" label="Related articles">
81
+ <aside-content></aside-content>
82
+ </cv-landmark>
83
+
84
+ <cv-landmark type="search" label="Site search">
85
+ <search-form></search-form>
86
+ </cv-landmark>
87
+
88
+ <cv-landmark type="region" label-id="section-heading">
89
+ <h2 id="section-heading">Latest News</h2>
90
+ <article-list></article-list>
91
+ </cv-landmark>
92
+ ```
@@ -0,0 +1,117 @@
1
+ # cv-link
2
+
3
+ Inline navigational element that directs the user to another page or resource.
4
+
5
+ **Headless:** [`createLink`](https://github.com/chromvoid/headless-ui/blob/main/specs/components/link.md)
6
+
7
+ ## Anatomy
8
+
9
+ ```
10
+ <cv-link> (host)
11
+ └── <a 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
+ | `href` | String | `""` | Target URL; reflected to the inner anchor's `href` |
25
+
26
+ ## Slots
27
+
28
+ | Slot | Description |
29
+ | ----------- | ---------------------------- |
30
+ | `(default)` | Link text |
31
+ | `prefix` | Icon or element before label |
32
+ | `suffix` | Icon or element after label |
33
+
34
+ ## CSS Parts
35
+
36
+ | Part | Element | Description |
37
+ | -------- | -------- | -------------------------------- |
38
+ | `base` | `<a>` | The anchor element |
39
+ | `label` | `<span>` | Wrapper around the default slot |
40
+ | `prefix` | `<span>` | Wrapper around the `prefix` slot |
41
+ | `suffix` | `<span>` | Wrapper around the `suffix` slot |
42
+
43
+ ## CSS Custom Properties
44
+
45
+ | Property | Default | Description |
46
+ | --------------------------------- | ------------------------------------------------------------------ | --------------------------------------- |
47
+ | `--cv-link-color` | `var(--cv-color-primary, #65d7ff)` | Default text and icon color |
48
+ | `--cv-link-color-hover` | `color-mix(in oklab, var(--cv-color-primary, #65d7ff) 78%, white)` | Text color on hover |
49
+ | `--cv-link-color-active` | `color-mix(in oklab, var(--cv-color-primary, #65d7ff) 60%, white)` | Text color on active press |
50
+ | `--cv-link-gap` | `var(--cv-space-1, 4px)` | Space between prefix, label, and suffix |
51
+ | `--cv-link-text-decoration` | `underline` | Text decoration style |
52
+ | `--cv-link-text-decoration-hover` | `none` | Text decoration on hover |
53
+ | `--cv-link-outline-color` | `var(--cv-color-primary, #65d7ff)` | Focus-visible outline color |
54
+ | `--cv-link-outline-offset` | `2px` | Focus-visible outline offset |
55
+
56
+ Additionally, component styles depend on theme tokens through fallback values:
57
+
58
+ | Theme Property | Default | Description |
59
+ | ---------------------- | --------- | ---------------------------- |
60
+ | `--cv-color-primary` | `#65d7ff` | Primary accent color |
61
+ | `--cv-duration-fast` | `120ms` | Transition duration |
62
+ | `--cv-easing-standard` | `ease` | Transition timing function |
63
+ | `--cv-space-1` | `4px` | Small spacing scale fallback |
64
+
65
+ ## Visual States
66
+
67
+ | Host selector | Description |
68
+ | ----------------------- | ---------------------------------------------------------------------- |
69
+ | `:host(:hover)` | Applies `--cv-link-color-hover` to text color; updates text decoration |
70
+ | `:host(:focus-visible)` | Shows outline ring around the base element |
71
+ | `:host(:active)` | Applies `--cv-link-color-active` to text color |
72
+
73
+ ## Reactive State Mapping
74
+
75
+ `cv-link` is a visual adapter over headless `createLink`.
76
+
77
+ | UIKit Property | Direction | Headless Binding |
78
+ | -------------- | -------------- | ----------------------------------------- |
79
+ | `href` | attr -> option | passed as `href` in `createLink(options)` |
80
+
81
+ | Headless State | Direction | DOM Reflection |
82
+ | -------------- | --------- | --------------------------------------- |
83
+ | _(none)_ | — | Link is stateless at the headless level |
84
+
85
+ - `contracts.getLinkProps()` is spread onto the inner `[part="base"]` element to apply `id`, `href`, and keyboard/click handlers.
86
+ - Because the inner element is a native `<a>`, `createLink` is called with `isSemanticHost: true`, so `role` and `tabindex` are omitted from the contract (the native element provides them).
87
+ - When `href` changes, the model is recreated with the new value (headless link options are immutable).
88
+ - UIKit dispatches a `press` event by providing an `onPress` callback to the headless `createLink` options.
89
+ - UIKit does not own activation logic; headless event handlers are the source of truth.
90
+
91
+ ## Events
92
+
93
+ | Event | Detail | Description |
94
+ | ------- | ---------------- | ----------------------------------------------- |
95
+ | `press` | `{href: string}` | Fires on activation (click or `Enter` keypress) |
96
+
97
+ ## Usage
98
+
99
+ ```html
100
+ <cv-link href="/about">About us</cv-link>
101
+
102
+ <cv-link href="/docs">
103
+ <icon-book slot="prefix"></icon-book>
104
+ Documentation
105
+ </cv-link>
106
+
107
+ <cv-link href="/settings">
108
+ Settings
109
+ <icon-arrow-right slot="suffix"></icon-arrow-right>
110
+ </cv-link>
111
+
112
+ <cv-link href="/home">
113
+ <icon-home slot="prefix"></icon-home>
114
+ Home
115
+ <icon-external slot="suffix"></icon-external>
116
+ </cv-link>
117
+ ```