@nubisco/ui 4.1.4 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (308) hide show
  1. package/dist/{AiLabel-VbZiFHAZ.js → AiLabel-Ci7eROcw.js} +1 -1
  2. package/dist/{AiLabel-DZ9GkGqL.cjs → AiLabel-DtM5ZCQC.cjs} +1 -1
  3. package/dist/{Banner-7XsX8ibI.js → Banner-C5Erb75B.js} +1 -1
  4. package/dist/{Banner-DI5fA8Ow.cjs → Banner-JubX-4yR.cjs} +1 -1
  5. package/dist/{BlueprintControls-CJAKrQ6U.js → BlueprintControls-BkwhsHI8.js} +1 -1
  6. package/dist/{BlueprintControls-aF11uokn.cjs → BlueprintControls-CdvNvRkW.cjs} +1 -1
  7. package/dist/{BlueprintMinimap-C-gCkMIW.cjs → BlueprintMinimap-BIBsnBFs.cjs} +1 -1
  8. package/dist/{BlueprintMinimap-C-65UzhM.js → BlueprintMinimap-QAw6aiCc.js} +1 -1
  9. package/dist/{BottomPanel-B-dhgMWB.js → BottomPanel-BoBCdANz.js} +1 -1
  10. package/dist/{BottomPanel-CmVH0Hsf.cjs → BottomPanel-dbllmH2v.cjs} +1 -1
  11. package/dist/Button-Dwv0rx46.cjs +1 -0
  12. package/dist/{Button-Cegx6vaT.js → Button-Q8MBLMvG.js} +12 -4
  13. package/dist/{Card-Cs-7jXxG.cjs → Card-Cn5OS4q-.cjs} +1 -1
  14. package/dist/{Card-TjV_N8RU.js → Card-eM6DEphF.js} +1 -1
  15. package/dist/{Checkbox-BJrnykX9.js → Checkbox-DG82KK8V.js} +1 -1
  16. package/dist/{Checkbox-D9qW3gph.cjs → Checkbox-vFN3fLyr.cjs} +1 -1
  17. package/dist/{CheckboxGroup-CUSPscyy.js → CheckboxGroup-5pmdu9fe.js} +1 -1
  18. package/dist/{CheckboxGroup-mWcKUeq9.cjs → CheckboxGroup-Cyj2NUtI.cjs} +1 -1
  19. package/dist/{ColorStrip-CR1JDzwX.js → ColorStrip-BBTJU1Ox.js} +47 -45
  20. package/dist/ColorStrip-D3nbTyfs.cjs +1 -0
  21. package/dist/CommandPalette-CPJKTiDt.cjs +1 -0
  22. package/dist/CommandPalette-iaEdat_y.js +223 -0
  23. package/dist/{Confirm-pgn2HajX.js → Confirm-C-HRTF0s.js} +23 -52
  24. package/dist/Confirm-w3Ig0L5j.cjs +1 -0
  25. package/dist/{DataTable-c0ltF6wT.js → DataTable-BVxSUB-h.js} +3 -3
  26. package/dist/{DataTable-BbiDmA1X.cjs → DataTable-Cnyh04sD.cjs} +1 -1
  27. package/dist/{DatePicker-YJ8-ViVK.js → DatePicker-BimOzKti.js} +1 -1
  28. package/dist/{DatePicker-C8_qR25v.cjs → DatePicker-CMPgr4Hp.cjs} +1 -1
  29. package/dist/{EmptyState-DVg8l-bl.js → EmptyState-CwMG-NeI.js} +1 -1
  30. package/dist/{EmptyState-henL7JH6.cjs → EmptyState-Cz91HAKF.cjs} +1 -1
  31. package/dist/{FileUploader-Lzy4bFn7.cjs → FileUploader-BJdRC-Kp.cjs} +1 -1
  32. package/dist/{FileUploader-BLwR6H3f.js → FileUploader-BO2cDUwP.js} +2 -2
  33. package/dist/{ImageCropper-CpEGFPKb.cjs → ImageCropper-D7mr-xRE.cjs} +1 -1
  34. package/dist/{ImageCropper-BX2BnJai.js → ImageCropper-DEaGU0cZ.js} +1 -1
  35. package/dist/{InfoHint-DesESwdO.cjs → InfoHint-BNpqLVSX.cjs} +1 -1
  36. package/dist/{InfoHint-JwhhBFZP.js → InfoHint-C663u_NL.js} +1 -1
  37. package/dist/{InlineEdit-CZEt1vhH.cjs → InlineEdit-D95I45Vt.cjs} +1 -1
  38. package/dist/{InlineEdit-DNMF_40m.js → InlineEdit-DrhJ0AX2.js} +1 -1
  39. package/dist/{Message-Daj6hLC4.cjs → Message-Ax7rnAQl.cjs} +1 -1
  40. package/dist/{Message-BuG5t7bu.js → Message-DqUW3GHc.js} +1 -1
  41. package/dist/Modal-B1CQyPNo.js +206 -0
  42. package/dist/Modal-DvukGfHg.cjs +1 -0
  43. package/dist/{NotificationCenter-DL_Tshyb.js → NotificationCenter-Duu3XZC3.js} +3 -3
  44. package/dist/{NotificationCenter-D51ty3Lq.cjs → NotificationCenter-oOzClQI-.cjs} +1 -1
  45. package/dist/{NumberInput-Vc2wzK62.cjs → NumberInput-DKZsdWLv.cjs} +1 -1
  46. package/dist/{NumberInput-6R8FkJc-.js → NumberInput-_ff3Xi2r.js} +2 -2
  47. package/dist/{Pagination-B6a62qvI.js → Pagination-6bF88x_p.js} +3 -3
  48. package/dist/{Pagination-CkBe9Naz.cjs → Pagination-EipK6BGe.cjs} +1 -1
  49. package/dist/{Panel-BVtGI7YH.js → Panel-D3s_MKfd.js} +1 -1
  50. package/dist/{Panel-DQfmVtie.cjs → Panel-qDfyu_0v.cjs} +1 -1
  51. package/dist/{ProgressBar-fAaKT9lD.cjs → ProgressBar-CbqsSdZZ.cjs} +1 -1
  52. package/dist/{ProgressBar-DjejtCKA.js → ProgressBar-aF2zBoRA.js} +2 -2
  53. package/dist/{Radio-CQveGtXr.js → Radio-BnI7bi9Y.js} +2 -2
  54. package/dist/{Radio-DSvkUCxV.cjs → Radio-BqjtCaST.cjs} +1 -1
  55. package/dist/{ReorderList-Bai4yaIG.cjs → ReorderList-DLQ3rVnX.cjs} +1 -1
  56. package/dist/{ReorderList-Be-qicSf.js → ReorderList-DpytAupm.js} +1 -1
  57. package/dist/{Select-swFFQIMN.js → Select-B5t5QtVe.js} +1 -1
  58. package/dist/{Select-ClCyOqQI.cjs → Select-dAYn2iZO.cjs} +1 -1
  59. package/dist/{Shell-B8YmApR6.cjs → Shell-9lzopP-w.cjs} +1 -1
  60. package/dist/{Shell-Dr7LHIqk.js → Shell-B3jhTiNP.js} +99 -96
  61. package/dist/{ShellPanel-I0ZMGQ4K.js → ShellPanel-B3vZcQhX.js} +1 -1
  62. package/dist/{ShellPanel-CnN9orWH.cjs → ShellPanel-ChujN0eX.cjs} +1 -1
  63. package/dist/{SidebarLink-y2If8dtl.js → SidebarLink-B_CGHs0b.js} +1 -1
  64. package/dist/{SidebarLink-CngTvuB6.cjs → SidebarLink-CZrDLC8g.cjs} +1 -1
  65. package/dist/{SidebarMenuItem-DoyuIs3w.cjs → SidebarMenuItem-Dc6oh2Nc.cjs} +1 -1
  66. package/dist/{SidebarMenuItem-DBINoxeA.js → SidebarMenuItem-Dpqr9e0A.js} +1 -1
  67. package/dist/{Skeleton-D8CHd_4p.cjs → Skeleton-DP9iM6Ku.cjs} +1 -1
  68. package/dist/{Skeleton-CC7LVdxd.js → Skeleton-sox6qUDk.js} +1 -1
  69. package/dist/Slider-BNiQaaVa.cjs +1 -0
  70. package/dist/{Slider-lOhGG7UX.js → Slider-C0761rBk.js} +47 -33
  71. package/dist/{StepperStep-w1SSX7t7.cjs → StepperStep-B9JEE6WJ.cjs} +1 -1
  72. package/dist/{StepperStep-DNXUj71b.js → StepperStep-DFeOJ1ju.js} +1 -1
  73. package/dist/{Tabs-W_4iyGVx.js → Tabs-CQP9zwDw.js} +1 -1
  74. package/dist/{Tabs-Clg7lzy5.cjs → Tabs-Dp27EDrK.cjs} +1 -1
  75. package/dist/{TextInput-CGD_wFwo.cjs → TextInput-D4jBlYm9.cjs} +2 -2
  76. package/dist/{TextInput-CxC2HVj6.js → TextInput-DNrd12uS.js} +2 -2
  77. package/dist/{Toast-DueO27yl.cjs → Toast-BBsrCQK8.cjs} +1 -1
  78. package/dist/{Toast-QXobTGZM.js → Toast-cisfK5Zd.js} +1 -1
  79. package/dist/{Toaster-DcA6PJPt.js → Toaster-C1Uyr6O7.js} +1 -1
  80. package/dist/{Toaster-DY8o_iiy.cjs → Toaster-Dz_o--LF.cjs} +1 -1
  81. package/dist/{TreeNode-DS1XJGty.cjs → TreeNode-DB7ipWCg.cjs} +1 -1
  82. package/dist/{TreeNode-BI-Azvhe.js → TreeNode-a0MHLI27.js} +1 -1
  83. package/dist/{Walkthrough-DHtLDsOk.cjs → Walkthrough-YD3YYxxM.cjs} +1 -1
  84. package/dist/{Walkthrough-l7HOZths.js → Walkthrough-qaQ1rved.js} +2 -2
  85. package/dist/all.cjs +1 -1
  86. package/dist/all.mjs +137 -135
  87. package/dist/component-styles.json +1 -1
  88. package/dist/components/AiLabel.cjs +1 -1
  89. package/dist/components/AiLabel.mjs +1 -1
  90. package/dist/components/AiLabel.vue.d.ts.map +1 -1
  91. package/dist/components/Banner.cjs +1 -1
  92. package/dist/components/Banner.mjs +1 -1
  93. package/dist/components/Banner.vue.d.ts.map +1 -1
  94. package/dist/components/BlueprintControls.cjs +1 -1
  95. package/dist/components/BlueprintControls.mjs +1 -1
  96. package/dist/components/BlueprintMinimap.cjs +1 -1
  97. package/dist/components/BlueprintMinimap.mjs +1 -1
  98. package/dist/components/BlueprintMinimap.vue.d.ts.map +1 -1
  99. package/dist/components/Board.vue.d.ts.map +1 -1
  100. package/dist/components/BottomPanel.cjs +1 -1
  101. package/dist/components/BottomPanel.mjs +1 -1
  102. package/dist/components/BottomPanel.vue.d.ts.map +1 -1
  103. package/dist/components/Button.cjs +1 -1
  104. package/dist/components/Button.d.ts +25 -1
  105. package/dist/components/Button.mjs +1 -1
  106. package/dist/components/Button.vue.d.ts +1 -1
  107. package/dist/components/Button.vue.d.ts.map +1 -1
  108. package/dist/components/Calendar.vue.d.ts.map +1 -1
  109. package/dist/components/Card.cjs +1 -1
  110. package/dist/components/Card.mjs +1 -1
  111. package/dist/components/Card.vue.d.ts.map +1 -1
  112. package/dist/components/Checkbox.cjs +1 -1
  113. package/dist/components/Checkbox.mjs +1 -1
  114. package/dist/components/Checkbox.vue.d.ts.map +1 -1
  115. package/dist/components/CheckboxGroup.cjs +1 -1
  116. package/dist/components/CheckboxGroup.mjs +1 -1
  117. package/dist/components/ColorStrip.cjs +1 -1
  118. package/dist/components/ColorStrip.mjs +1 -1
  119. package/dist/components/ColorStrip.vue.d.ts.map +1 -1
  120. package/dist/components/CommandPalette.cjs +1 -1
  121. package/dist/components/CommandPalette.d.ts +28 -0
  122. package/dist/components/CommandPalette.mjs +1 -1
  123. package/dist/components/CommandPalette.vue.d.ts +2 -0
  124. package/dist/components/CommandPalette.vue.d.ts.map +1 -1
  125. package/dist/components/Confirm.cjs +1 -1
  126. package/dist/components/Confirm.mjs +1 -1
  127. package/dist/components/Confirm.vue.d.ts +1 -1
  128. package/dist/components/Confirm.vue.d.ts.map +1 -1
  129. package/dist/components/DataTable.cjs +1 -1
  130. package/dist/components/DataTable.mjs +1 -1
  131. package/dist/components/DataTable.vue.d.ts.map +1 -1
  132. package/dist/components/DatePicker.cjs +1 -1
  133. package/dist/components/DatePicker.mjs +1 -1
  134. package/dist/components/DatePicker.vue.d.ts.map +1 -1
  135. package/dist/components/EmptyState.cjs +1 -1
  136. package/dist/components/EmptyState.mjs +1 -1
  137. package/dist/components/EmptyState.vue.d.ts.map +1 -1
  138. package/dist/components/FileUploader.cjs +1 -1
  139. package/dist/components/FileUploader.mjs +1 -1
  140. package/dist/components/FileUploader.vue.d.ts.map +1 -1
  141. package/dist/components/ImageCropper.cjs +1 -1
  142. package/dist/components/ImageCropper.mjs +1 -1
  143. package/dist/components/ImageCropper.vue.d.ts.map +1 -1
  144. package/dist/components/InfoHint.cjs +1 -1
  145. package/dist/components/InfoHint.mjs +1 -1
  146. package/dist/components/InfoHint.vue.d.ts.map +1 -1
  147. package/dist/components/InlineEdit.cjs +1 -1
  148. package/dist/components/InlineEdit.mjs +1 -1
  149. package/dist/components/InlineEdit.vue.d.ts.map +1 -1
  150. package/dist/components/Menu.vue.d.ts.map +1 -1
  151. package/dist/components/MenuItem.vue.d.ts.map +1 -1
  152. package/dist/components/Message.cjs +1 -1
  153. package/dist/components/Message.mjs +1 -1
  154. package/dist/components/Message.vue.d.ts.map +1 -1
  155. package/dist/components/Modal.cjs +1 -1
  156. package/dist/components/Modal.d.ts +39 -0
  157. package/dist/components/Modal.mjs +1 -1
  158. package/dist/components/Modal.vue.d.ts +3 -0
  159. package/dist/components/Modal.vue.d.ts.map +1 -1
  160. package/dist/components/NotificationCenter.cjs +1 -1
  161. package/dist/components/NotificationCenter.mjs +1 -1
  162. package/dist/components/NotificationCenter.vue.d.ts.map +1 -1
  163. package/dist/components/NotificationCenterItem.vue.d.ts.map +1 -1
  164. package/dist/components/NumberInput.cjs +1 -1
  165. package/dist/components/NumberInput.mjs +1 -1
  166. package/dist/components/NumberInput.vue.d.ts.map +1 -1
  167. package/dist/components/Pagination.cjs +1 -1
  168. package/dist/components/Pagination.mjs +1 -1
  169. package/dist/components/Pagination.vue.d.ts.map +1 -1
  170. package/dist/components/Panel.cjs +1 -1
  171. package/dist/components/Panel.mjs +1 -1
  172. package/dist/components/Panel.vue.d.ts.map +1 -1
  173. package/dist/components/ProgressBar.cjs +1 -1
  174. package/dist/components/ProgressBar.mjs +1 -1
  175. package/dist/components/ProgressBar.vue.d.ts.map +1 -1
  176. package/dist/components/Radio.cjs +1 -1
  177. package/dist/components/Radio.mjs +1 -1
  178. package/dist/components/Radio.vue.d.ts.map +1 -1
  179. package/dist/components/ReorderList.cjs +1 -1
  180. package/dist/components/ReorderList.mjs +1 -1
  181. package/dist/components/ReorderList.vue.d.ts.map +1 -1
  182. package/dist/components/Select.cjs +1 -1
  183. package/dist/components/Select.mjs +1 -1
  184. package/dist/components/Select.vue.d.ts.map +1 -1
  185. package/dist/components/Shell.cjs +1 -1
  186. package/dist/components/Shell.mjs +1 -1
  187. package/dist/components/Shell.vue.d.ts.map +1 -1
  188. package/dist/components/ShellPanel.cjs +1 -1
  189. package/dist/components/ShellPanel.mjs +1 -1
  190. package/dist/components/ShellPanel.vue.d.ts.map +1 -1
  191. package/dist/components/SidebarLink.cjs +1 -1
  192. package/dist/components/SidebarLink.mjs +1 -1
  193. package/dist/components/SidebarLink.vue.d.ts.map +1 -1
  194. package/dist/components/SidebarMenuItem.cjs +1 -1
  195. package/dist/components/SidebarMenuItem.mjs +1 -1
  196. package/dist/components/SidebarMenuItem.vue.d.ts.map +1 -1
  197. package/dist/components/Skeleton.cjs +1 -1
  198. package/dist/components/Skeleton.mjs +1 -1
  199. package/dist/components/Skeleton.vue.d.ts.map +1 -1
  200. package/dist/components/Slider.cjs +1 -1
  201. package/dist/components/Slider.d.ts +8 -0
  202. package/dist/components/Slider.mjs +1 -1
  203. package/dist/components/Slider.vue.d.ts +1 -0
  204. package/dist/components/Slider.vue.d.ts.map +1 -1
  205. package/dist/components/StepperStep.cjs +1 -1
  206. package/dist/components/StepperStep.mjs +1 -1
  207. package/dist/components/StepperStep.vue.d.ts.map +1 -1
  208. package/dist/components/Tabs.cjs +1 -1
  209. package/dist/components/Tabs.mjs +1 -1
  210. package/dist/components/Tabs.vue.d.ts.map +1 -1
  211. package/dist/components/TextInput.cjs +1 -1
  212. package/dist/components/TextInput.mjs +1 -1
  213. package/dist/components/TextInput.vue.d.ts.map +1 -1
  214. package/dist/components/Toast.cjs +1 -1
  215. package/dist/components/Toast.mjs +1 -1
  216. package/dist/components/Toast.vue.d.ts.map +1 -1
  217. package/dist/components/Toaster.cjs +1 -1
  218. package/dist/components/Toaster.mjs +1 -1
  219. package/dist/components/TreeNode.cjs +1 -1
  220. package/dist/components/TreeNode.mjs +1 -1
  221. package/dist/components/TreeNode.vue.d.ts.map +1 -1
  222. package/dist/components/UserMenu.vue.d.ts.map +1 -1
  223. package/dist/components/Walkthrough.cjs +1 -1
  224. package/dist/components/Walkthrough.mjs +1 -1
  225. package/dist/components/Walkthrough.vue.d.ts.map +1 -1
  226. package/dist/composables/useAppearance.composable.cjs +1 -0
  227. package/dist/composables/useAppearance.composable.d.ts +131 -0
  228. package/dist/composables/useAppearance.composable.d.ts.map +1 -0
  229. package/dist/composables/useAppearance.composable.mjs +65 -0
  230. package/dist/composables/useConfirm.composable.cjs +1 -1
  231. package/dist/composables/useConfirm.composable.mjs +2 -1
  232. package/dist/composables/useFocusTrap.composable.cjs +1 -0
  233. package/dist/composables/useFocusTrap.composable.d.ts +91 -0
  234. package/dist/composables/useFocusTrap.composable.d.ts.map +1 -0
  235. package/dist/composables/useFocusTrap.composable.mjs +98 -0
  236. package/dist/composables/useNamedTheme.composable.cjs +1 -0
  237. package/dist/composables/useNamedTheme.composable.d.ts +98 -0
  238. package/dist/composables/useNamedTheme.composable.d.ts.map +1 -0
  239. package/dist/composables/useNamedTheme.composable.mjs +68 -0
  240. package/dist/index.cjs +1 -1
  241. package/dist/index.mjs +45 -43
  242. package/dist/main.d.ts +5 -1
  243. package/dist/main.d.ts.map +1 -1
  244. package/dist/plugins/vite/index.d.ts.map +1 -1
  245. package/dist/plugins/vite/index.js +59 -0
  246. package/dist/styles/AiLabel.css +1 -1
  247. package/dist/styles/Banner.css +1 -1
  248. package/dist/styles/BlueprintMinimap.css +1 -1
  249. package/dist/styles/Board.css +1 -1
  250. package/dist/styles/BottomPanel.css +1 -1
  251. package/dist/styles/Button.css +1 -1
  252. package/dist/styles/Calendar.css +1 -1
  253. package/dist/styles/Card.css +1 -1
  254. package/dist/styles/Checkbox.css +1 -1
  255. package/dist/styles/ColorStrip.css +1 -1
  256. package/dist/styles/CommandPalette.css +1 -1
  257. package/dist/styles/Confirm.css +1 -1
  258. package/dist/styles/DataTable.css +1 -1
  259. package/dist/styles/DatePicker.css +1 -1
  260. package/dist/styles/EmptyState.css +1 -1
  261. package/dist/styles/FileUploader.css +1 -1
  262. package/dist/styles/ImageCropper.css +1 -1
  263. package/dist/styles/InfoHint.css +1 -1
  264. package/dist/styles/InlineEdit.css +1 -1
  265. package/dist/styles/Menu.css +1 -1
  266. package/dist/styles/MenuItem.css +1 -1
  267. package/dist/styles/Message.css +1 -1
  268. package/dist/styles/Modal.css +1 -1
  269. package/dist/styles/NotificationCenter.css +1 -1
  270. package/dist/styles/NotificationCenterItem.css +1 -1
  271. package/dist/styles/NumberInput.css +1 -1
  272. package/dist/styles/Pagination.css +1 -1
  273. package/dist/styles/Panel.css +1 -1
  274. package/dist/styles/ProgressBar.css +1 -1
  275. package/dist/styles/Radio.css +1 -1
  276. package/dist/styles/ReorderList.css +1 -1
  277. package/dist/styles/Select.css +1 -1
  278. package/dist/styles/Shell.css +1 -1
  279. package/dist/styles/ShellPanel.css +1 -1
  280. package/dist/styles/SidebarLink.css +1 -1
  281. package/dist/styles/SidebarMenuItem.css +1 -1
  282. package/dist/styles/Skeleton.css +1 -1
  283. package/dist/styles/Slider.css +1 -1
  284. package/dist/styles/StepperStep.css +1 -1
  285. package/dist/styles/Tabs.css +1 -1
  286. package/dist/styles/TextInput.css +1 -1
  287. package/dist/styles/Toast.css +1 -1
  288. package/dist/styles/TreeNode.css +1 -1
  289. package/dist/styles/UserMenu.css +1 -1
  290. package/dist/styles/Walkthrough.css +1 -1
  291. package/dist/ui.css +45 -45
  292. package/package.json +7 -4
  293. package/src/plugins/vite/index.ts +62 -0
  294. package/src/styles/_appearance.scss +144 -0
  295. package/src/styles/_theme-api.scss +193 -0
  296. package/src/styles/_theme.scss +91 -5
  297. package/src/styles/index.scss +8 -0
  298. package/src/styles/logic/_radius.scss +146 -0
  299. package/src/styles/logic/index.scss +1 -0
  300. package/src/styles/presets/_classic-fields.scss +55 -0
  301. package/dist/Button-Dqtcr4i0.cjs +0 -1
  302. package/dist/ColorStrip-CAcR1O_R.cjs +0 -1
  303. package/dist/CommandPalette-BNXzQurN.js +0 -174
  304. package/dist/CommandPalette-DBjeOPtA.cjs +0 -1
  305. package/dist/Confirm-CW160zEF.cjs +0 -1
  306. package/dist/Modal-8lgeNWj8.cjs +0 -1
  307. package/dist/Modal-iN94HtKE.js +0 -156
  308. package/dist/Slider-CxrK7cAU.cjs +0 -1
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@nubisco/ui",
3
- "version": "4.1.4",
3
+ "version": "5.1.0",
4
4
  "description": "Vue 3 UI component library",
