luxen-ui 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 (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +98 -0
  3. package/dist/css/elements/avatar.css +20 -0
  4. package/dist/css/elements/badge.css +159 -0
  5. package/dist/css/elements/button.css +171 -0
  6. package/dist/css/elements/close-button/circle.css +66 -0
  7. package/dist/css/elements/close-button/ring.css +71 -0
  8. package/dist/css/elements/close-button/square.css +70 -0
  9. package/dist/css/elements/disclosure.css +137 -0
  10. package/dist/css/elements/divider.css +75 -0
  11. package/dist/css/elements/input-otp.css +164 -0
  12. package/dist/css/elements/input-stepper/default.css +245 -0
  13. package/dist/css/elements/input-stepper/rounded.css +238 -0
  14. package/dist/css/elements/kbd.css +21 -0
  15. package/dist/css/elements/progress.css +114 -0
  16. package/dist/css/elements/select.css +71 -0
  17. package/dist/css/elements/skeleton.css +89 -0
  18. package/dist/css/elements/tabs/enclosed.css +148 -0
  19. package/dist/css/elements/tabs/line.css +138 -0
  20. package/dist/css/elements/toast.css +260 -0
  21. package/dist/css/index.css +885 -0
  22. package/dist/custom-elements.json +14424 -0
  23. package/dist/define.d.ts +9 -0
  24. package/dist/define.d.ts.map +1 -0
  25. package/dist/define.js +16 -0
  26. package/dist/elements/avatar/avatar.css +128 -0
  27. package/dist/elements/avatar/avatar.d.ts +21 -0
  28. package/dist/elements/avatar/avatar.d.ts.map +1 -0
  29. package/dist/elements/avatar/avatar.js +106 -0
  30. package/dist/elements/avatar/index.d.ts +8 -0
  31. package/dist/elements/avatar/index.d.ts.map +1 -0
  32. package/dist/elements/avatar/index.js +4 -0
  33. package/dist/elements/badge/badge.d.ts +17 -0
  34. package/dist/elements/badge/badge.d.ts.map +1 -0
  35. package/dist/elements/badge/badge.js +34 -0
  36. package/dist/elements/badge/index.d.ts +8 -0
  37. package/dist/elements/badge/index.d.ts.map +1 -0
  38. package/dist/elements/badge/index.js +4 -0
  39. package/dist/elements/carousel/carousel.css +205 -0
  40. package/dist/elements/carousel/carousel.d.ts +148 -0
  41. package/dist/elements/carousel/carousel.d.ts.map +1 -0
  42. package/dist/elements/carousel/carousel.js +473 -0
  43. package/dist/elements/carousel/index.d.ts +8 -0
  44. package/dist/elements/carousel/index.d.ts.map +1 -0
  45. package/dist/elements/carousel/index.js +4 -0
  46. package/dist/elements/carousel-item/carousel-item.css +11 -0
  47. package/dist/elements/carousel-item/carousel-item.d.ts +13 -0
  48. package/dist/elements/carousel-item/carousel-item.d.ts.map +1 -0
  49. package/dist/elements/carousel-item/carousel-item.js +20 -0
  50. package/dist/elements/carousel-item/index.d.ts +8 -0
  51. package/dist/elements/carousel-item/index.d.ts.map +1 -0
  52. package/dist/elements/carousel-item/index.js +4 -0
  53. package/dist/elements/dialog/dialog.css +92 -0
  54. package/dist/elements/dialog/dialog.d.ts +56 -0
  55. package/dist/elements/dialog/dialog.d.ts.map +1 -0
  56. package/dist/elements/dialog/dialog.js +204 -0
  57. package/dist/elements/dialog/dialog.styles.d.ts +8 -0
  58. package/dist/elements/dialog/dialog.styles.d.ts.map +1 -0
  59. package/dist/elements/dialog/dialog.styles.js +8 -0
  60. package/dist/elements/dialog/index.d.ts +8 -0
  61. package/dist/elements/dialog/index.d.ts.map +1 -0
  62. package/dist/elements/dialog/index.js +4 -0
  63. package/dist/elements/divider/divider.d.ts +23 -0
  64. package/dist/elements/divider/divider.d.ts.map +1 -0
  65. package/dist/elements/divider/divider.js +49 -0
  66. package/dist/elements/divider/index.d.ts +8 -0
  67. package/dist/elements/divider/index.d.ts.map +1 -0
  68. package/dist/elements/divider/index.js +4 -0
  69. package/dist/elements/drawer/drawer.css +66 -0
  70. package/dist/elements/drawer/drawer.d.ts +34 -0
  71. package/dist/elements/drawer/drawer.d.ts.map +1 -0
  72. package/dist/elements/drawer/drawer.js +46 -0
  73. package/dist/elements/drawer/index.d.ts +8 -0
  74. package/dist/elements/drawer/index.d.ts.map +1 -0
  75. package/dist/elements/drawer/index.js +4 -0
  76. package/dist/elements/dropdown/dropdown.css +31 -0
  77. package/dist/elements/dropdown/dropdown.d.ts +64 -0
  78. package/dist/elements/dropdown/dropdown.d.ts.map +1 -0
  79. package/dist/elements/dropdown/dropdown.js +322 -0
  80. package/dist/elements/dropdown/index.d.ts +8 -0
  81. package/dist/elements/dropdown/index.d.ts.map +1 -0
  82. package/dist/elements/dropdown/index.js +4 -0
  83. package/dist/elements/dropdown-item/dropdown-item.css +51 -0
  84. package/dist/elements/dropdown-item/dropdown-item.d.ts +25 -0
  85. package/dist/elements/dropdown-item/dropdown-item.d.ts.map +1 -0
  86. package/dist/elements/dropdown-item/dropdown-item.js +110 -0
  87. package/dist/elements/dropdown-item/index.d.ts +8 -0
  88. package/dist/elements/dropdown-item/index.d.ts.map +1 -0
  89. package/dist/elements/dropdown-item/index.js +4 -0
  90. package/dist/elements/icon/icon.css +10 -0
  91. package/dist/elements/icon/icon.d.ts +19 -0
  92. package/dist/elements/icon/icon.d.ts.map +1 -0
  93. package/dist/elements/icon/icon.js +53 -0
  94. package/dist/elements/icon/index.d.ts +8 -0
  95. package/dist/elements/icon/index.d.ts.map +1 -0
  96. package/dist/elements/icon/index.js +4 -0
  97. package/dist/elements/input-otp/index.d.ts +8 -0
  98. package/dist/elements/input-otp/index.d.ts.map +1 -0
  99. package/dist/elements/input-otp/index.js +4 -0
  100. package/dist/elements/input-otp/input-otp.d.ts +31 -0
  101. package/dist/elements/input-otp/input-otp.d.ts.map +1 -0
  102. package/dist/elements/input-otp/input-otp.js +139 -0
  103. package/dist/elements/input-stepper/index.d.ts +8 -0
  104. package/dist/elements/input-stepper/index.d.ts.map +1 -0
  105. package/dist/elements/input-stepper/index.js +4 -0
  106. package/dist/elements/input-stepper/input-stepper.d.ts +63 -0
  107. package/dist/elements/input-stepper/input-stepper.d.ts.map +1 -0
  108. package/dist/elements/input-stepper/input-stepper.js +249 -0
  109. package/dist/elements/popover/index.d.ts +8 -0
  110. package/dist/elements/popover/index.d.ts.map +1 -0
  111. package/dist/elements/popover/index.js +4 -0
  112. package/dist/elements/popover/popover.css +61 -0
  113. package/dist/elements/popover/popover.d.ts +62 -0
  114. package/dist/elements/popover/popover.d.ts.map +1 -0
  115. package/dist/elements/popover/popover.js +244 -0
  116. package/dist/elements/rating/index.d.ts +8 -0
  117. package/dist/elements/rating/index.d.ts.map +1 -0
  118. package/dist/elements/rating/index.js +4 -0
  119. package/dist/elements/rating/rating.css +102 -0
  120. package/dist/elements/rating/rating.d.ts +38 -0
  121. package/dist/elements/rating/rating.d.ts.map +1 -0
  122. package/dist/elements/rating/rating.js +193 -0
  123. package/dist/elements/skeleton/index.d.ts +8 -0
  124. package/dist/elements/skeleton/index.d.ts.map +1 -0
  125. package/dist/elements/skeleton/index.js +4 -0
  126. package/dist/elements/skeleton/skeleton.d.ts +12 -0
  127. package/dist/elements/skeleton/skeleton.d.ts.map +1 -0
  128. package/dist/elements/skeleton/skeleton.js +13 -0
  129. package/dist/elements/spinner/index.d.ts +8 -0
  130. package/dist/elements/spinner/index.d.ts.map +1 -0
  131. package/dist/elements/spinner/index.js +4 -0
  132. package/dist/elements/spinner/spinner.css +28 -0
  133. package/dist/elements/spinner/spinner.d.ts +16 -0
  134. package/dist/elements/spinner/spinner.d.ts.map +1 -0
  135. package/dist/elements/spinner/spinner.js +37 -0
  136. package/dist/elements/tabs/index.d.ts +8 -0
  137. package/dist/elements/tabs/index.d.ts.map +1 -0
  138. package/dist/elements/tabs/index.js +4 -0
  139. package/dist/elements/tabs/tabs.d.ts +48 -0
  140. package/dist/elements/tabs/tabs.d.ts.map +1 -0
  141. package/dist/elements/tabs/tabs.js +210 -0
  142. package/dist/elements/toast/index.d.ts +9 -0
  143. package/dist/elements/toast/index.d.ts.map +1 -0
  144. package/dist/elements/toast/index.js +5 -0
  145. package/dist/elements/toast/toast.d.ts +72 -0
  146. package/dist/elements/toast/toast.d.ts.map +1 -0
  147. package/dist/elements/toast/toast.js +375 -0
  148. package/dist/elements/tooltip/index.d.ts +8 -0
  149. package/dist/elements/tooltip/index.d.ts.map +1 -0
  150. package/dist/elements/tooltip/index.js +4 -0
  151. package/dist/elements/tooltip/tooltip.css +37 -0
  152. package/dist/elements/tooltip/tooltip.d.ts +59 -0
  153. package/dist/elements/tooltip/tooltip.d.ts.map +1 -0
  154. package/dist/elements/tooltip/tooltip.js +231 -0
  155. package/dist/elements/tree/index.d.ts +8 -0
  156. package/dist/elements/tree/index.d.ts.map +1 -0
  157. package/dist/elements/tree/index.js +4 -0
  158. package/dist/elements/tree/tree.css +26 -0
  159. package/dist/elements/tree/tree.d.ts +76 -0
  160. package/dist/elements/tree/tree.d.ts.map +1 -0
  161. package/dist/elements/tree/tree.js +432 -0
  162. package/dist/elements/tree-item/index.d.ts +8 -0
  163. package/dist/elements/tree-item/index.d.ts.map +1 -0
  164. package/dist/elements/tree-item/index.js +4 -0
  165. package/dist/elements/tree-item/tree-item.css +172 -0
  166. package/dist/elements/tree-item/tree-item.d.ts +74 -0
  167. package/dist/elements/tree-item/tree-item.d.ts.map +1 -0
  168. package/dist/elements/tree-item/tree-item.js +301 -0
  169. package/dist/index.d.ts +6 -0
  170. package/dist/index.d.ts.map +1 -0
  171. package/dist/index.js +4 -0
  172. package/dist/registry.d.ts +22 -0
  173. package/dist/registry.d.ts.map +1 -0
  174. package/dist/registry.js +33 -0
  175. package/dist/shared/controllers/popover.d.ts +44 -0
  176. package/dist/shared/controllers/popover.d.ts.map +1 -0
  177. package/dist/shared/controllers/popover.js +359 -0
  178. package/dist/shared/luxen-element.d.ts +20 -0
  179. package/dist/shared/luxen-element.d.ts.map +1 -0
  180. package/dist/shared/luxen-element.js +23 -0
  181. package/dist/shared/luxen-form-associated-element.d.ts +49 -0
  182. package/dist/shared/luxen-form-associated-element.d.ts.map +1 -0
  183. package/dist/shared/luxen-form-associated-element.js +123 -0
  184. package/dist/shared/styles/host.css +13 -0
  185. package/dist/shared/styles/host.styles.d.ts +9 -0
  186. package/dist/shared/styles/host.styles.d.ts.map +1 -0
  187. package/dist/shared/styles/host.styles.js +9 -0
  188. package/dist/skills/luxen-ui/SKILL.md +82 -0
  189. package/dist/skills/luxen-ui/references/avatar.md +259 -0
  190. package/dist/skills/luxen-ui/references/badge.md +289 -0
  191. package/dist/skills/luxen-ui/references/button.md +309 -0
  192. package/dist/skills/luxen-ui/references/close-button.md +104 -0
  193. package/dist/skills/luxen-ui/references/dialog.md +435 -0
  194. package/dist/skills/luxen-ui/references/drawer.md +400 -0
  195. package/dist/skills/luxen-ui/references/progress.md +133 -0
  196. package/dist/skills/luxen-ui/references/select.md +100 -0
  197. package/dist/skills/luxen-ui/references/toast.md +396 -0
  198. package/dist/skills/luxen-ui/references/tree.md +359 -0
  199. package/package.json +116 -0
  200. package/postcss-plugin-prefix.js +63 -0
  201. package/vite-plugin.ts +29 -0
@@ -0,0 +1,309 @@
1
+ ---
2
+ outline: deep
3
+ ---
4
+
5
+ # Button
6
+
7
+ Buttons are used to trigger actions such as submitting forms, confirming dialogs, or navigating. They are the primary interactive control in any interface.
8
+
9
+ <ElementSpec
10
+ tag="button"
11
+ type="native"
12
+ />
13
+
14
+ ## Options
15
+
16
+ ### Sizes
17
+
18
+ Add `data-size="sm"`, `data-size="lg"`, or `data-size="xl"`. Default is md.
19
+
20
+ ```html
21
+ <button
22
+ class="l-button"
23
+ data-size="sm"
24
+ >
25
+ Button sm
26
+ </button>
27
+ <button class="l-button">Button md</button>
28
+ <button
29
+ class="l-button"
30
+ data-size="lg"
31
+ >
32
+ Button lg
33
+ </button>
34
+ <button
35
+ class="l-button"
36
+ data-size="xl"
37
+ >
38
+ Button xl
39
+ </button>
40
+ ```
41
+
42
+ ### Primary
43
+
44
+ Add `data-variant="primary"`.
45
+
46
+ ```html
47
+ <button
48
+ class="l-button"
49
+ data-variant="primary"
50
+ >
51
+ Primary
52
+ </button>
53
+ <button
54
+ class="l-button"
55
+ data-variant="primary"
56
+ disabled
57
+ >
58
+ Primary disabled
59
+ </button>
60
+ ```
61
+
62
+ ### Destructive
63
+
64
+ Add `data-variant="destructive"`.
65
+
66
+ ```html
67
+ <button
68
+ class="l-button"
69
+ data-variant="destructive"
70
+ >
71
+ Delete
72
+ </button>
73
+ <button
74
+ class="l-button"
75
+ data-variant="destructive"
76
+ disabled
77
+ >
78
+ Delete
79
+ </button>
80
+ ```
81
+
82
+ ### Icon-only
83
+
84
+ Auto-detected when containing a single `<svg>`, `<l-icon>`, or `<iconify-icon>`.
85
+
86
+ ```html
87
+ <button
88
+ class="l-button"
89
+ aria-label="Settings"
90
+ >
91
+ <iconify-icon icon="lucide:settings"></iconify-icon>
92
+ </button>
93
+ <button
94
+ class="l-button"
95
+ data-variant="primary"
96
+ aria-label="Add"
97
+ >
98
+ <iconify-icon icon="lucide:plus"></iconify-icon>
99
+ </button>
100
+ ```
101
+
102
+ ### Disabled
103
+
104
+ Native `disabled` attribute.
105
+
106
+ ```html
107
+ <button
108
+ class="l-button"
109
+ disabled
110
+ >
111
+ Disabled
112
+ </button>
113
+ <button
114
+ class="l-button"
115
+ data-variant="primary"
116
+ disabled
117
+ >
118
+ Disabled primary
119
+ </button>
120
+ ```
121
+
122
+ ### As link
123
+
124
+ Use an `<a>` element instead of `<button>`.
125
+
126
+ ```html
127
+ <a
128
+ class="l-button"
129
+ href="#link"
130
+ >Link button</a
131
+ >
132
+ <a
133
+ class="l-button"
134
+ data-variant="primary"
135
+ href="#link"
136
+ >Primary link</a
137
+ >
138
+ ```
139
+
140
+ ### Press effect
141
+
142
+ Add `data-press-effect` attribute.
143
+
144
+ ```html
145
+ <button
146
+ class="l-button"
147
+ data-press-effect
148
+ >
149
+ Press me
150
+ </button>
151
+ <button
152
+ class="l-button"
153
+ data-variant="primary"
154
+ data-press-effect
155
+ >
156
+ Press me
157
+ </button>
158
+ ```
159
+
160
+ ### Loading
161
+
162
+ Add an `<l-spinner>` inside the button. The spinner inherits the button's text color.
163
+
164
+ ```html
165
+ <button
166
+ class="l-button"
167
+ disabled
168
+ >
169
+ <l-spinner></l-spinner>
170
+ Loading…
171
+ </button>
172
+ <button
173
+ class="l-button"
174
+ data-variant="primary"
175
+ disabled
176
+ >
177
+ <l-spinner></l-spinner>
178
+ Loading…
179
+ </button>
180
+ ```
181
+
182
+ ## Examples
183
+
184
+ ### With icon and text
185
+
186
+ ```html
187
+ <button class="l-button">
188
+ <iconify-icon icon="lucide:download"></iconify-icon>
189
+ Download
190
+ </button>
191
+ <button
192
+ class="l-button"
193
+ data-variant="primary"
194
+ >
195
+ <iconify-icon icon="lucide:send"></iconify-icon>
196
+ Send
197
+ </button>
198
+ ```
199
+
200
+ ### Button group
201
+
202
+ ```html
203
+ <div
204
+ role="group"
205
+ aria-label="Text formatting"
206
+ class="flex gap-0"
207
+ >
208
+ <button
209
+ class="l-button rounded-none border-r-0"
210
+ aria-label="Bold"
211
+ >
212
+ <iconify-icon icon="lucide:bold"></iconify-icon>
213
+ </button>
214
+ <button
215
+ class="l-button rounded-none border-r-0"
216
+ aria-label="Italic"
217
+ >
218
+ <iconify-icon icon="lucide:italic"></iconify-icon>
219
+ </button>
220
+ <button
221
+ class="l-button rounded-none"
222
+ aria-label="Underline"
223
+ >
224
+ <iconify-icon icon="lucide:underline"></iconify-icon>
225
+ </button>
226
+ </div>
227
+ ```
228
+
229
+ ### Form actions
230
+
231
+ ```html
232
+ <div class="flex gap-2 justify-end">
233
+ <button class="l-button">Cancel</button>
234
+ <button
235
+ class="l-button"
236
+ data-variant="primary"
237
+ >
238
+ Save changes
239
+ </button>
240
+ </div>
241
+ ```
242
+
243
+ ## Accessibility
244
+
245
+ ### Criteria
246
+
247
+ | Check | Description |
248
+ |-------|-------------|
249
+ | Color | Text and background colors meet AA contrast ratios across all variants |
250
+ | Focus state | Visible 2px focus ring for keyboard users |
251
+ | Hover state | Clear visual change on hover |
252
+ | Active state | Visual feedback on press |
253
+ | Disabled state | Reduced opacity, `cursor: not-allowed`, not focusable when disabled |
254
+ | Icon-only | Icon-only buttons must have `aria-label` for an accessible name |
255
+ | Role | Uses native `<button>` or `<a>` — no extra ARIA role needed |
256
+
257
+ ### Rules
258
+ - Use a native `<button>` element — never a `<div>` or `<span>`
259
+ - Always add `aria-label` to icon-only buttons
260
+ - Include `type="button"` to prevent form submission (except for submit buttons)
261
+ - When using `<a>` as a link button, add `role="button"` only if it triggers an action rather than navigating
262
+
263
+ ### Keyboard interactions
264
+
265
+ | Key | Description |
266
+ |-----|-------------|
267
+ | Enter | Activates the button |
268
+ | Space | Activates the button |
269
+ | Tab | Moves focus to the next focusable element |
270
+ | Shift + Tab | Moves focus to the previous focusable element |
271
+
272
+ ## API reference
273
+
274
+ ### Importing
275
+
276
+ ```css
277
+ @import 'luxen-ui/css/button';
278
+ ```
279
+
280
+ ### Attributes & Properties
281
+
282
+ <ApiTable :data="[
283
+ { Attribute: 'disabled', Description: 'Disables the button' },
284
+ { Attribute: 'command', Description: 'Invoker command (`show-modal`, `close`, `show-popover`, etc.)' },
285
+ { Attribute: 'commandfor', Description: 'ID of the target element for `command`' },
286
+ { Attribute: 'data-variant', Description: 'Visual variant (`primary`, `destructive`)' },
287
+ { Attribute: 'data-size', Description: 'Size (`sm`, `lg`, `xl`). Default is md.' },
288
+ { Attribute: 'data-icon-only', Description: 'Icon-only mode (square button, width equals height)' },
289
+ { Attribute: 'data-press-effect', Description: 'Press effect (scale + translate on active)' },
290
+ ]" />
291
+
292
+ ### CSS classes
293
+
294
+ <ApiTable :data="cssClasses" />
295
+
296
+ ### CSS custom properties
297
+
298
+ <ApiTable :data="[
299
+ { Name: '--height', Description: 'Button height' },
300
+ { Name: '--padding-inline', Description: 'Horizontal padding' },
301
+ { Name: '--background-color', Description: 'Background color' },
302
+ { Name: '--background-color-hover', Description: 'Background on hover' },
303
+ { Name: '--background-color-active', Description: 'Background on press' },
304
+ { Name: '--text-color', Description: 'Text color' },
305
+ { Name: '--text-color-hover', Description: 'Text color on hover' },
306
+ { Name: '--border-color', Description: 'Border color' },
307
+ { Name: '--border-color-hover', Description: 'Border color on hover' },
308
+ { Name: '--font-size', Description: 'Font size' },
309
+ ]" />
@@ -0,0 +1,104 @@
1
+ ---
2
+ outline: deep
3
+ ---
4
+
5
+ # Close button
6
+
7
+ Close buttons are used to dismiss overlays such as dialogs, drawers, toasts, and popovers. They render a close icon without any visible label.
8
+
9
+ <ElementSpec
10
+ tag="button"
11
+ type="native"
12
+ />
13
+
14
+ ## Options
15
+
16
+ ### Appearance
17
+
18
+ Pick a visual style via `data-appearance`. Each appearance has its own CSS import.
19
+
20
+ #### Ring
21
+
22
+ <ComponentWrapper :html="'<button type=&quot;button&quot; class=&quot;l-close&quot; data-appearance=&quot;ring&quot; aria-label=&quot;Close&quot;></button>'" />
23
+
24
+ ```css
25
+ @import 'luxen-ui/css/close-button/ring';
26
+ ```
27
+
28
+ #### Square
29
+
30
+ <ComponentWrapper :html="'<button type=&quot;button&quot; class=&quot;l-close&quot; data-appearance=&quot;square&quot; aria-label=&quot;Close&quot;></button>'" />
31
+
32
+ ```css
33
+ @import 'luxen-ui/css/close-button/square';
34
+ ```
35
+
36
+ #### Circle
37
+
38
+ <ComponentWrapper :html="'<button type=&quot;button&quot; class=&quot;l-close&quot; data-appearance=&quot;circle&quot; aria-label=&quot;Close&quot;></button>'" />
39
+
40
+ ```css
41
+ @import 'luxen-ui/css/close-button/circle';
42
+ ```
43
+
44
+ ## Accessibility
45
+
46
+ ### Criteria
47
+
48
+ | Check | Description |
49
+ |-------|-------------|
50
+ | Color | Icon and background colors meet AA contrast ratios |
51
+ | Size | Minimum 24×24px target size; larger for touch contexts |
52
+ | Icon | Decorative icon; `aria-label` on the button provides the accessible name |
53
+ | Hover state | Clear visual change on hover |
54
+ | Focus state | Visible focus ring for keyboard users |
55
+ | Active state | Visual feedback on press |
56
+ | Disabled state | Appears inactive, not focusable when disabled |
57
+ | Accessible name | Always provide `aria-label` or context-specific label |
58
+ | Role | Uses native `<button>` — no extra ARIA role needed |
59
+
60
+ ### Rules
61
+ - Always add `aria-label="Close"` (or a context-specific label like `aria-label="Close dialog"`)
62
+ - Use a native `<button>` element — never a `<div>` or `<span>`
63
+ - Include `type="button"` to prevent form submission
64
+
65
+ ### Keyboard interactions
66
+
67
+ | Key | Description |
68
+ |-----|-------------|
69
+ | Enter | Activates the close button |
70
+ | Space | Activates the close button |
71
+ | Tab | Moves focus to the next focusable element |
72
+ | Shift + Tab | Moves focus to the previous focusable element |
73
+
74
+ ## API reference
75
+
76
+ ### Importing
77
+
78
+ ```css
79
+ @import 'luxen-ui/css/close-button/ring';
80
+ ```
81
+
82
+ ### Attributes & Properties
83
+
84
+ <ApiTable :data="[
85
+ { Attribute: 'data-appearance', Description: '`ring` · `square` · `circle`' },
86
+ { Attribute: 'command', Description: 'Invoker command (typically `close`)' },
87
+ { Attribute: 'commandfor', Description: 'ID of the target element to close' },
88
+ ]" />
89
+
90
+ ### CSS classes
91
+
92
+ <ApiTable :data="[
93
+ { Class: '.l-close', Description: 'Base close button with X icon via CSS mask' },
94
+ ]" />
95
+
96
+ ### CSS custom properties
97
+
98
+ <ApiTable :data="[
99
+ { Name: '--size', Description: 'Button size (default: 36px)' },
100
+ { Name: '--icon-color', Description: 'Icon color' },
101
+ { Name: '--icon-size', Description: 'Icon size (default: 24px)' },
102
+ { Name: '--ring-color', Description: 'Hover ring color (`ring` appearance only)' },
103
+ { Name: '--ring-tickness', Description: 'Hover ring thickness (`ring` appearance only)' },
104
+ ]" />