opui-css 5.4.2 → 6.0.0-rc.1

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 (718) hide show
  1. package/CHANGELOG.md +648 -0
  2. package/MIGRATING-legacy.md +159 -0
  3. package/MIGRATING.md +1293 -69
  4. package/README.md +177 -26
  5. package/astro/index.ts +142 -13
  6. package/bin/opui-css.mjs +68 -0
  7. package/components/Accordion/Accordion.astro +6 -33
  8. package/components/Accordion/Accordion.react.tsx +23 -0
  9. package/components/Accordion/Accordion.svelte +27 -0
  10. package/components/Accordion/Accordion.vue +11 -28
  11. package/components/Accordion/AccordionActions.astro +16 -0
  12. package/components/Accordion/AccordionActions.react.tsx +15 -0
  13. package/components/Accordion/AccordionActions.svelte +23 -0
  14. package/components/Accordion/AccordionActions.vue +18 -0
  15. package/components/Accordion/AccordionContent.astro +9 -0
  16. package/components/Accordion/AccordionContent.react.tsx +6 -0
  17. package/components/Accordion/AccordionContent.svelte +15 -0
  18. package/components/Accordion/AccordionContent.vue +12 -0
  19. package/components/Accordion/AccordionSummary.astro +19 -0
  20. package/components/Accordion/AccordionSummary.react.tsx +30 -0
  21. package/components/Accordion/AccordionSummary.svelte +24 -0
  22. package/components/Accordion/AccordionSummary.vue +27 -0
  23. package/components/Accordion/icons.ts +2 -0
  24. package/components/Accordion/types.astro.ts +9 -0
  25. package/components/Accordion/types.react.ts +14 -0
  26. package/components/Accordion/types.svelte.ts +10 -2
  27. package/components/Accordion/types.ts +11 -5
  28. package/components/Accordion/types.vue-props.ts +22 -0
  29. package/components/Anchor/Anchor.astro +21 -33
  30. package/components/Anchor/Anchor.react.tsx +38 -0
  31. package/components/Anchor/Anchor.svelte +47 -0
  32. package/components/Anchor/Anchor.vue +32 -30
  33. package/components/Anchor/AnchorContent.astro +17 -0
  34. package/components/Anchor/AnchorContent.react.tsx +18 -0
  35. package/components/Anchor/AnchorContent.svelte +23 -0
  36. package/components/Anchor/AnchorContent.vue +20 -0
  37. package/components/Anchor/context.astro.ts +4 -0
  38. package/components/Anchor/context.react.ts +8 -0
  39. package/components/Anchor/context.svelte.ts +7 -0
  40. package/components/Anchor/context.vue.ts +4 -0
  41. package/components/Anchor/root.ts +12 -0
  42. package/components/Anchor/types.astro.ts +3 -0
  43. package/components/Anchor/types.react.ts +7 -0
  44. package/components/Anchor/types.svelte.ts +3 -3
  45. package/components/Anchor/types.ts +15 -6
  46. package/components/Anchor/types.vue-props.ts +15 -0
  47. package/components/Avatar/Avatar.astro +12 -8
  48. package/components/Avatar/Avatar.react.tsx +34 -0
  49. package/components/Avatar/Avatar.svelte +39 -0
  50. package/components/Avatar/Avatar.vue +10 -8
  51. package/components/Avatar/AvatarGroup.astro +9 -0
  52. package/components/Avatar/AvatarGroup.react.tsx +12 -0
  53. package/components/Avatar/AvatarGroup.svelte +15 -0
  54. package/components/Avatar/AvatarGroup.vue +12 -0
  55. package/components/Avatar/types.astro.ts +3 -2
  56. package/components/Avatar/types.react.ts +11 -0
  57. package/components/Avatar/types.svelte.ts +3 -4
  58. package/components/Avatar/types.ts +18 -15
  59. package/components/Avatar/types.vue-props.ts +11 -0
  60. package/components/Badge/Badge.astro +27 -22
  61. package/components/Badge/Badge.react.tsx +50 -0
  62. package/components/Badge/Badge.svelte +48 -0
  63. package/components/Badge/Badge.vue +15 -19
  64. package/components/Badge/types.react.ts +6 -0
  65. package/components/Badge/types.svelte.ts +4 -1
  66. package/components/Badge/types.ts +3 -3
  67. package/components/Badge/types.vue-props.ts +7 -0
  68. package/components/Button/Button.astro +12 -12
  69. package/components/Button/Button.react.tsx +33 -0
  70. package/components/Button/Button.svelte +37 -0
  71. package/components/Button/Button.vue +9 -9
  72. package/components/Button/types.astro.ts +2 -2
  73. package/components/Button/types.react.ts +11 -0
  74. package/components/Button/types.svelte.ts +11 -2
  75. package/components/Button/types.ts +20 -4
  76. package/components/Button/types.vue-props.ts +6 -0
  77. package/components/ButtonGroup/ButtonGroup.astro +7 -3
  78. package/components/ButtonGroup/ButtonGroup.react.tsx +30 -0
  79. package/components/ButtonGroup/ButtonGroup.svelte +34 -0
  80. package/components/ButtonGroup/ButtonGroup.vue +10 -7
  81. package/components/ButtonGroup/types.react.ts +4 -0
  82. package/components/ButtonGroup/types.ts +4 -4
  83. package/components/ButtonGroup/types.vue-props.ts +6 -0
  84. package/components/Callout/Callout.astro +7 -59
  85. package/components/Callout/Callout.react.tsx +26 -0
  86. package/components/Callout/Callout.svelte +32 -0
  87. package/components/Callout/Callout.vue +8 -48
  88. package/components/Callout/CalloutContent.astro +9 -0
  89. package/components/Callout/CalloutContent.react.tsx +6 -0
  90. package/components/Callout/CalloutContent.svelte +15 -0
  91. package/components/Callout/CalloutContent.vue +12 -0
  92. package/components/Callout/CalloutIcon.astro +25 -0
  93. package/components/Callout/CalloutIcon.react.tsx +26 -0
  94. package/components/Callout/CalloutIcon.svelte +24 -0
  95. package/components/Callout/CalloutIcon.vue +25 -0
  96. package/components/Callout/context.astro.ts +4 -0
  97. package/components/Callout/context.react.ts +8 -0
  98. package/components/Callout/context.svelte.ts +7 -0
  99. package/components/Callout/context.vue.ts +4 -0
  100. package/components/Callout/icons.ts +23 -0
  101. package/components/Callout/types.astro.ts +5 -0
  102. package/components/Callout/types.react.ts +9 -0
  103. package/components/Callout/types.svelte.ts +5 -3
  104. package/components/Callout/types.ts +5 -5
  105. package/components/Callout/types.vue-props.ts +14 -0
  106. package/components/Card/Card.astro +9 -25
  107. package/components/Card/Card.react.tsx +15 -0
  108. package/components/Card/Card.svelte +23 -0
  109. package/components/Card/Card.vue +10 -20
  110. package/components/Card/CardActions.astro +16 -0
  111. package/components/Card/CardActions.react.tsx +15 -0
  112. package/components/Card/CardActions.svelte +23 -0
  113. package/components/Card/CardActions.vue +18 -0
  114. package/components/Card/CardContent.astro +9 -0
  115. package/components/Card/CardContent.react.tsx +6 -0
  116. package/components/Card/CardContent.svelte +15 -0
  117. package/components/Card/CardContent.vue +12 -0
  118. package/components/Card/CardHeader.astro +9 -0
  119. package/components/Card/CardHeader.react.tsx +6 -0
  120. package/components/Card/CardHeader.svelte +15 -0
  121. package/components/Card/CardHeader.vue +12 -0
  122. package/components/Card/types.astro.ts +6 -0
  123. package/components/Card/types.react.ts +10 -0
  124. package/components/Card/types.svelte.ts +7 -3
  125. package/components/Card/types.ts +7 -7
  126. package/components/Card/types.vue-props.ts +17 -0
  127. package/components/Carousel/Carousel.astro +44 -0
  128. package/components/Carousel/Carousel.react.tsx +47 -0
  129. package/components/Carousel/Carousel.svelte +45 -0
  130. package/components/Carousel/Carousel.vue +44 -0
  131. package/components/Carousel/types.astro.ts +4 -0
  132. package/components/Carousel/types.react.ts +4 -0
  133. package/components/Carousel/types.svelte.ts +4 -0
  134. package/components/Carousel/types.ts +11 -0
  135. package/components/Carousel/types.vue-props.ts +6 -0
  136. package/components/Checkbox/Checkbox.astro +27 -15
  137. package/components/Checkbox/Checkbox.react.tsx +51 -0
  138. package/components/Checkbox/Checkbox.svelte +61 -0
  139. package/components/Checkbox/Checkbox.vue +39 -18
  140. package/components/Checkbox/CheckboxInput.astro +6 -2
  141. package/components/Checkbox/CheckboxInput.react.tsx +39 -0
  142. package/components/Checkbox/CheckboxInput.svelte +34 -0
  143. package/components/Checkbox/CheckboxInput.vue +29 -11
  144. package/components/Checkbox/types.astro.ts +2 -3
  145. package/components/Checkbox/types.react.ts +11 -0
  146. package/components/Checkbox/types.svelte.ts +8 -4
  147. package/components/Checkbox/types.ts +8 -4
  148. package/components/Checkbox/types.vue-props.ts +15 -0
  149. package/components/Chip/Chip.astro +22 -6
  150. package/components/Chip/Chip.react.tsx +45 -0
  151. package/components/Chip/Chip.svelte +45 -0
  152. package/components/Chip/Chip.vue +16 -9
  153. package/components/Chip/types.astro.ts +1 -1
  154. package/components/Chip/types.react.ts +15 -0
  155. package/components/Chip/types.svelte.ts +6 -4
  156. package/components/Chip/types.ts +22 -5
  157. package/components/Chip/types.vue-props.ts +11 -0
  158. package/components/DescriptionList/DescriptionList.astro +6 -2
  159. package/components/DescriptionList/DescriptionList.react.tsx +25 -0
  160. package/components/DescriptionList/DescriptionList.svelte +29 -0
  161. package/components/DescriptionList/DescriptionList.vue +7 -8
  162. package/components/DescriptionList/DescriptionListDescription.astro +9 -0
  163. package/components/DescriptionList/DescriptionListDescription.react.tsx +9 -0
  164. package/components/DescriptionList/DescriptionListDescription.svelte +15 -0
  165. package/components/DescriptionList/DescriptionListDescription.vue +15 -0
  166. package/components/DescriptionList/DescriptionListItem.astro +9 -0
  167. package/components/DescriptionList/DescriptionListItem.react.tsx +6 -0
  168. package/components/DescriptionList/DescriptionListItem.svelte +15 -0
  169. package/components/DescriptionList/{Item.vue → DescriptionListItem.vue} +5 -2
  170. package/components/DescriptionList/DescriptionListTerm.astro +9 -0
  171. package/components/DescriptionList/DescriptionListTerm.react.tsx +6 -0
  172. package/components/DescriptionList/DescriptionListTerm.svelte +15 -0
  173. package/components/DescriptionList/{Term.vue → DescriptionListTerm.vue} +5 -2
  174. package/components/DescriptionList/types.astro.ts +3 -3
  175. package/components/DescriptionList/types.react.ts +10 -0
  176. package/components/DescriptionList/types.svelte.ts +6 -0
  177. package/components/DescriptionList/types.ts +3 -1
  178. package/components/DescriptionList/types.vue-props.ts +12 -0
  179. package/components/Dialog/Dialog.astro +12 -26
  180. package/components/Dialog/Dialog.react.tsx +23 -0
  181. package/components/Dialog/Dialog.svelte +33 -0
  182. package/components/Dialog/Dialog.vue +13 -23
  183. package/components/Dialog/DialogContent.astro +9 -0
  184. package/components/Dialog/DialogContent.react.tsx +6 -0
  185. package/components/Dialog/DialogContent.svelte +15 -0
  186. package/components/Dialog/DialogContent.vue +12 -0
  187. package/components/Dialog/DialogFooter.astro +16 -0
  188. package/components/Dialog/DialogFooter.react.tsx +15 -0
  189. package/components/Dialog/DialogFooter.svelte +23 -0
  190. package/components/Dialog/DialogFooter.vue +18 -0
  191. package/components/Dialog/DialogHeader.astro +9 -0
  192. package/components/Dialog/DialogHeader.react.tsx +6 -0
  193. package/components/Dialog/DialogHeader.svelte +15 -0
  194. package/components/Dialog/DialogHeader.vue +12 -0
  195. package/components/Dialog/DialogTitle.astro +14 -0
  196. package/components/Dialog/DialogTitle.react.tsx +13 -0
  197. package/components/Dialog/DialogTitle.svelte +23 -0
  198. package/components/Dialog/DialogTitle.vue +18 -0
  199. package/components/Dialog/context.astro.ts +4 -0
  200. package/components/Dialog/context.react.ts +8 -0
  201. package/components/Dialog/context.svelte.ts +7 -0
  202. package/components/Dialog/context.vue.ts +4 -0
  203. package/components/Dialog/types.astro.ts +8 -0
  204. package/components/Dialog/types.react.ts +12 -0
  205. package/components/Dialog/types.svelte.ts +11 -3
  206. package/components/Dialog/types.ts +13 -6
  207. package/components/Dialog/types.vue-props.ts +24 -0
  208. package/components/Divider/Divider.astro +29 -7
  209. package/components/Divider/Divider.react.tsx +36 -0
  210. package/components/Divider/Divider.svelte +40 -0
  211. package/components/Divider/Divider.vue +22 -4
  212. package/components/Divider/types.react.ts +4 -0
  213. package/components/Divider/types.ts +3 -1
  214. package/components/Divider/types.vue-props.ts +6 -0
  215. package/components/Drawer/Drawer.astro +13 -18
  216. package/components/Drawer/Drawer.react.tsx +40 -0
  217. package/components/Drawer/Drawer.svelte +50 -0
  218. package/components/Drawer/Drawer.vue +14 -19
  219. package/components/Drawer/DrawerContent.astro +9 -0
  220. package/components/Drawer/DrawerContent.react.tsx +6 -0
  221. package/components/Drawer/DrawerContent.svelte +15 -0
  222. package/components/Drawer/DrawerContent.vue +12 -0
  223. package/components/Drawer/DrawerFooter.astro +9 -4
  224. package/components/Drawer/DrawerFooter.react.tsx +15 -0
  225. package/components/Drawer/DrawerFooter.svelte +23 -0
  226. package/components/Drawer/DrawerFooter.vue +10 -8
  227. package/components/Drawer/DrawerHeader.astro +18 -10
  228. package/components/Drawer/DrawerHeader.react.tsx +41 -0
  229. package/components/Drawer/DrawerHeader.svelte +42 -0
  230. package/components/Drawer/DrawerHeader.vue +18 -19
  231. package/components/Drawer/DrawerTitle.astro +14 -0
  232. package/components/Drawer/DrawerTitle.react.tsx +13 -0
  233. package/components/Drawer/DrawerTitle.svelte +23 -0
  234. package/components/Drawer/DrawerTitle.vue +18 -0
  235. package/components/Drawer/context.astro.ts +4 -0
  236. package/components/Drawer/context.react.ts +8 -0
  237. package/components/Drawer/context.svelte.ts +7 -0
  238. package/components/Drawer/context.vue.ts +4 -0
  239. package/components/Drawer/icons.ts +2 -0
  240. package/components/Drawer/types.astro.ts +5 -1
  241. package/components/Drawer/types.react.ts +13 -0
  242. package/components/Drawer/types.svelte.ts +6 -5
  243. package/components/Drawer/types.ts +15 -10
  244. package/components/Drawer/types.vue-props.ts +24 -0
  245. package/components/FieldDescription/FieldDescription.astro +1 -1
  246. package/components/FieldDescription/FieldDescription.react.tsx +6 -0
  247. package/components/FieldDescription/FieldDescription.svelte +15 -0
  248. package/components/FieldDescription/FieldDescription.vue +3 -3
  249. package/components/FieldDescription/types.react.ts +4 -0
  250. package/components/FieldDescription/types.vue-props.ts +6 -0
  251. package/components/FieldGroup/FieldGroup.astro +15 -15
  252. package/components/FieldGroup/FieldGroup.react.tsx +27 -0
  253. package/components/FieldGroup/FieldGroup.svelte +32 -0
  254. package/components/FieldGroup/FieldGroup.vue +8 -10
  255. package/components/FieldGroup/context.astro.ts +4 -0
  256. package/components/FieldGroup/context.react.ts +8 -0
  257. package/components/FieldGroup/context.svelte.ts +8 -0
  258. package/components/FieldGroup/context.vue.ts +4 -0
  259. package/components/FieldGroup/types.react.ts +4 -0
  260. package/components/FieldGroup/types.ts +3 -1
  261. package/components/FieldGroup/types.vue-props.ts +6 -0
  262. package/components/FieldLegend/FieldLegend.react.tsx +14 -0
  263. package/components/FieldLegend/FieldLegend.svelte +20 -0
  264. package/components/FieldLegend/FieldLegend.vue +8 -6
  265. package/components/FieldLegend/types.react.ts +6 -0
  266. package/components/FieldLegend/types.svelte.ts +3 -3
  267. package/components/FieldLegend/types.vue-props.ts +9 -0
  268. package/components/{FieldSet/FieldSet.astro → Fieldset/Fieldset.astro} +6 -2
  269. package/components/Fieldset/Fieldset.react.tsx +15 -0
  270. package/components/Fieldset/Fieldset.svelte +21 -0
  271. package/components/Fieldset/Fieldset.vue +21 -0
  272. package/components/Fieldset/types.react.ts +6 -0
  273. package/components/Fieldset/types.svelte.ts +6 -0
  274. package/components/Fieldset/types.ts +1 -0
  275. package/components/Fieldset/types.vue-props.ts +9 -0
  276. package/components/Form/Form.react.tsx +9 -0
  277. package/components/Form/Form.svelte +16 -0
  278. package/components/Form/Form.vue +7 -5
  279. package/components/Form/types.react.ts +6 -0
  280. package/components/Form/types.svelte.ts +3 -4
  281. package/components/Form/types.vue-props.ts +9 -0
  282. package/components/List/List.astro +3 -3
  283. package/components/List/List.react.tsx +27 -0
  284. package/components/List/List.svelte +31 -0
  285. package/components/List/List.vue +4 -9
  286. package/components/List/types.react.ts +4 -0
  287. package/components/List/types.ts +2 -3
  288. package/components/List/types.vue-props.ts +6 -0
  289. package/components/ListItem/ListItem.astro +46 -39
  290. package/components/ListItem/ListItem.react.tsx +65 -0
  291. package/components/ListItem/ListItem.svelte +80 -0
  292. package/components/ListItem/ListItem.vue +41 -46
  293. package/components/ListItem/types.astro.ts +2 -3
  294. package/components/ListItem/types.react.ts +17 -0
  295. package/components/ListItem/types.svelte.ts +7 -4
  296. package/components/ListItem/types.ts +14 -11
  297. package/components/ListItem/types.vue-props.ts +14 -0
  298. package/components/Menu/Menu.astro +86 -0
  299. package/components/Menu/Menu.react.tsx +87 -0
  300. package/components/Menu/Menu.svelte +71 -0
  301. package/components/Menu/Menu.vue +76 -0
  302. package/components/Menu/context.astro.ts +4 -0
  303. package/components/Menu/context.react.ts +8 -0
  304. package/components/Menu/context.svelte.ts +7 -0
  305. package/components/Menu/context.vue.ts +4 -0
  306. package/components/Menu/types.astro.ts +12 -0
  307. package/components/Menu/types.react.ts +12 -0
  308. package/components/Menu/types.svelte.ts +12 -0
  309. package/components/Menu/types.ts +23 -0
  310. package/components/Menu/types.vue-props.ts +16 -0
  311. package/components/Progress/Progress.astro +10 -21
  312. package/components/Progress/Progress.react.tsx +27 -0
  313. package/components/Progress/Progress.svelte +30 -0
  314. package/components/Progress/Progress.vue +17 -21
  315. package/components/Progress/types.astro.ts +2 -1
  316. package/components/Progress/types.react.ts +5 -0
  317. package/components/Progress/types.svelte.ts +2 -1
  318. package/components/Progress/types.ts +1 -6
  319. package/components/Progress/types.vue-props.ts +6 -0
  320. package/components/Radio/Radio.astro +29 -15
  321. package/components/Radio/Radio.react.tsx +51 -0
  322. package/components/Radio/Radio.svelte +59 -0
  323. package/components/Radio/Radio.vue +37 -16
  324. package/components/Radio/RadioInput.astro +5 -2
  325. package/components/Radio/RadioInput.react.tsx +10 -0
  326. package/components/Radio/RadioInput.svelte +27 -0
  327. package/components/Radio/RadioInput.vue +28 -3
  328. package/components/Radio/types.astro.ts +2 -1
  329. package/components/Radio/types.react.ts +11 -0
  330. package/components/Radio/types.svelte.ts +9 -5
  331. package/components/Radio/types.ts +9 -4
  332. package/components/Radio/types.vue-props.ts +15 -0
  333. package/components/Range/Range.astro +49 -38
  334. package/components/Range/Range.react.tsx +157 -0
  335. package/components/Range/Range.svelte +136 -0
  336. package/components/Range/Range.vue +116 -32
  337. package/components/Range/types.astro.ts +1 -3
  338. package/components/Range/types.react.ts +10 -0
  339. package/components/Range/types.svelte.ts +8 -3
  340. package/components/Range/types.ts +13 -14
  341. package/components/Range/types.vue-props.ts +16 -0
  342. package/components/Range/value.ts +27 -0
  343. package/components/Select/Select.astro +70 -31
  344. package/components/Select/Select.react.tsx +124 -0
  345. package/components/Select/Select.svelte +123 -0
  346. package/components/Select/Select.vue +108 -36
  347. package/components/Select/selection.ts +11 -0
  348. package/components/Select/types.react.ts +6 -0
  349. package/components/Select/types.svelte.ts +1 -1
  350. package/components/Select/types.ts +16 -13
  351. package/components/Select/types.vue-props.ts +20 -0
  352. package/components/Switch/Switch.astro +22 -26
  353. package/components/Switch/Switch.react.tsx +63 -0
  354. package/components/Switch/Switch.svelte +73 -0
  355. package/components/Switch/Switch.vue +36 -18
  356. package/components/Switch/SwitchInput.astro +5 -2
  357. package/components/Switch/SwitchInput.react.tsx +12 -0
  358. package/components/Switch/SwitchInput.svelte +30 -0
  359. package/components/Switch/SwitchInput.vue +25 -3
  360. package/components/Switch/types.astro.ts +4 -2
  361. package/components/Switch/types.react.ts +11 -0
  362. package/components/Switch/types.svelte.ts +11 -4
  363. package/components/Switch/types.ts +9 -6
  364. package/components/Switch/types.vue-props.ts +17 -0
  365. package/components/Table/Table.astro +15 -2
  366. package/components/Table/Table.react.tsx +24 -0
  367. package/components/Table/Table.svelte +28 -0
  368. package/components/Table/Table.vue +9 -8
  369. package/components/Table/TableBody.astro +9 -0
  370. package/components/Table/TableBody.react.tsx +5 -0
  371. package/components/Table/TableBody.svelte +9 -0
  372. package/components/Table/TableBody.vue +12 -0
  373. package/components/Table/TableCaption.astro +9 -0
  374. package/components/Table/TableCaption.react.tsx +5 -0
  375. package/components/Table/TableCaption.svelte +9 -0
  376. package/components/Table/TableCaption.vue +12 -0
  377. package/components/Table/TableCell.astro +9 -0
  378. package/components/Table/TableCell.react.tsx +6 -0
  379. package/components/Table/TableCell.svelte +16 -0
  380. package/components/Table/TableCell.vue +12 -0
  381. package/components/Table/TableColumn.astro +8 -0
  382. package/components/Table/TableColumn.react.tsx +7 -0
  383. package/components/Table/TableColumn.svelte +8 -0
  384. package/components/Table/TableColumn.vue +12 -0
  385. package/components/Table/TableColumnGroup.astro +9 -0
  386. package/components/Table/TableColumnGroup.react.tsx +5 -0
  387. package/components/Table/TableColumnGroup.svelte +9 -0
  388. package/components/Table/TableColumnGroup.vue +12 -0
  389. package/components/Table/TableFoot.astro +9 -0
  390. package/components/Table/TableFoot.react.tsx +5 -0
  391. package/components/Table/TableFoot.svelte +9 -0
  392. package/components/Table/TableFoot.vue +12 -0
  393. package/components/Table/TableHead.astro +9 -0
  394. package/components/Table/TableHead.react.tsx +5 -0
  395. package/components/Table/TableHead.svelte +9 -0
  396. package/components/Table/TableHead.vue +12 -0
  397. package/components/Table/TableHeaderCell.astro +9 -0
  398. package/components/Table/TableHeaderCell.react.tsx +10 -0
  399. package/components/Table/TableHeaderCell.svelte +16 -0
  400. package/components/Table/TableHeaderCell.vue +12 -0
  401. package/components/Table/TableRow.astro +9 -0
  402. package/components/Table/TableRow.react.tsx +5 -0
  403. package/components/Table/TableRow.svelte +9 -0
  404. package/components/{DescriptionList/Description.vue → Table/TableRow.vue} +3 -3
  405. package/components/Table/types.astro.ts +17 -11
  406. package/components/Table/types.react.ts +22 -0
  407. package/components/Table/types.svelte.ts +19 -7
  408. package/components/Table/types.ts +8 -3
  409. package/components/Table/types.vue-props.ts +28 -0
  410. package/components/Tabs/Tabs.astro +23 -13
  411. package/components/Tabs/Tabs.react.tsx +43 -0
  412. package/components/Tabs/Tabs.svelte +43 -0
  413. package/components/Tabs/Tabs.vue +19 -9
  414. package/components/Tabs/TabsItem.astro +16 -28
  415. package/components/Tabs/TabsItem.react.tsx +47 -0
  416. package/components/Tabs/TabsItem.svelte +52 -0
  417. package/components/Tabs/TabsItem.vue +23 -21
  418. package/components/Tabs/TabsLabel.astro +16 -0
  419. package/components/Tabs/TabsLabel.react.tsx +17 -0
  420. package/components/Tabs/TabsLabel.svelte +19 -0
  421. package/components/Tabs/TabsLabel.vue +16 -0
  422. package/components/Tabs/TabsPanel.astro +2 -9
  423. package/components/Tabs/TabsPanel.react.tsx +6 -0
  424. package/components/Tabs/TabsPanel.svelte +15 -0
  425. package/components/Tabs/TabsPanel.vue +3 -22
  426. package/components/Tabs/context.astro.ts +4 -0
  427. package/components/Tabs/context.react.ts +8 -0
  428. package/components/Tabs/context.svelte.ts +7 -0
  429. package/components/Tabs/context.vue.ts +4 -0
  430. package/components/Tabs/types.astro.ts +5 -3
  431. package/components/Tabs/types.react.ts +12 -0
  432. package/components/Tabs/types.svelte.ts +6 -6
  433. package/components/Tabs/types.ts +10 -8
  434. package/components/Tabs/types.vue-props.ts +25 -0
  435. package/components/TextField/TextField.astro +36 -52
  436. package/components/TextField/TextField.react.tsx +70 -0
  437. package/components/TextField/TextField.svelte +84 -0
  438. package/components/TextField/TextField.vue +59 -39
  439. package/components/TextField/types.astro.ts +1 -3
  440. package/components/TextField/types.react.ts +12 -0
  441. package/components/TextField/types.svelte.ts +2 -4
  442. package/components/TextField/types.ts +11 -25
  443. package/components/TextField/types.vue-props.ts +21 -0
  444. package/components/Textarea/Textarea.astro +34 -48
  445. package/components/Textarea/Textarea.react.tsx +64 -0
  446. package/components/Textarea/Textarea.svelte +80 -0
  447. package/components/Textarea/Textarea.vue +55 -31
  448. package/components/Textarea/types.astro.ts +1 -3
  449. package/components/Textarea/types.react.ts +8 -0
  450. package/components/Textarea/types.svelte.ts +1 -9
  451. package/components/Textarea/types.ts +10 -22
  452. package/components/Textarea/types.vue-props.ts +20 -0
  453. package/components/ToggleButton/ToggleButton.astro +14 -14
  454. package/components/ToggleButton/ToggleButton.react.tsx +57 -0
  455. package/components/ToggleButton/ToggleButton.svelte +58 -0
  456. package/components/ToggleButton/ToggleButton.vue +41 -17
  457. package/components/ToggleButton/types.react.ts +4 -0
  458. package/components/ToggleButton/types.svelte.ts +0 -2
  459. package/components/ToggleButton/types.ts +2 -6
  460. package/components/ToggleButton/types.vue-props.ts +11 -0
  461. package/components/ToggleGroup/ToggleGroup.astro +16 -18
  462. package/components/ToggleGroup/ToggleGroup.react.tsx +54 -0
  463. package/components/ToggleGroup/ToggleGroup.svelte +54 -0
  464. package/components/ToggleGroup/ToggleGroup.vue +29 -20
  465. package/components/ToggleGroup/context.astro.ts +5 -0
  466. package/components/ToggleGroup/context.react.ts +8 -0
  467. package/components/ToggleGroup/context.svelte.ts +8 -0
  468. package/components/ToggleGroup/context.vue.ts +4 -0
  469. package/components/ToggleGroup/selection.ts +12 -0
  470. package/components/ToggleGroup/types.react.ts +12 -0
  471. package/components/ToggleGroup/types.svelte.ts +1 -4
  472. package/components/ToggleGroup/types.ts +11 -9
  473. package/components/ToggleGroup/types.vue-props.ts +6 -0
  474. package/components/Tooltip/Tooltip.astro +6 -7
  475. package/components/Tooltip/Tooltip.react.tsx +24 -0
  476. package/components/Tooltip/Tooltip.svelte +29 -0
  477. package/components/Tooltip/Tooltip.vue +7 -8
  478. package/components/Tooltip/types.react.ts +4 -0
  479. package/components/Tooltip/types.svelte.ts +1 -4
  480. package/components/Tooltip/types.ts +2 -8
  481. package/components/Tooltip/types.vue-props.ts +6 -0
  482. package/components/content.svelte +9 -0
  483. package/components/context.astro.ts +15 -0
  484. package/components/cx.ts +12 -0
  485. package/components/dev.ts +63 -0
  486. package/components/group.ts +2 -0
  487. package/components/id.ts +9 -0
  488. package/components/style.ts +33 -0
  489. package/components/tag.ts +6 -0
  490. package/components/vue.ts +18 -0
  491. package/core/normalize.css +56 -79
  492. package/core/palette.css +99 -282
  493. package/core/utils.css +31 -44
  494. package/css/compat/avatar.css +7 -0
  495. package/css/compat/menu.css +20 -0
  496. package/css/compat.css +3 -0
  497. package/css/components/accordion.css +123 -59
  498. package/css/components/anchor.css +21 -8
  499. package/css/components/avatar.css +57 -17
  500. package/css/components/badge.css +84 -45
  501. package/css/components/button-group.css +120 -129
  502. package/css/components/button.css +326 -116
  503. package/css/components/callout.css +88 -47
  504. package/css/components/card.css +181 -63
  505. package/css/components/carousel.css +399 -0
  506. package/css/components/checkbox.css +27 -148
  507. package/css/components/chip.css +175 -52
  508. package/css/components/choice.css +291 -0
  509. package/css/components/description-list.css +51 -41
  510. package/css/components/dialog.css +120 -30
  511. package/css/components/divider.css +62 -9
  512. package/css/components/drawer.css +181 -51
  513. package/css/components/form.css +51 -66
  514. package/css/components/layout.css +92 -0
  515. package/css/components/link.css +44 -12
  516. package/css/components/list.css +252 -135
  517. package/css/components/menu.css +174 -0
  518. package/css/components/progress.css +37 -29
  519. package/css/components/radio.css +32 -141
  520. package/css/components/range.css +244 -101
  521. package/css/components/select.css +84 -65
  522. package/css/components/spinner.css +31 -12
  523. package/css/components/switch.css +98 -171
  524. package/css/components/table.css +120 -79
  525. package/css/components/tabs.css +230 -36
  526. package/css/components/text-field.css +296 -186
  527. package/css/components/textarea.css +5 -11
  528. package/css/components/toggle-button.css +84 -44
  529. package/css/components/toggle-group.css +62 -32
  530. package/css/components/tooltip.css +87 -30
  531. package/css/components/typography.css +519 -298
  532. package/css/components.css +25 -18
  533. package/css/imports.css +2 -4
  534. package/css/js/checkbox.d.ts +3 -0
  535. package/css/js/checkbox.js +10 -0
  536. package/css/js/range.d.ts +1 -0
  537. package/css/js/range.js +44 -0
  538. package/css/layers.css +2 -0
  539. package/css/theme.css +729 -103
  540. package/dist/op.css +12 -237
  541. package/dist/op.css.map +1 -1
  542. package/dist/opui.baseline-2023.css +9209 -0
  543. package/dist/opui.baseline-2023.css.map +1 -0
  544. package/dist/opui.baseline-2024.css +9209 -0
  545. package/dist/opui.baseline-2024.css.map +1 -0
  546. package/dist/opui.baseline-2025.css +9209 -0
  547. package/dist/opui.baseline-2025.css.map +1 -0
  548. package/dist/opui.baseline-2026.css +9209 -0
  549. package/dist/opui.baseline-2026.css.map +1 -0
  550. package/dist/opui.components.css +5497 -3291
  551. package/dist/opui.components.css.map +1 -1
  552. package/dist/opui.css +6616 -4255
  553. package/dist/opui.css.map +1 -1
  554. package/dist/opui.no-compat.css +9182 -0
  555. package/dist/opui.no-compat.css.map +1 -0
  556. package/env.d.ts +10 -7
  557. package/open-props.css +10 -1
  558. package/package.json +63 -17
  559. package/react/elements.ts +13 -0
  560. package/react/index.ts +176 -0
  561. package/skills/opui/SKILL.md +75 -0
  562. package/skills/opui/references/accordion.md +253 -0
  563. package/skills/opui/references/anchor.md +213 -0
  564. package/skills/opui/references/avatar.md +202 -0
  565. package/skills/opui/references/badge.md +199 -0
  566. package/skills/opui/references/button-group.md +239 -0
  567. package/skills/opui/references/button.md +242 -0
  568. package/skills/opui/references/callout.md +221 -0
  569. package/skills/opui/references/card.md +222 -0
  570. package/skills/opui/references/carousel.md +269 -0
  571. package/skills/opui/references/checkbox.md +241 -0
  572. package/skills/opui/references/chip.md +135 -0
  573. package/skills/opui/references/customizing.md +85 -0
  574. package/skills/opui/references/description-list.md +191 -0
  575. package/skills/opui/references/dialog.md +301 -0
  576. package/skills/opui/references/divider.md +112 -0
  577. package/skills/opui/references/drawer.md +802 -0
  578. package/skills/opui/references/form.md +260 -0
  579. package/skills/opui/references/getting-started.md +398 -0
  580. package/skills/opui/references/index.md +89 -0
  581. package/skills/opui/references/layout.md +161 -0
  582. package/skills/opui/references/list.md +216 -0
  583. package/skills/opui/references/menu.md +248 -0
  584. package/skills/opui/references/progress.md +114 -0
  585. package/skills/opui/references/radio.md +234 -0
  586. package/skills/opui/references/range.md +150 -0
  587. package/skills/opui/references/select.md +255 -0
  588. package/skills/opui/references/spinner.md +85 -0
  589. package/skills/opui/references/switch.md +223 -0
  590. package/skills/opui/references/table.md +480 -0
  591. package/skills/opui/references/tabs.md +257 -0
  592. package/skills/opui/references/text-field.md +167 -0
  593. package/skills/opui/references/textarea.md +169 -0
  594. package/skills/opui/references/theming.md +278 -0
  595. package/skills/opui/references/toggle.md +222 -0
  596. package/skills/opui/references/tooltip.md +167 -0
  597. package/skills/opui/references/typography.md +159 -0
  598. package/svelte/elements.ts +7 -0
  599. package/svelte/index.ts +177 -0
  600. package/themes/bootstrap.css +223 -0
  601. package/themes/brutalist.css +105 -0
  602. package/themes/m3.css +152 -0
  603. package/themes/shadcn.css +125 -0
  604. package/tokens.json +3729 -0
  605. package/vue/index.ts +136 -15
  606. package/components/AGENTS.md +0 -247
  607. package/components/Accordion/types.d.vue.ts +0 -15
  608. package/components/Accordion/types.solid.ts +0 -6
  609. package/components/Anchor/types.d.vue.ts +0 -10
  610. package/components/Anchor/types.solid.ts +0 -6
  611. package/components/Avatar/types.d.vue.ts +0 -12
  612. package/components/Avatar/types.solid.ts +0 -11
  613. package/components/Badge/types.d.vue.ts +0 -10
  614. package/components/Badge/types.solid.ts +0 -4
  615. package/components/Button/types.d.vue.ts +0 -10
  616. package/components/Button/types.solid.ts +0 -8
  617. package/components/ButtonGroup/types.d.vue.ts +0 -10
  618. package/components/ButtonGroup/types.solid.ts +0 -4
  619. package/components/Callout/types.d.vue.ts +0 -10
  620. package/components/Callout/types.solid.ts +0 -6
  621. package/components/Card/types.d.vue.ts +0 -10
  622. package/components/Card/types.solid.ts +0 -6
  623. package/components/Checkbox/types.d.vue.ts +0 -11
  624. package/components/Checkbox/types.solid.ts +0 -9
  625. package/components/Chip/types.d.vue.ts +0 -10
  626. package/components/Chip/types.solid.ts +0 -10
  627. package/components/ClassicSelect/ClassicSelect.astro +0 -60
  628. package/components/ClassicSelect/ClassicSelect.vue +0 -54
  629. package/components/ClassicSelect/types.astro.ts +0 -8
  630. package/components/ClassicSelect/types.d.vue.ts +0 -10
  631. package/components/ClassicSelect/types.solid.ts +0 -5
  632. package/components/ClassicSelect/types.svelte.ts +0 -5
  633. package/components/ClassicSelect/types.ts +0 -15
  634. package/components/DescriptionList/Description.astro +0 -9
  635. package/components/DescriptionList/Item.astro +0 -9
  636. package/components/DescriptionList/Term.astro +0 -9
  637. package/components/DescriptionList/index.ts +0 -12
  638. package/components/DescriptionList/types.d.vue.ts +0 -10
  639. package/components/DescriptionList/types.solid.ts +0 -4
  640. package/components/Dialog/types.d.vue.ts +0 -10
  641. package/components/Dialog/types.solid.ts +0 -8
  642. package/components/Divider/types.d.vue.ts +0 -6
  643. package/components/Divider/types.solid.ts +0 -4
  644. package/components/Drawer/types.d.vue.ts +0 -31
  645. package/components/Drawer/types.solid.ts +0 -12
  646. package/components/FieldDescription/types.d.vue.ts +0 -10
  647. package/components/FieldDescription/types.solid.ts +0 -5
  648. package/components/FieldGroup/types.d.vue.ts +0 -12
  649. package/components/FieldGroup/types.solid.ts +0 -5
  650. package/components/FieldLegend/types.d.vue.ts +0 -11
  651. package/components/FieldLegend/types.solid.ts +0 -5
  652. package/components/FieldSet/FieldSet.vue +0 -18
  653. package/components/FieldSet/types.d.vue.ts +0 -11
  654. package/components/FieldSet/types.solid.ts +0 -5
  655. package/components/FieldSet/types.svelte.ts +0 -8
  656. package/components/FieldSet/types.ts +0 -5
  657. package/components/Form/types.d.vue.ts +0 -11
  658. package/components/Form/types.solid.ts +0 -5
  659. package/components/IconButton/IconButton.astro +0 -24
  660. package/components/IconButton/IconButton.vue +0 -24
  661. package/components/IconButton/types.astro.ts +0 -6
  662. package/components/IconButton/types.d.vue.ts +0 -10
  663. package/components/IconButton/types.solid.ts +0 -8
  664. package/components/IconButton/types.svelte.ts +0 -6
  665. package/components/IconButton/types.ts +0 -16
  666. package/components/List/types.d.vue.ts +0 -10
  667. package/components/List/types.solid.ts +0 -4
  668. package/components/ListItem/types.d.vue.ts +0 -10
  669. package/components/ListItem/types.solid.ts +0 -12
  670. package/components/Progress/types.d.vue.ts +0 -10
  671. package/components/Progress/types.solid.ts +0 -4
  672. package/components/Radio/types.d.vue.ts +0 -11
  673. package/components/Radio/types.solid.ts +0 -9
  674. package/components/Range/types.d.vue.ts +0 -14
  675. package/components/Range/types.solid.ts +0 -6
  676. package/components/Select/types.d.vue.ts +0 -17
  677. package/components/Select/types.solid.ts +0 -6
  678. package/components/Switch/types.d.vue.ts +0 -13
  679. package/components/Switch/types.solid.ts +0 -9
  680. package/components/Table/Body.astro +0 -11
  681. package/components/Table/Body.vue +0 -5
  682. package/components/Table/Cell.astro +0 -11
  683. package/components/Table/Cell.vue +0 -5
  684. package/components/Table/Column.astro +0 -12
  685. package/components/Table/Column.vue +0 -19
  686. package/components/Table/ColumnGroup.astro +0 -11
  687. package/components/Table/ColumnGroup.vue +0 -5
  688. package/components/Table/Head.astro +0 -11
  689. package/components/Table/Head.vue +0 -5
  690. package/components/Table/HeaderCell.astro +0 -11
  691. package/components/Table/HeaderCell.vue +0 -5
  692. package/components/Table/Row.astro +0 -11
  693. package/components/Table/Row.vue +0 -5
  694. package/components/Table/index.ts +0 -20
  695. package/components/Table/types.d.vue.ts +0 -10
  696. package/components/Table/types.solid.ts +0 -8
  697. package/components/Tabs/TabsTab.astro +0 -15
  698. package/components/Tabs/TabsTab.vue +0 -24
  699. package/components/Tabs/index.ts +0 -14
  700. package/components/Tabs/types.d.vue.ts +0 -31
  701. package/components/Tabs/types.solid.ts +0 -12
  702. package/components/TextField/types.d.vue.ts +0 -20
  703. package/components/TextField/types.solid.ts +0 -22
  704. package/components/Textarea/types.d.vue.ts +0 -19
  705. package/components/Textarea/types.solid.ts +0 -6
  706. package/components/Toast/Toast.astro +0 -42
  707. package/components/Toast/Toast.vue +0 -48
  708. package/components/ToggleButton/types.d.vue.ts +0 -10
  709. package/components/ToggleButton/types.solid.ts +0 -7
  710. package/components/ToggleGroup/types.d.vue.ts +0 -15
  711. package/components/ToggleGroup/types.solid.ts +0 -4
  712. package/components/Tooltip/types.d.vue.ts +0 -10
  713. package/components/Tooltip/types.solid.ts +0 -6
  714. package/css/components/icon-button.css +0 -139
  715. package/css/components/text-input.css +0 -68
  716. package/css/components/toast.css +0 -157
  717. package/css/js/toast.js +0 -94
  718. /package/components/{FieldSet → Fieldset}/types.astro.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,653 @@
