@nubisco/ui 4.1.3 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AiLabel-VbZiFHAZ.js → AiLabel-Ci7eROcw.js} +1 -1
- package/dist/{AiLabel-DZ9GkGqL.cjs → AiLabel-DtM5ZCQC.cjs} +1 -1
- package/dist/{Banner-7XsX8ibI.js → Banner-C5Erb75B.js} +1 -1
- package/dist/{Banner-DI5fA8Ow.cjs → Banner-JubX-4yR.cjs} +1 -1
- package/dist/{BlueprintControls-CJAKrQ6U.js → BlueprintControls-BkwhsHI8.js} +1 -1
- package/dist/{BlueprintControls-aF11uokn.cjs → BlueprintControls-CdvNvRkW.cjs} +1 -1
- package/dist/{BlueprintMinimap-C-gCkMIW.cjs → BlueprintMinimap-BIBsnBFs.cjs} +1 -1
- package/dist/{BlueprintMinimap-C-65UzhM.js → BlueprintMinimap-QAw6aiCc.js} +1 -1
- package/dist/{BottomPanel-B-dhgMWB.js → BottomPanel-BoBCdANz.js} +1 -1
- package/dist/{BottomPanel-CmVH0Hsf.cjs → BottomPanel-dbllmH2v.cjs} +1 -1
- package/dist/Button-Dwv0rx46.cjs +1 -0
- package/dist/{Button-Cegx6vaT.js → Button-Q8MBLMvG.js} +12 -4
- package/dist/{Card-Cs-7jXxG.cjs → Card-Cn5OS4q-.cjs} +1 -1
- package/dist/{Card-TjV_N8RU.js → Card-eM6DEphF.js} +1 -1
- package/dist/{Checkbox-BJrnykX9.js → Checkbox-DG82KK8V.js} +1 -1
- package/dist/{Checkbox-D9qW3gph.cjs → Checkbox-vFN3fLyr.cjs} +1 -1
- package/dist/{CheckboxGroup-CUSPscyy.js → CheckboxGroup-5pmdu9fe.js} +1 -1
- package/dist/{CheckboxGroup-mWcKUeq9.cjs → CheckboxGroup-Cyj2NUtI.cjs} +1 -1
- package/dist/{ColorStrip-CR1JDzwX.js → ColorStrip-BBTJU1Ox.js} +47 -45
- package/dist/ColorStrip-D3nbTyfs.cjs +1 -0
- package/dist/{Confirm-pgn2HajX.js → Confirm-C-HRTF0s.js} +23 -52
- package/dist/Confirm-w3Ig0L5j.cjs +1 -0
- package/dist/{DataTable-c0ltF6wT.js → DataTable-BVxSUB-h.js} +3 -3
- package/dist/{DataTable-BbiDmA1X.cjs → DataTable-Cnyh04sD.cjs} +1 -1
- package/dist/{DatePicker-YJ8-ViVK.js → DatePicker-BimOzKti.js} +1 -1
- package/dist/{DatePicker-C8_qR25v.cjs → DatePicker-CMPgr4Hp.cjs} +1 -1
- package/dist/{EmptyState-DVg8l-bl.js → EmptyState-CwMG-NeI.js} +1 -1
- package/dist/{EmptyState-henL7JH6.cjs → EmptyState-Cz91HAKF.cjs} +1 -1
- package/dist/{FileUploader-Lzy4bFn7.cjs → FileUploader-BJdRC-Kp.cjs} +1 -1
- package/dist/{FileUploader-BLwR6H3f.js → FileUploader-BO2cDUwP.js} +2 -2
- package/dist/ImageCropper-D7mr-xRE.cjs +1 -0
- package/dist/{ImageCropper-BT9lfFrs.js → ImageCropper-DEaGU0cZ.js} +74 -53
- package/dist/{InfoHint-DesESwdO.cjs → InfoHint-BNpqLVSX.cjs} +1 -1
- package/dist/{InfoHint-JwhhBFZP.js → InfoHint-C663u_NL.js} +1 -1
- package/dist/{InlineEdit-CZEt1vhH.cjs → InlineEdit-D95I45Vt.cjs} +1 -1
- package/dist/{InlineEdit-DNMF_40m.js → InlineEdit-DrhJ0AX2.js} +1 -1
- package/dist/{Message-Daj6hLC4.cjs → Message-Ax7rnAQl.cjs} +1 -1
- package/dist/{Message-BuG5t7bu.js → Message-DqUW3GHc.js} +1 -1
- package/dist/Modal-B1CQyPNo.js +206 -0
- package/dist/Modal-DvukGfHg.cjs +1 -0
- package/dist/{NotificationCenter-DL_Tshyb.js → NotificationCenter-Duu3XZC3.js} +3 -3
- package/dist/{NotificationCenter-D51ty3Lq.cjs → NotificationCenter-oOzClQI-.cjs} +1 -1
- package/dist/{NumberInput-Vc2wzK62.cjs → NumberInput-DKZsdWLv.cjs} +1 -1
- package/dist/{NumberInput-6R8FkJc-.js → NumberInput-_ff3Xi2r.js} +2 -2
- package/dist/{Pagination-B6a62qvI.js → Pagination-6bF88x_p.js} +3 -3
- package/dist/{Pagination-CkBe9Naz.cjs → Pagination-EipK6BGe.cjs} +1 -1
- package/dist/{Panel-BVtGI7YH.js → Panel-D3s_MKfd.js} +1 -1
- package/dist/{Panel-DQfmVtie.cjs → Panel-qDfyu_0v.cjs} +1 -1
- package/dist/{ProgressBar-fAaKT9lD.cjs → ProgressBar-CbqsSdZZ.cjs} +1 -1
- package/dist/{ProgressBar-DjejtCKA.js → ProgressBar-aF2zBoRA.js} +2 -2
- package/dist/{Radio-CQveGtXr.js → Radio-BnI7bi9Y.js} +2 -2
- package/dist/{Radio-DSvkUCxV.cjs → Radio-BqjtCaST.cjs} +1 -1
- package/dist/{ReorderList-Bai4yaIG.cjs → ReorderList-DLQ3rVnX.cjs} +1 -1
- package/dist/{ReorderList-Be-qicSf.js → ReorderList-DpytAupm.js} +1 -1
- package/dist/{Select-swFFQIMN.js → Select-B5t5QtVe.js} +1 -1
- package/dist/{Select-ClCyOqQI.cjs → Select-dAYn2iZO.cjs} +1 -1
- package/dist/{Shell-B8YmApR6.cjs → Shell-9lzopP-w.cjs} +1 -1
- package/dist/{Shell-Dr7LHIqk.js → Shell-B3jhTiNP.js} +99 -96
- package/dist/{ShellPanel-I0ZMGQ4K.js → ShellPanel-B3vZcQhX.js} +1 -1
- package/dist/{ShellPanel-CnN9orWH.cjs → ShellPanel-ChujN0eX.cjs} +1 -1
- package/dist/{SidebarLink-y2If8dtl.js → SidebarLink-B_CGHs0b.js} +1 -1
- package/dist/{SidebarLink-CngTvuB6.cjs → SidebarLink-CZrDLC8g.cjs} +1 -1
- package/dist/{SidebarMenuItem-DoyuIs3w.cjs → SidebarMenuItem-Dc6oh2Nc.cjs} +1 -1
- package/dist/{SidebarMenuItem-DBINoxeA.js → SidebarMenuItem-Dpqr9e0A.js} +1 -1
- package/dist/{Skeleton-D8CHd_4p.cjs → Skeleton-DP9iM6Ku.cjs} +1 -1
- package/dist/{Skeleton-CC7LVdxd.js → Skeleton-sox6qUDk.js} +1 -1
- package/dist/Slider-BNiQaaVa.cjs +1 -0
- package/dist/{Slider-lOhGG7UX.js → Slider-C0761rBk.js} +47 -33
- package/dist/{StepperStep-w1SSX7t7.cjs → StepperStep-B9JEE6WJ.cjs} +1 -1
- package/dist/{StepperStep-DNXUj71b.js → StepperStep-DFeOJ1ju.js} +1 -1
- package/dist/{Tabs-W_4iyGVx.js → Tabs-CQP9zwDw.js} +1 -1
- package/dist/{Tabs-Clg7lzy5.cjs → Tabs-Dp27EDrK.cjs} +1 -1
- package/dist/{TextInput-CGD_wFwo.cjs → TextInput-D4jBlYm9.cjs} +2 -2
- package/dist/{TextInput-CxC2HVj6.js → TextInput-DNrd12uS.js} +2 -2
- package/dist/{Toast-DueO27yl.cjs → Toast-BBsrCQK8.cjs} +1 -1
- package/dist/{Toast-QXobTGZM.js → Toast-cisfK5Zd.js} +1 -1
- package/dist/{Toaster-DcA6PJPt.js → Toaster-C1Uyr6O7.js} +1 -1
- package/dist/{Toaster-DY8o_iiy.cjs → Toaster-Dz_o--LF.cjs} +1 -1
- package/dist/{TreeNode-DS1XJGty.cjs → TreeNode-DB7ipWCg.cjs} +1 -1
- package/dist/{TreeNode-BI-Azvhe.js → TreeNode-a0MHLI27.js} +1 -1
- package/dist/{Walkthrough-DHtLDsOk.cjs → Walkthrough-YD3YYxxM.cjs} +1 -1
- package/dist/{Walkthrough-l7HOZths.js → Walkthrough-qaQ1rved.js} +2 -2
- package/dist/all.cjs +1 -1
- package/dist/all.mjs +137 -135
- package/dist/component-styles.json +1 -1
- package/dist/components/AiLabel.cjs +1 -1
- package/dist/components/AiLabel.mjs +1 -1
- package/dist/components/AiLabel.vue.d.ts.map +1 -1
- package/dist/components/Banner.cjs +1 -1
- package/dist/components/Banner.mjs +1 -1
- package/dist/components/Banner.vue.d.ts.map +1 -1
- package/dist/components/BlueprintControls.cjs +1 -1
- package/dist/components/BlueprintControls.mjs +1 -1
- package/dist/components/BlueprintMinimap.cjs +1 -1
- package/dist/components/BlueprintMinimap.mjs +1 -1
- package/dist/components/BlueprintMinimap.vue.d.ts.map +1 -1
- package/dist/components/Board.vue.d.ts.map +1 -1
- package/dist/components/BottomPanel.cjs +1 -1
- package/dist/components/BottomPanel.mjs +1 -1
- package/dist/components/BottomPanel.vue.d.ts.map +1 -1
- package/dist/components/Button.cjs +1 -1
- package/dist/components/Button.d.ts +25 -1
- package/dist/components/Button.mjs +1 -1
- package/dist/components/Button.vue.d.ts +1 -1
- package/dist/components/Button.vue.d.ts.map +1 -1
- package/dist/components/Calendar.vue.d.ts.map +1 -1
- package/dist/components/Card.cjs +1 -1
- package/dist/components/Card.mjs +1 -1
- package/dist/components/Card.vue.d.ts.map +1 -1
- package/dist/components/Checkbox.cjs +1 -1
- package/dist/components/Checkbox.mjs +1 -1
- package/dist/components/Checkbox.vue.d.ts.map +1 -1
- package/dist/components/CheckboxGroup.cjs +1 -1
- package/dist/components/CheckboxGroup.mjs +1 -1
- package/dist/components/ColorStrip.cjs +1 -1
- package/dist/components/ColorStrip.mjs +1 -1
- package/dist/components/ColorStrip.vue.d.ts.map +1 -1
- package/dist/components/CommandPalette.vue.d.ts.map +1 -1
- package/dist/components/Confirm.cjs +1 -1
- package/dist/components/Confirm.mjs +1 -1
- package/dist/components/Confirm.vue.d.ts +1 -1
- package/dist/components/Confirm.vue.d.ts.map +1 -1
- package/dist/components/DataTable.cjs +1 -1
- package/dist/components/DataTable.mjs +1 -1
- package/dist/components/DataTable.vue.d.ts.map +1 -1
- package/dist/components/DatePicker.cjs +1 -1
- package/dist/components/DatePicker.mjs +1 -1
- package/dist/components/DatePicker.vue.d.ts.map +1 -1
- package/dist/components/EmptyState.cjs +1 -1
- package/dist/components/EmptyState.mjs +1 -1
- package/dist/components/EmptyState.vue.d.ts.map +1 -1
- package/dist/components/FileUploader.cjs +1 -1
- package/dist/components/FileUploader.mjs +1 -1
- package/dist/components/FileUploader.vue.d.ts.map +1 -1
- package/dist/components/ImageCropper.cjs +1 -1
- package/dist/components/ImageCropper.mjs +1 -1
- package/dist/components/ImageCropper.vue.d.ts.map +1 -1
- package/dist/components/InfoHint.cjs +1 -1
- package/dist/components/InfoHint.mjs +1 -1
- package/dist/components/InfoHint.vue.d.ts.map +1 -1
- package/dist/components/InlineEdit.cjs +1 -1
- package/dist/components/InlineEdit.mjs +1 -1
- package/dist/components/InlineEdit.vue.d.ts.map +1 -1
- package/dist/components/Menu.vue.d.ts.map +1 -1
- package/dist/components/MenuItem.vue.d.ts.map +1 -1
- package/dist/components/Message.cjs +1 -1
- package/dist/components/Message.mjs +1 -1
- package/dist/components/Message.vue.d.ts.map +1 -1
- package/dist/components/Modal.cjs +1 -1
- package/dist/components/Modal.d.ts +39 -0
- package/dist/components/Modal.mjs +1 -1
- package/dist/components/Modal.vue.d.ts +3 -0
- package/dist/components/Modal.vue.d.ts.map +1 -1
- package/dist/components/NotificationCenter.cjs +1 -1
- package/dist/components/NotificationCenter.mjs +1 -1
- package/dist/components/NotificationCenter.vue.d.ts.map +1 -1
- package/dist/components/NotificationCenterItem.vue.d.ts.map +1 -1
- package/dist/components/NumberInput.cjs +1 -1
- package/dist/components/NumberInput.mjs +1 -1
- package/dist/components/NumberInput.vue.d.ts.map +1 -1
- package/dist/components/Pagination.cjs +1 -1
- package/dist/components/Pagination.mjs +1 -1
- package/dist/components/Pagination.vue.d.ts.map +1 -1
- package/dist/components/Panel.cjs +1 -1
- package/dist/components/Panel.mjs +1 -1
- package/dist/components/Panel.vue.d.ts.map +1 -1
- package/dist/components/ProgressBar.cjs +1 -1
- package/dist/components/ProgressBar.mjs +1 -1
- package/dist/components/ProgressBar.vue.d.ts.map +1 -1
- package/dist/components/Radio.cjs +1 -1
- package/dist/components/Radio.mjs +1 -1
- package/dist/components/Radio.vue.d.ts.map +1 -1
- package/dist/components/ReorderList.cjs +1 -1
- package/dist/components/ReorderList.mjs +1 -1
- package/dist/components/ReorderList.vue.d.ts.map +1 -1
- package/dist/components/Select.cjs +1 -1
- package/dist/components/Select.mjs +1 -1
- package/dist/components/Select.vue.d.ts.map +1 -1
- package/dist/components/Shell.cjs +1 -1
- package/dist/components/Shell.mjs +1 -1
- package/dist/components/Shell.vue.d.ts.map +1 -1
- package/dist/components/ShellPanel.cjs +1 -1
- package/dist/components/ShellPanel.mjs +1 -1
- package/dist/components/ShellPanel.vue.d.ts.map +1 -1
- package/dist/components/SidebarLink.cjs +1 -1
- package/dist/components/SidebarLink.mjs +1 -1
- package/dist/components/SidebarLink.vue.d.ts.map +1 -1
- package/dist/components/SidebarMenuItem.cjs +1 -1
- package/dist/components/SidebarMenuItem.mjs +1 -1
- package/dist/components/SidebarMenuItem.vue.d.ts.map +1 -1
- package/dist/components/Skeleton.cjs +1 -1
- package/dist/components/Skeleton.mjs +1 -1
- package/dist/components/Skeleton.vue.d.ts.map +1 -1
- package/dist/components/Slider.cjs +1 -1
- package/dist/components/Slider.d.ts +8 -0
- package/dist/components/Slider.mjs +1 -1
- package/dist/components/Slider.vue.d.ts +1 -0
- package/dist/components/Slider.vue.d.ts.map +1 -1
- package/dist/components/StepperStep.cjs +1 -1
- package/dist/components/StepperStep.mjs +1 -1
- package/dist/components/StepperStep.vue.d.ts.map +1 -1
- package/dist/components/Tabs.cjs +1 -1
- package/dist/components/Tabs.mjs +1 -1
- package/dist/components/Tabs.vue.d.ts.map +1 -1
- package/dist/components/TextInput.cjs +1 -1
- package/dist/components/TextInput.mjs +1 -1
- package/dist/components/TextInput.vue.d.ts.map +1 -1
- package/dist/components/Toast.cjs +1 -1
- package/dist/components/Toast.mjs +1 -1
- package/dist/components/Toast.vue.d.ts.map +1 -1
- package/dist/components/Toaster.cjs +1 -1
- package/dist/components/Toaster.mjs +1 -1
- package/dist/components/TreeNode.cjs +1 -1
- package/dist/components/TreeNode.mjs +1 -1
- package/dist/components/TreeNode.vue.d.ts.map +1 -1
- package/dist/components/UserMenu.vue.d.ts.map +1 -1
- package/dist/components/Walkthrough.cjs +1 -1
- package/dist/components/Walkthrough.mjs +1 -1
- package/dist/components/Walkthrough.vue.d.ts.map +1 -1
- package/dist/composables/useAppearance.composable.cjs +1 -0
- package/dist/composables/useAppearance.composable.d.ts +131 -0
- package/dist/composables/useAppearance.composable.d.ts.map +1 -0
- package/dist/composables/useAppearance.composable.mjs +65 -0
- package/dist/composables/useConfirm.composable.cjs +1 -1
- package/dist/composables/useConfirm.composable.mjs +2 -1
- package/dist/composables/useFocusTrap.composable.cjs +1 -0
- package/dist/composables/useFocusTrap.composable.d.ts +91 -0
- package/dist/composables/useFocusTrap.composable.d.ts.map +1 -0
- package/dist/composables/useFocusTrap.composable.mjs +98 -0
- package/dist/composables/useNamedTheme.composable.cjs +1 -0
- package/dist/composables/useNamedTheme.composable.d.ts +98 -0
- package/dist/composables/useNamedTheme.composable.d.ts.map +1 -0
- package/dist/composables/useNamedTheme.composable.mjs +68 -0
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +44 -42
- package/dist/main.d.ts +4 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/plugins/vite/index.d.ts.map +1 -1
- package/dist/plugins/vite/index.js +59 -0
- package/dist/styles/AiLabel.css +1 -1
- package/dist/styles/Banner.css +1 -1
- package/dist/styles/BlueprintMinimap.css +1 -1
- package/dist/styles/Board.css +1 -1
- package/dist/styles/BottomPanel.css +1 -1
- package/dist/styles/Button.css +1 -1
- package/dist/styles/Calendar.css +1 -1
- package/dist/styles/Card.css +1 -1
- package/dist/styles/Checkbox.css +1 -1
- package/dist/styles/ColorStrip.css +1 -1
- package/dist/styles/CommandPalette.css +1 -1
- package/dist/styles/Confirm.css +1 -1
- package/dist/styles/DataTable.css +1 -1
- package/dist/styles/DatePicker.css +1 -1
- package/dist/styles/EmptyState.css +1 -1
- package/dist/styles/FileUploader.css +1 -1
- package/dist/styles/ImageCropper.css +1 -1
- package/dist/styles/InfoHint.css +1 -1
- package/dist/styles/InlineEdit.css +1 -1
- package/dist/styles/Menu.css +1 -1
- package/dist/styles/MenuItem.css +1 -1
- package/dist/styles/Message.css +1 -1
- package/dist/styles/Modal.css +1 -1
- package/dist/styles/NotificationCenter.css +1 -1
- package/dist/styles/NotificationCenterItem.css +1 -1
- package/dist/styles/NumberInput.css +1 -1
- package/dist/styles/Pagination.css +1 -1
- package/dist/styles/Panel.css +1 -1
- package/dist/styles/ProgressBar.css +1 -1
- package/dist/styles/Radio.css +1 -1
- package/dist/styles/ReorderList.css +1 -1
- package/dist/styles/Select.css +1 -1
- package/dist/styles/Shell.css +1 -1
- package/dist/styles/ShellPanel.css +1 -1
- package/dist/styles/SidebarLink.css +1 -1
- package/dist/styles/SidebarMenuItem.css +1 -1
- package/dist/styles/Skeleton.css +1 -1
- package/dist/styles/Slider.css +1 -1
- package/dist/styles/StepperStep.css +1 -1
- package/dist/styles/Tabs.css +1 -1
- package/dist/styles/TextInput.css +1 -1
- package/dist/styles/Toast.css +1 -1
- package/dist/styles/TreeNode.css +1 -1
- package/dist/styles/UserMenu.css +1 -1
- package/dist/styles/Walkthrough.css +1 -1
- package/dist/ui.css +45 -45
- package/package.json +7 -4
- package/src/plugins/vite/index.ts +62 -0
- package/src/styles/_appearance.scss +144 -0
- package/src/styles/_theme-api.scss +193 -0
- package/src/styles/_theme.scss +91 -5
- package/src/styles/index.scss +8 -0
- package/src/styles/logic/_radius.scss +146 -0
- package/src/styles/logic/index.scss +1 -0
- package/src/styles/presets/_classic-fields.scss +55 -0
- package/dist/Button-Dqtcr4i0.cjs +0 -1
- package/dist/ColorStrip-CAcR1O_R.cjs +0 -1
- package/dist/Confirm-CW160zEF.cjs +0 -1
- package/dist/ImageCropper-B0J5wwza.cjs +0 -1
- package/dist/Modal-8lgeNWj8.cjs +0 -1
- package/dist/Modal-iN94HtKE.js +0 -156
- package/dist/Slider-CxrK7cAU.cjs +0 -1
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nubisco/ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Vue 3 UI component library",
|
|
5
|
-
"packageManager": "pnpm@
|
|
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
|
+
}
|
package/src/styles/_theme.scss
CHANGED
|
@@ -251,9 +251,30 @@
|
|
|
251
251
|
layers.token(layers.$light, text-subtle)
|
|
252
252
|
)};
|
|
253
253
|
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
|
|
760
|
-
|
|
761
|
-
|
|
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
|
package/src/styles/index.scss
CHANGED
|
@@ -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;
|