5
- "packageManager": "pnpm@11.0.8",
5
+ "packageManager": "pnpm@12.3.4+sha512.961aa41fb077da3a04a441d9f8e15ebc0c96da8ef710b2eb67bf9ee7cb0610eabd48f1fd85f51cffe73846785fa0f87c56a3a872a1d893f8446741b5cce45457",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/nubisco/ui.git"
@@ -140,7 +140,7 @@
140
140
  "build:lib": "vite build",
141
141
  "build:types": "vue-tsc --noEmit false --declaration --emitDeclarationOnly --outDir dist && node scripts/copy-type-modules.mjs && node scripts/rewrite-dist-aliases.mjs dist",
142
142
  "build:plugins": "tsc --project tsconfig.plugins.json",
143
- "verify:types": "pnpm run verify:dist-types && pnpm run verify:consumer-types && pnpm run verify:consumer-globals && pnpm run verify:resolution && pnpm run verify:styles && pnpm run verify:glyph-defaults",
143
+ "verify:types": "pnpm run verify:dist-types && pnpm run verify:consumer-types && pnpm run verify:consumer-globals && pnpm run verify:resolution && pnpm run verify:styles && pnpm run verify:glyph-defaults && pnpm run verify:theme-export",
144
144
  "verify:dist-types": "node scripts/verify-dist-types.mjs dist",