1
1
  # Changelog
2
2
 
3
+ ## 6.0.0 - Unreleased
4
+
5
+ React and Svelte components, `Carousel`, `Menu`, `AvatarGroup`, the `Layout` classes, four example themes and `tokens.json`. Every theme token is prefixed `--ui-`, the scope classes derive every token again, more contrast works through knobs, and most component props are renamed to one naming model. Migration steps per component are in [MIGRATING.md](./MIGRATING.md).
6
+
7
+ ### Breaking
8
+
9
+ - `Accordion` markers are the `svg` with `.ui-marker`. Add `.ui-marker` to the chevron to keep it rotating. Other icons in the `summary` stay put.
10
+ - `Accordion` renders a chevron marker by default in Astro and Vue, hidden from screen readers with `aria-hidden="true"`. The `marker` slot on `AccordionSummary` replaces it, so move a custom chevron there and give it `.ui-marker`, or it shows twice. An empty `marker` slot shows the native arrow.
11
+ - `Accordion` and `Dialog` no longer render `.ui-card`, and `Badge` and `Tooltip` no longer render `.ui-anchor`. `card.css` and `anchor.css` style `.ui-accordion`, `.ui-dialog`, `.ui-badge` and `.ui-tooltip` themselves, so HTML takes one root class. CSS that reached these components through `.ui-card` or `.ui-anchor` needs their own class.
12
+ - `Accordion`, `Anchor`, `Avatar`, `Badge`, `Button`, `ButtonGroup`, `Callout`, `Card`, `Checkbox`, `Chip`, `Drawer`, `List`, `Progress`, `Radio`, `Range`, `Select`, `Switch`, `Table`, `TextField`, `Textarea`, `ToggleButton`, `ToggleGroup` and `Tooltip` private custom properties follow one scheme: `--_accent`, `--_text-color`, `--_bg-color`, `--_duration`/`--_ease`, `--_size` and `--_radius`. A color says what it paints (`-bg-color`, `-text-color`, `-border-color`), `--_size` is the one name for a control's size (`--_min-height`, `--_height` and `--_input-size` are gone), other sizes are logical (`--_track-block-size`, not `--_track-height`), and names aren't abbreviated (`--_shift-x`, not `--_anchor-tx`). MIGRATING lists every rename.
13
+ - `Accordion` in Astro and Vue takes parts instead of slots: `AccordionSummary`, `AccordionContent` and `AccordionActions`. The root no longer wraps its children in `.ui-content`, and the `marker` slot moves to `AccordionSummary`.
14
+ - `Accordion` `variant="default"` is gone. An accordion without a variant is `plain`, the page surface with padding and no border, like a `Card`, and a group card without a variant pads its accordions too. Use `variant="transparent"` (`.ui-transparent`) for the previous look, with no surface or padding.
15
+ - `Anchor` with `trigger="hover"` and `Tooltip` no longer wrap their trigger in a `<span interestfor>`. Add `interestfor` with the anchor's `id` to the trigger element. `trigger` only takes `"hover"`: leave it out instead of `trigger="always"`.
16
+ - `Anchor`, `Badge` and `Tooltip` floating content is `.ui-floating` instead of `.ui-anchor-floating`.
17
+ - `Anchor` and `Tooltip` `alignment` is `positionArea`, named after the CSS `position-area` value it takes, and `.ui-with-arrow` on a tooltip is `.ui-arrow`, like the `arrow` prop.
18
+ - `Anchor` in Astro and Vue takes `AnchorContent` instead of the `anchored` slot. Without it, no floating element renders.
19
+ - `Anchor` requires `id` with `trigger="hover"` and no longer generates one. Pass the same `id` to `interestfor` on the trigger.
20
+ - `Avatar` requires `alt` when `src` is set (types). `alt=""` is still allowed for decorative images.
21
+ - `Avatar` `variant` is `shape` (`"circle"`, `"rounded"`, `"squared"`, `"squircle"`), with `circle` as the default. The classes are unchanged.
22
+ - `Avatar`, `Button` and `Chip` types match the rendered element: a button `Avatar` or `Chip` needs `as="button"`, a link `Chip` needs `href`, `disabled` only goes with a button or a link, and `Button` takes link attributes only with `href` (types).
23
+ - `Avatar` no longer takes `isGroup`. Wrap avatars in `AvatarGroup`, which renders `div.ui-avatar-group` with `role="group"`.
24
+ - `Badge` `alignment` is `corner`, since it picks a corner of the child. The classes are unchanged.
25
+ - `Badge` `label` is a `string` (types). Pass a number as a string.
26
+ - `Badge` indicator is `.ui-indicator` instead of `.ui-badge-indicator`.
27
+ - `Button` no longer takes `.ui-icon-only`. A button whose only child is an `svg` is square, at every size and inside `ButtonGroup`, so remove the class.
28
+ - `Button` in Astro and Vue no longer adds `.ui-disabled` to a disabled `<button>`. It sets `disabled`, and `aria-disabled="true"` on links. Target `:disabled` or `[aria-disabled="true"]` instead of `.ui-disabled`.
29
+ - `Button` icon styles only apply to a direct child `svg` (`> svg`), sized with `--_icon-size`. An `svg` nested in another element is no longer sized. Padding scales with `--_padding-inline` (`1ex` x-small, `1.25ex` small, `1.5ex` default, `2.5ex` large; was `0.5ex`, `0.75ex`, `1.5ex` and `4ex`), and the icon side gets tighter padding when a direct child `svg` sits next to a wrapped label (`<span class="ui-text">`). Wrap the label when the button has an icon: text next to an `svg` without a wrapper renders as icon-only.
30
+ - `Button`, and `Chip` and `Avatar` with `as="button"`, render `type="button"` by default in Astro and Vue, so they no longer submit forms. Pass `type="submit"` for submit buttons.
31
+ - `Button` and `Chip` links with `disabled` (`aria-disabled="true"`) no longer render `href`, so they can't be focused or followed. `button.css` and `chip.css` no longer set `pointer-events: none` on disabled links, so remove `href` from them in HTML.
32
+ - `ButtonGroup` variants apply to the whole group. A variant class on a single button inside a group is no longer supported.
33
+ - `Callout` in Astro and Vue takes parts instead of slots: `CalloutIcon` renders the severity icon and `CalloutContent` the content. The root no longer renders an icon or wraps its children in `.ui-content`. The `title` slot and `headingLevel` are gone: write the title as a plain heading of any level first in `CalloutContent`. A custom icon is an `svg` placed first in `Callout`.
34
+ - `Card` `variant="text"` is `variant="transparent"` (`.ui-transparent` instead of `.ui-text`), so `.ui-text` only names the text part of a component. The default card is named `plain`.
35
+ - `Card` in Astro and Vue takes parts instead of slots: `CardHeader`, `CardContent` and `CardActions`. `actionsAlign` is `align` on `CardActions`.
36
+ - `Card` actions sit at the end, like in `Accordion` and the `Dialog` and `Drawer` footers. `CardActions` `align="start"` (`.ui-align-start`) lines them up with the content, and `.ui-align-end` no longer does anything on them.
37
+ - `Card` no longer has `--_shadow-light` and `--_shadow-dark`. Set `--ui-shadow-elevated` in your theme, one shadow for both schemes whose default color follows `--ui-shadow-color`, or `--_elevated-shadow` on the card.
38
+ - `Checkbox` and `Radio` internal variables are private (`--_` prefix): `--highlight-size` is `--_ripple-size`, `--thumb-scale` is `--_thumb-scale` and `--_input-size` is `--_size`, the name every sized control uses. `--isLTR` and `--isRTL` are removed, the halo centers itself in both directions. `--_ripple-size` and `--_size` are inputs to override; `--_thumb-scale` is set by the hover and active states.
39
+ - `Checkbox`, `Radio` and `Switch` take `orientation="vertical"` (`.ui-vertical`) instead of `stack` (`.ui-stack`) to put the label under the control, like the other components with a layout axis.
40
+ - `Checkbox`, `Progress`, `Radio`, `Range`, `Select`, `Switch` and `ToggleButton` in Astro and Vue put `style` on the root, like `class`, instead of the `<select>`, `<input>` or `<progress>`, so `--_` properties set through `style` apply.
41
+ - `Checkbox`, `Radio`, `Switch`, `Range`, `DescriptionList` and `Table` type files are named like the other components: `components/Checkbox/types*` export `Props` and `Slots` instead of `CheckboxProps` and `CheckboxSlots` (likewise `Radio`, `Switch` and `Range`), `DescriptionList` exports `DescriptionListTermProps`, `DescriptionListDescriptionProps` and `DescriptionListItemProps` instead of `TermProps`, `DescriptionProps` and `ItemProps`, and `Table` exports one type per part (`TableBodyProps`, `TableCellProps` and the rest) instead of `SectionProps`, and `TableColumnProps` instead of `ColumnProps`. Import the types from `opui-css/<framework>` instead.
42
+ - `Checkbox`, `Radio`, `Switch`, `CheckboxInput` and `SwitchInput` in Astro no longer type a `type` prop, and `Radio` no longer types the native `size` (types).
43
+ - `Chip`, `Drawer` and `Progress` in Astro and Vue no longer render the class of their default look: no `.ui-tonal` on a tonal `Chip` or `Progress`, and no `.ui-inline-start` on a `Drawer` that opens from the inline start. In HTML these classes add nothing and can go. CSS that targets them can use `.ui-chip:not(.ui-outlined)`, `.ui-progress:not(.ui-filled)` and `.ui-drawer:not(.ui-block-end, .ui-block-start, .ui-inline-end)` instead.
44
+ - `Chip` no longer has a default slot. Pass the text as `label`, or rich content in the `label` slot, which renders in `.ui-text` like the prop.
45
+ - `DescriptionList` in Vue exports `DescriptionListDescription` instead of `Description`, like Astro.
46
+ - `DescriptionList` `bordered` is a boolean in Astro and Vue, and `dotted` makes its line dotted: replace `bordered="dotted"` with `bordered dotted`. The classes are unchanged.
47
+ - `DescriptionList` items are plain `div`s: `DescriptionListItem` no longer renders `.ui-item`, and the list styles `dl.ui-description-list > div`.
48
+ - `Dialog` in Astro and Vue takes parts instead of slots: `DialogHeader`, `DialogTitle`, `DialogContent` and `DialogFooter`. `actionsAlign` is `align` on `DialogFooter`. `aria-labelledby` points at the `DialogTitle` unless you pass `aria-label` or `aria-labelledby`, so a dialog without a `DialogTitle` needs `aria-label`. An `id` on `DialogTitle` only applies when the dialog has `aria-label` or `aria-labelledby`, and a dev warning says when it is replaced. `align="start"` on `DialogFooter` adds `.ui-align-start`; `end` is the default and adds no class.
49
+ - `Dialog` regions are `.ui-header`, `.ui-content` and `.ui-footer`, like `Drawer`. The header is a `div.ui-header` row instead of an `hgroup`, and `aria-labelledby` points at the title heading inside it. `.ui-footer` replaces `.ui-actions` at the end of the dialog, and `.ui-align-end` on it is the default and can go. The title heading is `--ui-font-size-h4` through `--_title-font-size`, so it needs no `.ui-h4`.
50
+ - `Dialog` page scroll lock lives in `core/utils.css`, shared with the `Drawer` `.ui-scroll-lock`, and no longer sets `block-size: 100%` on `html`. If you import single files, import `utils.css` too, or the page scrolls behind a modal dialog.
51
+ - `Divider` variants render `.ui-filled` and `.ui-tonal` instead of `.ui-border-filled` and `.ui-border-tonal`, and `variant="primary"` is `color="primary"`, which renders `.ui-primary` instead of `.ui-border-primary`. A primary line keeps its color with any variant.
52
+ - `Drawer` in Astro and Vue takes parts instead of slots: `DrawerHeader`, `DrawerTitle`, `DrawerContent` and `DrawerFooter`. `DrawerTitle` replaces the `DrawerHeader` `heading` prop and names the drawer. The drawer no longer looks for a heading: without a `DrawerTitle`, pass `aria-label`. An `id` on `DrawerTitle` only applies when the drawer has `aria-label` or `aria-labelledby`, and a dev warning says when it is replaced. In Astro and Vue, `DrawerHeader` in a `Drawer` closes it with `command="close"` (Invoker Commands) instead of a click handler, so the Vue `DrawerHeader` closes the drawer without hydration, and browsers without Invoker Commands need a polyfill.
53
+ - `Drawer` in Astro and Vue no longer locks page scroll by default. Set `scrollLock` (`.ui-scroll-lock`) on drawers that should lock it.
54
+ - `Drawer` requires `id` (types) and no longer generates one, since its trigger points at it with `commandfor`.
55
+ - `Drawer` title is `--ui-font-size-h4`, like the `Dialog` title, instead of `--ui-font-size-large`, and `--_header-font-size` is `--_title-font-size`. It sizes a heading that is a direct child of `.ui-header`.
56
+ - `DrawerFooter` takes `align`, like `DialogFooter`. Its content sits at the end on every side, and `align="start"` (`.ui-align-start`) moves it to the start, instead of starting in an `inline-end` drawer.
57
+ - `FieldGroup` no longer sets `role="group"`. Wrap it in a `Fieldset` (a `<fieldset>`, already a group) to group and name the fields. `Fieldset` with another element in `as` gets `role="group"`.
58
+ - `FieldGroup` `direction` (`"row"`, `"column"`) is `orientation` (`"auto"`, `"horizontal"`, `"vertical"`), like `ButtonGroup`, `ToggleGroup` and `Carousel`, and `.ui-row` and `.ui-column` are `.ui-horizontal` and `.ui-vertical`. `auto`, the default, stacks fields and lines up a group of only buttons in a row.
59
+ - `Fieldset` (`.ui-fieldset`) no longer reads `data-invalid`. Its end text turns red when a control inside has `aria-invalid="true"` or is `:user-invalid`, so mark each control in the group (`error` on each `Checkbox`, `Radio` or `Switch` in Astro and Vue).
60
+ - `FieldSet` is `Fieldset` (`components/Fieldset/Fieldset.*`), and `FieldDescription` renders `.ui-description` instead of `.ui-field-description`.
61
+ - `List` no longer takes `divided`. Use `bordered` (`.ui-bordered`) ([#395](https://github.com/felix-bohlin/ui/issues/395)).
62
+ - `List` `gutterless` (`.ui-gutterless`) is `flush` (`.ui-flush`).
63
+ - `List` styles `.ui-start` and `.ui-end` only as direct children of a row, or of the `a`, `button` or `label` directly in it. One inside another wrapper no longer gets the row layout.
64
+ - `List`, `Range` and `Progress` no longer take `variant="default"` (`.ui-default`, the page surface), because it wasn't the default look. Use `outlined` (the default), `filled` or `tonal` on a `Range`, `tonal` (the default) or `filled` on a `Progress`, and `filled` (the default), `tonal` or `transparent` on a `List`.
65
+ - `List` no longer styles `[aria-selected="true"]` on a row's `li`, `a`, `button` or `label`, where ARIA doesn't allow it. Mark the current row with `aria-current="page"`. Options (`option` and `[role="option"]`) keep the selected style.
66
+ - `ListItem` `headline` is `label`, and the `text` slot is gone: `label` and `description` take a string or, as slots of the same name, rich content, rendered as the two paragraphs in `.ui-text`. The default slot adds more content after them.
67
+ - `ListItem` `as` only accepts `"a"` or `"button"` (types). A static item leaves `as` out and renders its content straight in the `<li>`.
68
+ - `ListItem` `type` can't be combined with `as` or `href` (types).
69
+ - `Range` in Astro and Vue no longer sets `--_track-fill` from script. The track fill is a scroll-driven animation in CSS.
70
+ - `Range` takes `items` instead of `options` for its tick marks (`RangeItem[]`). In Astro and Vue, the label goes in the `label` slot instead of the default slot, and the readout slot is `value-text` instead of `value`, the name React and Svelte use (`valueText`).
71
+ - `Range` in Astro types its extra attributes as `<input>` attributes only, since they go to the input (types).
72
+ - `Select` items are typed `SelectItem`, with a `number | string` `value`, and take `label` instead of `text`, like `Menu` and `Range` items. Rename imports of `Item` from `components/Select/types`.
73
+ - `Switch` takes `size="small"` instead of `small`, like `Checkbox`.
74
+ - `Table` `variant` is `density` (`"dense"`, `"normal"`, `"spacious"`), so `variant` only names a surface. The classes are unchanged.
75
+ - `Table` and `DescriptionList` part files are `components/Table/TableBody.*`, `TableCell.*`, `TableColumn.*`, `TableColumnGroup.*`, `TableHead.*`, `TableHeaderCell.*`, `TableRow.*` and `components/DescriptionList/DescriptionListDescription.*`, `DescriptionListItem.*`, `DescriptionListTerm.*`. The `opui-css/<framework>` exports are unchanged; update deep `./components/*` imports.
76
+ - `TableColumn` `width` takes a CSS length. A declaration string (`width="min-width: 10rem"`) is no longer parsed; pass `style` instead.
77
+ - `Tabs` look like segmented controls: the tabs sit on a rounded track and the selected tab is a raised pill. `--_accent-color` and `--_bg-color` are gone, use `--_selected-bg-color`, `--_selected-text-color`, `--_indicator-bg-color` and `--_track-bg-color`, or a `variant`. The selected pill is outlined with `--ui-control-border-color`, or `--ui-field-border-color`, so it reaches 3:1 against the track without the shadow. The open panel gets a `--ui-space-2` top margin. In dark mode the selected pill takes `--ui-state-hover-alpha-dark`.
78
+ - `Tabs` render no `tablist`, `tab` or `tabpanel` roles and no `aria-controls`/`aria-labelledby`, so screen readers announce the radio group they are. `TabsItem` and `TabsPanel` no longer take `panelId`, and `TabsPanel` no longer takes `tabId`. `tabs.css` no longer matches `[role="tab"]` or `[role="tabpanel"]`, use `.ui-label` and `.ui-panel`.
79
+ - `Tabs` parts are `.ui-input`, `.ui-label` and `.ui-panel` instead of `.ui-tab-input`, `.ui-tab-label` and `.ui-tab-panel`, and `TabsTab` is `TabsLabel` (`components/Tabs/TabsLabel.*`).
80
+ - `Tabs`, `Table` and `DescriptionList` in Astro no longer have dot aliases such as `Tabs.Item`, `Table.Head` and `DescriptionList.Item`. Import the flat names, such as `TabsItem`, `TableHead` and `DescriptionListItem`, like React, Svelte and Vue. The `components/{Tabs,Table,DescriptionList}/index.ts` files that held the aliases are gone.
81
+ - `TabsItem` `open` and `ToggleButton` `pressed` are `checked`, the native attribute they set.
82
+ - `TabsItem` takes `id` instead of `tabId`, and `TabsLabel` takes `for` (`htmlFor` in React) instead of `tabId`, the native names of the attributes they set. The item still generates the id and passes it to its label when both are omitted.
83
+ - `TextField`, `Textarea` and `Select` in Astro and Vue no longer generate an input `id`. Pass `id` when something outside the component needs to reference the input.
84
+ - `TextField` and `Textarea` take a `size` prop instead of `small`. Replace `small` with `size="small"`.
85
+ - `TextField` and `Textarea` in Astro pass extra attributes to the `<input>`/`<textarea>` instead of the `<label>`. `class` and `style` stay on the label. In Vue, `style` now goes to the label instead of the input.
86
+ - `TextField` and `Textarea` take `variant="filled"` like `Select` instead of the boolean `filled`. Replace `filled` with `variant="filled"`.
87
+ - `TextField`, `Textarea`, `Select`, `Switch`, `Checkbox`, `Radio` and `Range` are marked invalid with `aria-invalid="true"` on the control instead of `data-invalid` on the root. `error` in Astro and Vue sets only `aria-invalid`. Replace `data-invalid` on the root with `aria-invalid="true"` on the `<input>`, `<select>` or `<textarea>`.
88
+ - `TextField`, `Textarea` and `Select` take `startText` (the `start-text` slot) instead of `description`, matching `endText`, `Range` and the `.ui-start-text` class.
89
+ - `TextField`, `Textarea` and `Select` slots inside the field's border are `start` and `end` (`.ui-start`, `.ui-end`) instead of `prefix` and `suffix` (`.ui-prefix`, `.ui-suffix`), and `top` and `bottom` (`.ui-top`, `.ui-bottom`) instead of `header` and `footer` (`.ui-header`, `.ui-footer`), so `start` and `end` mean the inline sides in every component and the container regions keep their own names.
90
+ - `TextField` styles in `text-input.css` moved into `text-field.css`, and `text-input.css` is removed. Remove its import.
91
+ - `ToggleButton` in Astro and Vue no longer generates an input `id`. Pass `id` when something outside the component needs to reference the input.
92
+ - `ToggleButton` no longer supports `.ui-disabled`, and Astro and Vue no longer add it. Set `disabled` on the input, the toggle is styled through `:has(input:disabled)`.
93
+ - `ToggleButton` `value` no longer falls back to `label`. Pass `value` when the input needs one, such as in a form or a `ToggleGroup`.
94
+ - `ToggleButton` icon styles only apply to a direct child `svg`, sized with `--_icon-size`. An `svg` nested in another element is no longer sized.
95
+ - `ToggleGroup` `size="default"` is `size="medium"`, the name of its default look.
96
+ - `ToggleGroup` `selection` is `multiple`. A group is single-select by default, so add `multiple` to a group that left `selection` out or set `selection="multiple"`, and drop `selection="single"`.
97
+ - `Tooltip` requires an `id` (types). Without it the trigger can't reference the tooltip.
98
+ - `Tooltip` in Astro and Vue takes `TooltipContent` instead of `label` and the `content` slot.
99
+ - `Typography` rich text only styles headings without a class, like lists. Component parts such as the `Callout` title keep their own styles. Use the `.ui-h1`–`.ui-h6` classes to style a heading that has a class.
100
+ - `Typography` theme tokens: `--ui-font-size-h1` to `--ui-font-size-h4` grow from one type scale step to the next over one shared viewport window, `--ui-fluid-min-inline-size` (20rem) to `--ui-fluid-max-inline-size` (48rem), with `progress()`, instead of each over its own `vi` slope. `--ui-font-size-h3` has a higher minimum (`--ui-font-size-500`), `--ui-font-size-h4` scales between `--ui-font-size-400` and `--ui-font-size-500` instead of a fixed size, and `--ui-font-size-h6` is `--ui-font-size-300`, so heading sizes no longer invert or drop below body text on narrow viewports. Browsers without `progress()` keep the `clamp()` sizes.
101
+ - `Typography` rich text lives in a new `components.prose` layer, below `components.root`, so component styles inside rich text win over prose styles. The layer order is `openprops, theme, normalize, components.prose, components.root, components.extended, components.compat, utils`. If you declare the layer order yourself, add `components.prose` before `components.root`, or it sorts after `components.extended` and prose styles beat component styles inside rich text.
102
+ - `choice.css` holds the layout, label, end text, sizes and disabled styles shared by `Checkbox`, `Radio` and `Switch`, which moved out of `checkbox.css`, `radio.css` and `switch.css`. Import it with them, in any order, or use `components.css`.
103
+ - `normalize.css` no longer declares `--_page-bg-color`. The page background reads `--ui-surface`; set that, or `background-color` on `html`.
104
+ - `theme.css` and `core/palette.css` no longer make `del`, `ins`, `abbr`, `dfn`, `.ui-del`, `.ui-ins`, `.ui-abbr` and `.ui-dfn` severity scopes. `del` and `.ui-del` read `--ui-critical-text`, `ins` and `.ui-ins` read `--ui-success-text`, and the `abbr` and `dfn` underline reads `--ui-info`. Wrap content that read a `--ui-palette-*` role inside them in `.ui-critical`, `.ui-success` or `.ui-info`.
105
+ - `theme.css` `--ui-focus-ring-color` is black on light surfaces and white on dark ones, by the surface's OKLCH lightness, instead of `var(--ui-primary)`, and the global `:focus-visible` ring and the component rings read it, with `--ui-focus-ring-width`, `--ui-focus-ring-style` and `--ui-focus-ring-offset`. Set `--ui-focus-ring-color: var(--ui-primary)` to keep the old value.
106
+ - `theme.css` holds `--ui-motion` and its `prefers-reduced-motion` default, which moved from `core/normalize.css`. The `.ui-motion-*` classes moved to `core/utils.css`. If you import single files, import `theme.css` and `utils.css` too, or `--ui-motion` is undefined and the `.ui-motion-*` classes are missing.
107
+ - `theme.css` no longer sets `--ui-button-radius` and `--ui-field-radius`. `Button`, `ButtonGroup`, `ToggleButton`, `ToggleGroup` and the fields fall back to `--ui-radius` when they're unset, also where it's set on a part of the page, so one token sets the corners of every component. If your styles read them, add the fallback: `var(--ui-button-radius, var(--ui-radius))`.
108
+ - `theme.css`, `palette.css` and the components name every theme token with a `--ui-` prefix, like the classes: `--primary` is `--ui-primary`, `--border-color` is `--ui-border-color` and `--color-1` is `--ui-color-1`. Open Props tokens such as `--size-3` keep their names, and no component or theme token reads them any more. Add `ui-` to the tokens you set or read.
109
+ - `theme.css` `--font-size-05` is `--ui-font-size-small`. Rename it where you set or read it.
110
+ - `theme.css` tokens follow one naming model: `--ui-on-*` is the text and icon color on a fill, `-text` after a color is that color tuned for reading, and `light`, `dark`, `inverse` and `contrast` each mean one thing. Beyond the `--ui-` prefix, `--text-primary` is `--ui-text-strong`, `--primary-contrast` is `--ui-on-primary`, `--text-primary-contrast` is `--ui-on-inverse`, `--text-muted` is `--ui-text`, `--text-muted-contrast` is removed (`kbd` and `var` read `--ui-surface-inverse` and `--ui-on-inverse`), `--surface-default` is `--ui-surface`, `--border-radius` is `--ui-radius`, `--button-border-radius` is `--ui-button-radius` and `--field-border-radius` is `--ui-field-radius`. MIGRATING lists them.
111
+ - `theme.css` roles are what components read, so overriding a palette step (`--ui-gray-N`, `--ui-color-N`) or an Open Props value such as `--size-3` on a part of the page no longer changes the components there. Override the role instead, such as `--ui-surface`, `--ui-border-color` or `--ui-space-3`, or put `.ui-palette` on the part so the roles are derived again from its palette. A subtree that should follow its own knobs takes `.ui-palette`.
112
+ - `theme.css` keeps one palette hue, green (`145`), in both color schemes instead of switching to blue in dark mode. Set `--ui-palette-hue: 240` on `html.ui-dark` and under `prefers-color-scheme: dark` to keep the blue dark palette.
113
+ - `types.d.vue.ts` in every component folder is `types.vue-props.ts`, since TypeScript reads a `*.d.vue.ts` file as a declaration file and `skipLibCheck` skipped it. Update deep imports from `opui-css/components/<Name>/types.d.vue` to `types.vue-props`, or import the types from `opui-css/vue`.
114
+
115
+ ### Removed
116
+
117
+ - `Accordion`, `Anchor`, `Callout`, `Card`, `Dialog`, `Drawer` and `Tooltip` no longer export a `Slots` type from `types.ts`, and the Vue `Drawer` types no longer export `DrawerHeadingIdKey`, `DrawerSlots`, `DrawerHeaderSlots` or `DrawerFooterSlots`.
118
+ - `Chip` hover and press ripple. Remove any `--ripple` overrides.
119
+ - `ClassicSelect`. Use `Select`: it renders the same field, with the browser's own picker where customizable select isn't supported.
120
+ - `DescriptionList` `.ui-term` and `.ui-description`. The list styles `dt` and `dd` by element, and `DescriptionListTerm` and `DescriptionListDescription` render a plain `dt` and `dd`.
121
+ - `IconButton` (`.ui-icon-button`). Use `Button`: an icon-only button is square by default, `round` (`.ui-round`) makes it a circle. The hover halo is gone: icon-only buttons get the button's hover background. The old default size (28px) is `size="x-small"`. The old `small` (20px) has no preset: use `x-small` with `--_size: var(--size-4)`. Icons are smaller (`--_icon-size: var(--size-5)` matches the old 24px), and the icon color is the button's accent instead of the inherited text color.
122
+ - `Range` no longer wraps the scroll-driven track fill in `@supports (animation-timeline: view())`.
123
+ - `Range` thumbs no longer change their border inside a focused `.ui-fieldset-item`, a class no component renders.
124
+ - `Select` no longer hides `option::before`.
125
+ - `TextField` and `Textarea` no longer take `supportingText` or the `supporting-text` slot. Use `endText` (`end-text`).
126
+ - `TextField` no longer styles `::-webkit-file-upload-button`, only `::file-selector-button`.
127
+ - `Toast`. The Astro and Vue components, `toast.css` with `.ui-toast` and its parts (`.ui-close-button`, `.ui-exiting`, `.ui-icon`, `.ui-title`), `css/js/toast.js` with `initToastManager()` and `showToast()`, and their types are gone.
128
+ - `ToggleGroup` no longer exports the unused `ToggleContext` type.
129
+ - `normalize.css` no longer includes `::-webkit-file-upload-button`, `:-webkit-autofill` and `::-moz-placeholder`.
130
+ - `normalize.css` no longer falls back to `--text-color-2` when `--ui-text` is unset.
131
+ - `normalize.css` no longer sets `text-rendering: optimizeLegibility` on `body`.
132
+ - `open-props.css` no longer imports Open Props' `props.palette.css`, so `opui-css/open-props` (`dist/op.css`) no longer declares `--palette-hue`, `--palette-chroma`, `--palette-hue-rotate-by` or `--color-1` to `--color-16`. `core/palette.css` declares them as `--ui-palette-*` and `--ui-color-1` to `--ui-color-16`.
133
+ - `palette.css` no longer registers the palette variables (`--color-*`, `--gray-*`, `--palette-source` and `--palette-hue`) with `@property`.
134
+ - `theme.css` `--primary-dark` and `--primary-light`. Derive a shade from `--ui-primary` with relative color instead, such as `oklch(from var(--ui-primary) calc(l * 0.75) c h)`.
135
+ - `types.solid.ts` from every component folder. There are no Solid components.
136
+
137
+ ### Added
138
+
139
+ - `Accordion` takes a `markerAnimation` prop (`rotate`, `flip`, `turn`) that sets how the marker animates when it opens. Defaults to `rotate`, which needs no class; `.ui-marker-animation-flip` mirrors the chevron and `.ui-marker-animation-turn` points it to the inline end when closed and down when open, also in right-to-left.
140
+ - `Accordion`, `Avatar`, `Button`, `ButtonGroup`, `Card`, `Checkbox`, `Chip`, `Divider`, `List`, `Progress`, `Radio`, `Range`, `Select`, `Switch`, `Tabs`, `TextField`, `Textarea`, `ToggleButton` and `ToggleGroup` accept their default by name, which adds no class: `size="medium"` on every sized component, `variant="plain"` on `Accordion` and `Card`, `"transparent"` on `Button` and `ButtonGroup`, `"outlined"` on `Divider` and `Range`, `"filled"` on `List`, and `"tonal"` on `Progress` and `Tabs`. In HTML, a `Drawer` opens from the inline start without `.ui-inline-start`.
141
+ - `Accordion`, `Callout`, `Card`, `Dialog`, `Drawer`, `Menu` and the `Select` picker read the optional `--ui-border-color-raised` for the edge of a raised surface: tonal and elevated cards, accordions and dialogs, callouts without a severity, drawers, menus and the picker. A theme sets it once to outline them all, or to `transparent` to drop the edges. `Drawer` takes `--_edge-border-color` for its edge alone.
142
+ - `AccordionActions` takes `align` (`.ui-align-start`), like `CardActions`, `DialogFooter` and `DrawerFooter`.
143
+ - `Anchor` with `trigger="hover"`, `Drawer`, `Menu` and `Tooltip` warn in development when `id` is missing, since their trigger reaches them through `commandfor` or `interestfor` and a `Drawer` names itself after it.
144
+ - `Avatar` and `ListItem` links take `disabled`, like `Button` and `Chip`: the link drops its `href` and gets `aria-disabled="true"`.
145
+ - `Avatar` takes a `size` prop (`.ui-x-small`, `.ui-small`, `.ui-large`) that matches the control sizes. Letters and icons scale with it, and large initials are `--ui-font-size-large`.
146
+ - `AvatarGroup` component (`div.ui-avatar-group[role="group"]`) in Astro, React, Svelte and Vue. It takes `class`, attributes such as `aria-label`, and avatars as children, and raises a focused avatar so the next one doesn't cover its focus ring.
147
+ - `Badge` `corner` takes `"start-end"`, the default corner.
148
+ - `Badge` takes `hideLabel`, which renders `label` as visually hidden text (`.ui-sr-only`) inside the indicator, and hides the `indicator` slot from assistive technology. Pass the whole translated text as `label` ("5 unread messages") and the short visible form in the `indicator` slot ("5"), so the component never joins a number and words. A `dot` badge hides its `label` the same way.
149
+ - `Badge`, `Button`, `Card`, `Carousel`, `Checkbox`, `Dialog`, `Progress`, `Radio`, `Range`, `Table`, `Tabs`, `TextField`, `Textarea`, `ToggleButton` and `Tooltip` transitions read `--_duration` and `--_ease`, like `Accordion`, `Drawer`, `Menu`, `Select` and `Switch`. The `Carousel` button scale reads `--_scale-duration`, and the `Range` and `Tabs` focus rings `--_focus-ring-duration`.
150
+ - `Button` takes a `round` prop (`.ui-round`). Icon size is set with `--_icon-size`.
151
+ - `Button` links with `aria-disabled="true"` look disabled and get no hover or press styles.
152
+ - `Button` types require `aria-label`, `aria-labelledby` or `children` in React and Svelte, so a button always has a name (types only).
153
+ - `Button` reads optional theme tokens: `--ui-button-accent` and `--ui-button-on-accent` for the color of buttons and button groups without `.ui-primary` or `.ui-critical`, `--ui-control-border-color` for the border of outlined buttons and the edge and dividers of outlined button groups, `--ui-control-border-color-filled` for filled and tonal ones, `--ui-button-font-weight`, and `--ui-button-hover-shadow` and `--ui-button-hover-translate` for the shadow and offset on hover. In dark mode their text keeps the accent's lightness at `--ui-text-min-lightness` or more and its chroma within `--ui-text-max-chroma`, like the intent `-text` roles. `--ui-font-size-control` sets the font size of the default `Button`, `Select`, `Tabs`, `TextField`, `Textarea` and `ToggleButton`.
154
+ - `Button`, `ButtonGroup`, `Callout`, `.ui-link` and rich text links read `--ui-primary-text` for primary text. It defaults to `--ui-primary` with its lightness kept within `--ui-text-max-lightness` and `--ui-text-min-lightness`, so it keeps 4.5:1 on every surface and every primary text is one color, and themes whose primary is too light or too dark to read set it.
155
+ - `Button` and `ButtonGroup` with `.ui-primary` and `.ui-tonal` read the optional `--ui-primary-tonal` and `--ui-on-primary-tonal`. When unset, they keep the palette tint. m3 sets Material's `primary-container`, shadcn its `secondary`.
156
+ - `ButtonGroup` and `ToggleGroup` take `overflow`: `"wrap"`, the default, wraps their items onto more rows, `"scroll"` (`.ui-overflow-scroll`) keeps them on one row and scrolls sideways, and `"shrink"` (`.ui-overflow-shrink`) keeps them on one row and truncates labels with an ellipsis.
157
+ - `ButtonGroup` and `ToggleGroup` `orientation` takes `"horizontal"`, the default, like `Carousel`.
158
+ - `CalloutIcon` renders a check icon for `severity="success"`, like `info`, `warning` and `critical`.
159
+ - `Card` takes `.ui-card-link` on a link to make the whole card clickable. Other links and buttons in the card stay clickable.
160
+ - `CardHeader` renders `hgroup.ui-header`, the header region class `Dialog` and `Drawer` use, and `card.css` styles `.ui-header` like the `hgroup`.
161
+ - `Carousel` takes an `aspectRatio` prop that crops media, like `--_media-aspect-ratio`.
162
+ - `Carousel` component (`ul.ui-carousel`). Scroll snap, with previous/next buttons (`::scroll-button()`) and markers (`markers`, `.ui-markers`, with `::scroll-marker`) generated by CSS. Buttons use inverted colors with a gray border derived from the button color so they contrast with any item, show an SVG chevron that follows the color scheme, and sit over the items without a class, beside them (`buttons="outside"`, `.ui-buttons-outside`) or nowhere (`buttons="none"`, `.ui-buttons-none`). Images, videos and iframes fill the item with a configurable aspect ratio. Supports items per view (`itemsPerView`, `--_items-per-view`), peek (`peek`, `.ui-peek`), center alignment (`align="center"`, `.ui-align-center`), RTL, and custom properties for every size, color, icon and label. No JavaScript needed, with Astro, React, Svelte and Vue components, and it falls back to a snapping scroller. The buttons take `--ui-shadow-overlay`, markers are 24px targets around an 8px ring in `--ui-text`, which keeps its contrast in every theme, and the current marker is a 16px dot in `--ui-selected-strong`, and motion, smooth scrolling included, follows `--ui-motion` like the other components.
163
+ - `Carousel` buttons take an image icon via `--_button-image`, sized with `--_button-image-size`. It defaults to a chevron that points right, drawn as the inverse of the button face so it follows `.ui-dark`, `.ui-light` and forced colors, mirrored for the previous button and in RTL, and rotated in vertical carousels.
164
+ - `Carousel` takes a `persistentButtons` prop (`.ui-persistent-buttons`) that keeps both buttons visible. A disabled button keeps its fill and gets a more muted border (`--_button-disabled-border-color`).
165
+ - `Carousel` takes `orientation="vertical"` (`.ui-vertical`) to scroll on the block axis. Set its height with `--_block-size`. Markers sit in a column beside the items.
166
+ - `Carousel` takes `stretch` (`.ui-stretch`), which stretches each item's content, such as a card, to the item's height.
167
+ - `Checkbox`, `Radio` and `Switch` take `card` (`.ui-card`), which renders the control as a card styled by `card.css`: outlined by default, tinted when hovered and when checked, with the focus ring on the card. `variant` (`outlined`, `tonal` or `elevated`) changes the surface. Cards in a horizontal `FieldGroup` share the row equally. `--_card-padding`, `--_checked-bg-color` and `--_hover-bg-color` are the knobs. With more contrast, the checked fill drops to `--ui-state-hover-alpha-accent`, like selected `List` rows, so the label and end text keep 7:1 in dark mode.
168
+ - `Checkbox`, `Radio` and `Switch` take a `label` string, a shorthand for the default slot.
169
+ - `Checkbox` and `Radio` take `size="x-small"` (`.ui-x-small`), 14px from the new `--ui-choice-size-x-small` token.
170
+ - `Checkbox`, `Radio` and `Switch` take an `endText` string in Astro and Vue, like `TextField`.
171
+ - `Checkbox`, `Radio`, `Switch` and `Range` read the optional `--ui-choice-accent` and `--ui-choice-on-accent` for their checked fill, thumb and mark. When unset, they keep `--ui-primary` with the dark mode lightness cap. m3 and shadcn set them to the plain primary. A checked invalid `Checkbox` or `Radio` draws its check, dash or dot in `--ui-on-fill`, so it keeps its contrast on the red fill when a theme sets `--ui-choice-on-accent`.
172
+ - `Checkbox`, `Radio` and `Switch` read the optional `--ui-choice-border-color` for their unchecked border and track edge. When unset, they keep `--ui-field-border-color`, and the token promises 3:1 against `--ui-surface`. shadcn sets it to its primary, like shadcn/ui, so its faint field border no longer draws the choices.
173
+ - `CheckboxInput`, `RadioInput` and `SwitchInput` take `class` in Vue, and the Vue entry exports `DescriptionListDescriptionProps`, `DescriptionListItemProps` and `DescriptionListTermProps`.
174
+ - `Chip` supports `aria-disabled="true"` on a link chip. A static chip takes `.ui-disabled` for an inactive look, since a `div` can't carry a disabled state.
175
+ - `Chip` takes a `large` size (`.ui-large`, 40px) for chips next to default-size fields and buttons. Chip heights come from `--ui-chip-size-small`, `--ui-chip-size` and `--ui-chip-size-large`, which follow the control size scale.
176
+ - `Chip` takes `size="x-small"` (`.ui-x-small`), 24px tall from the new `--ui-chip-size-x-small` token.
177
+ - `Chip` takes a `severity` prop (`.ui-critical`, `.ui-info`, `.ui-neutral`, `.ui-success`, `.ui-warning`) that tints a tonal chip, and `dot` (`.ui-dot`) for a leading dot in that color. The dot is a diamond for critical, a triangle for warning and a ring for neutral, and stays visible in forced colors mode. On an outlined chip only the dot is colored. The tint, border, text and dot read the `--ui-palette-*` roles, like `Callout`.
178
+ - `Chip` takes a `disabled` prop in Astro, React, Svelte and Vue. A button chip gets `disabled`, a link chip `aria-disabled="true"`.
179
+ - `Chip` styles a button chip with `aria-pressed="true"` as pressed, for filters and choices: filled with `--ui-selected`, or `--ui-primary`, under `--ui-on-selected` text like a checked `ToggleButton`, darker on hover, dimmed with `--ui-disabled-opacity` when disabled and `SelectedItem` in forced colors. `--_pressed-bg-color` sets the fill.
180
+ - `DescriptionList` takes `orientation="horizontal"` (`.ui-horizontal`), which keeps the term and the description side by side at any width. The default, `auto`, stacks them when the list is `45ch` or narrower.
181
+ - `Dialog` and `Drawer` share their parts: a header row whose title (`DialogTitle`, `DrawerTitle`) takes the free space and names the overlay, a paragraph in the header gets a row of its own, the content draws its focus ring inside when it is focusable, and the footer (`DialogFooter`, `DrawerFooter`) is a row for buttons, text or anything else, with `align`. `.ui-actions` groups the buttons in a footer and moves them to the end when other content comes first.
182
+ - `Dialog` and `Drawer` show a subtle scroll shadow under the header and above the footer while the content scrolls (scroll-state container queries).
183
+ - `Dialog` types `closedby` in every framework.
184
+ - `Divider` reads a `--ui-divider-gap` theme token for the space around it. Cards, callouts, dialogs and drawers set it to `--ui-space-3`.
185
+ - `Divider` takes content in the middle of the line, text or any element, through the default slot (a `<div>` instead of the `<hr>`), or in HTML as a `<div class="ui-divider">` or `<p class="ui-divider">`. `align` (`.ui-align-start`, `.ui-align-end`) moves it to one side, and the lines follow the variant.
186
+ - `DrawerHeader` takes a `commandfor` prop (the drawer `id`). Inside a `Drawer` it defaults to the drawer's `id`, and the close button uses `command="close"` (Invoker Commands). Outside a `Drawer` without `commandfor`, it closes the nearest `<dialog>` with a script.
187
+ - `Layout` classes for the space between components: `.ui-layout-column` (a column), `.ui-layout-row` (a row that wraps, with `.ui-spread` to push its children to the two ends), `.ui-layout-grid` (columns that fill the width without breakpoints), `.ui-layout-media` (a fixed-size start, such as an avatar, next to text that fills the rest and truncates) and `.ui-layout-container` (a centered, capped width). On a `ul` or `ol`, the row and the grid drop the bullets and list margins, and a `.ui-card` alone in an `li` of a grid fills its cell. Gaps come from the `--ui-space-*` scale, with `.ui-x-small`, `.ui-small` and `.ui-large`. CSS only, in `css/components/layout.css`, in the `utils` layer.
188
+ - `List` takes `--_selected-indicator-bg-color`, `--_selected-indicator-size`, `--_start-image-size` and `--_start-video-size`, `Tooltip` takes `--_max-inline-size`, and `Carousel` takes `--_marker-selected-padding` and `--_marker-border-color`.
189
+ - `ListItem` takes a `submenu` slot, rendered inside the `<li>` after the element set by `as`, for a nested `Menu`.
190
+ - `ListItem` takes `color="critical"` (`li.ui-critical`) for a destructive item in a `Menu`.
191
+ - `Menu` component (`menu.ui-menu[popover]`), styled by `list.css` like a `List`. It requires an `id` for its trigger's `commandfor`, opens over `--ui-duration-slow` with `--ui-ease-enter` and closes with `--ui-ease-exit`. Opens with Invoker Commands, anchors to its trigger with no `anchor-name`, shrinks to the space on its side and flips when that side has less than `12rem`, and moves below or above its trigger when neither side fits. Browsers without `calc-size()` (Firefox and Safari) cap it at `60dvb`, flip it when it doesn't fit, and move it below or above its trigger, where it scrolls, when no side has room. Its placements use `self-` `position-area` keywords, so in a right-to-left part of a left-to-right page it opens from its trigger's right edge (not yet in Firefox, which places it toward the wrong side). Supports an `items` prop (items take native `a` and `button` attributes in every framework), `bordered` (`.ui-bordered`, a divider between items), custom `ListItem` content, placements, end alignment (`align="end"`, `.ui-align-end`), `--ui-anchor-position-area` and critical items. Items are built like `List` items, with the text in `.ui-text` and shortcuts in `.ui-end`. Items take a `label`, close the whole menu on click, also from a submenu, unless they set `keepOpen`. Group headings (`li.ui-heading`) are HTML and CSS only. Submenus go in the `submenu` slot of a `ListItem`. On iOS, submenus anchor to their parent menu instead of their trigger item, at every depth (`css/compat/menu.css`). When space is tight, the menu keeps at most 40% of the viewport height. Its border and dividers are `--ui-border-color-on-raised`, like other elevated surfaces.
192
+ - `Progress` has a `--_loop-duration` property for the length of its indeterminate loop.
193
+ - `Radio` takes a `spread` prop (`.ui-spread`), like `Checkbox` and `Switch`.
194
+ - `Range` takes an `error` prop (`aria-invalid="true"` on the input) for the invalid state, like the other fields.
195
+ - `Range` takes a `size` prop (`.ui-x-small`, `.ui-small`, `.ui-large`), like the other form controls. The thumb and the track scale with it.
196
+ - `Range` has a `--_track-base-bg-color` property for the empty track at rest. The pressed and disabled states override it.
197
+ - `Select` items take `selected`, and `value` preselects options in Astro, Svelte and Vue, and `defaultValue` or `value` in React (an array with `multiple`). Options render `selected` on the server.
198
+ - `Select` and `Range` export `SelectItem` and `RangeItem` from every framework barrel.
199
+ - `Select` takes `autoFit` (`.ui-auto-fit`), like `TextField`: the field's width follows the selected option, from `25ch`.
200
+ - `Select` styles `<optgroup>` groups like `<div role="group">` ones. A `<legend>` first in the group is the heading, and the `label` attribute names the group and shows in browsers without customizable select.
201
+ - `Switch` takes `size="x-small"` and `size="large"` (`.ui-x-small`, `.ui-large`), from the new `--ui-switch-thumb-size-*`, `--ui-switch-track-block-size-*` and `--ui-switch-track-inline-size-*` x-small and large tokens. The dot inset follows the track and dot size, so custom `--ui-switch-*` values stay centered.
202
+ - `Switch`, `Progress` and `Range` read the optional `--ui-track-bg-color` for the empty part of their track. When unset, they keep their current colors. shadcn sets it to its field border.
203
+ - `Table` takes `stickyHeader` (`.ui-sticky-header`), which keeps the header rows at the top of the nearest scroll container and shows a shadow once they are stuck (scroll-state container queries). Offset it with `--_sticky-offset`.
204
+ - `Table` has `TableCaption` and `TableFoot` parts for `<caption>` and `<tfoot>`.
205
+ - `Table` exports a props type for every part from `opui-css/astro`, `opui-css/react`, `opui-css/svelte` and `opui-css/vue`: `TableBodyProps`, `TableCaptionProps`, `TableCellProps`, `TableColumnGroupProps`, `TableFootProps`, `TableHeadProps`, `TableHeaderCellProps` and `TableRowProps`.
206
+ - `Table` takes `flush` (`.ui-flush`), which drops its block margin for a table in a card or another padded box, and `overflow="scroll"` (`.ui-overflow-scroll`), which keeps each cell on one line and scrolls the table sideways when the columns don't fit. The last column takes the space left over. A scrolling table needs `tabindex="0"`.
207
+ - `TableCell` and `TableHeaderCell` take `numeric` (`.ui-numeric`): the cell aligns to the end and uses tabular figures, so the digits of a number column line up.
208
+ - `Tabs` take a `variant` prop. `filled` (`.ui-filled`) fills the selected tab with `--ui-selected-strong`, the primary color unless a theme sets it, `line` (`.ui-line`) drops the track and marks the selected tab with a line, and `outlined` (`.ui-outlined`) uses a bordered track without a background.
209
+ - `Tabs` take `overflow="scroll"` (`.ui-overflow-scroll`). The tabs stay on one row and scroll sideways when they don't fit, and the open panel stays in view. Takes any number of tabs.
210
+ - `Tabs` take a bindable `value`: `bind:value` in Svelte, `v-model` in Vue, `value`, `defaultValue` and `onValueChange` in React, and in Astro the `value` of the tab to select on the server. A `TabsItem` with a `value` takes its checked state from it once the tabs have one, so a tab that loses its check to another one no longer drifts from the state. The item's own `checked` or `defaultChecked` is then ignored, and a dev warning says so.
211
+ - `TextField`, `Textarea`, `Select` and `Range` take `hideLabel`, which renders the label as `.ui-sr-only` instead of `.ui-label`, so the field keeps its accessible name without a visible label.
212
+ - `TextField`, `Textarea` and `Select` take `x-small` (`.ui-x-small`, 28px) and `large` (`.ui-large`, 48px) sizes, so every field size has a matching `Button` size. x-small fields set their text in `--ui-font-size-caption`, like x-small buttons, and keep `--ui-font-size-control` on touch screens. Their block padding follows `--ui-space-scale`, like the other sizes.
213
+ - `ToggleButton` and `ToggleGroup` take a `large` size (`.ui-large`), and `ButtonGroup` takes `x-small` (`.ui-x-small`).
214
+ - `ToggleButton`, `ToggleGroup`, outlined `Chip` and the outlined `Tabs` track read `--ui-control-border-color` for their border, like outlined buttons, so one token outlines every unfilled control. They keep their current border when a theme doesn't set it.
215
+ - `ToggleButton` when checked, `Chip` without `.ui-outlined` and the `Carousel` buttons read `--ui-control-border-color-filled` for their border, like filled buttons.
216
+ - `ToggleButton` when checked, the selected `ToggleGroup` item, and selected or current `List` items and `Select` options read the optional `--ui-selected` and `--ui-on-selected`. When unset, toggles are filled with `--ui-primary` and List items and Select options get a primary tint. m3 and shadcn set them to their tonal surface.
217
+ - `ToggleButton` in Vue binds a standalone button's checked state with `v-model`, like `bind:checked` in Svelte and `checked` with `onChange` in React. In a `ToggleGroup` the group's `v-model` still wins.
218
+ - `ToggleGroup` takes a bindable `value`: `bind:value` in Svelte, `v-model` in Vue, and `value`, `defaultValue` and `onValueChange` in React. It is a string, and an array of strings with `multiple`, in the types of every framework, and a `ToggleButton` in the group takes its checked state from it once the group has one. The button's own `checked` or `defaultChecked` is then ignored, and a dev warning says so.
219
+ - `Typography` reads a `--ui-rhythm-step` theme token (`0.25rem`). Heading font sizes snap to half a step and heading line heights to a full step with `round()`.
220
+ - `Typography` rich text styles `hr`, tables (which scroll sideways in a narrow column), `pre > samp` and preformatted text without `code`.
221
+ - `Typography` rich text task lists (an `li` that starts with a checkbox, or with a classless `label` around one) show the checkbox in place of the bullet.
222
+ - `Typography` `.ui-icon` sizes an `svg` to `--ui-icon-size` and keeps it from shrinking in a flex row, with `.ui-small` and `.ui-large` for `--ui-icon-size-small` and `--ui-icon-size-large`.
223
+ - `Typography` `.ui-swatch` is a small dot for a color legend. It takes a severity class (`.ui-info`) for its tone, or any color in `--_swatch-bg-color`, and defaults to the palette accent of the scope it sits in.
224
+ - `checkbox.js` exports `syncIndeterminate(input)`, which sets a checkbox's `indeterminate` property from its `data-indeterminate` attribute. The module ships type declarations.
225
+ - `compat.css` and the `components.compat` layer, after `components.extended`, hold the browser fallbacks that take more than the browser default, one file per component in `css/compat/`. Each one sits in `@supports`, so it only applies where a browser needs it. `imports.css`, `dist/opui.css` and `dist/opui.components.css` include them. `dist/opui.no-compat.css` leaves them out, and `dist/opui.baseline-<year>.css`, one per Baseline year from 2023, keeps only the ones for features that became Baseline after that year, plus the browser bug fixes, such as the iOS `Menu` submenu anchor.
226
+ - `layers.css` holds the `@layer` order, for importing single component files.
227
+ - `layers.css` declares the `theme.palette`, `theme.base`, `theme.custom` and `theme.severity` sublayers. `theme.custom` is empty, for your own tokens: it beats the defaults in `theme.base` and loses to every component and utility. `theme.severity` holds the palette source of `.ui-critical`, `.ui-info`, `.ui-neutral`, `.ui-success` and `.ui-warning`, so a theme that sets `--ui-palette-source` on `.ui-palette` or `.ui-contrast-more` (bootstrap, brutalist and m3 do) no longer gives a severity class on the same element the theme's colors.
228
+ - `opui-css` has a command: `npx opui-css skill` copies the agent skill into `.claude/skills/opui`, or into `<path>/opui` with `--dir <path>` for another agent's skills folder. It prints where it wrote and the package version, and refuses to replace an existing copy without `--force`.
229
+ - `opui-css/astro`, `opui-css/react`, `opui-css/svelte` and `opui-css/vue` export the component `Props` types (`ButtonProps`, `TabsLabelProps`, …), `MenuItem` and `SelectItem`.
230
+ - `opui-css/react` exports React 19 components for every Astro and Vue component. Containers take parts, such as `CardHeader` and `DialogFooter`. Other slots are props (`children`, and camelCased names such as `endText`), form controls (`ToggleButton` and `TabsItem` too) take the native `value`/`defaultValue`, `checked`/`defaultChecked` and `onChange` props, and components that need context, state or effects are marked `"use client"` so the rest also render as React Server Components. `react` and `react-dom` `^19` are optional peer dependencies.
231
+ - `opui-css/svelte` exports Svelte 5 components for every Astro and Vue component. Containers take parts, such as `CardHeader` and `DialogFooter`. Other slots are snippets (`children`, and camelCased names such as `endText`), `TextField`, `Textarea`, `Select`, `Range` and `ToggleGroup` support `bind:value`, `Checkbox` and `Switch` support `bind:checked` and `bind:group`, `ToggleButton` supports `bind:checked`, and `Radio` supports `bind:group`. `svelte` `^5.57` is an optional peer dependency.
232
+ - `package.json` has a `svelte` field and a `svelte` export condition on `opui-css/svelte` (`./svelte/index.ts`), which `@sveltejs/vite-plugin-svelte` reads to compile the package for SSR in SvelteKit and Vite instead of externalizing it.
233
+ - `range.js` (`opui-css/css/js/range.js`) exports `initRange()`, which keeps a `.ui-range` `<output class="ui-value" data-live>` in sync with its slider, after a form reset and across `astro:after-swap`. `Range.astro` calls it; HTML pages can import it instead of wiring the output themselves.
234
+ - `skills` references list each component's `--_` custom properties: the inputs to set, with their descriptions, and the outputs that states derive, like the Component properties tables on the docs pages.
235
+ - `skills/opui` is an agent skill shipped with the package. It has one reference per component page that covers every framework, generated from the API data: the parts and their selectors, the props with the class or attribute they render, their values and defaults, the slots, model and notes, the component properties and the theme tokens the stylesheets read, then a section per framework with its import line, slot syntax, hydration notes and the page's first example, and links to the full docs page per framework. Getting started has a section per framework, theming and customizing are written once, and an index maps every exported component and part to its reference.
236
+ - `theme.css` adds `--ui-icon-size-x-small` (`0.75rem`) and `--ui-radius-large` (`--ui-radius` times 1.5) to complete their families, and `--ui-shadow-color` under Elevation, the color and base opacity of every default shadow, a `light-dark()` pair of OKLCH colors.
237
+ - `theme.css` adds `--ui-choice-label-offset` to nudge `Checkbox`, `Radio` and `Switch` labels against their control for fonts with unusual metrics, and `--ui-invalid-text` for validation messages, darker in light mode and lighter in dark mode so it keeps its contrast on dark and tinted surfaces. The validation messages and invalid labels of `Checkbox`, `Radio`, `Switch`, `Range`, `TextField`, `Textarea` and `Select` read it.
238
+ - `theme.css` adds motion tokens: `--ui-duration-fast`, `--ui-duration`, `--ui-duration-slow`, `--ui-ease`, `--ui-ease-enter` and `--ui-ease-exit`. Every component transition and animation reads them, multiplied by `--ui-motion`.
239
+ - `theme.css` adds `--ui-focus-ring-inset` for focus rings drawn inside a control, read by `Accordion`, `ButtonGroup`, `List`, `Select`, `Tabs` and `ToggleButton`.
240
+ - `theme.css` adds icon tokens: `--ui-icon-size-small`, `--ui-icon-size` and `--ui-icon-size-large`.
241
+ - `theme.css` adds choice control tokens: `--ui-choice-fill-max-lightness` (the dark mode cap of a checked fill), `--ui-choice-size-small`, `--ui-choice-size`, `--ui-choice-size-large`, `--ui-switch-thumb-size-x-small`, `--ui-switch-thumb-size-small`, `--ui-switch-thumb-size`, `--ui-switch-thumb-size-large`, `--ui-switch-track-block-size-x-small`, `--ui-switch-track-block-size-small`, `--ui-switch-track-block-size`, `--ui-switch-track-block-size-large`, `--ui-switch-track-inline-size-x-small`, `--ui-switch-track-inline-size-small`, `--ui-switch-track-inline-size` and `--ui-switch-track-inline-size-large`. They are multiplied by `--ui-density`, and each track width is twice its track height until a theme sets it.
242
+ - `theme.css` adds overlay tokens, `--ui-backdrop-bg-color` (`--ui-text` at 50% in light mode, a darkened `--ui-surface` at 50% in dark mode) and `--ui-backdrop-blur`, read by `Dialog` and `Drawer`, and inverse surface tokens, `--ui-surface-inverse` and `--ui-on-inverse`.
243
+ - `theme.css` adds state and text tokens: `--ui-disabled-opacity`, `--ui-state-hover-alpha-light`, `--ui-state-hover-alpha-dark`, `--ui-state-active-alpha-light`, `--ui-state-active-alpha-dark`, `--ui-state-hover-alpha-accent`, `--ui-state-active-alpha-accent`, `--ui-text-disabled`, `--ui-invalid`, `--ui-font-weight-normal`, `--ui-font-weight-medium`, `--ui-font-weight-semibold` and `--ui-font-weight-bold`. A disabled control without a fill (text and outlined `Button`, `Chip`, an unchecked `ToggleButton`) takes `--ui-text-disabled` for its text and border and no opacity; filled and tonal controls and a checked toggle take `--ui-disabled-opacity`, so a disabled label is never dimmed twice.
244
+ - `theme.css` adds field text tokens: `--ui-field-label-text-color`, `--ui-field-label-font-size`, `--ui-field-label-font-weight`, `--ui-field-helper-text-color`, `--ui-field-helper-font-size`, `--ui-field-helper-line-height` and `--ui-field-required-text-color`, read by `Checkbox`, `Form`, `Radio`, `Range`, `Switch` and `TextField`.
245
+ - `theme.css` declares every derived token (the color roles, the control, chip, choice and switch sizes, the spacing steps, the type roles and the radii) on `:where(html, .ui-palette, .ui-contrast-more)`, and the knobs (`--ui-palette-hue`, `--ui-density`, `--ui-space-scale`, the limits and strengths) on `html` only. A subtree with `class="ui-palette"` derives everything again from the knobs it sets or inherits, so `style="--ui-palette-hue: 30"` or `style="--ui-density: 0.875"` on it works. A theme sets its pinned roles on the same selector so the scopes keep them.
246
+ - `theme.css` adds `--ui-fluid-min-inline-size`, `--ui-fluid-max-inline-size` and `--ui-fluid-progress`: the viewport window the heading sizes grow over, and the position in it (0 to 1, from `progress()`) for themes to ramp other values on.
247
+ - `theme.css` adds `--ui-density`, a multiplier for `--ui-control-size-x-small`, `--ui-control-size-small`, `--ui-control-size` and `--ui-control-size-large`. Defaults to `1`. `Button`, `Select`, `Textarea` and `TextField` padding shrinks to fit a smaller control size, down to the height of the text.
248
+ - `theme.css` adds `--ui-contrast`, set to `more` under `prefers-contrast: more` or with `.ui-contrast-more`. More contrast sets no color: it tightens the knobs the roles derive from (`--ui-text-strength-light`, `--ui-text-strength-dark`, `--ui-border-strength-light`, `--ui-border-strength-dark`, `--ui-field-border-strength`, `--ui-text-disabled-strength`, `--ui-text-max-lightness`, `--ui-text-min-lightness`, `--ui-accent-fill-max-lightness`, `--ui-accent-max-lightness`, `--ui-accent-max-chroma`, `--ui-primary-max-lightness`, `--ui-primary-min-lightness`, `--ui-invalid-min-lightness`, `--ui-palette-accent-min-lightness`, `--ui-palette-border-max-lightness`, `--ui-palette-border-min-lightness`, `--ui-palette-text-max-lightness`, `--ui-palette-text-min-lightness`, `--ui-palette-tint-max-lightness`, `--ui-palette-tint-min-lightness`, `--ui-code-bg-alpha-light`, `--ui-code-bg-alpha-dark`, `--ui-state-active-alpha-dark` and `--ui-focus-ring-width`) on `html` and on `.ui-contrast-more`, which is a scope like `.ui-palette`. Components with translucent text or fills (`Badge`, `Button`, `ButtonGroup`, `Divider`, `List`, `Menu`, `Progress`, `Spinner`, `Tabs`, `TextField`, `ToggleButton` and `Typography`) keep their own style queries. `.ui-contrast-normal` on `html` ignores the OS preference. A theme that sets knobs or `--ui-primary-source` works with more contrast; a role it pins stays pinned.
249
+ - `theme.css` adds `--ui-primary-source`, the color `--ui-primary` is derived from within `--ui-primary-max-lightness` and `--ui-primary-min-lightness`. Themes set it to their brand color so more contrast darkens or lightens the primary without changing its hue; setting `--ui-primary` pins it. The example themes set it instead of `--ui-primary`, `--ui-on-primary` and `--ui-primary-text`, so their primary, its text and the text on it follow more contrast. The named colors, `--ui-neutral`, `--ui-invalid`, `--ui-text`, `--ui-text-disabled`, `--ui-border-color` and `--ui-field-border-color` are formulas of the knobs too, so the same values come out at normal contrast and a theme that changes `--ui-text-strong` or `--ui-surface` moves them along.
250
+ - `theme.css` adds `--ui-choice-ripple-bg-color` for the `Checkbox` and `Radio` hover halo, `--ui-text` at 20%.
251
+ - `theme.css` has font tokens: `--ui-font-body` for text, fields and buttons, `--ui-font-heading` for `h1`–`h6` and `.ui-h1`–`.ui-h6`, and `--ui-font-code` for `code`, `kbd`, `samp` and `pre` in rich text, `.ui-kbd`, `.ui-samp`, `.ui-var`, code blocks and `kbd` in buttons and lists. `--ui-font-heading` is unset and headings follow `--ui-font-body` per element.
252
+ - `theme.css` has a spacing scale, `--ui-space-1` to `--ui-space-8`, multiplied by `--ui-space-scale`. Every gap, padding, offset and small size in the components reads it instead of Open Props `--size-*`, and so do native `fieldset`, `dt` and `figure` and `--ui-divider-gap`, so `--ui-space-scale` reaches all of them. Nothing moves at the default scale. Controls keep following `--ui-density`.
253
+ - `theme.css` has elevation tokens: `--ui-shadow-elevated` for elevated `Card` and `Accordion`, one shadow in both schemes whose layers take `--ui-shadow-color`, and `--ui-shadow-overlay` for `Dialog`, `Drawer`, `Menu`, the `Select` picker and the `Carousel` buttons. `--ui-shadow-control` is the shadow of buttons with a variant, a standalone `ToggleButton`, an outlined `Chip` and fields, the file input included (the optional `--ui-shadow-field` overrides it for fields), and `--ui-shadow-surface` the shadow of tonal and outlined `Card` and `Accordion` and of `Callout`, both `none` by default. `--ui-shadow-selected` is the shadow of the selected tab, and `--ui-shadow-scroll` the scroll shadow of `Dialog` and `Drawer` content and of a sticky `Table` header. The elevated, overlay, scroll and selected shadows have the shapes of Open Props `--shadow-3`, `--shadow-3`, `--shadow-4` and `--shadow-1`, written into `theme.css`, and every layer adds its own opacity to `--ui-shadow-color` with relative color, so they darken in dark mode, also in a nested `.ui-dark`.
254
+ - `theme.css` has `--ui-border-color-on-raised` and `--ui-field-border-color-on-raised`, the borders inside tonal and elevated `Card` and `Accordion`, `Dialog`, `Drawer`, `Menu` and `Callout` without a severity, and `--ui-border-color-on-filled`, the border inside lists without a variant and table headers. `--ui-border-color-on-raised` is the border mix of `--ui-border-color` and `--ui-field-border-color-on-raised` the field border mix, in both modes. `--ui-field-border-color-on-filled` is the field border mix against `--ui-surface-filled`. Each of those components sets `--ui-border-color` and `--ui-field-border-color` to the pair on its own root, so `theme.css` names no component. A theme that wants another border on raised surfaces, such as the page background in dark mode, sets the `-on-raised` tokens.
255
+ - `theme.css` adds a type scale and type roles. `--ui-font-size-100` to `--ui-font-size-900` are the nine steps (12 to 56px); `--ui-font-size-caption`, `--ui-font-size-small`, `--ui-font-size-body`, `--ui-font-size-control`, `--ui-font-size-large` and the heading sizes read them, and every component reads a role instead of an Open Props step, the `normalize.css` body text and the field helper text (`--ui-field-helper-font-size`, `--ui-field-helper-line-height`) included. `--ui-line-height-tight`, `--ui-line-height-control`, `--ui-line-height` and `--ui-line-height-relaxed` replace the Open Props line heights and the literal ones, and `--ui-letter-spacing-display`, `--ui-letter-spacing-heading` and `--ui-letter-spacing-caps` the literal letter spacings. A theme pins one role, moves one step, or replaces the scale with its own.
256
+ - `theme.css` adds shape roles. `--ui-radius-round` is the pill radius, `--ui-radius-small` (`--ui-radius` capped at 5px) rounds `kbd`, inline `code`, `mark`, `var`, `Tooltip`, the file input and rounded avatars, `--ui-radius-x-small` (capped at 2px) the checkbox box, and `--ui-border-width-thick` draws the table head and foot rules, the blockquote bar, the `AvatarGroup` ring, the `Badge` border, the neutral `Chip` dot, the dotted `DescriptionList` rule and the `Tabs` indicator. No component reads an Open Props radius or border size any more.
257
+ - `theme.css` adds palette roles. `--ui-palette-strong`, `--ui-palette-on-strong`, `--ui-palette-text`, `--ui-palette-accent`, `--ui-palette-border`, `--ui-palette-tint`, `--ui-palette-on-tint`, and `--ui-palette-tint-subtle` name the shades of the current palette and are re-derived inside every severity scope, and the text, tint, accent and border shades get stronger with more contrast, so `Callout`, `Badge`, `Button`, `del`, `ins` and `abbr` read a role instead of a palette step. `--ui-on-fill` is the near-white text on an intent fill, an intent color kept within `--ui-accent-fill-max-lightness`, `--ui-switch-thumb-bg-color` and `--ui-switch-track-bg-color` the unchecked switch, and `--ui-code-block-bg-color` and `--ui-code-block-text-color` the code blocks, a dark block in both modes: `--ui-surface-inverse` and `--ui-on-inverse` in light mode, `--ui-surface-filled` and `--ui-text-strong` in dark mode. Component CSS reads no palette step or Open Props primitive any more.
258
+ - `theme.css` adds `--ui-selected-strong` and `--ui-on-selected-strong`, the mark of a selected item that has to stand out from the page on its own (3:1): the current `Carousel` marker, the bar on selected `List` rows and the selected tab of filled `Tabs`. They default to `--ui-primary` and `--ui-on-primary`. `--ui-selected` stays the fill behind a selected item.
259
+ - `theme.css` adds `--ui-critical-text`, `--ui-info-text`, `--ui-neutral-text`, `--ui-success-text` and `--ui-warning-text`, the intent colors as text with 4.5:1 on every surface, like `--ui-primary-text` and `--ui-invalid-text`. All seven keep the lightness of their color within `--ui-text-max-lightness` (`0.41`, `0.3` with more contrast) in light mode and `--ui-text-min-lightness` (`0.8`, `0.9` with more contrast) in dark mode, where their chroma is capped at `--ui-text-max-chroma` (`0.1`). `theme.css` adds the three limits too. The critical items of a `Menu` and a `.ui-critical` `Button` with no variant or `.ui-outlined` read `--ui-critical-text`. It also adds `--ui-on-warning`, the text on a warning fill, read by the warning `Badge`.
260
+ - `theme.css` adds `--ui-underline-offset`, `--ui-underline-offset-small` and `--ui-underline-thickness-hover`, read by `Link`, rich text links and the underlined text elements.
261
+ - `theme.css` adds `--ui-accent-fill-max-lightness`, the highest lightness of an intent color filled under light text (`0.48`, and `0.45` with more contrast), read by the critical, info, neutral and success `Badge` and the fills of critical `Button`s. It also adds `--ui-surface-tonal-hover`, the hover fill of clickable `Chip`s without a `severity` and filled `TextField`, `Select` and `Textarea` fields, and `--ui-code-bg-color`, the background of inline `code` in rich text: `--ui-text` at `--ui-code-bg-alpha-light` (`12%`) in light mode and `--ui-code-bg-alpha-dark` (`10%`) in dark mode, two knobs that more contrast lowers to `6%`.
262
+ - `theme.css` adds optional `--ui-button-hover`. `layer` makes `Button` and `ButtonGroup` show hover and pressed states as translucent state layers in `--ui-state-hover-alpha-accent` and `--ui-state-active-alpha-accent`: the text color over filled and tonal buttons, the accent over outlined ones, which keep their text and border. Unset, filled buttons shade their fill and outlined and tonal buttons fill with the accent, as before.
263
+ - `theme.css` adds optional `--ui-button-padding-inline`, `--ui-button-padding-inline-x-small`, `--ui-button-padding-inline-small` and `--ui-button-padding-inline-large`, the horizontal padding of `Button` per size (`1.5ex`, `1ex`, `1.25ex` and `2.5ex` when unset).
264
+ - `theme.css` adds optional field tokens: `--ui-field-bg-color`, the background of `TextField`, `Textarea` and `Select` fields (`--ui-surface` when unset), `--ui-field-padding-inline`, their horizontal padding (`--ui-space-2` when unset), and `--ui-field-placeholder-text-color`, the placeholder color (`--ui-text-subtle` when unset).
265
+ - `theme.css` adds optional `--ui-chip-radius`, `--ui-dialog-radius` and `--ui-menu-radius`, the corner radius of `Chip`, `Dialog` and `Menu` (`--ui-radius` when unset).
266
+ - `theme.css` adds optional `--ui-tabs-accent`, the color of the selected `Tabs` label and of the indicator with `.ui-line` (`--ui-text-strong` when unset). m3 sets its primary.
267
+ - `theme.css` adds `--ui-text-subtle`, the secondary text role: placeholders, field helper text (`--ui-field-helper-text-color` reads it), descriptions in `List` and `Menu` items, unselected `Tabs` labels and `Table` captions. It is `--ui-text` unless a theme sets it, so nothing changes by default. bootstrap, m3 and shadcn set their muted text colors, and m3 body text is its on-surface color.
268
+ - `theme.css` adds optional `--ui-button-accent-filled` and `--ui-button-on-accent-filled`, the fill and text of filled `Button`s and `ButtonGroup`s without `.ui-primary` or `.ui-critical`, and of hovered outlined and tonal ones (`--ui-button-accent` and `--ui-button-on-accent` when unset). brutalist fills its buttons with the main blue while text and outlined buttons stay black.
269
+ - `theme.css` adds optional `--ui-card-padding`, the padding of `Card`, `Dialog` and `Accordion` content, headers and actions, and `--ui-list-item-padding-inline`, the horizontal padding of `List` and `Menu` items and `Select` options (`--ui-space-3` when unset).
270
+ - `theme.css` adds optional `--ui-control-accent` and `--ui-on-control-accent`, a hook pair every control reads: `Button` and `ButtonGroup` before `--ui-palette-strong`, and a checked `Checkbox`, `Radio` and `Switch` and the `Range` thumb and fill before `--ui-primary`. `--ui-control-accent: var(--ui-primary)` gives every control the brand color in one line, and `--ui-button-accent`, `--ui-button-on-accent`, `--ui-choice-accent` and `--ui-choice-on-accent` still override it per component. `themes/m3.css` and `themes/shadcn.css` set the pair instead of the four component tokens.
271
+ - `themes/bootstrap.css` (a Bootstrap 5 look), `themes/brutalist.css` (a neobrutalism look), `themes/m3.css` (a Material 3 look) and `themes/shadcn.css` (a shadcn/ui look) are example themes in the `theme.custom` layer, made only of tokens and with every color in OKLCH. They name their fonts but don't load them, and they copy their originals' contrast at normal contrast, also where it falls short of WCAG. They start with the layer order, so they work wherever they load. Import one, or copy it as a starting point. They set every token on `:where(html, .ui-palette, .ui-contrast-more)`, the selector the library derives on, so `.ui-palette` and `.ui-contrast-more` subtrees keep the theme. With more contrast, they hand their borders, field borders, focus ring and subtle text back to the library with `revert-layer` (brutalist draws its borders in `--ui-text`), so every theme meets the contrast promises.
272
+ - `tokens.json` lists every theme token, the palette steps `--ui-color-1` to `--ui-color-16` and `--ui-gray-1` to `--ui-gray-16`, and the instance inputs components read (`--ui-anchor-position-area`) in the W3C design tokens format: its `$type`, description and default as `$value`, and under `$extensions.opui` its CSS variable, tier (`knob` for an input a theme turns, `primitive` for a step derived from the knobs that no component reads, `role`, `hook` for an optional role every component with that job reads with a default of its own, `component`, or `input` for a property set on an element that no theme sets, declared beside each token instead of guessed from its name), dark and more-contrast values (`modes`) and, where a token guarantees one, the contrast ratio it promises and against which tokens. Every `-text`, `-text-color` and `on-` role a component paints text with promises 4.5:1 against its fill or the surfaces it sits on, `--ui-on-fill` against each intent fill and `--ui-palette-text` and the field text colors against every surface included. `--ui-palette-text` is at least `0.8` lightness in dark mode (`--ui-palette-text-min-lightness`), like the intent text roles, so it keeps the promise in every example theme. A plain number, a `px` or `rem` length and an alias of another token are native design token values, with the CSS beside them as `$extensions.opui.css`; the other values are CSS expressions. Tokens that are unset by default have no `$value`, only an `example`. The theme tokens page shows the same promises. Import it from `opui-css/tokens.json`. The agent skill ships a copy and a table of which token to change for what.
273
+ - `utils.css` adds `.ui-focusable`, which shows a `.ui-sr-only` element while it has keyboard focus, for skip links.
274
+
275
+ ### Changed
276
+
277
+ - `Accordion`, `ButtonGroup`, `Callout`, `Card`, `Chip`, `DescriptionList`, `List`, `Table`, `ToggleButton` and `ToggleGroup` borders read `--ui-border-width`, and `Checkbox`, `Radio`, `Switch` and `TextField` borders read `--ui-field-border-width`, instead of a hardcoded `1px`.
278
+ - `Accordion` with `variant="tonal"` or `variant="elevated"` has a border in the page background color unless a theme sets `--ui-border-color-raised`, like tonal and elevated cards, so it stays visible on tonal surfaces.
279
+ - `Accordion` actions line up with the content and the chevron, with the summary's block padding below them instead of a large gap above.
280
+ - `Accordion`, `Drawer` and rich text use `overflow-inline`/`overflow-block` instead of `overflow-x`/`overflow-y`, so scrolling follows the writing mode. Browsers older than Chrome 135, Firefox 69 and Safari 26 ignore them, so those containers don't scroll there, and neither do `Dialog` content and `ButtonGroup`, `Tabs` and `ToggleGroup` with `overflow="scroll"`.
281
+ - `Accordion` with `variant="elevated"` uses `--ui-shadow-elevated`, the elevated `Card` shadow, which takes the darker `--ui-shadow-color` in dark mode.
282
+ - `Avatar` and `Badge` text uses `--ui-on-primary`.
283
+ - `Avatar`, `List` and `ButtonGroup` sizes follow `--ui-control-size` and `--ui-button-size-*`.
284
+ - `Avatar` no longer declares `command`, `commandfor` and `interestfor` as props. They pass through as attributes.
285
+ - `Avatar` squircle without `corner-shape` falls back to a rounded square with corners at 27% of its size instead of `--radius-3`. The fallback moved from `avatar.css` to `css/compat/avatar.css`: import it, or `compat.css`, with `avatar.css`, or the squircle is a circle there, as in `dist/opui.no-compat.css`.
286
+ - `Avatar` (rounded), `Checkbox`, `Tooltip`, file inputs, `kbd`, `mark` and `var` never get rounder than `--ui-radius`.
287
+ - `AvatarGroup` avatars overlap by `--ui-space-2` instead of `--ui-space-3`, so the initials stay whole at every size.
288
+ - `Badge` on a round `Avatar` sits on the avatar's edge instead of the corner of its box.
289
+ - `Badge` in an `Avatar` group sits on the avatar's start side, the part the next avatar doesn't cover, with the same ring as the avatars (the group's `--_outline-color`).
290
+ - `Button` critical keeps light text on a fill a little darker than `--ui-critical`, while its border keeps `--ui-critical`, tonal primary and critical buttons use dark text on a light container in light mode and light text on a dark container in dark mode, and text and outlined buttons use a lighter accent for text in dark mode.
291
+ - `Button`, `Divider` and `Typography` borders read `--ui-border-width` instead of `--border-size-1`.
292
+ - `ButtonGroup` buttons draw a `ButtonBorder` border under `forced-colors: active`, where their shadows disappear.
293
+ - `ButtonGroup` focus ring sits inside the button with a gap and uses `--ui-focus-ring-color`, so it shows on every variant and isn't clipped by the group.
294
+ - `ButtonGroup` and `ToggleGroup` wrap onto more rows when they don't fit, instead of overflowing. The group draws its outer edge and rounded corners, and dividers sit between items in every row.
295
+ - `ButtonGroup` small buttons are `--ui-button-size-small` (32px) instead of 30px, with the same `--ui-font-size-small` text as a small `Button`.
296
+ - `ButtonGroup` item styles select `.ui-button` instead of `button`, so `Button` links (`<a class="ui-button">`) are styled like the buttons. A plain `<button>` without `.ui-button` no longer gets the group item styles.
297
+ - `ButtonGroup` sizes and variants are Button's own rules, and icon-only buttons in a group use Button's icon size, the same as buttons with a label.
298
+ - `Callout` tonal severities have a visible fill in light mode, 60% of the third palette step instead of 20% of the second.
299
+ - `Callout` links, `Card` links, `Chip`, `Link`, `List`, `Range`, `Table`, `TextField`, the `Checkbox` and `Radio` halo and rich text links only show hover styles on devices that can hover, so they no longer stick after a tap.
300
+ - `Card` captions, `Tooltip` text and keyboard hints in buttons use `--ui-line-height-tight` (1.25) instead of 1.3 and 1.2.
301
+ - `Card` tonal and elevated variants (and `Dialog`) have a border in the page background color, so they stay visible on tonal surfaces. In dark mode, borders and field borders inside them also use the page background.
302
+ - `Card` actions stick to the bottom of stretched cards and wrap.
303
+ - `Card`, `Accordion`, `Dialog` and `Drawer` content (`.ui-content`) is a stack: a grid with `--ui-space-3` between its children, which lose their block margins, so a body with a heading, a paragraph and a list needs no CSS of its own. Content with inline children (links, `strong`, chips, buttons) or a `Carousel` keeps the normal flow, and rich text content (`.ui-content.ui-rich-text`) keeps its own spacing. The rules have no specificity, so a `display` or `gap` set on the content wins.
304
+ - `Checkbox`, `Radio` and `Switch` keep a light marker in dark mode on a fill darkened to keep 3:1 contrast.
305
+ - `Checkbox`, `Radio` and `Switch` line up with the first line of their label and center on it.
306
+ - `Checkbox` and `Radio` root selectors are wrapped in `:where()`, like other components.
307
+ - `Checkbox` and `Radio` no longer render an empty `.ui-label` without a default slot, and warn in dev without an accessible name, like `Switch`.
308
+ - `Checkbox`, `Radio`, `Switch` and `Progress` align to the middle when there's no visible label, so they center in table cells and lines of text. Give them a hidden label (`hideLabel`, or `.ui-sr-only` in HTML). `Checkbox`, `Radio` and `Switch` then keep a box of at least `--ui-space-5` (24px) around the control, so the label stays a 24px pointer target.
309
+ - `Checkbox`, `Radio` and `Switch` in Vue warn in development when they have no label, `aria-label` or `aria-labelledby`, like Astro.
310
+ - `Chip` uses `--ui-radius` (8px) instead of Open Props `--radius-2` (5px).
311
+ - `Chip` small is `--ui-chip-size-small` (28px, the x-small control size) instead of 24px.
312
+ - `Chip` labels truncate with an ellipsis unless the chip is `multiline`.
313
+ - `Chip` hover is stronger in light mode: button and link chips without a `severity` read `--ui-surface-tonal-hover`, the hover of filled fields.
314
+ - `Dialog` and `Drawer` open over `--ui-duration-slow` (`0.3s`, was `0.2s`) with `--ui-ease-enter`, and `Drawer` closes with `--ui-ease-exit`, as the tokens describe.
315
+ - `Dialog` takes `--ui-shadow-overlay`, like `Drawer` and `Menu`, instead of the raised card shadow.
316
+ - `Dialog` has a maximum height. The header and footer stay in place and the content scrolls.
317
+ - `Dialog` width is set with `--_max-inline-size` (`60ch` by default), and the dialog keeps its margin on small screens at any width.
318
+ - `Dialog` fades its backdrop in with the panel.
319
+ - `Divider` that is a direct child of a card has no margin, since the card's gap spaces it.
320
+ - `Drawer` backdrop dims and blurs like `Dialog`, through `--ui-backdrop-bg-color` and `--ui-backdrop-blur`. `.ui-backdrop-transparent` still removes it.
321
+ - `Drawer` content padding is `--ui-space-3`, like its header and footer and `Dialog`. It was `--ui-space-4`, so the title and the body text didn't line up.
322
+ - `Drawer` header headings take the free space and the header has a gap, so several actions line up at the end. Without a heading, the first icon-only button is pushed to the end.
323
+ - `Drawer` sits on `--ui-surface-elevated`, like `Dialog` and `Menu`, and borders and field borders inside it read `--ui-border-color-on-raised` and `--ui-field-border-color-on-raised`.
324
+ - `FieldGroup` and `ToggleGroup` in Astro pass the group `name` and selection to their inputs through context instead of rewriting the slot HTML, so a bare `<input>`, `<select>` or `<textarea>` in a `FieldGroup` no longer gets the group `name`, like in React, Svelte and Vue.
325
+ - `Form`, `Fieldset` and `FieldLegend` type `as` in Vue as `"div" | "form"`, `"div" | "fieldset"` and `"legend" | "p"`.
326
+ - `Link` (`.ui-link`) and rich text links darken in light mode and lighten in dark mode on hover and focus, from their own color so they keep the contrast of `--ui-primary-text`, and their underline gets `--ui-underline-thickness-hover` (`3px`) thick.
327
+ - `List` start and end icons are smaller: `--ui-icon-size` by default and `--ui-icon-size-small` in dense lists (were `--ui-icon-size-large` and `--ui-icon-size`).
328
+ - `List` dense rows keep the default inline padding, so they line up with `Card` content.
329
+ - `List` only styles direct `li`/`option` children (and options in a `[role="group"]`) as rows, so nested lists inside a row stay normal lists. Headings and paragraphs in `.ui-text` have no margin.
330
+ - `List` checked `option` uses `--ui-state-active-alpha-accent`.
331
+ - `List` selected and current rows and options have a bar on their start edge in `--ui-selected-strong`, and a stronger fill than hover (`--ui-state-active-alpha-accent`, the hover tint with more contrast), so they no longer differ from a hovered row by a tint alone. Selected `Select` options read `--ui-primary-text`. Images and videos in `.ui-start` are `3.5rem` and `4rem` instead of `56px` and `64px`.
332
+ - `List` has rounded corners (`--_radius`, `--ui-radius`) and clips its rows to them. As a direct child of a `Card`, `Accordion` or `Dialog` it stays square, since they round and clip it.
333
+ - `List` dense rows are `--ui-control-size-small` tall instead of a fixed `--ui-space-7`, so they follow `--ui-density`.
334
+ - `Progress` outlines its track with `--ui-field-border-color`, so the empty part is visible.
335
+ - `Radio` is `--ui-choice-size` (20px) like `Checkbox`, instead of 18px.
336
+ - `Range` pressed thumb ring reads `--ui-state-active-alpha-light` and `--ui-state-active-alpha-dark`, so it is 30% in dark mode (was 20%).
337
+ - `Range` with more contrast draws its empty track in the page color with an inset `--ui-field-border-color` edge, so the fill stands out from it.
338
+ - `Range`, `Switch` and `TextField` invalid states use `--ui-invalid`.
339
+ - `Range` generates the `<datalist>` id when `items` or the `datalist` slot is used, so `list` is optional.
340
+ - `Range` in Vue scopes the `value-text` slot with the current `value`, so custom readout content follows the thumb.
341
+ - `Range` with a value readout announces each step once, with its unit: the input gets `aria-valuetext` (the value and `valueSuffix`) and the `.ui-value` output `aria-live="off"`, so screen readers no longer read the value twice. In HTML, `initRange()` keeps `aria-valuetext` in sync when the output has a `data-suffix`.
342
+ - `Range` thumb, halo and track fill follow `--_accent` on `.ui-range`.
343
+ - `Select` keeps the browser's checkmark at the end of the selected option instead of hiding it.
344
+ - `Select` group labels take a shade of the picker's surface and `--ui-text` for their text, instead of fixed gray steps.
345
+ - `Select` chevron flips when the picker opens, with a transition, like the `Accordion` flip marker.
346
+ - `Select` and `TextField` auto-suggest arrows share one size and inset, and keep the same space for the arrow, at every size.
347
+ - `Select` and `TextField` auto-suggest arrows are a chevron instead of a triangle.
348
+ - `Select` pickers and `Drawer` use `--ui-shadow-overlay` (`--shadow-3`, was `--shadow-2`), like `Menu`.
349
+ - `Select` picker paints `--ui-surface-elevated` with the raised edge and the `-on-raised` borders inside, like `Menu`, instead of `--ui-surface-filled` with a field border, so a theme that tunes overlays changes both.
350
+ - `Spinner` shows on busy buttons and links that have `aria-describedby`. Other elements with `aria-describedby` still opt out, for the progress bar pattern.
351
+ - `Spinner` styles have no specificity (`:where()`), so a page's own `::before` rules override them, like other component roots.
352
+ - `Spinner` ring is at least `--ui-border-width-thick` and grows with its size (`0.1875em`, `3px` at `16px`).
353
+ - `Switch` unchecked track border is `--ui-field-border-color`, like the checkbox and radio borders, instead of the dot color.
354
+ - `Switch`, `Tooltip`, `Textarea`, `Table`, `List`, `Tabs`, `Spinner`, `Dialog`, `Drawer` and the typography styles use logical properties only (`min-inline-size`, `inset-inline-start`, `padding-block`/`padding-inline`, `resize: block` …), so they follow the writing mode, and the `DescriptionList`, `Range`, `Select` and `TextField` container queries read `inline-size`. Horizontal left-to-right rendering is unchanged.
355
+ - `Switch` turns its checked track red when invalid, like `Checkbox` and `Radio`, with a `--ui-on-fill` thumb.
356
+ - `Table` centers a checkbox that is alone in a cell and shrinks the column to fit it.
357
+ - `Table` dense cells have less block padding.
358
+ - `Textarea` minimum height is three lines plus padding at every size. Small was a fixed 64px.
359
+ - `TextField`, `Select` and `Textarea` with `.ui-small` set their text in `--ui-font-size-small`, like small buttons, instead of the default size. On touch screens, small and x-small fields keep `--ui-font-size-control`, since iOS Safari zooms in on a focused field with text under 16px.
360
+ - `TextField` file input takes `--ui-shadow-field` like other fields instead of an inset Open Props shadow, so it's flat by default.
361
+ - `TextField`, `Textarea`, `Select` and `Range` with `spread` split their container into equal label and field columns, so spread fields line up at one width. The fixed `30ch` textarea and `25ch` range minimums are gone.
362
+ - `TextField`, `Textarea` and `Select` keep a `12ch` minimum width in table cells.
363
+ - `ToggleButton` when checked is filled with `--ui-primary` (or `--ui-selected`) instead of a tint.
364
+ - `ToggleButton` standalone and `Chip` outlined take `--ui-shadow-control` like buttons (none by default), and toggle corners are capped at half the control height so a round `--ui-button-radius` doesn't clip grouped toggles.
365
+ - `ToggleButton` and `ToggleGroup` text shrinks with the size like `Button`: `--ui-font-size-small` when small and `--ui-font-size-caption` when x-small.
366
+ - `ToggleButton` disabled state uses `--ui-disabled-opacity` like `Button`, and `--ui-text-disabled` when unchecked (a checked one keeps its selected text color), its hover uses `--ui-state-hover-alpha-light`, and `ToggleButton` and `ToggleGroup` read `--ui-button-size*` instead of `--ui-field-size*`.
367
+ - `ToggleButton` grows from `--ui-button-size` with its content instead of having a fixed height.
368
+ - `ToggleGroup` is in the `components.extended` layer, like `ButtonGroup`.
369
+ - `Tooltip` uses `--ui-surface-inverse` and `--ui-on-inverse`.
370
+ - `Typography` inline `code` in rich text is rounded with `--ui-radius-small` (5px by default) like `kbd` and `mark`, instead of the full `--ui-radius`.
371
+ - `Typography` rich text spacing derives from one flow space (`1.25em` of the body text), and every margin derived from it snaps to `--ui-rhythm-step`. Headings get more space above than below, so they sit closer to the text they introduce, and lists with block content, description lists, `details`, `address`, code blocks and figures follow the same rhythm.
372
+ - `Typography` rich text list gutters are measured in `ch`, so two-digit markers fit, and ordered lists widen their gutter for three- and four-digit numbers, also with `start`. Bulleted and numbered list text starts at the same position.
373
+ - `Typography` `sup` and `sub` are `0.75em` in rich text and in `.ui-sup` and `.ui-sub`, and no longer change the line height.
374
+ - `Typography` rich text figure captions are muted and start-aligned under quotes, code blocks and tables.
375
+ - `Typography` heading group subtitle line heights and spacing, in rich text `hgroup` and `.ui-hgroup`, snap to `--ui-rhythm-step`.
376
+ - `Typography` headings share one line height, `1em + 0.5rem` rounded to `--ui-rhythm-step`, in rich text and in the `.ui-h1`–`.ui-h6` classes.
377
+ - `Typography` rich text headings, `pre` and `small` scale with the inherited font size.
378
+ - `Typography` `.ui-small` is at least `0.75em` of the surrounding text instead of `0.5em`, like rich text `small`, so it stays in proportion in headings.
379
+ - `Typography` styles `.ui-overline`, `.ui-hgroup` and rich text `hgroup`, and `.ui-code-block` and rich text `pre`, with one rule per pair in `@scope (…) to (.ui-not-rich-text)` blocks, and `link.css` styles `.ui-link` and rich text links the same way, so the class and the classless version can't drift. Rich text links need `link.css` next to `typography.css`.
380
+ - `Typography` rich text `var` uses the monospace font and wraps long names, like `.ui-var`.
381
+ - `Typography` overlines (`.ui-overline` and the first paragraph of a heading group) read `--ui-text-subtle` instead of a lighter or darker `--ui-text` of their own, and follow more contrast through the role.
382
+ - `Typography` `kbd`, `var`, `.ui-kbd` and `.ui-var` sit on `--ui-surface-inverse` with `--ui-on-inverse` text, like `Tooltip`, instead of on `--ui-text`.
383
+ - `--ui-field-border-color` is a 50% mix of the text color into the page (3:1 or more) instead of `--ui-border-color`, so fields, checkboxes, radios, switches and the range track have a visible boundary without more contrast. Inside filled surfaces it mixes into `--ui-surface-filled` the same way. The example themes keep their own.
384
+ - `--ui-invalid` is lighter in dark mode with more contrast, so invalid fields, checkboxes, radios, switches and ranges keep a visible edge.
385
+ - `normalize.css` sets `box-shadow` instead of `-webkit-box-shadow` on autofilled fields, and font and color inheritance on `::file-selector-button`.
386
+ - `normalize.css` reads `--ui-line-height-relaxed` for the page line height, `--ui-icon-size-large` for an `svg` without `width` (`1.5rem` instead of `2rem`) and `--ui-space-7` for the scroll margin of `:target`.
387
+ - `open-props` is an optional peer dependency. `theme.css` and the example themes read nothing from Open Props: the sizes, radii, border size, easings, font stacks, font weights, hues and shadow shapes they took from it are written into `theme.css` with the same values, so `tokens.json` holds no `var(--size-2)` style values. `css/imports.css` no longer imports `open-props.css`, so a bundler build needs no `open-props` package. `dist/opui.css` still bundles Open Props, and `opui-css/open-props` (`dist/op.css`) and `open-props.css` stay for your own CSS. Install `open-props` only to import `open-props.css`.
388
+ - `open-props.css` imports the Open Props files one by one instead of `open-props/src/index.css`, so `dist/op.css` and `dist/opui.css` no longer contain Open Props' `@custom-media` rules. Import `open-props/media` yourself if a PostCSS plugin reads them.
389
+ - `theme.css` severity scopes (`.ui-critical`, `.ui-info`, `.ui-neutral`, `.ui-success`, `.ui-warning`) take their hue from the intent tokens, and `.ui-neutral` its chroma too, so a theme's `--ui-success` reaches every success surface and its `--ui-neutral` every neutral one. `--ui-neutral` and the named colors set the lightness of palette steps 7 and 9 as a number instead of reading the element's own palette, so a severity class also keeps its palette on a `.ui-palette` or `.ui-contrast-more` element.
390
+ - `theme.css` `--ui-primary` is `--ui-color-9` in light mode and `--ui-color-6` in dark mode, and `--ui-on-primary` is dark in dark mode, so text on primary and primary text both pass WCAG AA in light and dark.
391
+ - `theme.css` declares every palette knob, `--ui-palette-hue`, `--ui-palette-chroma`, `--ui-palette-hue-rotate-by`, `--ui-gray-hue` and `--ui-gray-chroma`, and `core/palette.css` no longer declares its own, which disagreed with `theme.css` and never applied. `.ui-palette` and the severity scopes inherit the knobs from their ancestors instead of resetting them to the defaults.
392
+ - `theme.css` derives `--ui-on-primary` from `--ui-primary` and `--ui-on-warning` from `--ui-warning` with relative color, from the fill's relative luminance (the `y` of `xyz-d65`): white text on a fill below 0.182 and near-black above it, so either side keeps 4.5:1 and custom primaries get readable text.
393
+ - `theme.css` named colors use the Open Props hue angles: `--ui-blue` is `240`, `--ui-green` `145`, `--ui-orange` `75` and `--ui-red` `25`, like the severity scopes. `--ui-info` and `--ui-blue` use `240`, the same blue as the `.ui-info` palette. White text on an info `Badge` is 4.58:1.
394
+ - `theme.css` is in the `theme.base` layer instead of `theme`, so overrides in `@layer theme` or `@layer theme.custom` beat the defaults wherever they load.
395
+ - `theme.css` control and chip sizes are in `rem` (`1.75rem`, `2rem`, `2.5rem` and `3rem`, and `1.5rem` for the x-small chip) instead of `px`, like the choice, switch and icon sizes, so the whole size scale follows the root font size. At the default 16px the sizes are the same, except `--ui-control-size-large`, which is 48px instead of 46px, so large buttons, fields, toggles and selects grow by 2px.
396
+ - `themes/bootstrap.css` follows Bootstrap 5 closer: `oklch(0.91 0.007 248)` field borders, gray secondary default buttons (`oklch(0.525 0.017 245)`, darker than Bootstrap's `oklch(0.558 0.016 245)` so their text reads on the tonal surface and on the tint behind a `kbd` shortcut, and `oklch(0.77 0.014 248)` in dark mode), the danger, warning, info and neutral colors and the subtle alert palettes on the severity scopes, white 32px switches, 16px checks with 4px corners and no ripple, `0.75rem` button and field padding, `0.875rem` helper text, solid blue selected items, black tooltips, 1.5 line height, no heading letter spacing, no backdrop blur and no shadow on dropdowns, modals and drawers. The contrast test lists its field border as a known exception.
397
+ - `themes/brutalist.css` follows neobrutalism closer: the `oklch(0.92 0.019 266)` and `oklch(0.283 0.019 276)` pages, white fields and tracks, 500 weight body text, 700 headings, 14px control text, main-colored filled buttons and selected items, state layers instead of fills on hover, black links, main-colored tooltips, 24px card padding, 8px menu item padding, 16px checks with 5px corners, the hard shadow on dialogs and menus, and 36px and 44px small and large controls.
398
+ - `themes/m3.css` follows Material 3 closer: the error red, 8% and 10% state layers on every button, 24px button padding, 28px dialogs, 4px menus, 8px chips, 18px checkboxes, 52 by 32px switches with the outline thumb, 16px field padding, on-surface body text with on-surface-variant secondary text, primary tab labels and line indicators, the inverse surface for tooltips, the emphasized easing, a 32% scrim without blur, no rim on elevated cards and 1.5 line height.
399
+ - `themes/shadcn.css` follows shadcn/ui closer: the accent tint on hover instead of a fill, 16px button padding, 32px small and 40px large controls, 8px chips and menus, 10px dialogs, 16px checks with 4px corners, a 32px switch with a white thumb, the destructive red, primary-colored tooltips, 16px icons, 14px helper text, placeholders, descriptions and tab labels in a slightly darker muted gray (`oklch(0.52 0 0)`, so it reads on tonal and checked cards), 12px field padding, 24px card padding, 8px menu item padding, 0.5 disabled opacity, 1.5 line height and the Tailwind shadows for selected tabs and scroll edges.
400
+
401
+ ### Fixed
402
+
403
+ - `Accordion` summaries, `Button`, `Checkbox`, `Radio` and `Switch` labels, `List` items on touch screens, `Tabs` labels, `ToggleButton` and disabled fields, fieldsets and ranges can no longer be selected by a press or a drag in Safari, which only reads `-webkit-user-select`, like in Chromium and Firefox.
404
+ - `Accordion`, `Avatar`, `Divider`, `List`, `Progress`, `Range`, `Select`, `Switch`, `Tabs`, `Textarea`, `TextField` and `ToggleButton` keep their state visible in forced colors mode: selected tabs, toggles and list items use `SelectedItem`, switches, ranges, progress bars and dividers are drawn with system colors, focused fields get a `Highlight` outline, elevated and tonal accordions get a `CanvasText` border, and letter avatars an outline.
405
+ - `Accordion` focus ring is drawn inside the summary of `.ui-elevated`, `.ui-outlined`, `.ui-tonal` and grouped accordions, so the card no longer clips it, and outside the summary of a transparent accordion, so it no longer cuts through the text and marker.
406
+ - `Accordion` content in a transparent group lines up with the summary.
407
+ - `Accordion` group styles only apply to a `Card` with `role="group"` whose accordions are direct children, so a card with an accordion inside its `CardContent` keeps its layout and padding.
408
+ - `Accordion` (elevated and tonal) and the default `Callout` remap `--ui-border-color` and `--ui-field-border-color` like raised cards, so dividers and field borders inside them stay visible in dark mode.
409
+ - `Accordion` summaries with a marker let their items shrink and cut off with an ellipsis, so a badge, a chip or a long word no longer pushes the marker out.
410
+ - `Accordion` actions keep room for the focus ring, so the last button's ring isn't clipped in a transparent group.
411
+ - `Anchor` with `trigger="hover"` and `Tooltip` stay visible on a scrolled page in Chrome 141. `normalize.css` gives `html` `min-block-size: 100%` instead of `block-size: 100%`, and `body` `min-block-size: 100svb` instead of `100%`, because `position-visibility: anchors-visible` hid every popover whose trigger was below the first screen.
412
+ - `Anchor` and `Badge` render a user `id` on the root. With `trigger="hover"` it stays the floating element's id.
413
+ - `Anchor`, `Badge`, `Divider`, `Drawer`, `TableColumn`, `Tabs`, `ToggleButton` and `ToggleGroup` in Vue update derived values when props change.
414
+ - `Anchor` and `Tooltip` inside a `Badge` no longer shift their floating element by the badge's offset.
415
+ - `Anchor` and `Tooltip` default to `self-` `position-area` keywords (`self-start self-end` and `self-block-start`), so floating content follows its own writing direction and mirrors in a right-to-left part of a left-to-right page. Before, it followed the page's direction while its margins followed its own.
416
+ - `Avatar` doesn't shrink in flex rows.
417
+ - `Avatar` groups overlap from the start, so the group's box ends at its last avatar.
418
+ - `Avatar` in Vue accepts arrays and objects for `class`, and the image always has an `alt` attribute.
419
+ - `Avatar`, `Button` and `Chip` share one helper for `disabled`, `aria-disabled`, `href` and `type`, so they render those attributes the same way in every framework.
420
+ - `Avatar` button and link avatars dim and show the not-allowed cursor when disabled.
421
+ - `Badge` no longer shrinks in flex rows, so an icon with a badge in an `Accordion` summary keeps its size next to long text. A bare `img` or `svg` in the summary keeps its size too.
422
+ - `Badge` severity colors use their own text color instead of `--ui-on-primary`, and warning badges use `--ui-on-warning`, dark text on the warning fill.
423
+ - `Badge` and `Tabs` respect `--ui-motion` and `prefers-reduced-motion`.
424
+ - `Badge` indicators mirror in RTL.
425
+ - `Badge` dots sit in every corner, not only the default one.
426
+ - `Badge` and `Anchor` no longer write the unused `--_anchor-inset`, and aligned badges no longer write `--ui-anchor-position-area`.
427
+ - `Badge` with `invisible` hides the indicator from screen readers too.
428
+ - `Button` `kbd` uses the button's text color, also on hover, instead of 80% of it, so it passes contrast on colored buttons.
429
+ - `Button` critical text buttons have readable text on tonal surfaces in dark mode.
430
+ - `Button` and `ButtonGroup` style `[aria-disabled="true"]` the same as `[disabled]`, e.g. for `<a class="ui-button" aria-disabled="true">` or focusable disabled buttons.
431
+ - `Button` and `ButtonGroup` hover styles only apply on devices that support hover, so they no longer stick after a tap.
432
+ - `Button` disabled text color applies to text and outlined buttons in every color. Filled and tonal buttons keep their own text color and dim with the disabled opacity, so the label stays readable on the fill.
433
+ - `Button`, `ButtonGroup`, `Card`, `Range`, `Select`, `Tabs`, `Textarea`, `TextField` and `ToggleButton` focus rings grow in like the rest of the library. `normalize.css` animates the `:focus-visible` ring with the `ui-focus-ring` keyframes instead of an `outline-offset` transition, which a component's own `transition` overrode.
434
+ - `Button`, `Chip`, `Checkbox` and `Radio` show no hover or active state inside a disabled fieldset.
435
+ - `Button` without a variant shows its pressed background while held with the keyboard, like outlined, tonal and filled buttons.
436
+ - `Button` with `.ui-primary` or `.ui-critical` and an accent darker than L 0.3 lightens on hover and press like other buttons, instead of darkening further.
437
+ - `ButtonGroup` only styles its direct child buttons, so a `Menu` inside it (split button) keeps its own item styles.
438
+ - `ButtonGroup` dividers are no longer double thick.
439
+ - `ButtonGroup` vertical only squares icon-only buttons.
440
+ - `ButtonGroup` vertical `small` items are as tall as their size.
441
+ - `ButtonGroup` focus rings stay off the label when a theme or more contrast widens the ring.
442
+ - `Callout` keeps bare text and inline elements like links on one line instead of stacking them as separate rows.
443
+ - `Callout` only uses the icon layout for a direct child `svg`, keeps its content at the top when stretched, and no longer shows lighter corners.
444
+ - `Callout` rich text inside `.ui-content` no longer gets doubled margins.
445
+ - `Callout` icons take the severity color with `color`, so fill icons no longer get a colored outline.
446
+ - `Callout` links in a tonal callout take the hover color on keyboard focus too, and it keeps 4.5:1 on the tonal background.
447
+ - `Callout` severity icons use a lighter palette step in dark mode, so they reach 3:1 against the callout.
448
+ - `Callout` with `variant="tonal"` no longer renders `.ui-tonal`, a class without a rule.
449
+ - `Callout` icon offset scales with the font size.
450
+ - `Card` wraps long words.
451
+ - `Card` actions line up a plain last button with the content, and no longer pull a filled or outlined last button to the edge.
452
+ - `Card` actions keep the edge padding for a text button with extra classes.
453
+ - `Card`, `ToggleButton`, `Checkbox`, `Radio`, `Switch` and the busy spinner read the local `--_motion`, so `style="--_motion: 0"` turns off their focus ring animation, hover halo and spin speed-up like other components.
454
+ - `Card`, `Accordion` and `Dialog` actions line up the label of a text button at their start or end with the content: the button pulls itself out by its padding and border (`--_actions-shift`), as far as the focus ring stays inside the card. Accordion actions had no compensation, so the label sat 14px inside the content edge.
455
+ - `Card` content followed by a divider has no bottom padding, so the divider sits evenly between the two contents.
456
+ - `Carousel` leaves room around the items for their box shadows (`--_shadow-room`, `--ui-space-3`), so the scroll container no longer clips a card's shadow at the bottom or at the scroll end. It is padding that a negative margin cancels, so the layout and the button and marker positions stay the same. On the scroll axis the room is at most `--_gap` and shrinks by the peek, so the next item stays hidden.
457
+ - `Checkbox`, `Radio`, `Switch` and `ToggleButton` style `aria-disabled="true"` on the input like `disabled`: dimmed, a `not-allowed` cursor and no hover tint on toggle buttons. The browser doesn't block the change, so a script has to.
458
+ - `Checkbox` and `Radio` show a red border when invalid and unchecked (`aria-invalid="true"` or `:user-invalid`), like Switch and TextField. Before, only a checked control turned red.
459
+ - `Checkbox` forced-colors styles apply to checked and indeterminate boxes.
460
+ - `Checkbox` and `Radio` required asterisks in stacked labels sit after the label in RTL.
461
+ - `Checkbox` and `Radio` show their hover and press halo without `core/utils.css`, so `dist/opui.components.css` and single-file imports get it too.
462
+ - `Checkbox` `initCheckbox()` adds its `astro:after-swap` listener once, however often it is called.
463
+ - `Checkbox`, `Radio` and `Switch` required asterisks, and the `Fieldset` legend's, follow the last word of a wrapped label instead of jumping to the end of the row.
464
+ - `Checkbox`, `Radio`, `Switch`, `TextField`, `Textarea`, `Select` and `Range` pass a user `aria-invalid` to the control when `error` isn't set.
465
+ - `Checkbox` unchecked border reads `--ui-field-border-color` like Radio and the text fields.
466
+ - `Checkbox`, `Dialog`, `Drawer`, `Radio`, `Switch`, `Tabs` and `ToggleButton` no longer need Vite's `import.meta.env` types or runtime for their dev-only warnings. Where `import.meta.env.DEV` is undefined they read `process.env.NODE_ENV`, so the warnings also show with webpack and Turbopack (Next.js).
467
+ - `Checkbox`, `Radio`, `Switch`, `TextField` and `Textarea` no longer point `aria-describedby` at the end text, so screen readers don't read it twice. The wrapping `<label>` already makes it part of the name.
468
+ - `Checkbox` and `Radio` no longer set `--ui-primary` when invalid, so links and other content in their label keep the primary color.
469
+ - `Checkbox`, `Radio`, `Switch`, `TextField`, `Textarea`, `Select` and `Fieldset` required asterisks are left out of the accessible name, so screen readers don't read "star".
470
+ - `Checkbox`, `Radio`, `Range`, `Select`, `Switch`, `TextField` and `Textarea` in Vue render a text prop and its slot together, like Astro, instead of dropping the prop.
471
+ - `Checkbox` draws a disabled box in `GrayText` in forced colors mode, like `Switch`, instead of the enabled colors at reduced opacity.
472
+ - `Chip` with a start and an end icon gets the smaller padding on both sides, and an icon inside `.ui-text` no longer changes the padding.
473
+ - `Chip` disabled text color applies to tonal and outlined chips.
474
+ - `Chip` in Astro only renders `href` when the chip is an `a`.
475
+ - `DescriptionList` switches layout based on its own width instead of the page, shares space between long terms and values, and wraps long values. A nested list sizes to its content and follows the outer list's layout, and `.ui-bordered` leaders only apply to the list's own items.
476
+ - `DescriptionList`, `List` row links, `Card` (and `Dialog`) heading groups, `FieldDescription`, and `Button` and `List` `kbd` no longer pick up rich text padding, margins, font weight or font.
477
+ - `DescriptionList` no longer clips the focus ring of a link or button in a term.
478
+ - `DescriptionListDescription`, `DescriptionListItem` and `DescriptionListTerm` in Vue no longer accept the list's `bordered` prop.
479
+ - `Dialog` backdrop is themeable via `--_backdrop-bg-color` and `--_backdrop-blur` (same as `Drawer`).
480
+ - `Dialog` scroll-lock matches `.ui-scroll-lock` and no longer shifts the layout when the scrollbar disappears.
481
+ - `Dialog` only locks page scroll for modal dialogs (`showModal()`).
482
+ - `Dialog` actions only tighten the end padding when the last button is a text button, keeping room for its focus ring like `Card`, and start-aligned actions use Card's padding, so filled buttons line up with the content.
483
+ - `Dialog` and `Drawer` only style their own direct parts, so a Callout, Card or TextField inside them keeps its own padding and alignment.
484
+ - `Dialog` and `Drawer` open without a focus ring around them. Safari focuses the `dialog` itself when nothing inside it is in the Tab order, and `normalize.css` drew its focus ring there. The ring stays on the controls inside, and the rule no longer needs `!important`.
485
+ - `Drawer` is hidden (`display: none`) when closed, so it is no longer keyboard focusable.
486
+ - `Drawer` with `.ui-backdrop-transparent` (`backdrop="transparent"`) no longer dims the page behind it. It only removed the blur before.
487
+ - `FieldGroup` `name` only applies to its own fields in Astro and Vue.
488
+ - `FieldGroup` `orientation="vertical"` stacks a group of only buttons.
489
+ - `FieldGroup` in Vue passes a `name` that changes or comes from an outer group to its inputs.
490
+ - `Fieldset` no longer overrides the error color of an invalid `Checkbox`, `Radio` or `Switch` end text inside it. Its helper styles only apply to its own end text.
491
+ - `Fieldset`, `FieldLegend`, `FieldDescription`, `FieldGroup` and `Form` in Vue no longer apply attributes and listeners twice.
492
+ - `Form` only resets the margin of dividers that are its direct children, text dividers included, so dividers nested deeper keep `--ui-divider-gap`.
493
+ - `List` and `Menu` descriptions on a selected or current row, and `Select` options, read `--ui-on-selected` when a theme sets it, instead of keeping `--ui-text` on the selected fill.
494
+ - `List` separators (`.ui-bordered`, `.ui-border-top`) are visible on tonal lists in dark mode.
495
+ - `List` text can shrink below its longest word, and `.ui-inset` follows the dense gap.
496
+ - `List` and `Table` borders on filled lists and table headers are visible in light mode.
497
+ - `List` keyboard shortcuts in `.ui-end` pass contrast.
498
+ - `List` rows with a video keep their end padding on the text side in right-to-left.
499
+ - `List` row text styles no longer reach the `.ui-text` of buttons and chips inside a row, and `.ui-end` only sizes `svg` icons that are its direct children.
500
+ - `List` `.ui-dense` also shrinks group labels in grouped lists, such as a dense Select.
501
+ - `List` text inherits the item's font weight, so `font-weight` on an `li` makes the whole row bold, e.g. for unread items.
502
+ - `List` only caps the start column at the icon size when it holds an `svg` directly, so an `Avatar` with an icon keeps its size.
503
+ - `List` sizes switches, checkboxes and radios through the public tokens, so switch sizes round to whole pixels in lists, and a size class on the control wins over the list's size.
504
+ - `List` `.ui-dense` tightens the separators of `.ui-bordered` lists too, not only `.ui-border-top`.
505
+ - `List` without a variant sets the field border to its own border, so checkbox and radio rings show on the filled row.
506
+ - `List` `.ui-end` passes clicks to a `label`, `select`, `summary`, `textarea` or `[tabindex]` element inside it, not only to links, buttons and inputs.
507
+ - `List` rows no longer force every element inside them to the row's font size, so a `Chip`, `Badge` or `Button` in `.ui-start` or `.ui-end` keeps its own size.
508
+ - `List` on touch screens only stops text selection in clickable rows (`a`, `button` and `label`), so end text and `Select` options can be selected and copied.
509
+ - `ListItem` with `href` and no `as` renders a link in Astro and Vue.
510
+ - `ListItem` with `as="button"` renders `type="button"`, so it no longer submits a surrounding form.
511
+ - `ListItem` `inset` no longer indents the label of a Chip or Button placed in `.ui-end`.
512
+ - `ListItem` with `type` renders the default slot inside `.ui-text` (or before `.ui-end` when there's no text), like it does without `type`.
513
+ - `ListItem` with `as="button" disabled` (or `aria-disabled="true"` on a link) looks disabled in a plain `List` too: dimmed, `not-allowed` cursor, no hover tint.
514
+ - `Progress` pulses in place under reduced motion (`--ui-motion: 0`, or `--_motion: 0` on the bar) instead of freezing. Its indeterminate animation was scaled to `0s`.
515
+ - `Progress` in Astro types `max` and `value` like React and Svelte, instead of intersecting them with the native `progress` attributes.
516
+ - `Radio` large (`.ui-large`) uses `--ui-choice-size-large`. It was the same size as the default.
517
+ - `Radio` sizes work on touch screens. Small and large radios were forced to `--size-4`, and the label sat off center.
518
+ - `Radio` dot is centered at every size. It was half a pixel off at small, default and large.
519
+ - `Radio` dot stays centered at every zoom level and screen scale. It's a `radial-gradient()` on the input's background instead of a separate `::after` box.
520
+ - `Radio` in Vue follows a passed `checked` without `v-model`.
521
+ - `Radio` in Vue compares `v-model` with its `value` like a native radio, so `ref(1)` checks the radio with `value="1"`.
522
+ - `Range` focus ring sits `--ui-focus-ring-offset` outside the thumb instead of `1ex` outside the track, also at every size.
523
+ - `Range` with `spread` (`.ui-spread`) collapses to a column when narrower than 400px, like `TextField`. The container query had no container, so it never applied, and the slider's minimum width could push its parent wider.
524
+ - `Range` in Vue shows the default value without `value` or `v-model`, and `v-model` returns a number.
525
+ - `Range` and `ToggleButton` in Vue take the `FieldGroup` name.
526
+ - `Range` invalid state colors the thumb and its halo too, except on a disabled range.
527
+ - `Range` fills the track in Chromium and Safari without JavaScript, also in plain HTML, with a scroll-driven animation. The hover ring is no longer clipped at min or max.
528
+ - `Range` with `spread`, a value and tick marks no longer draws the value over the tick labels, and the end text of a narrow spread range no longer overlaps the slider or the tick labels.
529
+ - `Range` tick labels line up with the thumb at both ends.
530
+ - `Range` updates its value `<output>` after its form is reset, in every browser, and leaves it when a `reset` listener cancels the reset. In Vue and Svelte, a range rendered on the client resets to the value it started with, instead of the middle of its range.
531
+ - `Range` (Astro) updates its value output after `<ClientRouter>` navigation, leaves `value-text` slot content and ranges it didn't render alone, and wires each output once.
532
+ - `Range` thumb stays centered on the track when `--_thumb-size` or `--_track-block-size` changes, also on touch screens.
533
+ - `Range` in a disabled `fieldset` gets the disabled thumb and no hover ring, like a disabled range.
534
+ - `Range` disabled thumb is opaque, so the track no longer shows through it.
535
+ - `Range` value lines up with the label's baseline.
536
+ - `Range` with a value readout points its root `<label>` at the input, so the label names the slider instead of the `<output>`.
537
+ - `Range` declares `--_track-block-size` and `--_track-radius` on the root, so setting them on the component works.
538
+ - `Range` with `variant="filled"` or `variant="tonal"` darkens its track on press and takes the disabled track color.
539
+ - `Range` hides its tick mark `<datalist>` from assistive technology with `aria-hidden="true"`, so it isn't exposed as an unnamed listbox next to the slider.
540
+ - `Select` with `spread` centers its arrow on the field.
541
+ - `Select` keeps its arrow and its space at the inline end in RTL. The arrow covered the text.
542
+ - `Select` keeps its padding and the height of the other fields in browsers that keep the `<button>` inside the `<select>` but have no customizable select, like Firefox, and wherever React, Svelte or Vue render it in the browser. The button turned the padding off there.
543
+ - `Select`, `Textarea` and `TextField` draw the focus ring around the field, like `Button`, only when the control itself has focus, not a link in the top or bottom slot. The border keeps its color while the ring shows.
544
+ - `Select` only opts selects inside `.ui-select` into `appearance: base-select`.
545
+ - `Select` and `TextField` show the select and autosuggest chevrons in forced colors mode.
546
+ - `Select` no longer shows the picker's square corners and shadow outside the rounded option list.
547
+ - `Select` and `Range` merge a user `aria-describedby` with the end text id instead of overwriting it.
548
+ - `Select` (Vue) keeps the browser's selection without `v-model`.
549
+ - `Select` adds its top slot, start text (`.ui-start-text`), end text and bottom slot to `aria-describedby`, in that order.
550
+ - `Select` `--_motion: 0` on the root also stops the picker animation.
551
+ - `Select` and `Range` in Astro merge a passed `aria-labelledby` instead of rendering the attribute twice.
552
+ - `Spinner` slows down to 1.5s per turn under reduced motion (`--ui-motion: 0`) instead of ignoring it.
553
+ - `Spinner` no longer sets `position: relative` on dialogs and popovers, so a busy `Drawer` stays in place.
554
+ - `Spinner` keeps the gap in its ring in forced colors, so the spin stays visible.
555
+ - `Switch` no longer needs Vite's `import.meta.env` types or runtime for its dev-only missing name warning.
556
+ - `Switch` icons shrink to fit beside the dot when the track is too narrow for both, instead of overlapping the dot.
557
+ - `Switch` focus ring is rounded.
558
+ - `Switch` draws its invalid ring as a `box-shadow`, so the focus ring shows outside it. In forced colors an invalid switch no longer looks focused.
559
+ - `Switch` gets the pointer cursor, `--ui-line-height-control` line height and `user-select: none` of `Checkbox` and `Radio`.
560
+ - `Switch` checked icon uses the dot's contrast color, so it shows on the accent track.
561
+ - `Table` padding no longer grows in narrow containers.
562
+ - `Table` uses `overflow: clip` instead of `overflow: hidden`, so it is no longer a scroll container and sticky cells inside it stick.
563
+ - `Table` footer rules and the row above the footer apply to `th` as well as `td`, so row headers line up with the footer line and a `th` in `tfoot` gets its top border and padding.
564
+ - `Table` row hover only highlights body rows, not the header or footer.
565
+ - `Table` row headers (`<th scope="row">`, or a `th` next to `td` cells in `tbody`) keep the body background instead of the header fill.
566
+ - `Table` no longer clips the focus ring of controls in its first and last rows.
567
+ - `Table` row headers keep the border color of the body cells next to them.
568
+ - `Table` without a `thead` rounds its top corners when the first row starts with a row header `th`.
569
+ - `TableColumn` in Astro keeps `width` when `style` is an object.
570
+ - `Tabs` and `ToggleGroup` context only applies to their own children in Astro.
571
+ - `Tabs`, `TabsItem`, `ToggleGroup`, `Select`, `Range`, `Checkbox`, `Radio` and `Switch` in Vue render the same generated id prefixes as the other frameworks.
572
+ - `Tabs` in Astro names a `TabsItem` outside a `Tabs` and links its `TabsLabel`, like React and Svelte.
573
+ - `Tabs` and `ToggleButton` hide their inputs in `tabs.css` and `toggle-button.css` instead of `core/utils.css`, so single-file imports and `dist/opui.components.css` no longer show the radio and checkbox inputs.
574
+ - `Tabs` directly in an `Accordion`, `Card` or `Dialog` draw the focus ring inside, so the surface doesn't clip it, and on a filled selected tab the ring takes `--ui-on-selected-strong`, so it keeps 3:1 on the fill.
575
+ - `TabsItem` in Vue follows `id` and `tabId` changes.
576
+ - `Textarea` no longer adds the border width to its minimum height.
577
+ - `TextField`, `Textarea` and `Select` with `spread` (`.ui-spread`) collapse to a column when narrower than 400px. Previously the field was squeezed next to the label.
578
+ - `TextField` and `Select` small fields are `--ui-field-size-small` (32px) high, like a small `Button`. They were 38px.
579
+ - `TextField` date, time, week and month inputs no longer grow taller than the field, so small ones are 32px and time inputs are no longer 41px.
580
+ - `TextField` file inputs are `--ui-field-size` high. They were 2px taller.
581
+ - `TextField`, `Textarea` and `Select` keep their field height when a grid or flex parent stretches them, e.g. next to a field with end text. The extra space went into the field.
582
+ - `TextField` start and end icons are capped at `--ui-icon-size`, so a large icon no longer makes the field taller.
583
+ - `TextField` autosuggest arrow sits at the inline end in RTL. It overlapped the text.
584
+ - `TextField` and `Select` without a label are as high as their field. The empty label row added 4px above it.
585
+ - `TextField` start and end affixes use the field line height, so they no longer make the field taller on pages with a large line height.
586
+ - `TextField`, `Textarea` and `Select` no longer darken a filled field on hover when a disabled `fieldset` disables it.
587
+ - `TextField` with a `list` and `Select` no longer shorten the label by 28px.
588
+ - `TextField` and `Textarea` with `autoFit` (`.ui-auto-fit`) shrink to their content in a block container or a field group, up to the container's width, and long helper text wraps at the field's width. They filled the container.
589
+ - `TextField`, `Textarea` and `Select` (Vue) can be edited when given a `value` without `v-model`.
590
+ - `TextField`, `Textarea` and `Select` required asterisks are spaced like the `Checkbox`, `Radio`, `Switch` and `Fieldset` ones (`0.25ex`).
591
+ - `TextField` and `Select` with `spread` keep the start text under the label when the field has a top or bottom slot.
592
+ - `TextField`, `Select` and `Textarea` look disabled when a disabled `fieldset` disables the control or it has `aria-disabled="true"`, and a disabled `option` no longer makes a `Select` look disabled. Read-only and `aria-disabled` fields get no hover styles.
593
+ - `TextField` and `Select` keep the control height of buttons in Firefox and Safari. Single-line inputs and selects get a definite height, `1lh` plus their padding, so the engine's own input height and padding rounding no longer make the field up to 2px taller.
594
+ - `ToggleButton` draws the focus ring of a checked button in `--ui-on-selected` (or `--ui-on-primary`), so the inset ring shows on the fill in dark mode.
595
+ - `ToggleButton` only grows inside a `ToggleGroup`. On its own in a flex container it stretched to fill the row.
596
+ - `ToggleButton` in Vue is a radio in a single-selection `ToggleGroup`, like Astro, even with a `type`.
597
+ - `ToggleButton` keeps its selected tint on hover, also in a `ToggleGroup`, and a disabled selected button no longer changes on hover.
598
+ - `ToggleButton` declares `--_selected-bg-color` on the root with its other inputs, so an override on `.ui-toggle-button` reaches the checked button instead of losing to the checked rule.
599
+ - `ToggleGroup` in Svelte and Vue leaves each button's own `checked` alone when no `value` is bound, like React.
600
+ - `ToggleGroup` keeps its control size in forced colors instead of being one border width short, and the selected item no longer shows a gray divider there.
601
+ - `ToggleGroup` `.ui-vertical` items stretch to the group's width, like `ButtonGroup`, so dividers and the checked background line up.
602
+ - `ToggleGroup` is as high as a `ToggleButton` of the same size. The group border made it 2px taller.
603
+ - `ToggleGroup` separators show in forced colors.
604
+ - `Tooltip` transitions now respect `--ui-motion` (`prefers-reduced-motion`, `.ui-motion-off`).
605
+ - `Tooltip` shifts along the viewport edge instead of squeezing, with or without an arrow, and shows when its trigger is more than one viewport down the page.
606
+ - `Tooltip` arrow points at the trigger for every position, after flips and shifts.
607
+ - `Tooltip` keeps its edge in forced colors with a `CanvasText` border, and the arrow stays visible.
608
+ - `Tooltip` aligned to a span switches inline sides before it jumps to the other block side.
609
+ - `Typography` rich text inline `code`, `kbd` and `var` no longer make their line taller than the line height.
610
+ - `Typography` `kbd`, `var`, `.ui-kbd` and `.ui-var` no longer draw a border in their own background color. The border width is folded into the padding, so the box keeps its size.
611
+ - `Typography` rich text removes the top margin of the first child and the bottom margin of the last child in a component's `.ui-content`.
612
+ - `Typography` rich text lists after a heading or `hr` no longer get a top margin, and nested lists get their smaller margins.
613
+ - `Typography` rich text no longer overflows grid and flex parents with long words, URLs or code lines, and list items, figure content and table cells no longer push it wider than its container on narrow viewports.
614
+ - `Typography` rich text inline `code` styles no longer apply to `code` inside `pre`.
615
+ - `Typography` rich text `ol[type]` keeps its marker type, and consecutive `dt` elements are no longer spaced apart.
616
+ - `Typography` rich text no longer styles an `a` without `href` as a link.
617
+ - `Typography` rich text `code` inside a link gets a darker background in dark mode, so the link color keeps its contrast.
618
+ - `Typography` `.ui-mark` has a background, and `del`, `ins`, `.ui-del` and `.ui-ins` text reads `--ui-critical-text` and `--ui-success-text`, so it passes contrast in light and dark mode.
619
+ - `Typography` rich text `pre` and inline `code` run left to right in RTL.
620
+ - `Typography` `.ui-p.ui-small` is `--ui-font-size-small` (14px) instead of 12px.
621
+ - `Typography` `.ui-abbr` and `.ui-dfn` underlines use the info color, like `abbr` and `dfn`.
622
+ - `Typography` overline and heading group overline text, `code` in dark mode, `code` in `del`/`ins`, linked `code` in light mode and links in `mark` pass contrast.
623
+ - `Typography` inline `code` directly inside `.ui-rich-text` gets the same padding and radius as inline code in a paragraph.
624
+ - `Typography` `.ui-small` also applies to `<small>`.
625
+ - `Typography` inline `code` in `del` and `ins` has no inline padding, so no gap shows before the next character.
626
+ - `Typography` `abbr` and `dfn` with a `title` get the same underline offset as without one.
627
+ - `Typography` linked `code` in rich text has no inline padding where its background is transparent, so the underline doesn't run past the text.
628
+ - `Typography` `.ui-small` on a `span` or `p` sits below the component layers, so a small `Chip` rendered as a `span` keeps its own font size.
629
+ - `button.css` gives file inputs outside a `TextField` readable text (`--ui-text`) and the field border tokens. The text used the inverse surface color.
630
+ - `components/AGENTS.md`, the internal guide, no longer ships in the package.
631
+ - `dist` source maps no longer embed the sources (`sourcesContent`) or `node_modules/.pnpm` paths. Open Props sources point to `../../open-props/`, and `opui.components.css.map` accounts for the `@layer` order line.
632
+ - `dist/opui.components.css` starts with the `@layer` order statement.
633
+ - `env.d.ts` is in the package `exports`, so `/// <reference types="opui-css/env.d.ts" />` resolves.
634
+ - `env.d.ts` types `interestfor` on `<a>` and `<button>` for Astro.
635
+ - `normalize.css` gives `.ui-light` and `.ui-dark` on an element other than `html` the page surface and text color, and `.ui-contrast-more` on one the text, accent and caret colors. `theme.css` declares `--ui-color-scheme`, `light` on `html` and `dark` under the OS preference or `.ui-dark`, so `Typography` reads the right scheme without a class.
636
+ - `normalize.css` gives autofilled fields `--ui-surface` instead of the undefined `--well-1`.
637
+ - `normalize.css` body text reads `--ui-font-weight-normal` and headings `--ui-font-weight-bold`, so a theme's weights reach bare text and headings.
638
+ - `opui-css/css/js/checkbox.js` resolves through `exports`. It resolved to `checkbox.js.css`.
639
+ - `opui-css/open-props.css` resolves through `exports`.
640
+ - `opui-css/react` adds its element types with `import type {} from "react"`, so the type-only module no longer imports React at runtime.
641
+ - `package.json` `exports` resolve documented source imports with a `.css` extension (`opui-css/css/imports.css`, `opui-css/core/normalize.css`, `opui-css/css/components/button.css`, …) Previously they resolved to `*.css.css`.
642
+ - `package.json` peer dependency ranges are `astro` `^7`, `svelte` `^5.57` and `vue` `^3.5` instead of the versions used for development.
643
+ - `theme.css` shadows take a darker `--ui-shadow-color` in dark mode (`.ui-dark`, also on a part of the page, and the OS preference), so they show on dark surfaces. They used the light values before, and a part forced to `.ui-light` keeps them.
644
+
645
+ ## 5.4.3 - 2026-09-18
646
+
647
+ ### Fixed
648
+
649
+ Fix publish pnpm issue ([#357](https://github.com/felix-bohlin/ui/issues/357)) - thanks @onokumus!
650
+
3
651
  ## 5.4.2 - 2026-06-29
4
652
 
5
653
  ### Fixed