@nqmcreative/ui 0.1.0 → 0.2.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/README.md +151 -439
- package/cli/index.mjs +67 -30
- package/dist/core/calendar.d.ts +3 -0
- package/dist/core/calendar.js +36 -0
- package/dist/core/dialog.svelte.d.ts +14 -0
- package/dist/core/dialog.svelte.js +23 -0
- package/dist/core/files.d.ts +35 -0
- package/dist/core/files.js +62 -0
- package/dist/core/index.d.ts +37 -0
- package/dist/core/index.js +35 -0
- package/dist/core/list.svelte.d.ts +41 -0
- package/dist/core/list.svelte.js +77 -0
- package/dist/core/number.d.ts +7 -0
- package/dist/core/number.js +17 -0
- package/dist/core/pagination.d.ts +6 -0
- package/dist/core/pagination.js +21 -0
- package/dist/core/password.d.ts +8 -0
- package/dist/core/password.js +23 -0
- package/dist/core/table.d.ts +22 -0
- package/dist/core/table.js +41 -0
- package/dist/core/theme.svelte.d.ts +16 -0
- package/dist/core/theme.svelte.js +34 -0
- package/dist/core/trigger.d.ts +35 -0
- package/dist/core/trigger.js +77 -0
- package/dist/index.d.ts +11 -103
- package/dist/index.js +11 -75
- package/dist/{components → styles/matte}/AccordionItem.svelte +1 -1
- package/dist/{components → styles/matte}/AccordionItem.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Alert.svelte +8 -2
- package/dist/{components → styles/matte}/Alert.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Avatar.svelte +1 -1
- package/dist/{components → styles/matte}/Avatar.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Badge.svelte +8 -3
- package/dist/{components → styles/matte}/Badge.svelte.d.ts +1 -3
- package/dist/{components → styles/matte}/Breadcrumb.svelte +2 -2
- package/dist/{components → styles/matte}/Breadcrumb.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Button.svelte +1 -1
- package/dist/{components → styles/matte}/Button.svelte.d.ts +1 -1
- package/dist/styles/matte/CTASection.svelte +76 -0
- package/dist/styles/matte/CTASection.svelte.d.ts +18 -0
- package/dist/{components → styles/matte}/Calendar.svelte +7 -17
- package/dist/{components → styles/matte}/Calendar.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Card.svelte +1 -1
- package/dist/{components → styles/matte}/Card.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Checkbox.svelte +1 -1
- package/dist/{components → styles/matte}/Checkbox.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/CheckboxGroup.svelte +1 -1
- package/dist/{components → styles/matte}/CheckboxGroup.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Combobox.svelte +31 -42
- package/dist/{components → styles/matte}/Combobox.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/CommandPalette.svelte +26 -41
- package/dist/{components → styles/matte}/CommandPalette.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/ConfirmDialog.svelte +2 -2
- package/dist/{components → styles/matte}/ConfirmDialog.svelte.d.ts +2 -2
- package/dist/{components → styles/matte}/ContextMenu.svelte +5 -7
- package/dist/{components → styles/matte}/DatePicker.svelte +7 -11
- package/dist/{components → styles/matte}/DatePicker.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Drawer.svelte +4 -7
- package/dist/{components → styles/matte}/Dropdown.svelte +18 -36
- package/dist/{components → styles/matte}/Dropdown.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Dropzone.svelte +11 -43
- package/dist/{components → styles/matte}/Dropzone.svelte.d.ts +2 -5
- package/dist/{components → styles/matte}/EmptyState.svelte +1 -1
- package/dist/{components → styles/matte}/EmptyState.svelte.d.ts +1 -1
- package/dist/styles/matte/FeatureCard.svelte +58 -0
- package/dist/styles/matte/FeatureCard.svelte.d.ts +16 -0
- package/dist/styles/matte/FeatureGrid.svelte +62 -0
- package/dist/styles/matte/FeatureGrid.svelte.d.ts +16 -0
- package/dist/{components → styles/matte}/Footer.svelte +1 -1
- package/dist/{components → styles/matte}/Footer.svelte.d.ts +1 -1
- package/dist/styles/matte/HeroSection.svelte +80 -0
- package/dist/styles/matte/HeroSection.svelte.d.ts +21 -0
- package/dist/{components → styles/matte}/Input.svelte +1 -1
- package/dist/{components → styles/matte}/Input.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Link.svelte +1 -1
- package/dist/{components → styles/matte}/Link.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/LocaleProvider.svelte +1 -1
- package/dist/{components → styles/matte}/LocaleProvider.svelte.d.ts +1 -1
- package/dist/styles/matte/LogoCloud.svelte +61 -0
- package/dist/styles/matte/LogoCloud.svelte.d.ts +19 -0
- package/dist/{components → styles/matte}/MenuItem.svelte +1 -1
- package/dist/{components → styles/matte}/MenuItem.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Modal.svelte +4 -7
- package/dist/{components → styles/matte}/MultiSelect.svelte +18 -37
- package/dist/{components → styles/matte}/MultiSelect.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Navbar.svelte +2 -2
- package/dist/{components → styles/matte}/Navbar.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/NumberInput.svelte +4 -8
- package/dist/{components → styles/matte}/NumberInput.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Pagination.svelte +4 -15
- package/dist/{components → styles/matte}/Pagination.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/PasswordInput.svelte +4 -13
- package/dist/{components → styles/matte}/PasswordInput.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Popover.svelte +16 -41
- package/dist/{components → styles/matte}/Popover.svelte.d.ts +1 -1
- package/dist/styles/matte/PricingCard.svelte +107 -0
- package/dist/styles/matte/PricingCard.svelte.d.ts +25 -0
- package/dist/{components → styles/matte}/Progress.svelte +3 -2
- package/dist/{components → styles/matte}/Progress.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Radio.svelte +1 -1
- package/dist/{components → styles/matte}/Radio.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/RadioGroup.svelte +1 -1
- package/dist/{components → styles/matte}/RadioGroup.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/SegmentedControl.svelte +1 -1
- package/dist/{components → styles/matte}/SegmentedControl.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Select.svelte +1 -1
- package/dist/{components → styles/matte}/Select.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Sidebar.svelte +2 -2
- package/dist/{components → styles/matte}/Sidebar.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Slider.svelte +3 -2
- package/dist/{components → styles/matte}/Slider.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Spinner.svelte +2 -2
- package/dist/{components → styles/matte}/Spinner.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Stat.svelte +1 -1
- package/dist/{components → styles/matte}/Stat.svelte.d.ts +1 -1
- package/dist/styles/matte/StatsBand.svelte +57 -0
- package/dist/styles/matte/StatsBand.svelte.d.ts +20 -0
- package/dist/{components → styles/matte}/Steps.svelte +1 -1
- package/dist/{components → styles/matte}/Steps.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Switch.svelte +1 -1
- package/dist/{components → styles/matte}/Switch.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Table.svelte +6 -28
- package/dist/{components → styles/matte}/Table.svelte.d.ts +2 -6
- package/dist/{components → styles/matte}/Tabs.svelte +8 -1
- package/dist/{components → styles/matte}/Tabs.svelte.d.ts +1 -1
- package/dist/styles/matte/Testimonial.svelte +67 -0
- package/dist/styles/matte/Testimonial.svelte.d.ts +19 -0
- package/dist/{components → styles/matte}/Textarea.svelte +1 -1
- package/dist/{components → styles/matte}/Textarea.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/ThemeToggle.svelte +14 -27
- package/dist/{components → styles/matte}/ThemeToggle.svelte.d.ts +2 -6
- package/dist/{components → styles/matte}/Toaster.svelte +4 -4
- package/dist/{fonts.css → styles/matte/fonts.css} +4 -3
- package/dist/styles/matte/index.d.ts +109 -0
- package/dist/styles/matte/index.js +83 -0
- package/dist/{theme.css → styles/matte/theme.css} +0 -1
- package/dist/styles/paper/Accordion.svelte +17 -0
- package/dist/styles/paper/Accordion.svelte.d.ts +8 -0
- package/dist/styles/paper/AccordionItem.svelte +46 -0
- package/dist/styles/paper/AccordionItem.svelte.d.ts +14 -0
- package/dist/styles/paper/Alert.svelte +99 -0
- package/dist/styles/paper/Alert.svelte.d.ts +18 -0
- package/dist/styles/paper/Avatar.svelte +60 -0
- package/dist/styles/paper/Avatar.svelte.d.ts +16 -0
- package/dist/styles/paper/AvatarGroup.svelte +17 -0
- package/dist/styles/paper/AvatarGroup.svelte.d.ts +8 -0
- package/dist/styles/paper/Badge.svelte +58 -0
- package/dist/styles/paper/Badge.svelte.d.ts +16 -0
- package/dist/styles/paper/Breadcrumb.svelte +49 -0
- package/dist/styles/paper/Breadcrumb.svelte.d.ts +14 -0
- package/dist/styles/paper/Button.svelte +96 -0
- package/dist/styles/paper/Button.svelte.d.ts +21 -0
- package/dist/styles/paper/CTASection.svelte +76 -0
- package/dist/styles/paper/CTASection.svelte.d.ts +18 -0
- package/dist/styles/paper/Calendar.svelte +202 -0
- package/dist/styles/paper/Calendar.svelte.d.ts +22 -0
- package/dist/styles/paper/Card.svelte +78 -0
- package/dist/styles/paper/Card.svelte.d.ts +21 -0
- package/dist/styles/paper/Checkbox.svelte +75 -0
- package/dist/styles/paper/Checkbox.svelte.d.ts +15 -0
- package/dist/styles/paper/CheckboxGroup.svelte +111 -0
- package/dist/styles/paper/CheckboxGroup.svelte.d.ts +30 -0
- package/dist/styles/paper/Combobox.svelte +266 -0
- package/dist/styles/paper/Combobox.svelte.d.ts +29 -0
- package/dist/styles/paper/CommandPalette.svelte +209 -0
- package/dist/styles/paper/CommandPalette.svelte.d.ts +32 -0
- package/dist/styles/paper/ConfirmDialog.svelte +97 -0
- package/dist/styles/paper/ConfirmDialog.svelte.d.ts +22 -0
- package/dist/styles/paper/ContextMenu.svelte +88 -0
- package/dist/styles/paper/ContextMenu.svelte.d.ts +15 -0
- package/dist/styles/paper/DatePicker.svelte +192 -0
- package/dist/styles/paper/DatePicker.svelte.d.ts +23 -0
- package/dist/styles/paper/Divider.svelte +30 -0
- package/dist/styles/paper/Divider.svelte.d.ts +10 -0
- package/dist/styles/paper/Drawer.svelte +165 -0
- package/dist/styles/paper/Drawer.svelte.d.ts +20 -0
- package/dist/styles/paper/Dropdown.svelte +94 -0
- package/dist/styles/paper/Dropdown.svelte.d.ts +23 -0
- package/dist/styles/paper/Dropzone.svelte +210 -0
- package/dist/styles/paper/Dropzone.svelte.d.ts +29 -0
- package/dist/styles/paper/EmptyState.svelte +71 -0
- package/dist/styles/paper/EmptyState.svelte.d.ts +18 -0
- package/dist/styles/paper/FeatureCard.svelte +58 -0
- package/dist/styles/paper/FeatureCard.svelte.d.ts +16 -0
- package/dist/styles/paper/FeatureGrid.svelte +62 -0
- package/dist/styles/paper/FeatureGrid.svelte.d.ts +16 -0
- package/dist/styles/paper/Field.svelte +42 -0
- package/dist/styles/paper/Field.svelte.d.ts +16 -0
- package/dist/styles/paper/Footer.svelte +91 -0
- package/dist/styles/paper/Footer.svelte.d.ts +25 -0
- package/dist/styles/paper/HeroSection.svelte +86 -0
- package/dist/styles/paper/HeroSection.svelte.d.ts +21 -0
- package/dist/styles/paper/Input.svelte +60 -0
- package/dist/styles/paper/Input.svelte.d.ts +18 -0
- package/dist/styles/paper/InputGroup.svelte +20 -0
- package/dist/styles/paper/InputGroup.svelte.d.ts +11 -0
- package/dist/styles/paper/Kbd.svelte +17 -0
- package/dist/styles/paper/Kbd.svelte.d.ts +8 -0
- package/dist/styles/paper/Label.svelte +16 -0
- package/dist/styles/paper/Label.svelte.d.ts +9 -0
- package/dist/styles/paper/Link.svelte +44 -0
- package/dist/styles/paper/Link.svelte.d.ts +16 -0
- package/dist/styles/paper/LocaleProvider.svelte +24 -0
- package/dist/styles/paper/LocaleProvider.svelte.d.ts +10 -0
- package/dist/styles/paper/LogoCloud.svelte +61 -0
- package/dist/styles/paper/LogoCloud.svelte.d.ts +19 -0
- package/dist/styles/paper/MenuItem.svelte +64 -0
- package/dist/styles/paper/MenuItem.svelte.d.ts +18 -0
- package/dist/styles/paper/MenuSeparator.svelte +22 -0
- package/dist/styles/paper/MenuSeparator.svelte.d.ts +8 -0
- package/dist/styles/paper/Modal.svelte +118 -0
- package/dist/styles/paper/Modal.svelte.d.ts +21 -0
- package/dist/styles/paper/MultiSelect.svelte +287 -0
- package/dist/styles/paper/MultiSelect.svelte.d.ts +31 -0
- package/dist/styles/paper/Navbar.svelte +201 -0
- package/dist/styles/paper/Navbar.svelte.d.ts +33 -0
- package/dist/styles/paper/NumberInput.svelte +96 -0
- package/dist/styles/paper/NumberInput.svelte.d.ts +15 -0
- package/dist/styles/paper/Pagination.svelte +83 -0
- package/dist/styles/paper/Pagination.svelte.d.ts +15 -0
- package/dist/styles/paper/PasswordInput.svelte +100 -0
- package/dist/styles/paper/PasswordInput.svelte.d.ts +12 -0
- package/dist/styles/paper/Popover.svelte +89 -0
- package/dist/styles/paper/Popover.svelte.d.ts +19 -0
- package/dist/styles/paper/PricingCard.svelte +108 -0
- package/dist/styles/paper/PricingCard.svelte.d.ts +25 -0
- package/dist/styles/paper/Progress.svelte +59 -0
- package/dist/styles/paper/Progress.svelte.d.ts +17 -0
- package/dist/styles/paper/Radio.svelte +55 -0
- package/dist/styles/paper/Radio.svelte.d.ts +15 -0
- package/dist/styles/paper/RadioGroup.svelte +95 -0
- package/dist/styles/paper/RadioGroup.svelte.d.ts +27 -0
- package/dist/styles/paper/SegmentedControl.svelte +88 -0
- package/dist/styles/paper/SegmentedControl.svelte.d.ts +25 -0
- package/dist/styles/paper/Select.svelte +61 -0
- package/dist/styles/paper/Select.svelte.d.ts +20 -0
- package/dist/styles/paper/Sidebar.svelte +206 -0
- package/dist/styles/paper/Sidebar.svelte.d.ts +36 -0
- package/dist/styles/paper/Skeleton.svelte +46 -0
- package/dist/styles/paper/Skeleton.svelte.d.ts +13 -0
- package/dist/styles/paper/Slider.svelte +80 -0
- package/dist/styles/paper/Slider.svelte.d.ts +19 -0
- package/dist/styles/paper/Spinner.svelte +34 -0
- package/dist/styles/paper/Spinner.svelte.d.ts +13 -0
- package/dist/styles/paper/Stat.svelte +51 -0
- package/dist/styles/paper/Stat.svelte.d.ts +16 -0
- package/dist/styles/paper/StatsBand.svelte +63 -0
- package/dist/styles/paper/StatsBand.svelte.d.ts +20 -0
- package/dist/styles/paper/Steps.svelte +141 -0
- package/dist/styles/paper/Steps.svelte.d.ts +24 -0
- package/dist/styles/paper/Switch.svelte +64 -0
- package/dist/styles/paper/Switch.svelte.d.ts +14 -0
- package/dist/styles/paper/Table.svelte +217 -0
- package/dist/styles/paper/Table.svelte.d.ts +66 -0
- package/dist/styles/paper/Tabs.svelte +102 -0
- package/dist/styles/paper/Tabs.svelte.d.ts +23 -0
- package/dist/styles/paper/Testimonial.svelte +64 -0
- package/dist/styles/paper/Testimonial.svelte.d.ts +19 -0
- package/dist/styles/paper/Textarea.svelte +54 -0
- package/dist/styles/paper/Textarea.svelte.d.ts +12 -0
- package/dist/styles/paper/ThemeToggle.svelte +130 -0
- package/dist/styles/paper/ThemeToggle.svelte.d.ts +16 -0
- package/dist/styles/paper/Toaster.svelte +132 -0
- package/dist/styles/paper/Toaster.svelte.d.ts +8 -0
- package/dist/styles/paper/Tooltip.svelte +33 -0
- package/dist/styles/paper/Tooltip.svelte.d.ts +12 -0
- package/dist/styles/paper/fonts.css +46 -0
- package/dist/styles/paper/index.d.ts +109 -0
- package/dist/styles/paper/index.js +83 -0
- package/dist/styles/paper/theme.css +222 -0
- package/package.json +531 -201
- package/registry.json +658 -339
- /package/dist/{actions → core/actions}/anchor.d.ts +0 -0
- /package/dist/{actions → core/actions}/anchor.js +0 -0
- /package/dist/{actions → core/actions}/dismissable.d.ts +0 -0
- /package/dist/{actions → core/actions}/dismissable.js +0 -0
- /package/dist/{date.d.ts → core/date.d.ts} +0 -0
- /package/dist/{date.js → core/date.js} +0 -0
- /package/dist/{locale.svelte.d.ts → core/locale.svelte.d.ts} +0 -0
- /package/dist/{locale.svelte.js → core/locale.svelte.js} +0 -0
- /package/dist/{toast.svelte.d.ts → core/toast.svelte.d.ts} +0 -0
- /package/dist/{toast.svelte.js → core/toast.svelte.js} +0 -0
- /package/dist/{tones.d.ts → core/tones.d.ts} +0 -0
- /package/dist/{tones.js → core/tones.js} +0 -0
- /package/dist/{components → styles/matte}/Accordion.svelte +0 -0
- /package/dist/{components → styles/matte}/Accordion.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/AvatarGroup.svelte +0 -0
- /package/dist/{components → styles/matte}/AvatarGroup.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/ContextMenu.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Divider.svelte +0 -0
- /package/dist/{components → styles/matte}/Divider.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Drawer.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Field.svelte +0 -0
- /package/dist/{components → styles/matte}/Field.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/InputGroup.svelte +0 -0
- /package/dist/{components → styles/matte}/InputGroup.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Kbd.svelte +0 -0
- /package/dist/{components → styles/matte}/Kbd.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Label.svelte +0 -0
- /package/dist/{components → styles/matte}/Label.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/MenuSeparator.svelte +0 -0
- /package/dist/{components → styles/matte}/MenuSeparator.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Modal.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Skeleton.svelte +0 -0
- /package/dist/{components → styles/matte}/Skeleton.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Toaster.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Tooltip.svelte +0 -0
- /package/dist/{components → styles/matte}/Tooltip.svelte.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,506 +1,218 @@
|
|
|
1
1
|
# @nqmcreative/ui
|
|
2
2
|
|
|
3
|
-
Svelte 5 (runes) + Tailwind CSS v4 component library
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Svelte 5 (runes) + Tailwind CSS v4 component library. One package, **two
|
|
4
|
+
styles**, 65 components each — the same props, the same behaviour, a different
|
|
5
|
+
look. Eight tones, light and dark, no runtime dependencies.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
| style | import | character |
|
|
8
|
+
| ------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
9
|
+
| `matte` | `@nqmcreative/ui/matte` | Flat and sharp-cornered — no radius, no shadow, no gloss. Hairline rules and mono micro-labels do the work borders usually do. |
|
|
10
|
+
| `paper` | `@nqmcreative/ui/paper` | The neutral one. Start here if unsure: soft corners, light shadows, generous spacing, and nothing that fights the content. |
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
The docs site lives in this repo — every component with a live demo, plus
|
|
13
|
+
theming, locale and contributing guides. `bun run dev` to read it.
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
## Install
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
`text-inverse`), type (`font-sans` Work Sans, `font-heading` Sora, `font-mono`
|
|
17
|
-
JetBrains Mono) and motion (`ease-brand`, `ease-brand-out`).
|
|
18
|
-
|
|
19
|
-
**Colour is tonal.** `brand` (teal `#1c6358`) is the primary, and seven more
|
|
20
|
-
hues follow the exact same four-step shape:
|
|
21
|
-
|
|
22
|
-
| tone | base | used for |
|
|
23
|
-
| --------- | --------- | --------------------------------- |
|
|
24
|
-
| `brand` | `#1c6358` | primary actions, active states |
|
|
25
|
-
| `accent` | `#c2410c` | secondary emphasis, highlights |
|
|
26
|
-
| `violet` | `#6d28d9` | tertiary / categorical |
|
|
27
|
-
| `info` | `#1d4ed8` | informational messaging |
|
|
28
|
-
| `success` | `#15803d` | confirmations, positive deltas |
|
|
29
|
-
| `warning` | `#b45309` | soft warnings, quotas |
|
|
30
|
-
| `danger` | `#b91c1c` | destructive actions, errors |
|
|
31
|
-
| `neutral` | `#475569` | quiet chrome, disabled-ish states |
|
|
32
|
-
|
|
33
|
-
Each one ships four steps — `--color-<tone>`, `-hover`, `-light` (tinted
|
|
34
|
-
surface) and `-border` — so `bg-accent`, `hover:bg-accent-hover`,
|
|
35
|
-
`bg-accent-light` and `border-accent-border` all exist as utilities.
|
|
36
|
-
|
|
37
|
-
Every tonal component takes the same `tone` prop:
|
|
38
|
-
|
|
39
|
-
```svelte
|
|
40
|
-
<Button tone="danger">Delete</Button>
|
|
41
|
-
<Badge tone="warning" dot>Quota</Badge>
|
|
42
|
-
<Alert tone="success" title="Deployed" />
|
|
43
|
-
<Progress tone="violet" value={40} />
|
|
17
|
+
```bash
|
|
18
|
+
bun add @nqmcreative/ui
|
|
44
19
|
```
|
|
45
20
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
own components can join the same system.
|
|
49
|
-
|
|
50
|
-
### Components
|
|
51
|
-
|
|
52
|
-
| group | components |
|
|
53
|
-
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
54
|
-
| Actions | `Button`, `Link` |
|
|
55
|
-
| Forms | `Input`, `Textarea`, `Select`, `Combobox`, `MultiSelect`, `DatePicker`, `Calendar`, `Checkbox`, `CheckboxGroup`, `Radio`, `RadioGroup`, `SegmentedControl`, `Switch`, `Slider`, `NumberInput`, `PasswordInput`, `InputGroup`, `Dropzone`, `Field`, `Label` |
|
|
56
|
-
| Data display | `Badge`, `Avatar`, `AvatarGroup`, `Card`, `Stat`, `Table`, `Kbd` |
|
|
57
|
-
| Feedback | `Alert`, `Toaster` + `toast`, `Progress`, `Spinner`, `Skeleton`, `EmptyState` |
|
|
58
|
-
| Layout & nav | `Divider`, `Tabs`, `Accordion`, `AccordionItem`, `Breadcrumb`, `Pagination`, `Steps` |
|
|
59
|
-
| App shell | `Navbar`, `Sidebar`, `Footer` |
|
|
60
|
-
| Overlay | `Modal`, `ConfirmDialog`, `Drawer`, `Dropdown` + `MenuItem` + `MenuSeparator`, `ContextMenu`, `CommandPalette`, `Popover`, `Tooltip` |
|
|
61
|
-
| System | `ThemeToggle`, `LocaleProvider` |
|
|
62
|
-
|
|
63
|
-
Notable props:
|
|
64
|
-
|
|
65
|
-
- `Button` — `variant` (`solid` / `soft` / `outline` / `ghost` / `link`),
|
|
66
|
-
`size` (`sm` / `md` / `lg` / `xl`), `tone`, `loading`, `block`, `href`.
|
|
67
|
-
- `Input` — `prefix` / `suffix` snippets, `invalid`, `size`, `tone`.
|
|
68
|
-
- `Field` — wraps any control with `label`, `hint`, `error`, `required`.
|
|
69
|
-
- `Combobox` — searchable select with grouping, keyboard nav and `clearable`.
|
|
70
|
-
- `Dropzone` — drag & drop with `accept`, `maxSize`, `maxFiles`; reports what it
|
|
71
|
-
turned away through `onreject`.
|
|
72
|
-
- `Table` — `columns` + `rows`, per-column `sortable`, `bind:sort`,
|
|
73
|
-
`selectable` with `bind:selected` and `rowKey`, `stickyHeader`, and a `cell`
|
|
74
|
-
snippet for custom rendering.
|
|
75
|
-
- `Modal` / `Drawer` — native `<dialog>`, `bind:open`, `footer` snippet;
|
|
76
|
-
`Drawer` adds `side` and `size`.
|
|
77
|
-
- `Tabs` — `underline` / `pill` / `segmented`, `bind:value`.
|
|
78
|
-
- `Pagination` — `bind:page`, `total`, collapses with `…`.
|
|
79
|
-
- `CommandPalette` — `items` with `group` / `shortcut` / hidden `keywords`;
|
|
80
|
-
opens on ⌘K / Ctrl+K by default (`hotkey={null}` to wire your own trigger).
|
|
81
|
-
- `ConfirmDialog` — awaits `onconfirm`, staying open and busy until it settles.
|
|
82
|
-
- `ContextMenu` — right-click anywhere in `children`; the menu is placed at the
|
|
83
|
-
pointer and flipped near the edges.
|
|
84
|
-
- `CheckboxGroup` — `bind:value` as `string[]`, optional `max`.
|
|
85
|
-
- `MultiSelect` — chips in the field, grouping, `max`, Backspace peels the last
|
|
86
|
-
chip off.
|
|
87
|
-
- `DatePicker` / `Calendar` — value is a `YYYY-MM-DD` string, `min` / `max`, and
|
|
88
|
-
an `isDisabled(date)` predicate for weekends or holidays. Month names, weekday
|
|
89
|
-
order and the input's part order all follow the locale.
|
|
90
|
-
- `Navbar` — desktop links collapse into a `Drawer` below `md`; nested `items`
|
|
91
|
-
become a `Dropdown`.
|
|
92
|
-
- `Sidebar` — `sections` of nested `items`, `bind:value` for the active one,
|
|
93
|
-
`bind:collapsed` for the rail.
|
|
94
|
-
- `Steps` — horizontal or vertical, `bind:current`, per-step `error`, and
|
|
95
|
-
`clickable` to jump back to a finished step.
|
|
96
|
-
|
|
97
|
-
### Overlays without a dependency
|
|
98
|
-
|
|
99
|
-
`Dropdown`, `Popover` and `Combobox` render into `document.body` and are placed
|
|
100
|
-
by a small in-house action, so no floating-ui and no CSS anchor positioning:
|
|
101
|
-
|
|
102
|
-
- `anchored` — fixed positioning against a trigger, flips to the opposite side
|
|
103
|
-
when it doesn't fit, then clamps inside the viewport; follows scroll (capture
|
|
104
|
-
phase, so nested scrollers count) and resize.
|
|
105
|
-
- `clickOutside`, `focusTrap`, `portal`, `navigateList` — the behaviours every
|
|
106
|
-
overlay needs, exported so your own components can reuse them.
|
|
107
|
-
|
|
108
|
-
The trade-off: no sub-pixel middleware pipeline, no automatic arrow placement,
|
|
109
|
-
and `Tooltip` stays CSS-only (it can clip inside `overflow: hidden`, and doesn't
|
|
110
|
-
flip). Everything else escapes clipping and survives scrolling. Reach for
|
|
111
|
-
`Popover` when a tooltip would be clipped.
|
|
112
|
-
|
|
113
|
-
### Toasts
|
|
114
|
-
|
|
115
|
-
`toast` is a module-level store, so any file can fire one without prop
|
|
116
|
-
drilling. Mount `<Toaster />` once, near the root of your app:
|
|
117
|
-
|
|
118
|
-
```svelte
|
|
119
|
-
<script>
|
|
120
|
-
import { Toaster, toast } from '@nqmcreative/ui';
|
|
121
|
-
</script>
|
|
122
|
-
|
|
123
|
-
<Toaster position="bottom-right" />
|
|
124
|
-
|
|
125
|
-
<button onclick={() => toast.success('Project archived')}>Archive</button>
|
|
21
|
+
```bash
|
|
22
|
+
bunx nqm-ui init --style matte
|
|
126
23
|
```
|
|
127
24
|
|
|
128
|
-
`
|
|
129
|
-
|
|
130
|
-
`
|
|
25
|
+
`init` writes `src/app.css`, patches `src/app.html`, and adds the CSS import to
|
|
26
|
+
your root layout. It prints the one Vite change to paste — the Tailwind plugin,
|
|
27
|
+
before `sveltekit()`:
|
|
131
28
|
|
|
132
|
-
|
|
29
|
+
```ts
|
|
30
|
+
plugins: [tailwindcss(), sveltekit()];
|
|
31
|
+
```
|
|
133
32
|
|
|
134
|
-
|
|
135
|
-
utility is built on the tokens, so the whole system flips at once. The root
|
|
136
|
-
element decides:
|
|
33
|
+
Your project brings its own `svelte` ^5 and Tailwind CSS v4.
|
|
137
34
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
| `<html class="dark">` | dark, explicitly chosen |
|
|
141
|
-
| `<html class="light">` | light, explicitly chosen |
|
|
142
|
-
| `<html>` | follows the OS preference |
|
|
35
|
+
<details>
|
|
36
|
+
<summary>Wiring it by hand instead</summary>
|
|
143
37
|
|
|
144
|
-
|
|
145
|
-
|
|
38
|
+
```css
|
|
39
|
+
/* src/app.css */
|
|
40
|
+
@import 'tailwindcss';
|
|
41
|
+
@import '@nqmcreative/ui/matte/theme.css';
|
|
42
|
+
@import '@nqmcreative/ui/matte/fonts.css';
|
|
146
43
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
<ThemeToggle />
|
|
44
|
+
/* Tailwind v4 skips node_modules. Without this every component renders
|
|
45
|
+
unstyled, with no error anywhere. Point it at the style you import. */
|
|
46
|
+
@source '../node_modules/@nqmcreative/ui/dist/styles/matte';
|
|
151
47
|
```
|
|
152
48
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
49
|
+
Import exactly one style's `theme.css` — they all define the same token names,
|
|
50
|
+
so two would fight over every colour. Each style ships its own `fonts.css`
|
|
51
|
+
alongside it; skip it and the type falls back to the system stack.
|
|
52
|
+
|
|
53
|
+
Import that CSS once in `src/routes/+layout.svelte`, and put the font
|
|
54
|
+
preconnect plus the no-flash theme script in `src/app.html`, above
|
|
55
|
+
`%sveltekit.head%`:
|
|
156
56
|
|
|
157
57
|
```html
|
|
58
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
158
59
|
<script>
|
|
159
60
|
const saved = localStorage.getItem('nqm-theme');
|
|
160
61
|
if (saved === 'dark' || saved === 'light') document.documentElement.classList.add(saved);
|
|
161
62
|
</script>
|
|
162
63
|
```
|
|
163
64
|
|
|
164
|
-
|
|
165
|
-
`storedTheme()` are exported for the same purpose if you would rather not
|
|
166
|
-
hardcode it.
|
|
167
|
-
|
|
168
|
-
`@custom-variant dark` is registered too, so `dark:` utilities work in your own
|
|
169
|
-
markup when you need a one-off override.
|
|
170
|
-
|
|
171
|
-
### Dates
|
|
65
|
+
</details>
|
|
172
66
|
|
|
173
|
-
|
|
174
|
-
a `Date` is a UTC instant, so `new Date('2026-03-01')` is the last day of
|
|
175
|
-
February for anyone west of Greenwich. The helpers behind them (`toISO`,
|
|
176
|
-
`fromISO`, `addMonths`, `monthGrid`, `parseFormatted`, …) are exported and
|
|
177
|
-
stay in the viewer's local calendar throughout.
|
|
67
|
+
## Use
|
|
178
68
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
Every string a component renders on its own — ARIA names, `No data`, the words
|
|
182
|
-
in a rejected-file message — comes from one locale object. Nothing is hardcoded
|
|
183
|
-
inside a component.
|
|
184
|
-
|
|
185
|
-
```js
|
|
186
|
-
// one global locale, the common case
|
|
187
|
-
import { setLocale, idID } from '@nqmcreative/ui';
|
|
188
|
-
setLocale(idID);
|
|
189
|
-
```
|
|
69
|
+
The import names the style:
|
|
190
70
|
|
|
191
71
|
```svelte
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
<script>
|
|
195
|
-
import { LocaleProvider, idID } from '@nqmcreative/ui';
|
|
196
|
-
</script>
|
|
197
|
-
|
|
198
|
-
<LocaleProvider locale={idID}>
|
|
199
|
-
<App />
|
|
200
|
-
</LocaleProvider>
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
`enUS` and `idID` ship with the package; pass a partial to change just a few
|
|
204
|
-
keys. Precedence is per-instance prop → provider → global → `enUS`, so
|
|
205
|
-
`<Table empty="…" />` still wins over everything.
|
|
206
|
-
|
|
207
|
-
### `fonts.css`
|
|
208
|
-
|
|
209
|
-
Optional. Ships the three typefaces as plain `@font-face` rules pointing at
|
|
210
|
-
Google's CDN (Latin + Latin Extended, `font-display: swap`). Skip it if you
|
|
211
|
-
self-host fonts or already load them.
|
|
212
|
-
|
|
213
|
-
It deliberately does _not_ use `@import url('https://fonts.googleapis.com/…')`:
|
|
214
|
-
`@import` is only valid before every other rule, so bundlers drop it when the
|
|
215
|
-
file is pulled in after `tailwindcss` — the page then silently falls back to
|
|
216
|
-
`system-ui` with no error anywhere. `@font-face` works from any position.
|
|
217
|
-
|
|
218
|
-
Add this to your document head so the connection opens before the CSS parses:
|
|
219
|
-
|
|
220
|
-
```html
|
|
221
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
## Developing
|
|
225
|
-
|
|
226
|
-
```bash
|
|
227
|
-
bun install
|
|
228
|
-
bun run dev # preview components at localhost:5173
|
|
229
|
-
bun run check # type-check
|
|
230
|
-
bun run test # vitest
|
|
231
|
-
bun run build # svelte-package + publint -> dist/
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
**`dist/` is committed on purpose — rebuild and commit it with your change.**
|
|
235
|
-
Consuming projects read from `dist/`, not `src/`, and nothing builds it for
|
|
236
|
-
them: bun blocks a dependency's `prepare` script, and even once trusted it
|
|
237
|
-
runs without `node_modules/.bin` on PATH, so `svelte-kit` is not found.
|
|
238
|
-
Shipping the build output is what keeps installing from GitHub working.
|
|
239
|
-
|
|
240
|
-
```bash
|
|
241
|
-
bun run build && git add dist
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
`src/routes` is the docs site:
|
|
245
|
-
|
|
246
|
-
| route | what it is |
|
|
247
|
-
| -------------------- | ----------------------------------------------------------- |
|
|
248
|
-
| `/` | landing — palette, install, the full catalogue |
|
|
249
|
-
| `/components` | filterable index of all 57 |
|
|
250
|
-
| `/components/[slug]` | one page per component: live demo, source, what it pulls in |
|
|
251
|
-
| `/playground` | the old kitchen-sink preview |
|
|
252
|
-
| `/playground/shell` | navbar + sidebar + footer at a realistic size |
|
|
253
|
-
|
|
254
|
-
Component pages are generated from `registry.json`, and each demo lives in
|
|
255
|
-
`src/lib/site/demos/<slug>.svelte` — the file is both rendered live and shown
|
|
256
|
-
as its own source. Add a component and it appears in the nav, the index, the
|
|
257
|
-
command palette and the sidebar with no further wiring; only the demo file is
|
|
258
|
-
written by hand.
|
|
259
|
-
|
|
260
|
-
The site is fully prerendered and built with `@sveltejs/adapter-cloudflare`,
|
|
261
|
-
so `.svelte-kit/cloudflare` can be uploaded as-is.
|
|
262
|
-
|
|
263
|
-
Tests cover the logic that is easy to get quietly wrong: the date helpers
|
|
264
|
-
(timezone drift, impossible dates, per-locale parsing), the `anchored` action
|
|
265
|
-
(flip and viewport clamping), `Table` (numeric vs. string sorting, selection
|
|
266
|
-
after a sort), and `Dropzone` (type, size and count rules).
|
|
267
|
-
|
|
268
|
-
## Installing it in another project
|
|
269
|
-
|
|
270
|
-
> The docs site covers this with live examples — `/docs/installation`,
|
|
271
|
-
> `/docs/theming`, `/docs/locale` and `/docs/adding-components`. Run
|
|
272
|
-
> `bun run dev` to read them locally. What follows is the same ground in
|
|
273
|
-
> short form.
|
|
72
|
+
<script lang="ts">
|
|
73
|
+
import { Button, Field, Input } from '@nqmcreative/ui/matte';
|
|
274
74
|
|
|
275
|
-
|
|
75
|
+
let email = $state('');
|
|
76
|
+
</script>
|
|
276
77
|
|
|
277
|
-
|
|
78
|
+
<Field label="Work email">
|
|
79
|
+
<Input bind:value={email} placeholder="you@example.com" />
|
|
80
|
+
</Field>
|
|
278
81
|
|
|
279
|
-
|
|
280
|
-
bun add @nqmcreative/ui
|
|
82
|
+
<Button tone="accent">Get started</Button>
|
|
281
83
|
```
|
|
282
84
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
```
|
|
85
|
+
Per-component subpaths work too — the style, then the file name in kebab-case:
|
|
86
|
+
`@nqmcreative/ui/matte/avatar-group`.
|
|
286
87
|
|
|
287
|
-
|
|
88
|
+
**There is no root export.** `import { Button } from '@nqmcreative/ui'` resolves
|
|
89
|
+
to nothing, on purpose: a style is a choice, and picking one by accident is the
|
|
90
|
+
mistake this layout exists to prevent. Switching later is a find-and-replace of
|
|
91
|
+
the word after `@nqmcreative/ui/`.
|
|
288
92
|
|
|
289
|
-
###
|
|
93
|
+
### Tones
|
|
290
94
|
|
|
291
|
-
|
|
95
|
+
Eight of them — `brand`, `accent`, `violet`, `info`, `success`, `warning`,
|
|
96
|
+
`danger`, `neutral` — and every tonal component takes the same prop:
|
|
292
97
|
|
|
293
|
-
```
|
|
294
|
-
|
|
98
|
+
```svelte
|
|
99
|
+
<Button tone="danger">Delete</Button>
|
|
100
|
+
<Badge tone="warning" dot>Quota</Badge>
|
|
101
|
+
<Alert tone="success" title="Deployed" />
|
|
295
102
|
```
|
|
296
103
|
|
|
297
|
-
|
|
298
|
-
`
|
|
299
|
-
|
|
104
|
+
Each ships four steps: `bg-accent`, `hover:bg-accent-hover`, `bg-accent-light`,
|
|
105
|
+
`border-accent-border`. The token _names_ are a contract every style fills in,
|
|
106
|
+
so only the values differ between them. Redeclare any of them in your own
|
|
107
|
+
`@theme` block to rebrand everything at once.
|
|
300
108
|
|
|
301
|
-
|
|
302
|
-
time.
|
|
109
|
+
### Dark mode
|
|
303
110
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
111
|
+
Each style's `theme.css` ships both palettes; nothing in a component says
|
|
112
|
+
`dark:`. `<html class="dark">` or `class="light"` forces one, bare `<html>`
|
|
113
|
+
follows the OS. `ThemeToggle` handles all three.
|
|
307
114
|
|
|
308
|
-
###
|
|
115
|
+
### Locale
|
|
309
116
|
|
|
310
|
-
|
|
311
|
-
|
|
117
|
+
Every built-in string — ARIA names, `No data`, the calendar's month names —
|
|
118
|
+
comes from one object, shared by every style:
|
|
312
119
|
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
```
|
|
120
|
+
```js
|
|
121
|
+
import { setLocale, idID } from '@nqmcreative/ui/core';
|
|
316
122
|
|
|
317
|
-
|
|
318
|
-
bun add ./nqmcreative-ui-0.1.0.tgz # in your other project
|
|
123
|
+
setLocale(idID);
|
|
319
124
|
```
|
|
320
125
|
|
|
321
|
-
|
|
126
|
+
`enUS` and `idID` ship with the package; pass a partial to change a few keys.
|
|
127
|
+
Under SSR use `<LocaleProvider>` instead, so the locale is scoped to a request.
|
|
322
128
|
|
|
323
|
-
|
|
324
|
-
`EBUSY: failed opening cache/package/version dir` — bun copies the whole source
|
|
325
|
-
directory, `node_modules` (160 MB) included, into its cache. npm's symlink is
|
|
326
|
-
the way here:
|
|
129
|
+
## Layout
|
|
327
130
|
|
|
328
|
-
```bash
|
|
329
|
-
npm install file:../path/to/nqmcreative-ui
|
|
330
131
|
```
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
`init` does the wiring below for you — the `@source` line, the font preconnect
|
|
337
|
-
and the no-flash theme script are the three steps most easily forgotten:
|
|
338
|
-
|
|
339
|
-
```bash
|
|
340
|
-
bunx nqm-ui init
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
It detects SvelteKit or plain Vite, writes `src/app.css`, patches (or creates)
|
|
344
|
-
`src/app.html`, and adds the CSS import to `src/routes/+layout.svelte`. Every
|
|
345
|
-
write is idempotent — run it twice and the second run changes nothing. Add
|
|
346
|
-
`--dry-run` to see what it would touch.
|
|
347
|
-
|
|
348
|
-
It will not rewrite your Vite config; it prints the two lines to paste instead.
|
|
349
|
-
|
|
350
|
-
```bash
|
|
351
|
-
bunx nqm-ui list forms # every component in a category
|
|
352
|
-
bunx nqm-ui info date-picker # subpath, what it renders, what it imports
|
|
353
|
-
bunx nqm-ui add button badge # print the import lines
|
|
354
|
-
bunx nqm-ui add button --to src/routes/+page.svelte # …or insert them
|
|
132
|
+
src/lib/core/ behaviour, a11y, types — no markup, no classes
|
|
133
|
+
src/lib/styles/matte/ 65 components
|
|
134
|
+
src/lib/styles/paper/ 65 components
|
|
135
|
+
scripts/catalogue.mjs the list every style must implement
|
|
355
136
|
```
|
|
356
137
|
|
|
357
|
-
`
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
138
|
+
`core` holds what has no opinion about looks: focus traps, roving keyboard
|
|
139
|
+
navigation, viewport-aware anchoring, date maths, file validation, table
|
|
140
|
+
sorting, the toast queue, the locale strings. There is no `matte` version of a
|
|
141
|
+
focus trap, so no style writes one.
|
|
361
142
|
|
|
362
|
-
|
|
143
|
+
A style holds only markup and classes. It may differ from another completely —
|
|
144
|
+
different DOM, different animation — as long as the props and the behaviour
|
|
145
|
+
match. `bun run lint` fails if a style is missing a component from the
|
|
146
|
+
catalogue, and the parity suite mounts every style to assert they behave the
|
|
147
|
+
same.
|
|
363
148
|
|
|
364
|
-
|
|
365
|
-
Tailwind CSS v4. The package itself has no runtime dependencies.
|
|
149
|
+
## Components
|
|
366
150
|
|
|
367
|
-
|
|
151
|
+
| group | components |
|
|
152
|
+
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
153
|
+
| Actions | `Button`, `Link` |
|
|
154
|
+
| Forms | `Input`, `Textarea`, `Select`, `Combobox`, `MultiSelect`, `DatePicker`, `Calendar`, `Checkbox`, `CheckboxGroup`, `Radio`, `RadioGroup`, `SegmentedControl`, `Switch`, `Slider`, `NumberInput`, `PasswordInput`, `InputGroup`, `Dropzone`, `Field`, `Label` |
|
|
155
|
+
| Data display | `Badge`, `Avatar`, `AvatarGroup`, `Card`, `Stat`, `Table`, `Kbd` |
|
|
156
|
+
| Feedback | `Alert`, `Toaster` + `toast`, `Progress`, `Spinner`, `Skeleton`, `EmptyState` |
|
|
157
|
+
| Layout & nav | `Divider`, `Tabs`, `Accordion`, `AccordionItem`, `Breadcrumb`, `Pagination`, `Steps` |
|
|
158
|
+
| App shell | `Navbar`, `Sidebar`, `Footer` |
|
|
159
|
+
| Overlay | `Modal`, `ConfirmDialog`, `Drawer`, `Dropdown` + `MenuItem` + `MenuSeparator`, `ContextMenu`, `CommandPalette`, `Popover`, `Tooltip` |
|
|
160
|
+
| Marketing | `HeroSection`, `FeatureGrid`, `FeatureCard`, `PricingCard`, `Testimonial`, `LogoCloud`, `CTASection`, `StatsBand` |
|
|
161
|
+
| System | `ThemeToggle`, `LocaleProvider` |
|
|
368
162
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
```
|
|
163
|
+
Overlays are built on the native top layer and three in-house actions
|
|
164
|
+
(`portal`, `focusTrap`, `anchored`) rather than a positioning dependency.
|
|
372
165
|
|
|
373
|
-
|
|
374
|
-
cd myapp && bun add -d tailwindcss @tailwindcss/vite
|
|
375
|
-
```
|
|
166
|
+
## CLI
|
|
376
167
|
|
|
377
168
|
```bash
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
```ts
|
|
384
|
-
import tailwindcss from '@tailwindcss/vite';
|
|
385
|
-
import { sveltekit } from '@sveltejs/kit/vite';
|
|
386
|
-
|
|
387
|
-
export default defineConfig({
|
|
388
|
-
plugins: [tailwindcss(), sveltekit()]
|
|
389
|
-
});
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
Import the CSS once, in `src/routes/+layout.svelte`, and mount `Toaster` there
|
|
393
|
-
if you use toasts:
|
|
394
|
-
|
|
395
|
-
```svelte
|
|
396
|
-
<script lang="ts">
|
|
397
|
-
import '../app.css';
|
|
398
|
-
import { Toaster, setLocale, idID } from '@nqmcreative/ui';
|
|
399
|
-
|
|
400
|
-
setLocale(idID);
|
|
401
|
-
|
|
402
|
-
let { children } = $props();
|
|
403
|
-
</script>
|
|
404
|
-
|
|
405
|
-
{@render children()}
|
|
406
|
-
|
|
407
|
-
<Toaster position="bottom-right" />
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
Add the font preconnect to `src/app.html`, above `%sveltekit.head%` — it belongs
|
|
411
|
-
in plain HTML, because Svelte parses a bare `crossorigin` attribute as boolean
|
|
412
|
-
`true` and `svelte-check` rejects it:
|
|
413
|
-
|
|
414
|
-
```html
|
|
415
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
**3. Wire up the CSS.** In your app's Tailwind entry CSS:
|
|
419
|
-
|
|
420
|
-
```css
|
|
421
|
-
@import 'tailwindcss';
|
|
422
|
-
@import '@nqmcreative/ui/theme.css';
|
|
423
|
-
@import '@nqmcreative/ui/fonts.css'; /* optional */
|
|
424
|
-
|
|
425
|
-
/* Tailwind v4 ignores node_modules by default — point it at the package's
|
|
426
|
-
dist so the class names used inside the components are generated */
|
|
427
|
-
@source '../node_modules/@nqmcreative/ui/dist';
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
Adjust the `@source` path to wherever `node_modules` resolves relative to that
|
|
431
|
-
CSS file. Without it, every component renders unstyled — Tailwind never sees the
|
|
432
|
-
class names that live inside the package.
|
|
433
|
-
|
|
434
|
-
`@source` scans the whole package, so the generated CSS covers every component,
|
|
435
|
-
not only the ones you import — roughly 48 kB, 9 kB gzipped, for the full set.
|
|
436
|
-
|
|
437
|
-
**4. Use the components.** Import each one on its own:
|
|
438
|
-
|
|
439
|
-
```svelte
|
|
440
|
-
<script>
|
|
441
|
-
import Button from '@nqmcreative/ui/button';
|
|
442
|
-
import Badge from '@nqmcreative/ui/badge';
|
|
443
|
-
import Field from '@nqmcreative/ui/field';
|
|
444
|
-
import Input from '@nqmcreative/ui/input';
|
|
445
|
-
|
|
446
|
-
let email = $state('');
|
|
447
|
-
</script>
|
|
448
|
-
|
|
449
|
-
<Button>Get started</Button>
|
|
450
|
-
<Button variant="soft" tone="accent">Learn more</Button>
|
|
451
|
-
<Badge tone="success" dot>Live</Badge>
|
|
452
|
-
|
|
453
|
-
<Field label="Work email" hint="We only email about releases.">
|
|
454
|
-
<Input bind:value={email} placeholder="you@example.com" />
|
|
455
|
-
</Field>
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
Every component has its own subpath — the file name in kebab-case, so
|
|
459
|
-
`AvatarGroup` is `@nqmcreative/ui/avatar-group` and `DatePicker` is
|
|
460
|
-
`@nqmcreative/ui/date-picker`. The shared modules are there too:
|
|
461
|
-
`/tones`, `/locale`, `/date`, `/toast`, `/actions/anchor`,
|
|
462
|
-
`/actions/dismissable`.
|
|
463
|
-
|
|
464
|
-
The barrel still works if you prefer it:
|
|
465
|
-
|
|
466
|
-
```js
|
|
467
|
-
import { Button, Badge } from '@nqmcreative/ui';
|
|
169
|
+
bunx nqm-ui list forms # components in a category
|
|
170
|
+
bunx nqm-ui info date-picker # its import line in every style
|
|
171
|
+
bunx nqm-ui add button badge --style matte # print the import lines
|
|
172
|
+
bunx nqm-ui add button --style paper --to src/routes/+page.svelte
|
|
468
173
|
```
|
|
469
174
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
being explicit about what a file uses, and they cut the module graph the
|
|
473
|
-
bundler walks (177 modules to 123 in that test), not the output.
|
|
474
|
-
|
|
475
|
-
Update with `bun update @nqmcreative/ui`. The `exports` map is generated from
|
|
476
|
-
`src/lib` by `bun run exports`, and `bun run lint` fails if it is stale — a new
|
|
477
|
-
component cannot ship without its subpath.
|
|
478
|
-
|
|
479
|
-
## Adding more components
|
|
480
|
-
|
|
481
|
-
Drop a new `.svelte` file in `src/lib/components`, export it from
|
|
482
|
-
`src/lib/index.ts`, style it with the existing tokens (`bg-brand`,
|
|
483
|
-
`text-text-secondary`, `font-heading`, `ease-brand-out`, etc.) instead of raw
|
|
484
|
-
hex values, then `bun run build`.
|
|
175
|
+
`--style` has no default: the CLI lists the styles and asks, rather than
|
|
176
|
+
guessing.
|
|
485
177
|
|
|
486
|
-
|
|
487
|
-
writing colour classes by hand — Tailwind only sees literal class strings, so
|
|
488
|
-
`bg-{tone}` would silently produce nothing:
|
|
489
|
-
|
|
490
|
-
```svelte
|
|
491
|
-
<script lang="ts">
|
|
492
|
-
import { toneSoft, toneFill, type Tone } from '../tones.js';
|
|
493
|
-
|
|
494
|
-
let { tone = 'brand' }: { tone?: Tone } = $props();
|
|
495
|
-
</script>
|
|
496
|
-
|
|
497
|
-
<div class={toneSoft[tone]}>…</div>
|
|
498
|
-
```
|
|
178
|
+
## Developing
|
|
499
179
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
180
|
+
```bash
|
|
181
|
+
bun install
|
|
182
|
+
bun run dev # the docs site at localhost:5173
|
|
183
|
+
bun run check # type-check
|
|
184
|
+
bun run test # vitest, including the cross-style parity suite
|
|
185
|
+
bun run build # site + package
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`src/lib` is the package, `src/site` and `src/routes` are the docs site.
|
|
189
|
+
|
|
190
|
+
**The style is the first segment of the URL**, not a toggle:
|
|
191
|
+
`/matte/components/button` and `/paper/components/button` are two prerendered
|
|
192
|
+
pages. Each renders entirely in its own style — navbar, sidebar, footer and
|
|
193
|
+
search box included — because every page takes its components from
|
|
194
|
+
`UI[data.style]` rather than importing one style directly. The static HTML for
|
|
195
|
+
the two differs: `h-11 px-7` in one, `h-10 px-4 rounded-md` in the other.
|
|
196
|
+
|
|
197
|
+
Two pieces make that work. `src/hooks.server.ts` stamps `data-style` onto
|
|
198
|
+
`<html>` before the first paint — on `<html>` rather than a wrapper, so
|
|
199
|
+
portalled overlays reach the tokens too and dark mode's class lands on the same
|
|
200
|
+
element. `src/routes/styles.css` re-declares each style's tokens under
|
|
201
|
+
`[data-style]`, generated by `bun run scoped`.
|
|
202
|
+
|
|
203
|
+
Both are docs-only. The package still ships one global `theme.css` per style,
|
|
204
|
+
because `--color-brand` cannot hold two values on one element.
|
|
205
|
+
|
|
206
|
+
**`dist/` is committed — rebuild and commit it with your change**, so what is
|
|
207
|
+
in the repo always matches the source beside it.
|
|
208
|
+
|
|
209
|
+
Adding a component: add a line to `scripts/catalogue.mjs`, put any behaviour in
|
|
210
|
+
`src/lib/core`, write the file in **every** style folder, add **one** demo in
|
|
211
|
+
`src/site/demos`, then `bun run build`. Barrels, exports map, registry, scoped
|
|
212
|
+
tokens and the per-style demo copies are all generated — a demo is authored once
|
|
213
|
+
against `matte` and copied into every other style with its import path
|
|
214
|
+
rewritten. `bun run lint` fails if any is stale or a style is missing
|
|
215
|
+
the component. Full conventions are on the site under `/docs/adding-components`.
|
|
504
216
|
|
|
505
217
|
## License
|
|
506
218
|
|