@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.
Files changed (308) hide show
  1. package/README.md +151 -439
  2. package/cli/index.mjs +67 -30
  3. package/dist/core/calendar.d.ts +3 -0
  4. package/dist/core/calendar.js +36 -0
  5. package/dist/core/dialog.svelte.d.ts +14 -0
  6. package/dist/core/dialog.svelte.js +23 -0
  7. package/dist/core/files.d.ts +35 -0
  8. package/dist/core/files.js +62 -0
  9. package/dist/core/index.d.ts +37 -0
  10. package/dist/core/index.js +35 -0
  11. package/dist/core/list.svelte.d.ts +41 -0
  12. package/dist/core/list.svelte.js +77 -0
  13. package/dist/core/number.d.ts +7 -0
  14. package/dist/core/number.js +17 -0
  15. package/dist/core/pagination.d.ts +6 -0
  16. package/dist/core/pagination.js +21 -0
  17. package/dist/core/password.d.ts +8 -0
  18. package/dist/core/password.js +23 -0
  19. package/dist/core/table.d.ts +22 -0
  20. package/dist/core/table.js +41 -0
  21. package/dist/core/theme.svelte.d.ts +16 -0
  22. package/dist/core/theme.svelte.js +34 -0
  23. package/dist/core/trigger.d.ts +35 -0
  24. package/dist/core/trigger.js +77 -0
  25. package/dist/index.d.ts +11 -103
  26. package/dist/index.js +11 -75
  27. package/dist/{components → styles/matte}/AccordionItem.svelte +1 -1
  28. package/dist/{components → styles/matte}/AccordionItem.svelte.d.ts +1 -1
  29. package/dist/{components → styles/matte}/Alert.svelte +8 -2
  30. package/dist/{components → styles/matte}/Alert.svelte.d.ts +1 -1
  31. package/dist/{components → styles/matte}/Avatar.svelte +1 -1
  32. package/dist/{components → styles/matte}/Avatar.svelte.d.ts +1 -1
  33. package/dist/{components → styles/matte}/Badge.svelte +8 -3
  34. package/dist/{components → styles/matte}/Badge.svelte.d.ts +1 -3
  35. package/dist/{components → styles/matte}/Breadcrumb.svelte +2 -2
  36. package/dist/{components → styles/matte}/Breadcrumb.svelte.d.ts +1 -1
  37. package/dist/{components → styles/matte}/Button.svelte +1 -1
  38. package/dist/{components → styles/matte}/Button.svelte.d.ts +1 -1
  39. package/dist/styles/matte/CTASection.svelte +76 -0
  40. package/dist/styles/matte/CTASection.svelte.d.ts +18 -0
  41. package/dist/{components → styles/matte}/Calendar.svelte +7 -17
  42. package/dist/{components → styles/matte}/Calendar.svelte.d.ts +1 -1
  43. package/dist/{components → styles/matte}/Card.svelte +1 -1
  44. package/dist/{components → styles/matte}/Card.svelte.d.ts +1 -1
  45. package/dist/{components → styles/matte}/Checkbox.svelte +1 -1
  46. package/dist/{components → styles/matte}/Checkbox.svelte.d.ts +1 -1
  47. package/dist/{components → styles/matte}/CheckboxGroup.svelte +1 -1
  48. package/dist/{components → styles/matte}/CheckboxGroup.svelte.d.ts +1 -1
  49. package/dist/{components → styles/matte}/Combobox.svelte +31 -42
  50. package/dist/{components → styles/matte}/Combobox.svelte.d.ts +1 -1
  51. package/dist/{components → styles/matte}/CommandPalette.svelte +26 -41
  52. package/dist/{components → styles/matte}/CommandPalette.svelte.d.ts +1 -1
  53. package/dist/{components → styles/matte}/ConfirmDialog.svelte +2 -2
  54. package/dist/{components → styles/matte}/ConfirmDialog.svelte.d.ts +2 -2
  55. package/dist/{components → styles/matte}/ContextMenu.svelte +5 -7
  56. package/dist/{components → styles/matte}/DatePicker.svelte +7 -11
  57. package/dist/{components → styles/matte}/DatePicker.svelte.d.ts +1 -1
  58. package/dist/{components → styles/matte}/Drawer.svelte +4 -7
  59. package/dist/{components → styles/matte}/Dropdown.svelte +18 -36
  60. package/dist/{components → styles/matte}/Dropdown.svelte.d.ts +1 -1
  61. package/dist/{components → styles/matte}/Dropzone.svelte +11 -43
  62. package/dist/{components → styles/matte}/Dropzone.svelte.d.ts +2 -5
  63. package/dist/{components → styles/matte}/EmptyState.svelte +1 -1
  64. package/dist/{components → styles/matte}/EmptyState.svelte.d.ts +1 -1
  65. package/dist/styles/matte/FeatureCard.svelte +58 -0
  66. package/dist/styles/matte/FeatureCard.svelte.d.ts +16 -0
  67. package/dist/styles/matte/FeatureGrid.svelte +62 -0
  68. package/dist/styles/matte/FeatureGrid.svelte.d.ts +16 -0
  69. package/dist/{components → styles/matte}/Footer.svelte +1 -1
  70. package/dist/{components → styles/matte}/Footer.svelte.d.ts +1 -1
  71. package/dist/styles/matte/HeroSection.svelte +80 -0
  72. package/dist/styles/matte/HeroSection.svelte.d.ts +21 -0
  73. package/dist/{components → styles/matte}/Input.svelte +1 -1
  74. package/dist/{components → styles/matte}/Input.svelte.d.ts +1 -1
  75. package/dist/{components → styles/matte}/Link.svelte +1 -1
  76. package/dist/{components → styles/matte}/Link.svelte.d.ts +1 -1
  77. package/dist/{components → styles/matte}/LocaleProvider.svelte +1 -1
  78. package/dist/{components → styles/matte}/LocaleProvider.svelte.d.ts +1 -1
  79. package/dist/styles/matte/LogoCloud.svelte +61 -0
  80. package/dist/styles/matte/LogoCloud.svelte.d.ts +19 -0
  81. package/dist/{components → styles/matte}/MenuItem.svelte +1 -1
  82. package/dist/{components → styles/matte}/MenuItem.svelte.d.ts +1 -1
  83. package/dist/{components → styles/matte}/Modal.svelte +4 -7
  84. package/dist/{components → styles/matte}/MultiSelect.svelte +18 -37
  85. package/dist/{components → styles/matte}/MultiSelect.svelte.d.ts +1 -1
  86. package/dist/{components → styles/matte}/Navbar.svelte +2 -2
  87. package/dist/{components → styles/matte}/Navbar.svelte.d.ts +1 -1
  88. package/dist/{components → styles/matte}/NumberInput.svelte +4 -8
  89. package/dist/{components → styles/matte}/NumberInput.svelte.d.ts +1 -1
  90. package/dist/{components → styles/matte}/Pagination.svelte +4 -15
  91. package/dist/{components → styles/matte}/Pagination.svelte.d.ts +1 -1
  92. package/dist/{components → styles/matte}/PasswordInput.svelte +4 -13
  93. package/dist/{components → styles/matte}/PasswordInput.svelte.d.ts +1 -1
  94. package/dist/{components → styles/matte}/Popover.svelte +16 -41
  95. package/dist/{components → styles/matte}/Popover.svelte.d.ts +1 -1
  96. package/dist/styles/matte/PricingCard.svelte +107 -0
  97. package/dist/styles/matte/PricingCard.svelte.d.ts +25 -0
  98. package/dist/{components → styles/matte}/Progress.svelte +3 -2
  99. package/dist/{components → styles/matte}/Progress.svelte.d.ts +1 -1
  100. package/dist/{components → styles/matte}/Radio.svelte +1 -1
  101. package/dist/{components → styles/matte}/Radio.svelte.d.ts +1 -1
  102. package/dist/{components → styles/matte}/RadioGroup.svelte +1 -1
  103. package/dist/{components → styles/matte}/RadioGroup.svelte.d.ts +1 -1
  104. package/dist/{components → styles/matte}/SegmentedControl.svelte +1 -1
  105. package/dist/{components → styles/matte}/SegmentedControl.svelte.d.ts +1 -1
  106. package/dist/{components → styles/matte}/Select.svelte +1 -1
  107. package/dist/{components → styles/matte}/Select.svelte.d.ts +1 -1
  108. package/dist/{components → styles/matte}/Sidebar.svelte +2 -2
  109. package/dist/{components → styles/matte}/Sidebar.svelte.d.ts +1 -1
  110. package/dist/{components → styles/matte}/Slider.svelte +3 -2
  111. package/dist/{components → styles/matte}/Slider.svelte.d.ts +1 -1
  112. package/dist/{components → styles/matte}/Spinner.svelte +2 -2
  113. package/dist/{components → styles/matte}/Spinner.svelte.d.ts +1 -1
  114. package/dist/{components → styles/matte}/Stat.svelte +1 -1
  115. package/dist/{components → styles/matte}/Stat.svelte.d.ts +1 -1
  116. package/dist/styles/matte/StatsBand.svelte +57 -0
  117. package/dist/styles/matte/StatsBand.svelte.d.ts +20 -0
  118. package/dist/{components → styles/matte}/Steps.svelte +1 -1
  119. package/dist/{components → styles/matte}/Steps.svelte.d.ts +1 -1
  120. package/dist/{components → styles/matte}/Switch.svelte +1 -1
  121. package/dist/{components → styles/matte}/Switch.svelte.d.ts +1 -1
  122. package/dist/{components → styles/matte}/Table.svelte +6 -28
  123. package/dist/{components → styles/matte}/Table.svelte.d.ts +2 -6
  124. package/dist/{components → styles/matte}/Tabs.svelte +8 -1
  125. package/dist/{components → styles/matte}/Tabs.svelte.d.ts +1 -1
  126. package/dist/styles/matte/Testimonial.svelte +67 -0
  127. package/dist/styles/matte/Testimonial.svelte.d.ts +19 -0
  128. package/dist/{components → styles/matte}/Textarea.svelte +1 -1
  129. package/dist/{components → styles/matte}/Textarea.svelte.d.ts +1 -1
  130. package/dist/{components → styles/matte}/ThemeToggle.svelte +14 -27
  131. package/dist/{components → styles/matte}/ThemeToggle.svelte.d.ts +2 -6
  132. package/dist/{components → styles/matte}/Toaster.svelte +4 -4
  133. package/dist/{fonts.css → styles/matte/fonts.css} +4 -3
  134. package/dist/styles/matte/index.d.ts +109 -0
  135. package/dist/styles/matte/index.js +83 -0
  136. package/dist/{theme.css → styles/matte/theme.css} +0 -1
  137. package/dist/styles/paper/Accordion.svelte +17 -0
  138. package/dist/styles/paper/Accordion.svelte.d.ts +8 -0
  139. package/dist/styles/paper/AccordionItem.svelte +46 -0
  140. package/dist/styles/paper/AccordionItem.svelte.d.ts +14 -0
  141. package/dist/styles/paper/Alert.svelte +99 -0
  142. package/dist/styles/paper/Alert.svelte.d.ts +18 -0
  143. package/dist/styles/paper/Avatar.svelte +60 -0
  144. package/dist/styles/paper/Avatar.svelte.d.ts +16 -0
  145. package/dist/styles/paper/AvatarGroup.svelte +17 -0
  146. package/dist/styles/paper/AvatarGroup.svelte.d.ts +8 -0
  147. package/dist/styles/paper/Badge.svelte +58 -0
  148. package/dist/styles/paper/Badge.svelte.d.ts +16 -0
  149. package/dist/styles/paper/Breadcrumb.svelte +49 -0
  150. package/dist/styles/paper/Breadcrumb.svelte.d.ts +14 -0
  151. package/dist/styles/paper/Button.svelte +96 -0
  152. package/dist/styles/paper/Button.svelte.d.ts +21 -0
  153. package/dist/styles/paper/CTASection.svelte +76 -0
  154. package/dist/styles/paper/CTASection.svelte.d.ts +18 -0
  155. package/dist/styles/paper/Calendar.svelte +202 -0
  156. package/dist/styles/paper/Calendar.svelte.d.ts +22 -0
  157. package/dist/styles/paper/Card.svelte +78 -0
  158. package/dist/styles/paper/Card.svelte.d.ts +21 -0
  159. package/dist/styles/paper/Checkbox.svelte +75 -0
  160. package/dist/styles/paper/Checkbox.svelte.d.ts +15 -0
  161. package/dist/styles/paper/CheckboxGroup.svelte +111 -0
  162. package/dist/styles/paper/CheckboxGroup.svelte.d.ts +30 -0
  163. package/dist/styles/paper/Combobox.svelte +266 -0
  164. package/dist/styles/paper/Combobox.svelte.d.ts +29 -0
  165. package/dist/styles/paper/CommandPalette.svelte +209 -0
  166. package/dist/styles/paper/CommandPalette.svelte.d.ts +32 -0
  167. package/dist/styles/paper/ConfirmDialog.svelte +97 -0
  168. package/dist/styles/paper/ConfirmDialog.svelte.d.ts +22 -0
  169. package/dist/styles/paper/ContextMenu.svelte +88 -0
  170. package/dist/styles/paper/ContextMenu.svelte.d.ts +15 -0
  171. package/dist/styles/paper/DatePicker.svelte +192 -0
  172. package/dist/styles/paper/DatePicker.svelte.d.ts +23 -0
  173. package/dist/styles/paper/Divider.svelte +30 -0
  174. package/dist/styles/paper/Divider.svelte.d.ts +10 -0
  175. package/dist/styles/paper/Drawer.svelte +165 -0
  176. package/dist/styles/paper/Drawer.svelte.d.ts +20 -0
  177. package/dist/styles/paper/Dropdown.svelte +94 -0
  178. package/dist/styles/paper/Dropdown.svelte.d.ts +23 -0
  179. package/dist/styles/paper/Dropzone.svelte +210 -0
  180. package/dist/styles/paper/Dropzone.svelte.d.ts +29 -0
  181. package/dist/styles/paper/EmptyState.svelte +71 -0
  182. package/dist/styles/paper/EmptyState.svelte.d.ts +18 -0
  183. package/dist/styles/paper/FeatureCard.svelte +58 -0
  184. package/dist/styles/paper/FeatureCard.svelte.d.ts +16 -0
  185. package/dist/styles/paper/FeatureGrid.svelte +62 -0
  186. package/dist/styles/paper/FeatureGrid.svelte.d.ts +16 -0
  187. package/dist/styles/paper/Field.svelte +42 -0
  188. package/dist/styles/paper/Field.svelte.d.ts +16 -0
  189. package/dist/styles/paper/Footer.svelte +91 -0
  190. package/dist/styles/paper/Footer.svelte.d.ts +25 -0
  191. package/dist/styles/paper/HeroSection.svelte +86 -0
  192. package/dist/styles/paper/HeroSection.svelte.d.ts +21 -0
  193. package/dist/styles/paper/Input.svelte +60 -0
  194. package/dist/styles/paper/Input.svelte.d.ts +18 -0
  195. package/dist/styles/paper/InputGroup.svelte +20 -0
  196. package/dist/styles/paper/InputGroup.svelte.d.ts +11 -0
  197. package/dist/styles/paper/Kbd.svelte +17 -0
  198. package/dist/styles/paper/Kbd.svelte.d.ts +8 -0
  199. package/dist/styles/paper/Label.svelte +16 -0
  200. package/dist/styles/paper/Label.svelte.d.ts +9 -0
  201. package/dist/styles/paper/Link.svelte +44 -0
  202. package/dist/styles/paper/Link.svelte.d.ts +16 -0
  203. package/dist/styles/paper/LocaleProvider.svelte +24 -0
  204. package/dist/styles/paper/LocaleProvider.svelte.d.ts +10 -0
  205. package/dist/styles/paper/LogoCloud.svelte +61 -0
  206. package/dist/styles/paper/LogoCloud.svelte.d.ts +19 -0
  207. package/dist/styles/paper/MenuItem.svelte +64 -0
  208. package/dist/styles/paper/MenuItem.svelte.d.ts +18 -0
  209. package/dist/styles/paper/MenuSeparator.svelte +22 -0
  210. package/dist/styles/paper/MenuSeparator.svelte.d.ts +8 -0
  211. package/dist/styles/paper/Modal.svelte +118 -0
  212. package/dist/styles/paper/Modal.svelte.d.ts +21 -0
  213. package/dist/styles/paper/MultiSelect.svelte +287 -0
  214. package/dist/styles/paper/MultiSelect.svelte.d.ts +31 -0
  215. package/dist/styles/paper/Navbar.svelte +201 -0
  216. package/dist/styles/paper/Navbar.svelte.d.ts +33 -0
  217. package/dist/styles/paper/NumberInput.svelte +96 -0
  218. package/dist/styles/paper/NumberInput.svelte.d.ts +15 -0
  219. package/dist/styles/paper/Pagination.svelte +83 -0
  220. package/dist/styles/paper/Pagination.svelte.d.ts +15 -0
  221. package/dist/styles/paper/PasswordInput.svelte +100 -0
  222. package/dist/styles/paper/PasswordInput.svelte.d.ts +12 -0
  223. package/dist/styles/paper/Popover.svelte +89 -0
  224. package/dist/styles/paper/Popover.svelte.d.ts +19 -0
  225. package/dist/styles/paper/PricingCard.svelte +108 -0
  226. package/dist/styles/paper/PricingCard.svelte.d.ts +25 -0
  227. package/dist/styles/paper/Progress.svelte +59 -0
  228. package/dist/styles/paper/Progress.svelte.d.ts +17 -0
  229. package/dist/styles/paper/Radio.svelte +55 -0
  230. package/dist/styles/paper/Radio.svelte.d.ts +15 -0
  231. package/dist/styles/paper/RadioGroup.svelte +95 -0
  232. package/dist/styles/paper/RadioGroup.svelte.d.ts +27 -0
  233. package/dist/styles/paper/SegmentedControl.svelte +88 -0
  234. package/dist/styles/paper/SegmentedControl.svelte.d.ts +25 -0
  235. package/dist/styles/paper/Select.svelte +61 -0
  236. package/dist/styles/paper/Select.svelte.d.ts +20 -0
  237. package/dist/styles/paper/Sidebar.svelte +206 -0
  238. package/dist/styles/paper/Sidebar.svelte.d.ts +36 -0
  239. package/dist/styles/paper/Skeleton.svelte +46 -0
  240. package/dist/styles/paper/Skeleton.svelte.d.ts +13 -0
  241. package/dist/styles/paper/Slider.svelte +80 -0
  242. package/dist/styles/paper/Slider.svelte.d.ts +19 -0
  243. package/dist/styles/paper/Spinner.svelte +34 -0
  244. package/dist/styles/paper/Spinner.svelte.d.ts +13 -0
  245. package/dist/styles/paper/Stat.svelte +51 -0
  246. package/dist/styles/paper/Stat.svelte.d.ts +16 -0
  247. package/dist/styles/paper/StatsBand.svelte +63 -0
  248. package/dist/styles/paper/StatsBand.svelte.d.ts +20 -0
  249. package/dist/styles/paper/Steps.svelte +141 -0
  250. package/dist/styles/paper/Steps.svelte.d.ts +24 -0
  251. package/dist/styles/paper/Switch.svelte +64 -0
  252. package/dist/styles/paper/Switch.svelte.d.ts +14 -0
  253. package/dist/styles/paper/Table.svelte +217 -0
  254. package/dist/styles/paper/Table.svelte.d.ts +66 -0
  255. package/dist/styles/paper/Tabs.svelte +102 -0
  256. package/dist/styles/paper/Tabs.svelte.d.ts +23 -0
  257. package/dist/styles/paper/Testimonial.svelte +64 -0
  258. package/dist/styles/paper/Testimonial.svelte.d.ts +19 -0
  259. package/dist/styles/paper/Textarea.svelte +54 -0
  260. package/dist/styles/paper/Textarea.svelte.d.ts +12 -0
  261. package/dist/styles/paper/ThemeToggle.svelte +130 -0
  262. package/dist/styles/paper/ThemeToggle.svelte.d.ts +16 -0
  263. package/dist/styles/paper/Toaster.svelte +132 -0
  264. package/dist/styles/paper/Toaster.svelte.d.ts +8 -0
  265. package/dist/styles/paper/Tooltip.svelte +33 -0
  266. package/dist/styles/paper/Tooltip.svelte.d.ts +12 -0
  267. package/dist/styles/paper/fonts.css +46 -0
  268. package/dist/styles/paper/index.d.ts +109 -0
  269. package/dist/styles/paper/index.js +83 -0
  270. package/dist/styles/paper/theme.css +222 -0
  271. package/package.json +531 -201
  272. package/registry.json +658 -339
  273. /package/dist/{actions → core/actions}/anchor.d.ts +0 -0
  274. /package/dist/{actions → core/actions}/anchor.js +0 -0
  275. /package/dist/{actions → core/actions}/dismissable.d.ts +0 -0
  276. /package/dist/{actions → core/actions}/dismissable.js +0 -0
  277. /package/dist/{date.d.ts → core/date.d.ts} +0 -0
  278. /package/dist/{date.js → core/date.js} +0 -0
  279. /package/dist/{locale.svelte.d.ts → core/locale.svelte.d.ts} +0 -0
  280. /package/dist/{locale.svelte.js → core/locale.svelte.js} +0 -0
  281. /package/dist/{toast.svelte.d.ts → core/toast.svelte.d.ts} +0 -0
  282. /package/dist/{toast.svelte.js → core/toast.svelte.js} +0 -0
  283. /package/dist/{tones.d.ts → core/tones.d.ts} +0 -0
  284. /package/dist/{tones.js → core/tones.js} +0 -0
  285. /package/dist/{components → styles/matte}/Accordion.svelte +0 -0
  286. /package/dist/{components → styles/matte}/Accordion.svelte.d.ts +0 -0
  287. /package/dist/{components → styles/matte}/AvatarGroup.svelte +0 -0
  288. /package/dist/{components → styles/matte}/AvatarGroup.svelte.d.ts +0 -0
  289. /package/dist/{components → styles/matte}/ContextMenu.svelte.d.ts +0 -0
  290. /package/dist/{components → styles/matte}/Divider.svelte +0 -0
  291. /package/dist/{components → styles/matte}/Divider.svelte.d.ts +0 -0
  292. /package/dist/{components → styles/matte}/Drawer.svelte.d.ts +0 -0
  293. /package/dist/{components → styles/matte}/Field.svelte +0 -0
  294. /package/dist/{components → styles/matte}/Field.svelte.d.ts +0 -0
  295. /package/dist/{components → styles/matte}/InputGroup.svelte +0 -0
  296. /package/dist/{components → styles/matte}/InputGroup.svelte.d.ts +0 -0
  297. /package/dist/{components → styles/matte}/Kbd.svelte +0 -0
  298. /package/dist/{components → styles/matte}/Kbd.svelte.d.ts +0 -0
  299. /package/dist/{components → styles/matte}/Label.svelte +0 -0
  300. /package/dist/{components → styles/matte}/Label.svelte.d.ts +0 -0
  301. /package/dist/{components → styles/matte}/MenuSeparator.svelte +0 -0
  302. /package/dist/{components → styles/matte}/MenuSeparator.svelte.d.ts +0 -0
  303. /package/dist/{components → styles/matte}/Modal.svelte.d.ts +0 -0
  304. /package/dist/{components → styles/matte}/Skeleton.svelte +0 -0
  305. /package/dist/{components → styles/matte}/Skeleton.svelte.d.ts +0 -0
  306. /package/dist/{components → styles/matte}/Toaster.svelte.d.ts +0 -0
  307. /package/dist/{components → styles/matte}/Tooltip.svelte +0 -0
  308. /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, styled to match
