@justanarthur/modo-ui 0.5.0 → 0.6.0-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN.md +608 -0
- package/README.md +66 -44
- package/blocks/sidebar-app/examples.mdx +33 -0
- package/blocks/sidebar-app/index.tsx +218 -0
- package/blocks/sidebar-app/inset-topbar.tsx +25 -0
- package/blocks/sidebar-app/menu-grid.ts +26 -0
- package/blocks/sidebar-app/nav-data.ts +36 -0
- package/blocks/sidebar-app/search-field.tsx +48 -0
- package/blocks/sidebar-app/user-footer.tsx +67 -0
- package/blocks/sidebar-app/workspace-header.tsx +129 -0
- package/components/AI/input-message/examples.mdx +124 -0
- package/components/AI/input-message/file-thumbnail.tsx +173 -0
- package/components/AI/input-message/index.tsx +1383 -0
- package/components/AI/thinking-indicator/examples.mdx +27 -0
- package/components/AI/thinking-indicator/index.tsx +210 -0
- package/components/accordion/examples.mdx +148 -0
- package/components/accordion/index.tsx +1034 -0
- package/components/avatar/examples.mdx +95 -0
- package/components/avatar/index.tsx +129 -0
- package/components/badge/change-demo.tsx +29 -0
- package/components/badge/examples.mdx +120 -0
- package/components/badge/index.tsx +225 -0
- package/components/badge/variants.ts +73 -0
- package/components/button/examples.mdx +164 -0
- package/components/button/index.tsx +416 -0
- package/components/button/loading-demo.tsx +25 -0
- package/components/button/variants.ts +166 -0
- package/components/card/examples.mdx +212 -0
- package/components/card/index.tsx +1037 -0
- package/components/copy/examples.mdx +87 -0
- package/components/copy/index.tsx +482 -0
- package/components/inputs/checkbox/examples.mdx +83 -0
- package/components/inputs/checkbox/index.tsx +611 -0
- package/components/inputs/checkbox/select-all-demo.tsx +48 -0
- package/components/inputs/color-picker/examples.mdx +72 -0
- package/components/inputs/color-picker/index.tsx +1955 -0
- package/components/inputs/color-picker/variants.ts +401 -0
- package/components/inputs/combobox/examples.mdx +273 -0
- package/components/inputs/combobox/index.tsx +1436 -0
- package/components/inputs/combobox/remote-demo.tsx +101 -0
- package/components/inputs/date-time/calendar/examples.mdx +34 -0
- package/components/inputs/date-time/calendar/index.tsx +351 -0
- package/components/inputs/date-time/calendar/use-month-window.ts +163 -0
- package/components/inputs/date-time/date-picker/examples.mdx +166 -0
- package/components/inputs/date-time/date-picker/index.tsx +385 -0
- package/components/inputs/date-time/date-picker/masked-date-input.tsx +336 -0
- package/components/inputs/date-time/date-range-picker/examples.mdx +29 -0
- package/components/inputs/date-time/date-range-picker/index.tsx +217 -0
- package/components/inputs/date-time/duration-picker/examples.mdx +16 -0
- package/components/inputs/date-time/duration-picker/index.tsx +189 -0
- package/components/inputs/date-time/month-picker/examples.mdx +16 -0
- package/components/inputs/date-time/month-picker/index.tsx +190 -0
- package/components/inputs/date-time/picker-shell.tsx +395 -0
- package/components/inputs/date-time/time-columns.tsx +91 -0
- package/components/inputs/date-time/time-picker/examples.mdx +26 -0
- package/components/inputs/date-time/time-picker/index.tsx +166 -0
- package/components/inputs/field/examples.mdx +113 -0
- package/components/inputs/field/index.tsx +267 -0
- package/components/inputs/file-dropzone/examples.mdx +73 -0
- package/components/inputs/file-dropzone/file-row.tsx +201 -0
- package/components/inputs/file-dropzone/index.tsx +296 -0
- package/components/inputs/file-dropzone/upload-demo.tsx +67 -0
- package/components/inputs/file-dropzone/variants.ts +94 -0
- package/components/inputs/input/examples.mdx +135 -0
- package/components/inputs/input/index.tsx +494 -0
- package/components/inputs/input/password-demo.tsx +30 -0
- package/components/inputs/label/examples.mdx +67 -0
- package/components/inputs/label/index.tsx +85 -0
- package/components/inputs/number-input/examples.mdx +56 -0
- package/components/inputs/number-input/index.tsx +214 -0
- package/components/inputs/radio/examples.mdx +77 -0
- package/components/inputs/radio/index.tsx +636 -0
- package/components/inputs/search/examples.mdx +74 -0
- package/components/inputs/search/index.tsx +333 -0
- package/components/inputs/select/examples.mdx +218 -0
- package/components/inputs/select/index.tsx +862 -0
- package/components/inputs/select/variants.ts +32 -0
- package/components/inputs/slider/examples.mdx +127 -0
- package/components/inputs/slider/index.tsx +1734 -0
- package/components/inputs/switch/examples.mdx +94 -0
- package/components/inputs/switch/index.tsx +504 -0
- package/components/inputs/textarea/examples.mdx +88 -0
- package/components/inputs/textarea/index.tsx +161 -0
- package/components/navigation/navigation-menu/examples.mdx +109 -0
- package/components/navigation/navigation-menu/index.tsx +613 -0
- package/components/navigation/pagination/examples.mdx +68 -0
- package/components/navigation/pagination/index.tsx +401 -0
- package/components/navigation/sidebar/examples.mdx +319 -0
- package/components/navigation/sidebar/index.tsx +453 -0
- package/components/navigation/sidebar/sidebar-core.tsx +1408 -0
- package/components/navigation/sidebar/sidebar-menu.tsx +1495 -0
- package/components/navigation/sidebar/sidebar.css +74 -0
- package/components/navigation/sidebar/variants.ts +55 -0
- package/components/navigation/tabs/examples.mdx +89 -0
- package/components/navigation/tabs/index.tsx +494 -0
- package/components/navigation/tabs-subtle/examples.mdx +49 -0
- package/components/navigation/tabs-subtle/index.tsx +512 -0
- package/components/overlays/alert-dialog/examples.mdx +123 -0
- package/components/overlays/alert-dialog/index.tsx +276 -0
- package/components/overlays/alert-dialog/pending-demo.tsx +36 -0
- package/components/overlays/command/examples.mdx +113 -0
- package/components/overlays/command/index.tsx +425 -0
- package/components/overlays/context-menu/examples.mdx +56 -0
- package/components/overlays/context-menu/index.tsx +279 -0
- package/components/overlays/dialog/examples.mdx +165 -0
- package/components/overlays/dialog/index.tsx +451 -0
- package/components/overlays/dropdown/dropdown-search.tsx +395 -0
- package/components/overlays/dropdown/examples.mdx +294 -0
- package/components/overlays/dropdown/index.tsx +1169 -0
- package/components/overlays/dropdown/menu-item.tsx +464 -0
- package/components/overlays/dropdown/menu-parts.tsx +660 -0
- package/components/overlays/popover/anchored-demo.tsx +59 -0
- package/components/overlays/popover/examples.mdx +197 -0
- package/components/overlays/popover/index.tsx +317 -0
- package/components/overlays/preview-card/examples.mdx +61 -0
- package/components/overlays/preview-card/index.tsx +204 -0
- package/components/overlays/sheet/examples.mdx +101 -0
- package/components/overlays/sheet/index.tsx +307 -0
- package/components/overlays/toast/examples.mdx +85 -0
- package/components/overlays/toast/global-demo.tsx +72 -0
- package/components/overlays/toast/index.tsx +544 -0
- package/components/overlays/toast/manager.ts +193 -0
- package/components/overlays/tooltip/examples.mdx +106 -0
- package/components/overlays/tooltip/index.tsx +539 -0
- package/components/progress/examples.mdx +59 -0
- package/components/progress/index.tsx +174 -0
- package/components/progress/progress.css +49 -0
- package/components/progress/step-demo.tsx +27 -0
- package/components/table/examples.mdx +184 -0
- package/components/table/index.tsx +525 -0
- package/components/table/sort-demo.tsx +61 -0
- package/dist/base.css +100 -0
- package/dist/blocks/sidebar-app/index.js +39 -26
- package/dist/components/AI/input-message/index.js +22 -16
- package/dist/components/AI/thinking-indicator/index.js +9 -6
- package/dist/components/accordion/index.js +16 -13
- package/dist/components/avatar/index.d.ts +46 -0
- package/dist/components/avatar/index.js +18 -0
- package/dist/components/badge/index.d.ts +18 -11
- package/dist/components/badge/index.js +11 -7
- package/dist/components/badge/variants.d.ts +33 -0
- package/dist/components/badge/variants.js +10 -0
- package/dist/components/button/index.d.ts +53 -17
- package/dist/components/button/index.js +10 -6
- package/dist/components/button/variants.d.ts +39 -0
- package/dist/components/button/variants.js +8 -0
- package/dist/components/card/index.d.ts +16 -3
- package/dist/components/card/index.js +16 -11
- package/dist/components/copy/index.js +13 -9
- package/dist/components/inputs/checkbox/index.d.ts +28 -9
- package/dist/components/inputs/checkbox/index.js +17 -13
- package/dist/components/inputs/color-picker/index.d.ts +13 -13
- package/dist/components/inputs/color-picker/index.js +25 -18
- package/dist/components/inputs/color-picker/variants.d.ts +61 -0
- package/dist/components/inputs/color-picker/variants.js +28 -0
- package/dist/components/inputs/combobox/index.d.ts +60 -17
- package/dist/components/inputs/combobox/index.js +26 -18
- package/dist/components/inputs/date-time/calendar/index.js +14 -11
- package/dist/components/inputs/date-time/date-picker/index.d.ts +53 -11
- package/dist/components/inputs/date-time/date-picker/index.js +33 -25
- package/dist/components/inputs/date-time/date-range-picker/index.d.ts +3 -3
- package/dist/components/inputs/date-time/date-range-picker/index.js +32 -24
- package/dist/components/inputs/date-time/duration-picker/index.d.ts +3 -3
- package/dist/components/inputs/date-time/duration-picker/index.js +32 -24
- package/dist/components/inputs/date-time/month-picker/index.d.ts +3 -3
- package/dist/components/inputs/date-time/month-picker/index.js +31 -23
- package/dist/components/inputs/date-time/time-picker/index.d.ts +3 -3
- package/dist/components/inputs/date-time/time-picker/index.js +32 -24
- package/dist/components/inputs/field/index.d.ts +116 -0
- package/dist/components/inputs/field/index.js +28 -0
- package/dist/components/inputs/file-dropzone/index.d.ts +165 -0
- package/dist/components/inputs/file-dropzone/index.js +32 -0
- package/dist/components/inputs/file-dropzone/variants.d.ts +35 -0
- package/dist/components/inputs/file-dropzone/variants.js +12 -0
- package/dist/components/inputs/input/index.d.ts +95 -13
- package/dist/components/inputs/input/index.js +17 -9
- package/dist/components/inputs/label/index.d.ts +32 -0
- package/dist/components/inputs/label/index.js +11 -0
- package/dist/components/inputs/number-input/index.d.ts +84 -0
- package/dist/components/inputs/number-input/index.js +20 -0
- package/dist/components/inputs/radio/index.d.ts +20 -5
- package/dist/components/inputs/radio/index.js +15 -12
- package/dist/components/inputs/search/index.d.ts +3 -3
- package/dist/components/inputs/search/index.js +25 -18
- package/dist/components/inputs/select/index.d.ts +41 -11
- package/dist/components/inputs/select/index.js +27 -14
- package/dist/components/inputs/select/variants.d.ts +5 -0
- package/dist/components/inputs/select/variants.js +6 -0
- package/dist/components/inputs/slider/index.d.ts +2 -0
- package/dist/components/inputs/slider/index.js +7 -5
- package/dist/components/inputs/switch/index.d.ts +8 -2
- package/dist/components/inputs/switch/index.js +14 -12
- package/dist/components/inputs/textarea/index.d.ts +4 -0
- package/dist/components/inputs/textarea/index.js +8 -6
- package/dist/components/navigation/navigation-menu/index.d.ts +114 -0
- package/dist/components/navigation/navigation-menu/index.js +40 -0
- package/dist/components/navigation/pagination/index.d.ts +75 -0
- package/dist/components/navigation/pagination/index.js +39 -0
- package/dist/components/navigation/sidebar/index.d.ts +44 -21
- package/dist/components/navigation/sidebar/index.js +41 -31
- package/dist/components/navigation/sidebar/variants.d.ts +25 -0
- package/dist/components/navigation/sidebar/variants.js +28 -0
- package/dist/components/navigation/tabs/index.d.ts +8 -2
- package/dist/components/navigation/tabs/index.js +14 -10
- package/dist/components/navigation/tabs-subtle/index.js +12 -10
- package/dist/components/overlays/alert-dialog/index.d.ts +135 -16
- package/dist/components/overlays/alert-dialog/index.js +22 -13
- package/dist/components/overlays/command/index.d.ts +25 -20
- package/dist/components/overlays/command/index.js +24 -17
- package/dist/components/overlays/context-menu/index.d.ts +33 -17
- package/dist/components/overlays/context-menu/index.js +27 -18
- package/dist/components/overlays/dialog/index.d.ts +42 -16
- package/dist/components/overlays/dialog/index.js +19 -12
- package/dist/components/overlays/dropdown/index.d.ts +256 -30
- package/dist/components/overlays/dropdown/index.js +42 -17
- package/dist/components/overlays/popover/index.d.ts +38 -12
- package/dist/components/overlays/popover/index.js +12 -9
- package/dist/components/overlays/preview-card/index.js +11 -8
- package/dist/components/overlays/sheet/index.d.ts +25 -8
- package/dist/components/overlays/sheet/index.js +18 -13
- package/dist/components/overlays/toast/index.d.ts +209 -50
- package/dist/components/overlays/toast/index.js +22 -10
- package/dist/components/overlays/tooltip/index.d.ts +123 -21
- package/dist/components/overlays/tooltip/index.js +15 -6
- package/dist/components/progress/index.d.ts +56 -0
- package/dist/components/progress/index.js +15 -0
- package/dist/components/table/index.d.ts +63 -8
- package/dist/components/table/index.js +20 -9
- package/dist/index.d.ts +2380 -831
- package/dist/index.js +229 -82
- package/dist/lib/date-locale.d.ts +14 -0
- package/dist/lib/date-locale.js +16 -0
- package/dist/lib/field-classes.d.ts +144 -0
- package/dist/lib/field-classes.js +40 -0
- package/dist/lib/field-variants.d.ts +47 -0
- package/dist/lib/field-variants.js +26 -0
- package/dist/lib/fluid-hover-highlight.d.ts +112 -0
- package/dist/lib/fluid-hover-highlight.js +17 -0
- package/dist/lib/focus-ring.d.ts +18 -0
- package/dist/lib/focus-ring.js +10 -0
- package/dist/lib/goo-indicator.d.ts +46 -0
- package/dist/lib/goo-indicator.js +14 -0
- package/dist/lib/icon-context.d.ts +30 -0
- package/dist/lib/icon-context.js +12 -0
- package/dist/lib/inert.d.ts +9 -0
- package/dist/lib/inert.js +8 -0
- package/dist/lib/morph-layers.d.ts +93 -0
- package/dist/lib/morph-layers.js +13 -0
- package/dist/lib/morph-part.d.ts +21 -0
- package/dist/lib/morph-part.js +12 -0
- package/dist/lib/popup.d.ts +20 -0
- package/dist/lib/popup.js +12 -0
- package/dist/lib/reduced-motion.d.ts +9 -0
- package/dist/lib/reduced-motion.js +6 -0
- package/dist/lib/row-index.d.ts +10 -0
- package/dist/lib/row-index.js +8 -0
- package/dist/lib/row-order.d.ts +28 -0
- package/dist/lib/row-order.js +10 -0
- package/dist/lib/scroll-column.d.ts +27 -0
- package/dist/lib/scroll-column.js +18 -0
- package/dist/lib/shape-context.d.ts +30 -0
- package/dist/lib/shape-context.js +12 -0
- package/dist/lib/size-context.d.ts +94 -0
- package/dist/lib/size-context.js +20 -0
- package/dist/lib/size-scale.d.ts +79 -0
- package/dist/lib/size-scale.js +8 -0
- package/dist/lib/slot.d.ts +19 -0
- package/dist/lib/slot.js +6 -0
- package/dist/lib/springs.d.ts +44 -0
- package/dist/lib/springs.js +8 -0
- package/dist/lib/surface-classes.d.ts +19 -0
- package/dist/lib/surface-classes.js +10 -0
- package/dist/lib/surface-context.d.ts +9 -0
- package/dist/lib/surface-context.js +8 -0
- package/dist/lib/use-controllable-state.d.ts +2 -0
- package/dist/lib/use-controllable-state.js +6 -0
- package/dist/lib/use-fluid-hover.d.ts +138 -0
- package/dist/lib/use-fluid-hover.js +14 -0
- package/dist/lib/use-is-mobile.d.ts +2 -0
- package/dist/lib/use-is-mobile.js +6 -0
- package/dist/lib/use-keyboard-nav-gate.d.ts +20 -0
- package/dist/lib/use-keyboard-nav-gate.js +7 -0
- package/dist/lib/use-merge-split.d.ts +47 -0
- package/dist/lib/use-merge-split.js +15 -0
- package/dist/lib/use-morph.d.ts +101 -0
- package/dist/lib/use-morph.js +20 -0
- package/dist/lib/use-touch-primary.d.ts +2 -0
- package/dist/lib/use-touch-primary.js +6 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.js +6 -0
- package/dist/preset.d.ts +17 -0
- package/dist/preset.js +22 -2
- package/dist/primitives/code/index.js +7 -5
- package/dist/primitives/craft/index.js +9 -6
- package/dist/primitives/fluid-hover/index.js +9 -8
- package/dist/primitives/morph/index.js +15 -10
- package/dist/primitives/motion/index.js +10 -8
- package/dist/primitives/scroll-area/index.js +4 -3
- package/dist/primitives/separator/index.d.ts +25 -0
- package/dist/primitives/separator/index.js +9 -0
- package/dist/primitives/sizes/index.js +6 -4
- package/dist/primitives/skeleton/index.d.ts +35 -0
- package/dist/primitives/skeleton/index.js +12 -0
- package/dist/primitives/surface/index.js +6 -4
- package/dist/shared/{components-3mkepka5.js → components-0jmqhx2k.js} +28 -25
- package/dist/shared/{components-s5ngg32c.js → components-0khyhjn5.js} +121 -47
- package/dist/shared/{components-sn1rxx1d.js → components-0n95jaa2.js} +12 -11
- package/dist/shared/components-0x6mx1p5.js +252 -0
- package/dist/shared/components-124epb7f.js +53 -0
- package/dist/shared/{components-gz8zf3ec.js → components-1k0wv53d.js} +15 -43
- package/dist/shared/components-26snnbs9.js +322 -0
- package/dist/shared/{components-2dxkv6zm.js → components-2c0qcfx4.js} +8 -7
- package/dist/shared/{components-y9y0g8er.js → components-2gk4yywm.js} +23 -20
- package/dist/shared/{components-473g814w.js → components-2mt9te6d.js} +243 -137
- package/dist/shared/{components-hawvy2qz.js → components-2z48g4fp.js} +9 -30
- package/dist/shared/components-34txk9rj.js +35 -0
- package/dist/shared/components-3h92d94m.js +23 -0
- package/dist/shared/{components-s2bz1xpk.js → components-49bsynbw.js} +8 -5
- package/dist/shared/components-4bwsd46w.js +71 -0
- package/dist/shared/{components-0q0sqfh4.js → components-4y816hwp.js} +27 -49
- package/dist/shared/components-52ngsgca.js +399 -0
- package/dist/shared/components-559tf7yb.js +28 -0
- package/dist/shared/components-591m0a57.js +500 -0
- package/dist/shared/components-5mkga9hj.js +440 -0
- package/dist/shared/{components-zfnmn5d4.js → components-5nsn4w8c.js} +79 -35
- package/dist/shared/{components-kwa6mrf9.js → components-5s0nfqvw.js} +14 -9
- package/dist/shared/{components-39vmfq9s.js → components-5t2f1kq7.js} +24 -22
- package/dist/shared/{components-dk0gjr5a.js → components-60atskhp.js} +19 -18
- package/dist/shared/components-6zng858q.js +53 -0
- package/dist/shared/components-72w4ge68.js +64 -0
- package/dist/shared/{components-cv16mryv.js → components-78x40gee.js} +13 -7
- package/dist/shared/components-79q3xxwr.js +179 -0
- package/dist/shared/{components-b2wyq2cq.js → components-7d4r7hh1.js} +39 -57
- package/dist/shared/components-7ntvvegr.js +316 -0
- package/dist/shared/{components-5vgpnxgy.js → components-7xrqvk6g.js} +20 -17
- package/dist/shared/components-8nwsqjn8.js +34 -0
- package/dist/shared/{components-5xc2j8jz.js → components-8tt3xbb5.js} +19 -18
- package/dist/shared/{components-vc7vq5nz.js → components-9as3rf68.js} +6 -3
- package/dist/shared/components-adkarj8n.js +35 -0
- package/dist/shared/{components-b3c5et5b.js → components-ae9fncz4.js} +32 -31
- package/dist/shared/{components-jthe1pwb.js → components-ajhdkhjz.js} +101 -404
- package/dist/shared/{components-hqeq3w9q.js → components-awra5sff.js} +24 -16
- package/dist/shared/components-b1e239g3.js +28 -0
- package/dist/shared/{components-q5xj5c16.js → components-b1f2bjf1.js} +9 -8
- package/dist/shared/components-c9yr4ed1.js +44 -0
- package/dist/shared/components-d3shbwqq.js +95 -0
- package/dist/shared/{components-wvp1m52g.js → components-d6vf38m5.js} +22 -18
- package/dist/shared/{components-jjw69c4c.js → components-dcc02hs2.js} +7 -4
- package/dist/shared/{components-men63rwj.js → components-de99ykt7.js} +3 -2
- package/dist/shared/components-dhgk6mbt.js +16 -0
- package/dist/shared/components-drxrtnp2.js +25 -0
- package/dist/shared/{components-mjthm1kf.js → components-egy4tyjt.js} +11 -8
- package/dist/shared/components-f0xfpkhh.js +82 -0
- package/dist/shared/components-f7h57m6t.js +59 -0
- package/dist/shared/{components-frw34b65.js → components-faww1hy7.js} +114 -123
- package/dist/shared/components-gjd5v54y.js +271 -0
- package/dist/shared/{components-39jq9va1.js → components-gvbapfen.js} +29 -24
- package/dist/shared/components-h6p86be3.js +19 -0
- package/dist/shared/components-h83az0bz.js +33 -0
- package/dist/shared/{components-ar66gnt0.js → components-h9vrr1j2.js} +37 -34
- package/dist/shared/components-hbk69y68.js +298 -0
- package/dist/shared/{components-rr7a6ja9.js → components-jamcmdsd.js} +59 -27
- package/dist/shared/{components-zrkzcayz.js → components-jqpefjsn.js} +54 -6
- package/dist/shared/{components-xxvdw7k1.js → components-k1b0vhcq.js} +37 -34
- package/dist/shared/{components-1z6tdadk.js → components-k74j4hwh.js} +20 -17
- package/dist/shared/components-kswxnm3h.js +24 -0
- package/dist/shared/components-m1m46jdv.js +1444 -0
- package/dist/shared/{components-5pnw8183.js → components-mjnzv5vj.js} +23 -22
- package/dist/shared/components-mkezgkgk.js +10 -0
- package/dist/shared/{components-jbbmdr74.js → components-mkkbbgb7.js} +36 -17
- package/dist/shared/{components-pbmqctfa.js → components-mpw667rb.js} +169 -65
- package/dist/shared/{components-6p8tfcd6.js → components-my6hpnn6.js} +22 -19
- package/dist/shared/{components-s083f38z.js → components-nbvtmgme.js} +22 -21
- package/dist/shared/{components-jwst3vtj.js → components-ncdgtg6b.js} +224 -76
- package/dist/shared/{components-vfbhxf5r.js → components-pd42emw3.js} +6 -5
- package/dist/shared/{components-hw9yk32z.js → components-pmfszv7a.js} +35 -23
- package/dist/shared/{components-chacnk61.js → components-pw06rbxq.js} +19 -19
- package/dist/shared/{components-qmmjx1qw.js → components-q3pbax3p.js} +71 -72
- package/dist/shared/components-q5h7v6rr.js +104 -0
- package/dist/shared/{components-kvr7f9hy.js → components-qdm3yh26.js} +19 -10
- package/dist/shared/{components-27nnvrwe.js → components-qs4rkqsj.js} +15 -14
- package/dist/shared/{components-ta7shw28.js → components-r8eqs7gz.js} +4 -4
- package/dist/shared/{components-c6s6b43g.js → components-rrbpmfx4.js} +3 -2
- package/dist/shared/{components-d6xtjht3.js → components-tarz14gk.js} +33 -30
- package/dist/shared/{components-n7mjr357.js → components-tz1fv35x.js} +3 -2
- package/dist/shared/components-tz4gaf1v.js +23 -0
- package/dist/shared/{components-zx6b6yby.js → components-vf45j12c.js} +4 -18
- package/dist/shared/{components-gc5vtq2f.js → components-vqpzqwcg.js} +63 -29
- package/dist/shared/components-wktrrb4m.js +38 -0
- package/dist/shared/{components-8snj490h.js → components-wwd363me.js} +78 -32
- package/dist/shared/components-xdqmt6ed.js +20 -0
- package/dist/shared/{components-h2ajmhwn.js → components-y1w3a6wx.js} +107 -35
- package/dist/shared/{components-59efxjd9.js → components-yhgq0qxx.js} +13 -12
- package/dist/shared/components-z3v0n0de.js +11 -0
- package/dist/shared/{components-7r3etddy.js → components-z9n19fyk.js} +19 -54
- package/dist/shared/components-zbvjzh1p.js +141 -0
- package/dist/styles.css +241 -16
- package/dist/tailwind.css +13 -0
- package/dist/tokens.css +34 -0
- package/index.ts +60 -0
- package/lib/date-locale.ts +50 -0
- package/lib/field-classes.ts +115 -0
- package/lib/field-variants.ts +117 -0
- package/lib/fluid-hover-highlight.tsx +139 -0
- package/lib/focus-ring.tsx +46 -0
- package/lib/goo-indicator.tsx +261 -0
- package/lib/icon-context.tsx +310 -0
- package/lib/inert.ts +22 -0
- package/lib/morph-layers.tsx +102 -0
- package/lib/morph-part.tsx +49 -0
- package/lib/popup.ts +52 -0
- package/lib/reduced-motion.ts +19 -0
- package/lib/row-index.tsx +29 -0
- package/lib/row-order.tsx +115 -0
- package/lib/scroll-column.tsx +244 -0
- package/lib/shape-context.tsx +124 -0
- package/lib/size-context.tsx +66 -0
- package/lib/size-scale.ts +115 -0
- package/lib/slot.ts +35 -0
- package/lib/springs.ts +62 -0
- package/lib/surface-classes.ts +58 -0
- package/lib/surface-context.tsx +21 -0
- package/lib/use-controllable-state.ts +44 -0
- package/lib/use-fluid-hover.ts +541 -0
- package/lib/use-is-mobile.ts +25 -0
- package/lib/use-keyboard-nav-gate.ts +45 -0
- package/lib/use-merge-split.tsx +209 -0
- package/lib/use-morph.ts +557 -0
- package/lib/use-touch-primary.tsx +43 -0
- package/lib/utils.ts +37 -0
- package/package.json +177 -4
- package/preset.ts +196 -0
- package/primitives/code/examples.mdx +27 -0
- package/primitives/code/index.tsx +80 -0
- package/primitives/craft/demos.tsx +173 -0
- package/primitives/craft/examples.mdx +138 -0
- package/primitives/craft/index.tsx +76 -0
- package/primitives/fluid-hover/examples.mdx +84 -0
- package/primitives/fluid-hover/index.tsx +316 -0
- package/primitives/morph/examples.mdx +135 -0
- package/primitives/morph/index.tsx +192 -0
- package/primitives/motion/examples.mdx +100 -0
- package/primitives/motion/index.tsx +160 -0
- package/primitives/scroll-area/examples.mdx +58 -0
- package/primitives/scroll-area/index.tsx +200 -0
- package/primitives/separator/examples.mdx +30 -0
- package/primitives/separator/index.tsx +53 -0
- package/primitives/sizes/examples.mdx +167 -0
- package/primitives/sizes/index.tsx +89 -0
- package/primitives/skeleton/examples.mdx +51 -0
- package/primitives/skeleton/index.tsx +72 -0
- package/primitives/skeleton/skeleton.css +15 -0
- package/primitives/surface/examples.mdx +173 -0
- package/primitives/surface/index.tsx +109 -0
- package/primitives/surface/surface.css +176 -0
- package/dist/shared/components-0sn7ypjw.js +0 -61
- package/dist/shared/components-1434p1mh.js +0 -123
- package/dist/shared/components-3ky44908.js +0 -9
- package/dist/shared/components-a86dytt0.js +0 -986
- package/dist/shared/components-gf5s6ap9.js +0 -42
- package/dist/shared/components-hyq23phv.js +0 -310
- package/dist/shared/components-ng72k97e.js +0 -128
- package/dist/shared/components-raknhppb.js +0 -64
- package/dist/shared/components-vynjtrk6.js +0 -19
- package/dist/shared/components-wy9jpqny.js +0 -146
- /package/dist/shared/{components-1v7rxytx.js → components-3ey0hzpb.js} +0 -0
- /package/dist/shared/{components-ezxhrmer.js → components-jcnjay5g.js} +0 -0
package/DESIGN.md
ADDED
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: alpha
|
|
3
|
+
name: UI — Fluid Functionalism for modo
|
|
4
|
+
description: >-
|
|
5
|
+
A quiet, neutral, dense interface where motion carries the meaning: springs instead of durations,
|
|
6
|
+
one hover highlight that glides between rows, labels that get heavier without moving, eight nesting
|
|
7
|
+
surface levels, and overlays that melt out of whatever opened them through a liquid neck. Light values
|
|
8
|
+
are the plain token names; `-dark` twins are the dark scheme (every color is one light-dark() token in
|
|
9
|
+
tokens/colors.css and primitives/surface/surface.css).
|
|
10
|
+
colors:
|
|
11
|
+
primary: "oklch(0.205 0 0)"
|
|
12
|
+
on-primary: "oklch(0.985 0 0)"
|
|
13
|
+
background: "oklch(0.985 0 0)"
|
|
14
|
+
background-dark: "oklch(0.205 0 0)"
|
|
15
|
+
foreground: "oklch(0.205 0 0)"
|
|
16
|
+
foreground-dark: "oklch(0.97 0 0)"
|
|
17
|
+
card: "oklch(1 0 0)"
|
|
18
|
+
card-dark: "oklch(0.264 0 0)"
|
|
19
|
+
muted: "oklch(0.967 0.001 286.375)"
|
|
20
|
+
muted-dark: "oklch(0.235 0 0)"
|
|
21
|
+
muted-foreground: "oklch(0.556 0 0)"
|
|
22
|
+
muted-foreground-dark: "oklch(0.7155 0 0)"
|
|
23
|
+
accent: "oklch(0.922 0 0)"
|
|
24
|
+
accent-dark: "oklch(0.439 0 0)"
|
|
25
|
+
selected: "oklch(0.87 0 0)"
|
|
26
|
+
selected-dark: "oklch(0.439 0 0)"
|
|
27
|
+
border: "color-mix(in srgb, oklch(0.205 0 0) 12%, transparent)"
|
|
28
|
+
border-dark: "color-mix(in srgb, oklch(0.97 0 0) 12%, transparent)"
|
|
29
|
+
input: "oklch(0.922 0 0)"
|
|
30
|
+
input-dark: "oklch(0.371 0 0)"
|
|
31
|
+
control-border: "oklch(0.708 0 0)"
|
|
32
|
+
control-border-dark: "oklch(0.556 0 0)"
|
|
33
|
+
hover: "rgb(0 0 0 / 0.04)"
|
|
34
|
+
hover-dark: "rgb(255 255 255 / 0.06)"
|
|
35
|
+
active: "rgb(0 0 0 / 0.07)"
|
|
36
|
+
active-dark: "rgb(255 255 255 / 0.1)"
|
|
37
|
+
scrim: "oklch(0 0 0 / 0.4)"
|
|
38
|
+
scrim-dark: "oklch(0 0 0 / 0.8)"
|
|
39
|
+
brand: "oklch(0.693 0.16 265)"
|
|
40
|
+
brand-hover: "oklch(0.649 0.164 264.76)"
|
|
41
|
+
focus-ring: "oklch(0.693 0.16 265)"
|
|
42
|
+
thumb: "oklch(1 0 0)"
|
|
43
|
+
destructive: "oklch(0.6368 0.2078 25.33)"
|
|
44
|
+
destructive-dark: "oklch(0.7106 0.1661 22.22)"
|
|
45
|
+
destructive-light: "oklch(0.971 0.013 17.38)"
|
|
46
|
+
destructive-light-dark: "oklch(0.2575 0.0886 26.04)"
|
|
47
|
+
destructive-strong: "oklch(0.47 0.175 27)"
|
|
48
|
+
destructive-strong-dark: "oklch(0.81 0.105 22)"
|
|
49
|
+
destructive-wash: "color-mix(in oklab, oklch(0.6368 0.2078 25.33) 16%, transparent)"
|
|
50
|
+
destructive-wash-dark: "color-mix(in oklab, oklch(0.7106 0.1661 22.22) 16%, transparent)"
|
|
51
|
+
destructive-wash-hover: "color-mix(in oklab, oklch(0.6368 0.2078 25.33) 20%, transparent)"
|
|
52
|
+
destructive-wash-hover-dark: "color-mix(in oklab, oklch(0.7106 0.1661 22.22) 20%, transparent)"
|
|
53
|
+
destructive-wash-active: "color-mix(in oklab, oklch(0.6368 0.2078 25.33) 24%, transparent)"
|
|
54
|
+
destructive-wash-active-dark: "color-mix(in oklab, oklch(0.7106 0.1661 22.22) 24%, transparent)"
|
|
55
|
+
success-strong: "oklch(0.46 0.12 151)"
|
|
56
|
+
success-strong-dark: "oklch(0.83 0.15 152)"
|
|
57
|
+
success-wash: "color-mix(in oklab, oklch(0.723 0.192 149.58) 16%, transparent)"
|
|
58
|
+
success-wash-hover: "color-mix(in oklab, oklch(0.723 0.192 149.58) 20%, transparent)"
|
|
59
|
+
success-wash-active: "color-mix(in oklab, oklch(0.723 0.192 149.58) 24%, transparent)"
|
|
60
|
+
status-success: "oklch(0.723 0.192 149.58)"
|
|
61
|
+
status-loading: "oklch(0.715 0 0)"
|
|
62
|
+
status-warning: "oklch(0.7686 0.1647 70.08)"
|
|
63
|
+
status-info: "oklch(0.623 0.188 259.81)"
|
|
64
|
+
skeleton: "color-mix(in oklab, oklch(0.205 0 0) 8%, transparent)"
|
|
65
|
+
skeleton-dark: "color-mix(in oklab, oklch(0.97 0 0) 8%, transparent)"
|
|
66
|
+
image-edge: "rgb(0 0 0 / 0.1)"
|
|
67
|
+
image-edge-dark: "rgb(255 255 255 / 0.1)"
|
|
68
|
+
progress-track: "color-mix(in oklab, oklch(0.205 0 0) 10%, transparent)"
|
|
69
|
+
progress-track-dark: "color-mix(in oklab, oklch(0.97 0 0) 10%, transparent)"
|
|
70
|
+
surface-1: "oklch(0.985 0 0)"
|
|
71
|
+
surface-2: "oklch(0.991 0 0)"
|
|
72
|
+
surface-3: "oklch(1 0 0)"
|
|
73
|
+
surface-4: "oklch(1 0 0)"
|
|
74
|
+
surface-5: "oklch(1 0 0)"
|
|
75
|
+
surface-6: "oklch(1 0 0)"
|
|
76
|
+
surface-7: "oklch(1 0 0)"
|
|
77
|
+
surface-8: "oklch(1 0 0)"
|
|
78
|
+
surface-1-dark: "oklch(0.205 0 0)"
|
|
79
|
+
surface-2-dark: "oklch(0.235 0 0)"
|
|
80
|
+
surface-3-dark: "oklch(0.264 0 0)"
|
|
81
|
+
surface-4-dark: "oklch(0.293 0 0)"
|
|
82
|
+
surface-5-dark: "oklch(0.321 0 0)"
|
|
83
|
+
surface-6-dark: "oklch(0.349 0 0)"
|
|
84
|
+
surface-7-dark: "oklch(0.375 0 0)"
|
|
85
|
+
surface-8-dark: "oklch(0.402 0 0)"
|
|
86
|
+
typography:
|
|
87
|
+
display:
|
|
88
|
+
fontFamily: Inter Variable
|
|
89
|
+
fontSize: 28px
|
|
90
|
+
fontWeight: 700
|
|
91
|
+
lineHeight: 34px
|
|
92
|
+
fontVariation: "'wght' 700, 'opsz' 25"
|
|
93
|
+
title:
|
|
94
|
+
fontFamily: Inter Variable
|
|
95
|
+
fontSize: 16px
|
|
96
|
+
fontWeight: 550
|
|
97
|
+
lineHeight: 22px
|
|
98
|
+
fontVariation: "'wght' 550, 'opsz' 18"
|
|
99
|
+
subtitle:
|
|
100
|
+
fontFamily: Inter Variable
|
|
101
|
+
fontSize: 14px
|
|
102
|
+
fontWeight: 550
|
|
103
|
+
lineHeight: 20px
|
|
104
|
+
fontVariation: "'wght' 550, 'opsz' 18"
|
|
105
|
+
body:
|
|
106
|
+
fontFamily: Inter Variable
|
|
107
|
+
fontSize: 13px
|
|
108
|
+
fontWeight: 400
|
|
109
|
+
lineHeight: 20px
|
|
110
|
+
fontVariation: "'wght' 400, 'opsz' 14"
|
|
111
|
+
body-selected:
|
|
112
|
+
fontFamily: Inter Variable
|
|
113
|
+
fontSize: 13px
|
|
114
|
+
fontWeight: 550
|
|
115
|
+
lineHeight: 20px
|
|
116
|
+
fontVariation: "'wght' 550, 'opsz' 18"
|
|
117
|
+
caption:
|
|
118
|
+
fontFamily: Inter Variable
|
|
119
|
+
fontSize: 12px
|
|
120
|
+
fontWeight: 400
|
|
121
|
+
lineHeight: 16px
|
|
122
|
+
fontVariation: "'wght' 400, 'opsz' 14"
|
|
123
|
+
caption-medium:
|
|
124
|
+
fontFamily: Inter Variable
|
|
125
|
+
fontSize: 12px
|
|
126
|
+
fontWeight: 450
|
|
127
|
+
lineHeight: 16px
|
|
128
|
+
fontVariation: "'wght' 450, 'opsz' 15"
|
|
129
|
+
micro:
|
|
130
|
+
fontFamily: Inter Variable
|
|
131
|
+
fontSize: 11px
|
|
132
|
+
fontWeight: 400
|
|
133
|
+
lineHeight: 14px
|
|
134
|
+
fontVariation: "'wght' 400, 'opsz' 14"
|
|
135
|
+
display-compact:
|
|
136
|
+
fontFamily: Inter Variable
|
|
137
|
+
fontSize: 24px
|
|
138
|
+
fontWeight: 700
|
|
139
|
+
lineHeight: 34px
|
|
140
|
+
fontVariation: "'wght' 700, 'opsz' 25"
|
|
141
|
+
title-compact:
|
|
142
|
+
fontFamily: Inter Variable
|
|
143
|
+
fontSize: 15px
|
|
144
|
+
fontWeight: 550
|
|
145
|
+
lineHeight: 22px
|
|
146
|
+
fontVariation: "'wght' 550, 'opsz' 18"
|
|
147
|
+
subtitle-compact:
|
|
148
|
+
fontFamily: Inter Variable
|
|
149
|
+
fontSize: 13px
|
|
150
|
+
fontWeight: 550
|
|
151
|
+
lineHeight: 20px
|
|
152
|
+
fontVariation: "'wght' 550, 'opsz' 18"
|
|
153
|
+
body-compact:
|
|
154
|
+
fontFamily: Inter Variable
|
|
155
|
+
fontSize: 12px
|
|
156
|
+
fontWeight: 400
|
|
157
|
+
lineHeight: 20px
|
|
158
|
+
fontVariation: "'wght' 400, 'opsz' 14"
|
|
159
|
+
caption-compact:
|
|
160
|
+
fontFamily: Inter Variable
|
|
161
|
+
fontSize: 11px
|
|
162
|
+
fontWeight: 400
|
|
163
|
+
lineHeight: 16px
|
|
164
|
+
fontVariation: "'wght' 400, 'opsz' 14"
|
|
165
|
+
micro-compact:
|
|
166
|
+
fontFamily: Inter Variable
|
|
167
|
+
fontSize: 10px
|
|
168
|
+
fontWeight: 400
|
|
169
|
+
lineHeight: 14px
|
|
170
|
+
fontVariation: "'wght' 400, 'opsz' 14"
|
|
171
|
+
code:
|
|
172
|
+
fontFamily: ui-monospace
|
|
173
|
+
fontSize: 12px
|
|
174
|
+
fontWeight: 400
|
|
175
|
+
lineHeight: 16px
|
|
176
|
+
rounded:
|
|
177
|
+
glyph: 3px
|
|
178
|
+
box: 5px
|
|
179
|
+
md: 6px
|
|
180
|
+
lg: 8px
|
|
181
|
+
focus-ring: 10px
|
|
182
|
+
xl: 12px
|
|
183
|
+
2xl: 16px
|
|
184
|
+
pill: 20px
|
|
185
|
+
pill-focus-ring: 22px
|
|
186
|
+
3xl: 24px
|
|
187
|
+
full: 9999px
|
|
188
|
+
spacing:
|
|
189
|
+
space-1: 4px
|
|
190
|
+
space-2: 8px
|
|
191
|
+
space-3: 12px
|
|
192
|
+
space-4: 16px
|
|
193
|
+
space-5: 24px
|
|
194
|
+
space-6: 32px
|
|
195
|
+
control: 36px
|
|
196
|
+
control-compact: 28px
|
|
197
|
+
segment-item: 28px
|
|
198
|
+
segment-item-compact: 24px
|
|
199
|
+
control-px: 12px
|
|
200
|
+
control-px-compact: 10px
|
|
201
|
+
row-px: 8px
|
|
202
|
+
row-px-compact: 6px
|
|
203
|
+
gap: 8px
|
|
204
|
+
gap-compact: 4px
|
|
205
|
+
icon: 16px
|
|
206
|
+
icon-compact: 14px
|
|
207
|
+
goo-neck: 12px
|
|
208
|
+
measure: 45rem
|
|
209
|
+
motion:
|
|
210
|
+
fast: 80ms
|
|
211
|
+
fast-exit: 60ms
|
|
212
|
+
moderate: 160ms
|
|
213
|
+
moderate-exit: 120ms
|
|
214
|
+
slow: 240ms
|
|
215
|
+
slow-exit: 160ms
|
|
216
|
+
goo: 250ms
|
|
217
|
+
goo-exit: 200ms
|
|
218
|
+
loop: 2s
|
|
219
|
+
components:
|
|
220
|
+
button-primary:
|
|
221
|
+
backgroundColor: "{colors.foreground}"
|
|
222
|
+
textColor: "{colors.background}"
|
|
223
|
+
typography: "{typography.body}"
|
|
224
|
+
rounded: "{rounded.lg}"
|
|
225
|
+
height: "{spacing.control}"
|
|
226
|
+
padding: 0 16px
|
|
227
|
+
button-primary-hover:
|
|
228
|
+
backgroundColor: "color-mix(in srgb, oklch(0.205 0 0) 90%, oklch(0.985 0 0))"
|
|
229
|
+
button-primary-active:
|
|
230
|
+
backgroundColor: "color-mix(in srgb, oklch(0.205 0 0) 80%, oklch(0.985 0 0))"
|
|
231
|
+
button-secondary:
|
|
232
|
+
backgroundColor: "{colors.accent}"
|
|
233
|
+
textColor: "{colors.foreground}"
|
|
234
|
+
typography: "{typography.body}"
|
|
235
|
+
rounded: "{rounded.lg}"
|
|
236
|
+
height: "{spacing.control}"
|
|
237
|
+
padding: 0 16px
|
|
238
|
+
button-secondary-hover:
|
|
239
|
+
backgroundColor: "color-mix(in srgb, oklch(0.922 0 0) 80%, oklch(0.985 0 0))"
|
|
240
|
+
button-tertiary:
|
|
241
|
+
textColor: "{colors.foreground}"
|
|
242
|
+
rounded: "{rounded.lg}"
|
|
243
|
+
height: "{spacing.control}"
|
|
244
|
+
padding: 0 16px
|
|
245
|
+
button-tertiary-hover:
|
|
246
|
+
backgroundColor: "{colors.hover}"
|
|
247
|
+
button-ghost:
|
|
248
|
+
textColor: "{colors.muted-foreground}"
|
|
249
|
+
rounded: "{rounded.lg}"
|
|
250
|
+
height: "{spacing.control}"
|
|
251
|
+
button-ghost-hover:
|
|
252
|
+
backgroundColor: "{colors.hover}"
|
|
253
|
+
button-compact:
|
|
254
|
+
typography: "{typography.body-compact}"
|
|
255
|
+
height: "{spacing.control-compact}"
|
|
256
|
+
padding: 0 12px
|
|
257
|
+
input-field:
|
|
258
|
+
textColor: "{colors.foreground}"
|
|
259
|
+
typography: "{typography.body}"
|
|
260
|
+
rounded: "{rounded.lg}"
|
|
261
|
+
height: "{spacing.control}"
|
|
262
|
+
padding: 0 10px
|
|
263
|
+
input-field-focus:
|
|
264
|
+
backgroundColor: "{colors.card}"
|
|
265
|
+
menu-popup:
|
|
266
|
+
backgroundColor: "{colors.surface-3}"
|
|
267
|
+
rounded: "{rounded.xl}"
|
|
268
|
+
menu-row:
|
|
269
|
+
textColor: "{colors.foreground}"
|
|
270
|
+
typography: "{typography.body}"
|
|
271
|
+
rounded: "{rounded.lg}"
|
|
272
|
+
height: "{spacing.control}"
|
|
273
|
+
padding: 0 8px
|
|
274
|
+
hover-highlight:
|
|
275
|
+
backgroundColor: "{colors.hover}"
|
|
276
|
+
rounded: "{rounded.lg}"
|
|
277
|
+
popover:
|
|
278
|
+
backgroundColor: "{colors.surface-3}"
|
|
279
|
+
rounded: "{rounded.xl}"
|
|
280
|
+
padding: 16px
|
|
281
|
+
dialog:
|
|
282
|
+
backgroundColor: "{colors.surface-5}"
|
|
283
|
+
rounded: "{rounded.xl}"
|
|
284
|
+
padding: 24px
|
|
285
|
+
width: 400px
|
|
286
|
+
tabs-list:
|
|
287
|
+
backgroundColor: "{colors.muted}"
|
|
288
|
+
rounded: "{rounded.xl}"
|
|
289
|
+
height: "{spacing.control}"
|
|
290
|
+
padding: 4px
|
|
291
|
+
tabs-indicator:
|
|
292
|
+
backgroundColor: "{colors.surface-4}"
|
|
293
|
+
rounded: "{rounded.lg}"
|
|
294
|
+
height: "{spacing.segment-item}"
|
|
295
|
+
tooltip:
|
|
296
|
+
backgroundColor: "{colors.foreground}"
|
|
297
|
+
textColor: "{colors.background}"
|
|
298
|
+
typography: "{typography.caption-medium}"
|
|
299
|
+
rounded: "{rounded.lg}"
|
|
300
|
+
padding: 4px 8px
|
|
301
|
+
badge:
|
|
302
|
+
typography: "{typography.caption-medium}"
|
|
303
|
+
rounded: "{rounded.lg}"
|
|
304
|
+
height: 24px
|
|
305
|
+
padding: 0 10px
|
|
306
|
+
switch-track-on:
|
|
307
|
+
backgroundColor: "{colors.brand}"
|
|
308
|
+
switch-thumb:
|
|
309
|
+
backgroundColor: "{colors.thumb}"
|
|
310
|
+
rounded: "{rounded.full}"
|
|
311
|
+
code-block:
|
|
312
|
+
backgroundColor: "{colors.surface-2}"
|
|
313
|
+
textColor: "{colors.foreground}"
|
|
314
|
+
typography: "{typography.code}"
|
|
315
|
+
rounded: "{rounded.xl}"
|
|
316
|
+
padding: 16px
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
# UI — Fluid Functionalism for modo
|
|
320
|
+
|
|
321
|
+
The `ui` design system: Fluid Functionalism (Base UI flavor, MIT © 2026 Micka Touillaud) on UnoCSS and
|
|
322
|
+
`cn`, plus a local morph layer that makes overlays and indicators liquid. The front matter holds the
|
|
323
|
+
normative values; the CSS custom properties in `tokens/*.css` and `primitives/surface/surface.css` are
|
|
324
|
+
the source they are copied from, and they win if the two ever disagree. Component code never writes
|
|
325
|
+
these values: it reads the utility that maps to each token (the class in backticks below).
|
|
326
|
+
|
|
327
|
+
## Overview
|
|
328
|
+
|
|
329
|
+
Functional first, then fluid. The interface is neutral, compact and quiet at rest, and almost every
|
|
330
|
+
pixel of personality is spent on *how things change*: a state change is always legible, never abrupt,
|
|
331
|
+
and never decorative.
|
|
332
|
+
|
|
333
|
+
- **Neutral, ink on paper.** Greyscale everywhere. The one chromatic accent, a cool blue (`brand`), is
|
|
334
|
+
reserved for focus, "on" (switch track), drop targets and the selected swatch. Status hues appear only
|
|
335
|
+
in toasts, badges and errors.
|
|
336
|
+
- **Dense, desktop-grade.** 13px body text, 36px controls, a 28px compact step for toolbars, tables and
|
|
337
|
+
sidebars. Density is chosen per region (`SizeProvider`), never per control.
|
|
338
|
+
- **Hierarchy from size, weight and elevation**, not from color, borders, capitals or letter-spacing.
|
|
339
|
+
- **Motion is the signature.** Springs, not durations. One hover highlight per list that glides to the
|
|
340
|
+
nearest row. Selection backgrounds that melt from item to item like a drop of liquid. Overlays that
|
|
341
|
+
grow out of the control that opened them through a goo neck, then let go.
|
|
342
|
+
- **Calm under reduced motion.** Every effect degrades to a fade: fewer and gentler, never none.
|
|
343
|
+
|
|
344
|
+
The feeling to aim for: a precise instrument that happens to be made of liquid. Nothing bounces for
|
|
345
|
+
fun; the only overshoot in the system is the slow tier's 0.12 and the goo's 0.15.
|
|
346
|
+
|
|
347
|
+
## Colors
|
|
348
|
+
|
|
349
|
+
Two text colors, a greyscale ground, one blue.
|
|
350
|
+
|
|
351
|
+
- **Foreground (`text-foreground`)** — near-black ink in light, near-white in dark. Headings, labels,
|
|
352
|
+
values, selected items, the primary button's fill.
|
|
353
|
+
- **Muted foreground (`text-muted-foreground`)** — the only secondary text color: descriptions, captions,
|
|
354
|
+
placeholders, idle icons, idle tab labels. Never an opacity step of foreground (`text-foreground/60`
|
|
355
|
+
is wrong); a third text tone does not exist.
|
|
356
|
+
- **Background (`bg-background`)** — the page, equal to surface 1. Also the text color on the primary
|
|
357
|
+
button and the tooltip (`text-background`).
|
|
358
|
+
- **Surfaces (`bg-surface-1` … `bg-surface-8`)** — the elevation ladder (see Elevation & Depth). Prefer a
|
|
359
|
+
surface level over `card`/`background` for anything that floats or nests.
|
|
360
|
+
- **Muted (`bg-muted`)** — a recessed track: the segmented tabs' well, a sunken field at rest.
|
|
361
|
+
- **Accent (`bg-accent`)** — the secondary button and the switch's off track. `selected` is a firmer
|
|
362
|
+
grey for persistent selection fills.
|
|
363
|
+
- **Hover / Active (`bg-hover`, `bg-active`)** — translucent overlays (black 4% / 7% in light, white 6% /
|
|
364
|
+
10% in dark) so they read on any surface level. Every hover and press fill uses them; never an ad-hoc
|
|
365
|
+
grey. The raw tint direction is `--overlay` (`bg-overlay/8` → `rgb(var(--overlay) / 0.08)`).
|
|
366
|
+
- **Border (`border-border`, `ring-border`)** — 12% of foreground, so it tracks the scheme and nested
|
|
367
|
+
forced scopes. Hairlines only, 1px.
|
|
368
|
+
- **Brand (`bg-brand`, `ring-focus-ring`)** — `focus-ring` is `brand`: every keyboard ring is a 1px blue
|
|
369
|
+
ring 2px outside the element. The single theming point for focus.
|
|
370
|
+
- **Destructive (`text-destructive`, `bg-destructive-light`)** — errors and destructive confirms only.
|
|
371
|
+
- **Tinted actions (`text-destructive-strong` on `bg-destructive-wash`, `text-success-strong` on
|
|
372
|
+
`bg-success-wash`)** — the destructive and success buttons: the hue as text, dark enough for AA on its
|
|
373
|
+
wash, over a translucent wash of it that deepens on hover and press (`-hover`, `-active`). Never a
|
|
374
|
+
solid fill.
|
|
375
|
+
- **Skeleton (`bg-skeleton`)** — 8% of foreground: the loading placeholder, quieter than any border.
|
|
376
|
+
- **Image edge (`outline-image-edge`)** — a 1px inset edge (black or white at 10%) on images and
|
|
377
|
+
avatars, so a picture keeps its outline on any substrate.
|
|
378
|
+
- **Progress track (`bg-progress-track`)** — 10% of foreground under the ink (`bg-foreground`) fill of
|
|
379
|
+
a progress bar.
|
|
380
|
+
- **Status (`text-status-*`, `bg-status-*/16`)** — success, loading, error, warning, info, action. A
|
|
381
|
+
status shows as tinted text on a 16% wash of itself, never as a solid fill behind text.
|
|
382
|
+
- **Scrim (`bg-scrim`)** — behind a modal dialog; it fades with the morph's progress.
|
|
383
|
+
- **Syntax (`text-syntax-*`)** — low-chroma hues for code, so code reads as text first.
|
|
384
|
+
|
|
385
|
+
Every color is one `light-dark(light, dark)` token; the scheme comes from `color-scheme` on `<html>`
|
|
386
|
+
(`.light` / `.dark` pin it, also on any subtree). Shadows cannot ride `light-dark()`, so `--shadow-N` is
|
|
387
|
+
re-pointed per scheme in `surface.css`.
|
|
388
|
+
|
|
389
|
+
## Typography
|
|
390
|
+
|
|
391
|
+
**Inter Variable** with its optical-size axis (`@fontsource-variable/inter/opsz.css`). The opsz axis is
|
|
392
|
+
not optional: every weight is paired with an optical size so a label keeps its width when it gets
|
|
393
|
+
heavier.
|
|
394
|
+
|
|
395
|
+
Six roles, each a size and a whole-pixel line height, as utilities `text-<role>` (and
|
|
396
|
+
`text-<role>-compact` for the compact step, which keeps the role's leading):
|
|
397
|
+
|
|
398
|
+
| Role | Default | Compact | Use |
|
|
399
|
+
|---|---|---|---|
|
|
400
|
+
| `text-display` | 28/34 | 24 | The page title. The only bold text. |
|
|
401
|
+
| `text-title` | 16/22 | 15 | Section headings, dialog titles. |
|
|
402
|
+
| `text-subtitle` | 14/20 | 13 | Card and popover titles, emphasized rows. |
|
|
403
|
+
| `text-body` | 13/20 | 12 | Control labels, rows, body copy. The default. |
|
|
404
|
+
| `text-caption` | 12/16 | 11 | Descriptions, meta, errors, group labels, tooltips, badges. |
|
|
405
|
+
| `text-micro` | 11/14 | 10 | Keycaps, counters, tiny chips. Single line only. |
|
|
406
|
+
|
|
407
|
+
Body's 20px leading is what puts a padded row on the ladder: 8 + 20 + 8 = 36px.
|
|
408
|
+
|
|
409
|
+
Weights come from `font-variation-settings`, through the `weight-*` utilities, never `font-*`:
|
|
410
|
+
|
|
411
|
+
- `weight-normal` (400, opsz 14) — all running text and idle labels.
|
|
412
|
+
- `weight-medium` (450, opsz 15) — small labels that need to hold on a fill: tooltips, badges, errors.
|
|
413
|
+
- `weight-semibold` (550, opsz 18) — headings and anything selected, active or open.
|
|
414
|
+
- `weight-bold` (700, opsz 25) — the display role only.
|
|
415
|
+
|
|
416
|
+
A label that changes weight with state (a tab, a selected card title, an open accordion row) renders
|
|
417
|
+
twice in one grid cell: an invisible `weight-semibold` copy reserves the width, the visible copy tweens
|
|
418
|
+
`transition-[color,font-variation-settings] duration-fast`. Neighbours never move.
|
|
419
|
+
|
|
420
|
+
No uppercase, no letter-spacing, no eyebrows above titles in new UI (`Card.Eyebrow` is the one vendored
|
|
421
|
+
exception). Sentence case everywhere; the docs chrome capitalizes in content, not with CSS. Fixed-height
|
|
422
|
+
labels trim their box (`[text-box:trim-both_cap_alphabetic]`) so the cap height sits optically centered.
|
|
423
|
+
`h1–h3` balance, `p` wraps pretty. Code is `font-mono` at caption size.
|
|
424
|
+
|
|
425
|
+
## Layout
|
|
426
|
+
|
|
427
|
+
A 4px grid. Spacing tokens `--space-1…6` = 4, 8, 12, 16, 24, 32px (the docs chrome reads them);
|
|
428
|
+
component code uses the matching utilities (`gap-1`, `p-4`, …), which sit on the same 4px grid.
|
|
429
|
+
|
|
430
|
+
**The size ladder** is the layout system. Two steps only, and everything steps down together:
|
|
431
|
+
|
|
432
|
+
| Token (`useSize()`) | Default | Compact |
|
|
433
|
+
|---|---|---|
|
|
434
|
+
| `control` (buttons, inputs, select triggers, **and** list/menu rows) | 36px `h-9` | 28px `h-7` |
|
|
435
|
+
| `segmentItem` + `segmentPad` (segmented tabs) | 28 + 4 | 24 + 2 |
|
|
436
|
+
| `text` | `text-body` | `text-body-compact` |
|
|
437
|
+
| `px` (bounded controls) | 12px | 10px |
|
|
438
|
+
| `itemPx` (rows inside a padded popup) | 8px | 6px |
|
|
439
|
+
| `gap` (icon ↔ label, control ↔ control) | 8px | 4px |
|
|
440
|
+
| `icon` (glyphs, checkbox squares) | 16px | 14px |
|
|
441
|
+
|
|
442
|
+
A popup row is exactly as tall as the trigger that opened it. Density is a region decision: wrap the
|
|
443
|
+
region in one `SizeProvider size="compact"` and every control in it (menus it opens included) follows.
|
|
444
|
+
A component's own `size` prop wins over the provider.
|
|
445
|
+
|
|
446
|
+
Other fixed measures: popovers cap at `min(92vw, 20rem)`; dialogs are 400 / 540 / 880px wide (`sm`,
|
|
447
|
+
`lg`, `xl`), one notch narrower in compact regions; popup lists cap at `min(300px,
|
|
448
|
+
var(--available-height))` and scroll inside `ScrollArea` with a scroll-aware `scroll-fade`; reading
|
|
449
|
+
columns cap at `--modo-measure` (45rem). Native scrollbars are thin and low-contrast (overlay 8% → 12% on
|
|
450
|
+
hover → 16% while dragging), matching the `ScrollArea` thumb.
|
|
451
|
+
|
|
452
|
+
## Elevation & Depth
|
|
453
|
+
|
|
454
|
+
Eight surface levels that nest. Each `bg-surface-N` pairs 1:1 with a `shadow-surface-N`.
|
|
455
|
+
|
|
456
|
+
- **Light:** only two color steps (floor 0.985, sunken 0.991), then flat white from surface 3 up.
|
|
457
|
+
Elevation is carried by shadow alone: a 1px `--shadow-color` hairline (black 6%) plus stacked drops
|
|
458
|
+
whose offsets double per level (1, 3, 6, 12, 24, 48, 96px).
|
|
459
|
+
- **Dark:** an additive ladder from 0.205 to 0.402 in even steps, each with an inset top highlight, an
|
|
460
|
+
inset ring and black drops.
|
|
461
|
+
|
|
462
|
+
Substrate flows through React context (`useSurface()`, 1 = the page). A floating surface computes
|
|
463
|
+
`min(substrate + offset, 8)`, paints that level and re-provides it, so a popover inside a dialog lands
|
|
464
|
+
above the dialog without any prop:
|
|
465
|
+
|
|
466
|
+
| Surface | Offset | Shadow |
|
|
467
|
+
|---|---|---|
|
|
468
|
+
| Code block | +1 | none |
|
|
469
|
+
| Popover, dropdown, select, combobox, context menu, preview card, toast, search suggestions | +2 | fixed `shadow-surface-3` |
|
|
470
|
+
| Tabs' active indicator | +3 | matches level |
|
|
471
|
+
| Dialog, alert dialog, sheet | +4 | matches level |
|
|
472
|
+
| Tooltip | inverted: `bg-foreground`, no shadow | — |
|
|
473
|
+
|
|
474
|
+
Menus keep a fixed `shadow-surface-3` whatever their depth, so a menu still reads as a menu three layers
|
|
475
|
+
down. Hover and pressed states are overlays (`bg-hover`, `bg-active`), not levels, so they work at any
|
|
476
|
+
elevation. Use `Elevated offset={n}` (or `surfaceClasses(level)` / `SURFACE_BG[level]`) for anything new
|
|
477
|
+
that floats; never hard-code a surface.
|
|
478
|
+
|
|
479
|
+
## Shapes
|
|
480
|
+
|
|
481
|
+
Rounded, concentric, never mixed. Two shape modes from `useShape()`; **rounded** is the default and what
|
|
482
|
+
everything renders without a provider:
|
|
483
|
+
|
|
484
|
+
| Slot | Rounded | Pill |
|
|
485
|
+
|---|---|---|
|
|
486
|
+
| `item`, `bg`, `button`, `input` | 8px `rounded-lg` | 20px |
|
|
487
|
+
| `focusRing` (2px outside the element) | 10px | 22px |
|
|
488
|
+
| `container` (popups, cards, dialogs, segmented tracks) | 12px `rounded-xl` | 24px |
|
|
489
|
+
| `mergedBg` (merged selection runs) | 8px | 16px |
|
|
490
|
+
|
|
491
|
+
A rounded surface nested close inside another uses concentric corners: inner = outer − inset − border.
|
|
492
|
+
The shipped pair (12 → 8) assumes a 4px inset. Small boxes use `rounded-box` (5px: checkbox squares,
|
|
493
|
+
keycaps) and `rounded-glyph` (3px). Thumbs, dots and the loading button are circles (`rounded-full`).
|
|
494
|
+
Never write a radius: read `shape.*` so the pill mode follows.
|
|
495
|
+
|
|
496
|
+
## Motion
|
|
497
|
+
|
|
498
|
+
Springs, tiered by the size of what moves. The bigger the thing, the slower the spring. Never a
|
|
499
|
+
hand-written duration; never a fourth speed.
|
|
500
|
+
|
|
501
|
+
| Tier | Enter | Exit (tween, one tier quicker) | Use |
|
|
502
|
+
|---|---|---|---|
|
|
503
|
+
| `spring.fast` | 80ms spring, bounce 0 | 60ms | Hover highlight, focus ring, fades, icon stroke, weight changes |
|
|
504
|
+
| `spring.moderate` | 160ms spring, bounce 0 | 120ms | Indicators, thumbs, small panels, width changes, the loading fold |
|
|
505
|
+
| `spring.slow` | 240ms spring, bounce 0.12 | 160ms | Large surfaces: plain morphs, the search field's growth, shared parts |
|
|
506
|
+
| `spring.goo` | 250ms visual, bounce 0.15 | 200ms spring back | Every goo morph, so the liquid neck is on screen long enough to read |
|
|
507
|
+
|
|
508
|
+
CSS consumers use `duration-fast|moderate|slow[-exit]` and `delay-*`. `--duration-loop` (2s) is the
|
|
509
|
+
period of pending-state loops (the indeterminate progress sweep, the spinner, the skeleton pulse); it is
|
|
510
|
+
not a spring tier, and under reduced motion a loop pulses opacity in place. Animate `transform` and `opacity`;
|
|
511
|
+
a measured geometry engine (the morph layer, `GooIndicator`) is the only thing that writes boxes.
|
|
512
|
+
|
|
513
|
+
The signature behaviors:
|
|
514
|
+
|
|
515
|
+
- **Fluid hover.** One `bg-hover` highlight per list, on the item nearest the cursor (inside wins, else
|
|
516
|
+
nearest center), so it never blinks off in a gap. It travels on `spring.fast` and melts between rows.
|
|
517
|
+
A fresh pointer entry fades in where it is instead of sliding across. A click in a gap goes to the lit
|
|
518
|
+
row: what is lit is what a click hits.
|
|
519
|
+
- **Liquid indicators.** Anything that travels between items (the active tab, a switch thumb, selection
|
|
520
|
+
runs, the hover pill) leaves a blob behind that lingers a third of the spring and follows, melted
|
|
521
|
+
through a goo filter. At rest nothing is filtered.
|
|
522
|
+
- **Morphing overlays.** Popover, dropdown, select, combobox, context menu, tooltip, preview card,
|
|
523
|
+
dialog, sheet, command, search suggestions and toasts grow from their source (`from`: the trigger,
|
|
524
|
+
the press point, the center, a window edge, or any element) with an `effect`: `goo` (default, a
|
|
525
|
+
liquid neck that pinches off), `morph` (the box grows), `slide` or `fade`. They close back into where
|
|
526
|
+
they came from. With `hideSource` the trigger *becomes* the panel.
|
|
527
|
+
- **Press geometry.** A pressed button's fill shrinks exactly 1px per side at any width (spread shadow
|
|
528
|
+
collapse, not a scale), releasing slower than it presses.
|
|
529
|
+
- **Icons thicken, labels don't move.** Hovered/active icons step stroke 1.5 → 2 on the fast tier.
|
|
530
|
+
- **Loading folds.** A loading button folds its surface into a circle around the spinner while its box
|
|
531
|
+
stays put.
|
|
532
|
+
- **Exits are crisp.** A dismissal never replays the entrance backwards.
|
|
533
|
+
- **Reduced motion.** Every morph becomes a fade; travel snaps; opacity and color fades stay.
|
|
534
|
+
|
|
535
|
+
## Components
|
|
536
|
+
|
|
537
|
+
Each item lives at `<tier>/[<group>/]<name>/index.tsx` and composes from Base UI (behavior) plus the
|
|
538
|
+
shared systems above (look and motion). Ready-made patterns to reach for before writing anything:
|
|
539
|
+
|
|
540
|
+
- **Buttons** — `primary` (ink fill), `secondary` (accent fill), `tertiary` (transparent, a 1px
|
|
541
|
+
`border` ring that moves inward on press), `ghost` (transparent, muted text that turns foreground over
|
|
542
|
+
the hover overlay). A component token with no `backgroundColor` is transparent over its substrate.
|
|
543
|
+
Sizes `default` 36 / `compact` 28 / `icon` / `icon-compact`. Icons sit 4px closer to their edge than
|
|
544
|
+
text. `active` holds the pressed look while a menu it opened is showing. One primary per view.
|
|
545
|
+
`outline` is `tertiary` under its shadcn name. `destructive` and `success` are their hue as text on a
|
|
546
|
+
wash of it (Tinted actions), never a solid fill; `link` is underlined foreground text on the control
|
|
547
|
+
height, no padding. `xs` and `sm` resolve to `compact`: the ladder has two steps.
|
|
548
|
+
- **Inputs** — transparent and ringless at rest, a `bg-muted/50` wash plus a `ring-border` ring on
|
|
549
|
+
hover, `bg-card` plus the ring on focus; read-only keeps the ring but never lifts the fill. The label
|
|
550
|
+
sits above in muted body text (an asterisk when required), help text below in muted caption, both
|
|
551
|
+
inset to the text. Errors: destructive caption at `weight-medium`, a `destructive-light` wash.
|
|
552
|
+
Adornments are muted and light with the field; field actions are 4px inside the ring. File
|
|
553
|
+
dropzones: a dashed hairline on the container radius, a muted fill while files hover over it,
|
|
554
|
+
destructive for files it won't take; a drag it can partly take keeps the neutral fill and says that
|
|
555
|
+
some will be skipped.
|
|
556
|
+
- **Lists and menus** — rows on the control height, `itemPx` inset, one fluid hover highlight, rows
|
|
557
|
+
without their own `:hover` fill. Disabled rows stay registered but are skipped. Keyboard focus earns a
|
|
558
|
+
1px brand ring that springs between rows; pointer focus never shows it.
|
|
559
|
+
- **Selection** — checkbox and radio rows melt their selected backgrounds into one run; tabs and
|
|
560
|
+
subtle tabs carry an elevated (+3) or translucent indicator that melts between items; the selected
|
|
561
|
+
label goes `weight-semibold`. Checkbox, radio and switch also come bare (no label): just the box,
|
|
562
|
+
circle or track, with a 1px focus ring offset 2px, for tables and hand-laid forms. An indeterminate
|
|
563
|
+
checkbox shows a dash that blurs into the check. A loading control keeps its box: the combobox
|
|
564
|
+
chevron blurs into a spinner in the same slot.
|
|
565
|
+
- **Overlays** — popup surfaces at +2 with `shadow-surface-3`, dialogs at +4, `rounded-xl` containers,
|
|
566
|
+
12px goo neck between trigger and panel, content padding 16px (popover) or 24px (dialog). A confirm
|
|
567
|
+
that runs a task folds its button into the loading circle and holds the dialog until it settles.
|
|
568
|
+
- **Tooltips** — inverted (`bg-foreground` / `text-background`), caption at `weight-medium`, morph from
|
|
569
|
+
the trigger, a hand-off between grouped tooltips is instant; the same label whether written flat or
|
|
570
|
+
as Trigger + Content parts.
|
|
571
|
+
- **Badges** — 24px (20px compact), caption medium, a 15% wash of the color into the background with
|
|
572
|
+
foreground text; dot variant keeps a neutral outline; `outline` is that frame without the dot, and
|
|
573
|
+
no color.
|
|
574
|
+
- **Toasts** — a status pill that melts into a body; status color as text on a 16% wash. Shown from
|
|
575
|
+
anywhere through the global `toast()`; a custom icon sits in the same status disc.
|
|
576
|
+
- **Cards** — transparent and borderless, inheriting the substrate; hairline dividers and the fluid
|
|
577
|
+
hover do the framing; only clickable cards join the hover. `border="outlined"` gives a standalone
|
|
578
|
+
card the outlined group's hairline frame; `Card.Divider` is a full-bleed hairline between its parts.
|
|
579
|
+
- **Pagination** — the current page is a liquid `bg-accent` indicator on the fluid-hover strip; dense
|
|
580
|
+
tables use the jump-to-page field.
|
|
581
|
+
- **Avatar** — one control tall (36px, 28px compact), a circle, or a square on the item radius,
|
|
582
|
+
with the image edge; initials or an icon on `bg-accent` until the image loads, which then fades in.
|
|
583
|
+
- **Progress** — a 4px pill: the ink fill slides to its value on `spring.moderate`; with no value a
|
|
584
|
+
segment sweeps the track on the loop period. The spinner is the loading button's figure-eight.
|
|
585
|
+
- **Skeleton** — `bg-skeleton` blocks on the item radius pulsing in opacity, rows on the control
|
|
586
|
+
height; hidden from assistive tech (mark the loading region busy instead).
|
|
587
|
+
- **Separator** — the one 1px `border` hairline, horizontal or vertical; no ornament.
|
|
588
|
+
|
|
589
|
+
## Do's and Don'ts
|
|
590
|
+
|
|
591
|
+
- Do compose from an existing item before writing a new one; wrap rather than fork vendored code.
|
|
592
|
+
- Do read every visual from a token utility: `text-<role>`, `weight-*`, `bg-surface-N`,
|
|
593
|
+
`shadow-surface-N`, `bg-hover`, `shape.*`, `duration-<tier>`, `spring.*`.
|
|
594
|
+
- Do lift floating surfaces relative to the substrate (`useSurface()` + offset) and re-provide the level.
|
|
595
|
+
- Do size controls from `useSize()` and let regions choose density with `SizeProvider`.
|
|
596
|
+
- Do give every list exactly one fluid hover highlight, and every traveling indicator a `GooIndicator`.
|
|
597
|
+
- Do grow every new overlay out of its source through `useMorph` + `MorphSurface`.
|
|
598
|
+
- Do test light, dark, compact, keyboard and reduced motion.
|
|
599
|
+
- Don't write an arbitrary value for color, type, radius, shadow or motion (`text-[13px]`, `bg-[#…]`,
|
|
600
|
+
`rounded-[10px]`, `duration-[200ms]`); add the token instead. Layout geometry may be arbitrary.
|
|
601
|
+
- Don't use a third text color, an opacity step of a text color, uppercase, letter-spacing, or `font-*`
|
|
602
|
+
weights.
|
|
603
|
+
- Don't add a per-row `:hover` background next to a fluid hover list.
|
|
604
|
+
- Don't hand-write a `duration`, an easing curve or a fourth spring; don't animate `top`/`left`/`width`/
|
|
605
|
+
`height` outside the morph engine.
|
|
606
|
+
- Don't use the brand blue for anything but focus, "on", drop targets and selected swatches.
|
|
607
|
+
- Don't hard-code a surface background or a radius: a menu inside a dialog must still lift.
|
|
608
|
+
- Don't stack two measured-height animations: the outer one snaps when a child changed its size.
|