145
145
  "verify:consumer-types": "node scripts/verify-consumer-types.mjs",
146
146
  "verify:consumer-globals": "node scripts/verify-consumer-globals.mjs",
@@ -162,7 +162,9 @@
162
162
  "generate": "node scripts/generate-component-manifest.mjs && node scripts/generate-assets.mjs && node scripts/generate-entries.mjs",
163
163
  "verify:resolution": "node scripts/verify-compile-time-resolution.mjs dist",
164
164
  "verify:styles": "node scripts/verify-style-split.mjs dist",
165
- "verify:glyph-defaults": "node scripts/verify-default-glyphs.mjs dist"
165
+ "verify:glyph-defaults": "node scripts/verify-default-glyphs.mjs dist",
166
+ "verify:theme-export": "node scripts/verify-theme-export.mjs",
167
+ "test:e2e": "playwright test"
166
168
  },
167
169
  "simple-git-hooks": {
168
170
  "pre-commit": "npx lint-staged && pnpm run quality:check",
@@ -192,6 +194,7 @@
192
194
  "@fontsource/fira-code": "^5.2.7",
193
195
  "@fontsource/plus-jakarta-sans": "^5.2.8",
194
196
  "@phosphor-icons/core": "^2.1.1",
197
+ "@playwright/test": "^1.63.0",
195
198
  "@semantic-release/changelog": "^6.0.3",
196
199
  "@semantic-release/git": "^10.0.1",
197
200
  "@types/node": "^25.5.0",
@@ -91,6 +91,15 @@ const RESOLVER_ENTRIES = Object.entries(COMPONENT_MANIFEST) as [
91
91
  string,
92
92
  ][]
93
93
 
94
+ /**
95
+ * The full-stylesheet import, in the two spellings that reach the same file:
96
+ * the `./css` export condition and the path it maps to. Matched against source
97
+ * text rather than a resolved id so it is found before the CSS pipeline turns
98
+ * it into something else.
99
+ */
100
+ const FULL_SHEET =
101
+ /(?:^|["'\s(])@nubisco\/ui\/(?:css|dist\/ui\.css)(?=["'\s)]|$)/m
102
+
94
103
  export function nubiscoUI(options: INubiscoUIOptions = {}): Plugin[] {
95
104
  const { components = true, glyphs = true, styles = true } = options
96
105
  const componentOptions = typeof components === 'object' ? components : {}
@@ -103,6 +112,8 @@ export function nubiscoUI(options: INubiscoUIOptions = {}): Plugin[] {
103
112
 
104
113
  if (components !== false) {
105
114
  const lookup = new Map(RESOLVER_ENTRIES)
115
+ // Set by the first non-vendor module found importing the full sheet.
116
+ let fullSheetImporter: string | null = null
106
117
  const styleManifest = styles
107
118
  ? loadStyleManifest(options.distRoot ?? defaultDistRoot())
108
119
  : {}
@@ -149,7 +160,58 @@ export function nubiscoUI(options: INubiscoUIOptions = {}): Plugin[] {
149
160
  plugins.push({
150
161
  name: 'nubisco-ui:styles-check',
151
162
  apply: 'build',
163
+
164
+ /*
165
+ * The other half of the same mistake.
166
+ *
167
+ * `@nubisco/ui/css` is the whole 214KB sheet for all 86 components. It
168
+ * still exists and still works, so an app that keeps importing it
169
+ * while this plugin also links per-component sheets gets every rule
170
+ * twice: byte-identical, same specificity, nothing renders
171
+ * differently, and the only symptom is a CSS bundle roughly twice the
172
+ * size it should be.
173
+ *
174
+ * That combination is exactly what an upgrade produces, because
175
+ * importing the full sheet was the correct thing to do beforehand.
176
+ * The upgrade guide says to drop the line; this says so at the moment
177
+ * it starts costing something, which is the difference between a
178
+ * sentence someone read and a sentence someone acts on.
179
+ */
180
+ transform(code, id) {
181
+ if (fullSheetImporter) return
182
+ if (id.includes('/node_modules/')) return
183
+ if (!FULL_SHEET.test(code)) return
184
+ fullSheetImporter = id
185
+ return null
186
+ },
187
+
152
188
  closeBundle() {
189
+ /*
190
+ * Both halves of the condition matter, and the second one is not
191
+ * decoration.
192
+ *
193
+ * The full sheet is the RIGHT answer for a build that links no
194
+ * per-component stylesheets: an entry built without this plugin at
195
+ * all, or one whose components never got resolved. Warning on the
196
+ * import alone would fire on a file where importing it is the only
197
+ * thing keeping the app styled, and a diagnostic that cries wolf on
198
+ * correct code is how people learn to ignore it.
199
+ *
200
+ * So this fires only when both sources are actually feeding the same
201
+ * build. That also makes it mutually exclusive with the "nothing was
202
+ * linked" warning below, which is the opposite failure.
203
+ */
204
+ if (fullSheetImporter && resolvedComponents > 0) {
205
+ const where = fullSheetImporter.split('/').slice(-2).join('/')
206
+ console.warn(
207
+ `[nubisco-ui] ${where} imports the full stylesheet ` +
208
+ `('@nubisco/ui/css') and this plugin is also linking ` +
209
+ `per-component stylesheets, so every component rule is in ` +
210
+ `this build twice. It renders correctly and costs roughly ` +
211
+ `double the component CSS. Drop the import, or keep it and ` +
212
+ `pass \`nubiscoUI({ styles: false })\`.`,
213
+ )
214
+ }
153
215
  if (resolvedComponents) return
154
216
  console.warn(
155
217
  `[nubisco-ui] no components were linked in this build, so none of ` +
@@ -0,0 +1,144 @@
1
+ /// Square and rounded geometry.
2
+ ///
3
+ /// One attribute on `<html>` selects the scale:
4
+ ///
5
+ /// ```html
6
+ /// <html data-nb-appearance="rounded">
7
+ /// ```
8
+ ///
9
+ /// which is what `configureAppearance()` and `useAppearance()` write. It is on
10
+ /// the document element rather than the application root so that teleported
11
+ /// overlays, which mount as siblings of that root, inherit it too.
12
+ ///
13
+ /// Square is the default and needs no rules at all: the semantic roles in
14
+ /// `_theme.scss` are already the square scale, and they are the geometry the
15
+ /// library renders today. Everything here is the opt-in half.
16
+ ///
17
+ /// ## Independence
18
+ ///
19
+ /// Nothing in this file mentions a colour. Appearance and colour mode are
20
+ /// selected by different selectors (`[data-nb-appearance]` and `.dark`) that
21
+ /// never appear in the same rule, so the two cannot interfere: switching one
22
+ /// cannot reset the other, and a theme exported by the theme builder carries
23
+ /// colours only, never a baked-in corner.
24
+ ///
25
+ /// @group @nubisco/appearance
26
+
27
+ @use 'sass:map';
28
+
29
+ /// The rounded scale.
30
+ ///
31
+ /// This is not "square with the corners knocked off". Rounded is a different
32
+ /// design language, and the reference is Apple's: controls are capsules, and
33
+ /// every container carries a generous corner that its contents are concentric
34
+ /// with.
35
+ ///
36
+ /// Two families, because one radius cannot serve both:
37
+ ///
38
+ /// - **`control`** is a capsule. A button, a single-line field or a tag is a
39
+ /// pill: the radius exceeds half the height, so CSS clamps it and both ends
40
+ /// are semicircles. This is what "round" means on a control, and it is why
41
+ /// 4px was wrong.
42
+ /// - **`control-sm`** is a rounded rectangle, for the small square-ish
43
+ /// affordances a capsule would destroy. A checkbox at capsule radius is a
44
+ /// circle, which is a radio button; a sidebar row at capsule radius is a
45
+ /// lozenge that fights the rows above and below it.
46
+ ///
47
+ /// Containers step up with their size: a popover is small and close to the
48
+ /// pointer, a modal is the largest surface on screen and can carry the most
49
+ /// corner before it stops reading as geometric.
50
+ ///
51
+ /// The container values are deliberately larger than the previous 6/8/12, so
52
+ /// that an inset surface still has a corner left after the enclosing padding
53
+ /// is subtracted. Concentric geometry is only visible when the outer radius
54
+ /// exceeds the inset; at 8px against 16px of padding it always collapsed to
55
+ /// square, which is correct arithmetic and a wasted mechanism.
56
+ $rounded: (
57
+ control: '9999px',
58
+ control-sm: 'var(--nb-base-unit)',
59
+ // 8px
60
+ popover: 'calc(var(--nb-base-unit) * 1.5)',
61
+ // 12px
62
+ panel: 'calc(var(--nb-base-unit) * 1.75)',
63
+ // 14px
64
+ modal: 'calc(var(--nb-base-unit) * 2.5)',
65
+ );
66
+
67
+ @mixin appearance {
68
+ [data-nb-appearance='rounded'] {
69
+ --nb-radius-control: #{map.get($rounded, control)};
70
+ --nb-radius-control-sm: #{map.get($rounded, control-sm)};
71
+ --nb-radius-popover: #{map.get($rounded, popover)};
72
+ --nb-radius-panel: #{map.get($rounded, panel)};
73
+ --nb-radius-modal: #{map.get($rounded, modal)};
74
+
75
+ /*
76
+ * Fields become boxes.
77
+ *
78
+ * Square keeps the library's own idiom: a filled box with one bottom rule.
79
+ * A capsule cannot be drawn with a bottom rule alone, so rounded gives the
80
+ * field the outline the shape needs. Both are deliberate, and the square
81
+ * treatment is untouched.
82
+ *
83
+ * A textarea is not a capsule. It is a box of text, and a pill around
84
+ * several lines reads as a speech bubble, so multiline steps down to the
85
+ * panel corner.
86
+ *
87
+ * The side borders are added by ROUNDED, not neutralised by square, and
88
+ * only their WIDTH is set here. The colour stays `--nb-c-field-border`,
89
+ * named by each field component itself: a `var()` written in this block
90
+ * would substitute against the root palette and inherit that resolved
91
+ * value into a nested `.dark` region, giving one field light sides and a
92
+ * dark bottom rule.
93
+ *
94
+ * Drawing a transparent 1px side border in square too would keep the two
95
+ * appearances pixel-identical, and was tried: it makes every square field
96
+ * one pixel taller than it is today, which is a change to the default
97
+ * every existing application renders. Square compatibility is worth more
98
+ * than a pixel of parity on an opt-in switch, so a field is 1px taller in
99
+ * rounded and square is exactly what it was.
100
+ */
101
+ --nb-field-border-width: 1px;
102
+ --nb-field-radius: var(--nb-radius-control);
103
+ --nb-field-radius-multiline: var(--nb-radius-panel);
104
+ /*
105
+ * A validation state colours the whole box under rounded, because the
106
+ * whole box is drawn. The doubled bottom rule square uses would smear a
107
+ * one-sided shadow across a capsule, so it is switched off here and the
108
+ * border colour carries the state on its own.
109
+ */
110
+ --nb-field-status-emphasis: 0;
111
+
112
+ /*
113
+ * How far a child is held off a rounded parent's edge.
114
+ *
115
+ * Apple's rule, and the reason a rounded interface reads as calm: nothing
116
+ * sits hard against a rounded border, because a square child in a rounded
117
+ * corner cuts the arc. Square needs none of this, so it is zero there and
118
+ * every flush layout stays exactly as it was.
119
+ */
120
+ --nb-overlay-inset: calc(var(--nb-base-unit) * 0.75);
121
+ }
122
+
123
+ /*
124
+ * Square is written out as well as being the default.
125
+ *
126
+ * An application can nest the attribute to pin one region square inside a
127
+ * rounded page (a dense report inside a rounded shell, say). Without this
128
+ * block the inner region would inherit the rounded values, because custom
129
+ * properties inherit and "default" is not a thing the cascade knows about.
130
+ */
131
+ [data-nb-appearance='square'] {
132
+ --nb-radius-control: 0;
133
+ --nb-radius-control-sm: 0;
134
+ --nb-radius-popover: 0;
135
+ --nb-radius-panel: 0;
136
+ --nb-radius-modal: 0;
137
+ --nb-field-border-width: 0;
138
+ --nb-field-radius: 0;
139
+ --nb-field-radius-multiline: 0;
140
+ // Square states the validation on the one edge it draws.
141
+ --nb-field-status-emphasis: 1;
142
+ --nb-overlay-inset: 0px;
143
+ }
144
+ }
@@ -0,0 +1,193 @@
1
+ /// The public API for authoring a named theme.
2
+ ///
3
+ /// This file **emits nothing on its own**. That is the point: `@nubisco/ui/styles`
4
+ /// emits the whole stylesheet, so a theme file that imported it would ship a
5
+ /// second copy of the library's CSS. A theme imports this instead, calls
6
+ /// `theme()`, and emits only its own tokens.
7
+ ///
8
+ /// ```scss
9
+ /// @use '@nubisco/ui/styles/theme-api' as nb;
10
+ ///
11
+ /// @include nb.theme(
12
+ /// 'ocean',
13
+ /// $light: (primary: #0f6f8c, surface: #ffffff),
14
+ /// $dark: (primary: #4fb3cf, surface: #14232a)
15
+ /// );
16
+ /// ```
17
+ ///
18
+ /// ```ts
19
+ /// import '@nubisco/ui/styles' // the library, once
20
+ /// import './themes/ocean.scss' // the theme's tokens
21
+ ///
22
+ /// configureNamedTheme({ defaultTheme: 'ocean' })
23
+ /// ```
24
+ ///
25
+ /// ## Three independent axes
26
+ ///
27
+ /// A named theme carries **colour only**. It says nothing about light versus
28
+ /// dark (it supplies both halves and the existing `.dark` class chooses between
29
+ /// them) and nothing about square versus rounded (that is
30
+ /// `data-nb-appearance`). Selecting a theme cannot reset the other two, and
31
+ /// neither of them can reset it.
32
+ ///
33
+ /// ## What a theme has to supply
34
+ ///
35
+ /// Nothing, strictly: every key is optional and anything omitted falls through
36
+ /// to the default theme, because these rules only re-declare custom properties
37
+ /// on a scope that sits inside `:root`. A theme that changes one accent is one
38
+ /// key long.
39
+ ///
40
+ /// The keys are the semantic token names with the `--nb-c-` prefix dropped, so
41
+ /// `primary` writes `--nb-c-primary`. Layer keys are spelled as they are in the
42
+ /// token contract: `layer-0`, `layer-border-0`, `layer-hover-0`.
43
+ ///
44
+ /// The `.nb-layer-N` classes that re-point `--nb-c-surface` at each layer are
45
+ /// emitted once by the library and are shared by every theme, so a theme
46
+ /// redefines the twelve layer values and gets the whole surface system with
47
+ /// them. It does not need to restate the machinery.
48
+ ///
49
+ /// @group @nubisco/theme-api
50
+
51
+ @use 'sass:list';
52
+ @use 'sass:map';
53
+ @use 'sass:meta';
54
+ @use 'sass:string';
55
+ @use 'logic' as logic;
56
+
57
+ /// The tints every palette colour is expanded into, matching the library's own
58
+ /// ramp exactly.
59
+ $tints:
60
+ 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800,
61
+ 850, 900;
62
+
63
+ /// The roles the library pairs with a readable foreground.
64
+ ///
65
+ /// A theme that points one of these at a palette step gets the matching
66
+ /// `-a11y` value for free, so text on a themed button stays readable without
67
+ /// the author having to work it out. This is the list the library itself
68
+ /// maintains in `_theme.scss`; anything outside it has no `-a11y` counterpart
69
+ /// to set.
70
+ $a11y-roles:
71
+ 'primary', 'primary-hover', 'primary-active', 'secondary', 'secondary-hover',
72
+ 'secondary-active', 'success', 'success-hover', 'success-active', 'info',
73
+ 'info-hover', 'info-active', 'warning', 'warning-hover', 'warning-active',
74
+ 'danger', 'danger-hover', 'danger-active';
75
+
76
+ /// Turns a token key into its custom-property name.
77
+ @function _prop($key) {
78
+ @return --nb-c-#{$key};
79
+ }
80
+
81
+ /// Expands one base colour into the full ramp, plus its readable foregrounds.
82
+ ///
83
+ /// Same two functions the library uses, so a themed ramp and a built-in ramp
84
+ /// are generated by one implementation rather than by two that agree today.
85
+ @mixin _palette($palette) {
86
+ @each $name, $base in $palette {
87
+ $shades: logic.make-shades($base);
88
+ @each $tint in $tints {
89
+ $value: map.get($shades, $tint);
90
+ --nb-c-#{$name}-#{$tint}: #{$value};
91
+ --nb-c-#{$name}-#{$tint}-a11y: #{logic.color-contrast($value)};
92
+ }
93
+ }
94
+ }
95
+
96
+ /// Whether a role value names a step of a declared palette colour.
97
+ ///
98
+ /// `primary: 'accent-500'` points at the ramp; `primary: #0f6f8c` is a literal.
99
+ /// Both are allowed: a ramp step is how a theme normally works, and a literal
100
+ /// is the escape hatch for the handful of values (pure white, say) that are not
101
+ /// a step of anything.
102
+ @function _ramp-ref($value, $palette) {
103
+ @if meta.type-of($value) != string {
104
+ @return null;
105
+ }
106
+ @each $name, $base in $palette {
107
+ $prefix: '#{$name}-';
108
+ @if string.index($value, $prefix) == 1 {
109
+ @return $value;
110
+ }
111
+ }
112
+ @return null;
113
+ }
114
+
115
+ /// Emits one map as custom-property declarations.
116
+ @mixin _emit($tokens, $palette: ()) {
117
+ @each $key, $value in $tokens {
118
+ $ref: _ramp-ref($value, $palette);
119
+ @if $ref {
120
+ #{_prop($key)}: var(--nb-c-#{$ref});
121
+ /*
122
+ * The readable foreground travels with the colour it belongs to. A theme
123
+ * that moves `primary` to a darker step and leaves `primary-a11y`
124
+ * behind ships black text on a dark button, which is the failure this
125
+ * pairing exists to prevent.
126
+ */
127
+ @if list.index($a11y-roles, $key) {
128
+ #{_prop('#{$key}-a11y')}: var(--nb-c-#{$ref}-a11y);
129
+ }
130
+ } @else {
131
+ #{_prop($key)}: #{$value};
132
+ }
133
+ }
134
+ }
135
+
136
+ /// Declares a named theme.
137
+ ///
138
+ /// @param {String} $id - the identifier selected at runtime. Lowercase
139
+ /// letters, digits and hyphens; it becomes an attribute value, so it is
140
+ /// validated rather than interpolated blindly.
141
+ /// @param {Map} $light - tokens for the light half
142
+ /// @param {Map} $dark - tokens for the dark half
143
+ @mixin theme($id, $palette: (), $light: (), $dark: ()) {
144
+ // A theme id lands inside an attribute selector. Anything outside this set
145
+ // could close the selector and inject rules, so an invalid id is a build
146
+ // error rather than something that silently ships.
147
+ @if not _valid-id($id) {
148
+ @error "Invalid theme id #{$id}. Use lowercase letters, digits and hyphens.";
149
+ }
150
+
151
+ /*
152
+ * The ramp is emitted once, not per colour mode.
153
+ *
154
+ * A palette is a set of colours, and a colour does not change because the
155
+ * page went dark: what changes is which STEP of it a role points at. Both
156
+ * halves therefore read the same ramp, and only the role mappings below
157
+ * differ, which is also how the library's own `:root` ramp behaves.
158
+ */
159
+ @if $palette != () or map.keys($light) != () or $light != () {
160
+ [data-nb-theme='#{$id}'] {
161
+ @include _palette($palette);
162
+ @include _emit($light, $palette);
163
+ }
164
+ }
165
+
166
+ /*
167
+ * Two selectors, because the theme attribute and the dark class can land on
168
+ * the same element or on different ones. Both are more specific than the
169
+ * single-attribute block above, so the dark half wins inside a dark document
170
+ * regardless of the order the stylesheets happen to be concatenated in.
171
+ */
172
+ @if map.keys($dark) != () or $dark != () {
173
+ .dark[data-nb-theme='#{$id}'],
174
+ .dark [data-nb-theme='#{$id}'] {
175
+ @include _emit($dark, $palette);
176
+ }
177
+ }
178
+ }
179
+
180
+ /// Whether a string is safe to use as a theme id.
181
+ @function _valid-id($id) {
182
+ $allowed: 'abcdefghijklmnopqrstuvwxyz0123456789-';
183
+ @if string.length($id) == 0 {
184
+ @return false;
185
+ }
186
+ @for $i from 1 through string.length($id) {
187
+ $char: string.slice($id, $i, $i);
188
+ @if string.index($allowed, $char) == null {
189
+ @return false;
190
+ }
191
+ }
192
+ @return true;
193
+ }
@@ -251,9 +251,30 @@
251
251
  layers.token(layers.$light, text-subtle)
252
252
  )};
253
253
 
254
- // Form field tokens: heights and padding relative to --nb-base-unit (8px)
255
- --nb-c-field-bg: #{layers.token(layers.$light, field-bg)};
254
+ /*
255
+ * Form fields.
256
+ *
257
+ * The enabled fill used to be `field-bg` (#cacbcc): a mid grey, darker
258
+ * than every surface it sits on. A grey box with no outline is what most
259
+ * interfaces use to mean "unavailable", so the enabled state was wearing
260
+ * the disabled state's clothes, and `disabled` on top of it was only a
261
+ * 0.45 opacity. The two differed in brightness rather than in kind, and
262
+ * the enabled field read as the heavier of the two.
263
+ *
264
+ * The geometry is untouched: still a filled box with a single bottom
265
+ * rule, still square. Only the fills and the boundary contrast moved.
266
+ * `[data-nb-preset='classic-fields']` restores the old values.
267
+ */
268
+ --nb-c-field-bg: #f1f2f3;
256
269
  --nb-c-field-border: #{layers.token(layers.$light, field-border)};
270
+ // The historic enabled fill, now carrying the disabled state.
271
+ --nb-c-field-bg-disabled: #{layers.token(layers.$light, field-bg)};
272
+ // Disabled loses boundary contrast as well as gaining the darker fill,
273
+ // so the two states differ in kind. Deliberately under the 3:1 that WCAG
274
+ // 1.4.11 asks of an *operable* control boundary: this one is not operable.
275
+ --nb-c-field-border-disabled: #949596;
276
+ // Read-only sits between the two: quieter than editable, but still a rule.
277
+ --nb-c-field-border-readonly: #949596;
257
278
 
258
279
  // ── Status foregrounds ────────────────────────────────────────────────
259
280
  // Drawn as glyphs and outlines directly on a layer surface, so they are
@@ -389,6 +410,55 @@
389
410
  --nb-radius-lg: calc(var(--nb-base-unit) * 1.5); // 12px
390
411
  --nb-radius-pill: 9999px;
391
412
 
413
+ /*
414
+ * Semantic radius roles.
415
+ *
416
+ * The scale above is a set of sizes; these are the roles components
417
+ * actually consume, and they are what the square/rounded appearance
418
+ * setting switches. A component asks for "the radius a popover has", not
419
+ * for "4px", so one setting moves all of them coherently and nothing has
420
+ * to be hunted down by hand.
421
+ *
422
+ * These values are the SQUARE scale, and square is the default. They are
423
+ * not aspirational zeroes: they are what the library renders today, so an
424
+ * application that upgrades and calls nothing gets the pixels it had
425
+ * before. The rounded scale lives in the `appearance` mixin below.
426
+ *
427
+ * Roles are proportionate rather than uniform. A 12px corner on a modal
428
+ * and a 12px corner on a checkbox are not the same design; the larger the
429
+ * surface, the more corner it can carry before it stops reading as
430
+ * geometric.
431
+ */
432
+ --nb-radius-control: 0; // buttons and single-line fields (capsule when round)
433
+ --nb-radius-control-sm: 0; // checkboxes, sidebar rows, step markers
434
+ --nb-radius-popover: 0; // menus, dropdowns, tooltips
435
+ --nb-radius-panel: 0; // cards, panels, inspectors, table shells
436
+ --nb-radius-modal: 0; // modals, drawers
437
+
438
+ /*
439
+ * Geometry that is not decoration and never follows the appearance
440
+ * setting. An avatar is round because it is an avatar, a radio is round
441
+ * because a square radio is a checkbox, and a switch track is a track.
442
+ * Squaring these would not make the library look more geometric, it would
443
+ * make it look broken.
444
+ */
445
+ --nb-radius-circle: 50%;
446
+
447
+ /*
448
+ * The concentric context.
449
+ *
450
+ * A surface that draws a corner publishes it here, and any inset surface
451
+ * that follows that corner derives from it rather than picking its own
452
+ * value: `inner = max(0, outer - inset)`, which is the geometry that makes
453
+ * two nested rounded boxes look like one object instead of two.
454
+ *
455
+ * At the document root there is no enclosing surface, so the context is
456
+ * zero and a derived radius collapses to its own floor. Components that
457
+ * are standalone rather than inset ignore this entirely.
458
+ */
459
+ --nb-radius-context: 0px;
460
+ --nb-radius-inset: 0px;
461
+
392
462
  --nb-grid-max-width: #{grid.$grid-max-width}px;
393
463
  --nb-grid-columns: #{grid.$grid-columns};
394
464
  --nb-grid-gutter: #{grid.$grid-gutter}px;
@@ -756,9 +826,25 @@
756
826
  --nb-c-bg: var(--nb-c-layer-0);
757
827
  --nb-c-bg-soft: var(--nb-c-layer-1);
758
828
 
759
- // Form fields
760
- --nb-c-field-bg: #{layers.token(layers.$dark, field-bg)};
761
- --nb-c-field-border: #{layers.token(layers.$dark, field-border)};
829
+ /*
830
+ * Form fields. The dark ramp's old fill was an inset near-black rather
831
+ * than a mid grey, so it never had the light theme's "looks disabled"
832
+ * problem; it moves up one surface so an enabled field reads as raised
833
+ * out of the page, matching the relationship the light half now has.
834
+ *
835
+ * The dark ramp cannot separate enabled from disabled by fill at all
836
+ * (every surface in it sits within 1.21:1 of every other), so in this
837
+ * theme the bottom rule is the whole signal.
838
+ */
839
+ --nb-c-field-bg: #{layers.level(layers.$dark, surface, 1)};
840
+ // Picked against that fill directly rather than taken from the layer
841
+ // border ramp, whose brightest step (#696a6b) measures 3.05:1 here and
842
+ // clears 1.4.11 by four hundredths. This is 4.29:1.
843
+ --nb-c-field-border: #818283;
844
+ // Flush with the page ground: enabled is raised, disabled is not.
845
+ --nb-c-field-bg-disabled: #{layers.level(layers.$dark, surface, 0)};
846
+ --nb-c-field-border-disabled: #{layers.level(layers.$dark, border, 0)};
847
+ --nb-c-field-border-readonly: #{layers.level(layers.$dark, border, 1)};
762
848
 
763
849
  // Status foregrounds. The light values are mid-ramp fills that fall to
764
850
  // ~3:1 or below on the dark surfaces, so the dark theme steps up the
@@ -8,6 +8,8 @@
8
8
  @use 'typography';
9
9
  @use 'utils';
10
10
  @use 'patterns/inspector';
11
+ @use 'presets/classic-fields';
12
+ @use 'appearance';
11
13
 
12
14
  @include theme.base;
13
15
  @include theme.classes;
@@ -15,3 +17,9 @@
15
17
  @include theme.dark;
16
18
  @include directives.tooltip;
17
19
  @include grid.grid;
20
+ // Opt-out only: every rule inside is scoped to [data-nb-preset], so including
21
+ // it changes nothing until an application asks for the old field fills.
22
+ @include classic-fields.classic-fields;
23
+ // The rounded scale. Square needs no rules: the semantic roles are already
24
+ // the square values, so this only adds the opt-in half.
25
+ @include appearance.appearance;