4
- [nqmcreative.com](https://nqmcreative.com)flat surfaces, no shadows, no
5
- border-radius except pills, brand teal `#1c6358`, Sora/Work Sans/JetBrains Mono.
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
- Everything in `src/lib` is the package. Everything in `src/routes` is a local
8
- dev preview (`bun run dev`) it is not published.
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
- ## What's included
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
- ### Design tokens (`theme.css`)
15
+ ## Install
13
16
 
14
- A Tailwind v4 `@theme` block. Surfaces (`bg`, `bg-alt`, `bg-inset`, `hairline`,
15
- `hairline-strong`), text (`text`, `text-secondary`, `text-muted`,
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
- `tones.ts` exports the shared class maps (`toneSolid`, `toneSoft`, `toneText`,
47
- `toneFill`, `toneRing`, …) plus the `Tone` type and the `TONES` array, so your
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
- `toast.success` / `error` / `warning` / `info` / `loading`, plus `show`,
129
- `update(id, …)` for a loading toast that becomes a result, `dismiss(id)` and
130
- `clear()`.
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
- ### Dark mode
29
+ ```ts
30
+ plugins: [tailwindcss(), sveltekit()];
31
+ ```
133
32
 
134
- `theme.css` ships both palettes. Nothing in a component says `dark:` — every
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
- | root | result |
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
- `ThemeToggle` writes that class and remembers the choice under the
145
- `nqm-theme` key:
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
- ```svelte
148
- <ThemeToggle variant="segmented" />
149
- <!-- or a single cycling button -->
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
- Because the class is applied after hydration, a visitor who chose dark sees one
154
- light frame first. Set the class before first paint to avoid it — in SvelteKit
155
- this goes in `src/app.html`, above `%sveltekit.head%`:
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
- The key has to match what `ThemeToggle` writes. `applyTheme(theme)` and
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
- `DatePicker` and `Calendar` speak `YYYY-MM-DD` strings, never `Date` objects —
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
- ### Locale
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
- <!-- or scoped to a subtree — the right choice under SSR, where module
193
- state is shared between requests -->
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
- **bun is the package manager here**; `bun.lock` is the committed lockfile.
75
+ let email = $state('');
76
+ </script>
276
77
 
277
- ### Option A — npm (recommended)
78
+ <Field label="Work email">
79
+ <Input bind:value={email} placeholder="you@example.com" />
80
+ </Field>
278
81
 
279
- ```bash
280
- bun add @nqmcreative/ui
82
+ <Button tone="accent">Get started</Button>
281
83
  ```
282
84
 
283
- ```bash
284
- bunx nqm-ui init
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
- Update with `bun update @nqmcreative/ui`.
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
- ### Option A2 — straight from GitHub
93
+ ### Tones
290
94
 
291
- Tracks `main` rather than a release.
95
+ Eight of them — `brand`, `accent`, `violet`, `info`, `success`, `warning`,
96
+ `danger`, `neutral` — and every tonal component takes the same prop:
292
97
 
293
- ```bash
294
- bun add github:mukhsamr/nqmcreative-ui
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
- The repo is public, so this needs no authentication — no SSH key, no token.
298
- `git+https://github.com/mukhsamr/nqmcreative-ui.git` resolves to the same
299
- thing; bun rewrites both to `github:owner/repo#sha`.
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
- `dist/` is committed, so this works as-is: nothing has to be built at install
302
- time.
109
+ ### Dark mode
303
110
 
304
- > bun caches git dependencies by URL and will not notice new commits. Pin a
305
- > commit or tag with `#sha`, or clear the cache with `bun pm cache rm`.
306
- > Installing from npm avoids this entirely.
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
- ### Option B — a packed tarball
115
+ ### Locale
309
116
 
310
- Portable, and needs no repo access hand it to someone or drop it in a CI
311
- cache.
117
+ Every built-in stringARIA names, `No data`, the calendar's month names
118
+ comes from one object, shared by every style:
312
119
 
313
- ```bash
314
- bun run build && bun pm pack # in this repo
315
- ```
120
+ ```js
121
+ import { setLocale, idID } from '@nqmcreative/ui/core';
316
122
 
317
- ```bash
318
- bun add ./nqmcreative-ui-0.1.0.tgz # in your other project
123
+ setLocale(idID);
319
124
  ```
320
125
 
321
- ### Option C a live symlink, for developing both at once
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
- `bun link` and `bun add file:<dir>` both fail on Windows with
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
- `bun run build` in this repo then shows up without reinstalling.
333
-
334
- ### The CLI
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
- `add` is a convenience, not an installer: the whole library is already there
358
- after `bun add`, and a component pulls in whatever it renders internally — `add
359
- date-picker` mentions that `Calendar` comes with it, but there is nothing extra
360
- to install.
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
- ### Then, in every case
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
- **1. Peer requirements** — the consuming project brings its own `svelte` ^5 and
365
- Tailwind CSS v4. The package itself has no runtime dependencies.
149
+ ## Components
366
150
 
367
- **2. SvelteKit from scratch**, start to finish:
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
- ```bash
370
- bunx sv create myapp --template minimal --types ts --install bun
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
- ```bash
374
- cd myapp && bun add -d tailwindcss @tailwindcss/vite
375
- ```
166
+ ## CLI
376
167
 
377
168
  ```bash
378
- bun add @nqmcreative/ui
379
- ```
380
-
381
- Register the Tailwind plugin **before** `sveltekit()` in `vite.config.ts`:
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
- Both produce the same bundle measured on the same app, barrel and subpaths
471
- came out byte-identical, because the barrel tree-shakes. Subpaths are about
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
- If the component is tonal, import the maps from `../tones.js` rather than
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
- One more rule worth knowing: never put two same-property colour utilities on
501
- one element (`border-hairline` + `border-brand`), because CSS order — not class
502
- order decides the winner. Use the side-specific map (`toneBorderLeft`) or set
503
- the colour once per variant.
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