@dxlbnl/ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/README.md +94 -0
  2. package/dist/components/cards/Card.stories.svelte +82 -0
  3. package/dist/components/cards/Card.stories.svelte.d.ts +19 -0
  4. package/dist/components/cards/Card.svelte +28 -0
  5. package/dist/components/cards/Card.svelte.d.ts +12 -0
  6. package/dist/components/cards/NoteCard.stories.svelte +94 -0
  7. package/dist/components/cards/NoteCard.stories.svelte.d.ts +19 -0
  8. package/dist/components/cards/NoteCard.svelte +89 -0
  9. package/dist/components/cards/NoteCard.svelte.d.ts +18 -0
  10. package/dist/components/cards/ProductCard.stories.svelte +98 -0
  11. package/dist/components/cards/ProductCard.stories.svelte.d.ts +19 -0
  12. package/dist/components/cards/ProductCard.svelte +150 -0
  13. package/dist/components/cards/ProductCard.svelte.d.ts +22 -0
  14. package/dist/components/cards/ProjectCard.stories.svelte +88 -0
  15. package/dist/components/cards/ProjectCard.stories.svelte.d.ts +19 -0
  16. package/dist/components/cards/ProjectCard.svelte +109 -0
  17. package/dist/components/cards/ProjectCard.svelte.d.ts +20 -0
  18. package/dist/components/cards/index.d.ts +4 -0
  19. package/dist/components/cards/index.js +4 -0
  20. package/dist/components/data/Accordion.stories.svelte +316 -0
  21. package/dist/components/data/Accordion.stories.svelte.d.ts +19 -0
  22. package/dist/components/data/Accordion.svelte +23 -0
  23. package/dist/components/data/Accordion.svelte.d.ts +9 -0
  24. package/dist/components/data/AccordionItem.svelte +112 -0
  25. package/dist/components/data/AccordionItem.svelte.d.ts +11 -0
  26. package/dist/components/data/Table.composition.stories.svelte +67 -0
  27. package/dist/components/data/Table.composition.stories.svelte.d.ts +19 -0
  28. package/dist/components/data/Table.stories.svelte +137 -0
  29. package/dist/components/data/Table.stories.svelte.d.ts +19 -0
  30. package/dist/components/data/Table.svelte +83 -0
  31. package/dist/components/data/Table.svelte.d.ts +14 -0
  32. package/dist/components/data/Tabs.stories.svelte +386 -0
  33. package/dist/components/data/Tabs.stories.svelte.d.ts +19 -0
  34. package/dist/components/data/Tabs.svelte +142 -0
  35. package/dist/components/data/Tabs.svelte.d.ts +19 -0
  36. package/dist/components/data/index.d.ts +4 -0
  37. package/dist/components/data/index.js +4 -0
  38. package/dist/components/feedback/Modal.stories.svelte +192 -0
  39. package/dist/components/feedback/Modal.stories.svelte.d.ts +4 -0
  40. package/dist/components/feedback/Modal.svelte +185 -0
  41. package/dist/components/feedback/Modal.svelte.d.ts +19 -0
  42. package/dist/components/feedback/Toast.stories.svelte +203 -0
  43. package/dist/components/feedback/Toast.stories.svelte.d.ts +19 -0
  44. package/dist/components/feedback/Toast.svelte +109 -0
  45. package/dist/components/feedback/Toast.svelte.d.ts +15 -0
  46. package/dist/components/feedback/ToastRegion.stories.svelte +193 -0
  47. package/dist/components/feedback/ToastRegion.stories.svelte.d.ts +19 -0
  48. package/dist/components/feedback/ToastRegion.svelte +102 -0
  49. package/dist/components/feedback/ToastRegion.svelte.d.ts +9 -0
  50. package/dist/components/feedback/index.d.ts +3 -0
  51. package/dist/components/feedback/index.js +3 -0
  52. package/dist/components/forms/Checkbox.stories.svelte +103 -0
  53. package/dist/components/forms/Checkbox.stories.svelte.d.ts +19 -0
  54. package/dist/components/forms/Checkbox.svelte +150 -0
  55. package/dist/components/forms/Checkbox.svelte.d.ts +11 -0
  56. package/dist/components/forms/Field.stories.svelte +113 -0
  57. package/dist/components/forms/Field.stories.svelte.d.ts +19 -0
  58. package/dist/components/forms/Field.svelte +77 -0
  59. package/dist/components/forms/Field.svelte.d.ts +17 -0
  60. package/dist/components/forms/Input.stories.svelte +58 -0
  61. package/dist/components/forms/Input.stories.svelte.d.ts +19 -0
  62. package/dist/components/forms/Input.svelte +64 -0
  63. package/dist/components/forms/Input.svelte.d.ts +9 -0
  64. package/dist/components/forms/InputWrap.composition.stories.svelte +32 -0
  65. package/dist/components/forms/InputWrap.composition.stories.svelte.d.ts +19 -0
  66. package/dist/components/forms/InputWrap.stories.svelte +53 -0
  67. package/dist/components/forms/InputWrap.stories.svelte.d.ts +19 -0
  68. package/dist/components/forms/InputWrap.svelte +128 -0
  69. package/dist/components/forms/InputWrap.svelte.d.ts +21 -0
  70. package/dist/components/forms/Radio.stories.svelte +70 -0
  71. package/dist/components/forms/Radio.stories.svelte.d.ts +19 -0
  72. package/dist/components/forms/Radio.svelte +109 -0
  73. package/dist/components/forms/Radio.svelte.d.ts +9 -0
  74. package/dist/components/forms/RadioGroup.stories.svelte +115 -0
  75. package/dist/components/forms/RadioGroup.stories.svelte.d.ts +19 -0
  76. package/dist/components/forms/RadioGroup.svelte +116 -0
  77. package/dist/components/forms/RadioGroup.svelte.d.ts +24 -0
  78. package/dist/components/forms/Select.stories.svelte +168 -0
  79. package/dist/components/forms/Select.stories.svelte.d.ts +19 -0
  80. package/dist/components/forms/Select.svelte +262 -0
  81. package/dist/components/forms/Select.svelte.d.ts +23 -0
  82. package/dist/components/forms/Switch.stories.svelte +86 -0
  83. package/dist/components/forms/Switch.stories.svelte.d.ts +19 -0
  84. package/dist/components/forms/Switch.svelte +113 -0
  85. package/dist/components/forms/Switch.svelte.d.ts +11 -0
  86. package/dist/components/forms/Textarea.stories.svelte +40 -0
  87. package/dist/components/forms/Textarea.stories.svelte.d.ts +19 -0
  88. package/dist/components/forms/Textarea.svelte +66 -0
  89. package/dist/components/forms/Textarea.svelte.d.ts +9 -0
  90. package/dist/components/forms/field-context.d.ts +7 -0
  91. package/dist/components/forms/field-context.js +1 -0
  92. package/dist/components/forms/index.d.ts +9 -0
  93. package/dist/components/forms/index.js +9 -0
  94. package/dist/components/layout/Container.stories.svelte +67 -0
  95. package/dist/components/layout/Container.stories.svelte.d.ts +19 -0
  96. package/dist/components/layout/Container.svelte +52 -0
  97. package/dist/components/layout/Container.svelte.d.ts +14 -0
  98. package/dist/components/layout/Grid.stories.svelte +109 -0
  99. package/dist/components/layout/Grid.stories.svelte.d.ts +19 -0
  100. package/dist/components/layout/Grid.svelte +54 -0
  101. package/dist/components/layout/Grid.svelte.d.ts +19 -0
  102. package/dist/components/layout/Inline.stories.svelte +136 -0
  103. package/dist/components/layout/Inline.stories.svelte.d.ts +19 -0
  104. package/dist/components/layout/Inline.svelte +46 -0
  105. package/dist/components/layout/Inline.svelte.d.ts +19 -0
  106. package/dist/components/layout/Prose.stories.svelte +423 -0
  107. package/dist/components/layout/Prose.stories.svelte.d.ts +19 -0
  108. package/dist/components/layout/Prose.svelte +176 -0
  109. package/dist/components/layout/Prose.svelte.d.ts +12 -0
  110. package/dist/components/layout/Rule.stories.svelte +80 -0
  111. package/dist/components/layout/Rule.stories.svelte.d.ts +19 -0
  112. package/dist/components/layout/Rule.svelte +33 -0
  113. package/dist/components/layout/Rule.svelte.d.ts +9 -0
  114. package/dist/components/layout/Spread.stories.svelte +118 -0
  115. package/dist/components/layout/Spread.stories.svelte.d.ts +19 -0
  116. package/dist/components/layout/Spread.svelte +38 -0
  117. package/dist/components/layout/Spread.svelte.d.ts +16 -0
  118. package/dist/components/layout/Stack.stories.svelte +90 -0
  119. package/dist/components/layout/Stack.stories.svelte.d.ts +19 -0
  120. package/dist/components/layout/Stack.svelte +37 -0
  121. package/dist/components/layout/Stack.svelte.d.ts +16 -0
  122. package/dist/components/layout/index.d.ts +7 -0
  123. package/dist/components/layout/index.js +7 -0
  124. package/dist/components/navigation/Breadcrumb.stories.svelte +122 -0
  125. package/dist/components/navigation/Breadcrumb.stories.svelte.d.ts +19 -0
  126. package/dist/components/navigation/Breadcrumb.svelte +70 -0
  127. package/dist/components/navigation/Breadcrumb.svelte.d.ts +13 -0
  128. package/dist/components/navigation/Nav.stories.svelte +323 -0
  129. package/dist/components/navigation/Nav.stories.svelte.d.ts +19 -0
  130. package/dist/components/navigation/Nav.svelte +257 -0
  131. package/dist/components/navigation/Nav.svelte.d.ts +21 -0
  132. package/dist/components/navigation/index.d.ts +2 -0
  133. package/dist/components/navigation/index.js +2 -0
  134. package/dist/components/patterns/ActivityRow.stories.svelte +45 -0
  135. package/dist/components/patterns/ActivityRow.stories.svelte.d.ts +19 -0
  136. package/dist/components/patterns/ActivityRow.svelte +69 -0
  137. package/dist/components/patterns/ActivityRow.svelte.d.ts +16 -0
  138. package/dist/components/patterns/Alert.stories.svelte +63 -0
  139. package/dist/components/patterns/Alert.stories.svelte.d.ts +19 -0
  140. package/dist/components/patterns/Alert.svelte +91 -0
  141. package/dist/components/patterns/Alert.svelte.d.ts +16 -0
  142. package/dist/components/patterns/CtaBlock.stories.svelte +62 -0
  143. package/dist/components/patterns/CtaBlock.stories.svelte.d.ts +19 -0
  144. package/dist/components/patterns/CtaBlock.svelte +80 -0
  145. package/dist/components/patterns/CtaBlock.svelte.d.ts +16 -0
  146. package/dist/components/patterns/KvList.stories.svelte +48 -0
  147. package/dist/components/patterns/KvList.stories.svelte.d.ts +19 -0
  148. package/dist/components/patterns/KvList.svelte +65 -0
  149. package/dist/components/patterns/KvList.svelte.d.ts +15 -0
  150. package/dist/components/patterns/PageHero.stories.svelte +62 -0
  151. package/dist/components/patterns/PageHero.stories.svelte.d.ts +19 -0
  152. package/dist/components/patterns/PageHero.svelte +62 -0
  153. package/dist/components/patterns/PageHero.svelte.d.ts +14 -0
  154. package/dist/components/patterns/ProgressBar.stories.svelte +83 -0
  155. package/dist/components/patterns/ProgressBar.stories.svelte.d.ts +19 -0
  156. package/dist/components/patterns/ProgressBar.svelte +71 -0
  157. package/dist/components/patterns/ProgressBar.svelte.d.ts +13 -0
  158. package/dist/components/patterns/SectionFoot.stories.svelte +37 -0
  159. package/dist/components/patterns/SectionFoot.stories.svelte.d.ts +19 -0
  160. package/dist/components/patterns/SectionFoot.svelte +70 -0
  161. package/dist/components/patterns/SectionFoot.svelte.d.ts +15 -0
  162. package/dist/components/patterns/SectionHead.stories.svelte +67 -0
  163. package/dist/components/patterns/SectionHead.stories.svelte.d.ts +19 -0
  164. package/dist/components/patterns/SectionHead.svelte +54 -0
  165. package/dist/components/patterns/SectionHead.svelte.d.ts +14 -0
  166. package/dist/components/patterns/StatCard.stories.svelte +59 -0
  167. package/dist/components/patterns/StatCard.stories.svelte.d.ts +19 -0
  168. package/dist/components/patterns/StatCard.svelte +57 -0
  169. package/dist/components/patterns/StatCard.svelte.d.ts +15 -0
  170. package/dist/components/patterns/index.d.ts +9 -0
  171. package/dist/components/patterns/index.js +9 -0
  172. package/dist/components/primitives/Button.stories.svelte +132 -0
  173. package/dist/components/primitives/Button.stories.svelte.d.ts +19 -0
  174. package/dist/components/primitives/Button.svelte +142 -0
  175. package/dist/components/primitives/Button.svelte.d.ts +16 -0
  176. package/dist/components/primitives/Heading.stories.svelte +137 -0
  177. package/dist/components/primitives/Heading.stories.svelte.d.ts +19 -0
  178. package/dist/components/primitives/Heading.svelte +107 -0
  179. package/dist/components/primitives/Heading.svelte.d.ts +23 -0
  180. package/dist/components/primitives/Led.stories.svelte +63 -0
  181. package/dist/components/primitives/Led.stories.svelte.d.ts +19 -0
  182. package/dist/components/primitives/Led.svelte +65 -0
  183. package/dist/components/primitives/Led.svelte.d.ts +11 -0
  184. package/dist/components/primitives/TagPill.stories.svelte +90 -0
  185. package/dist/components/primitives/TagPill.stories.svelte.d.ts +19 -0
  186. package/dist/components/primitives/TagPill.svelte +44 -0
  187. package/dist/components/primitives/TagPill.svelte.d.ts +9 -0
  188. package/dist/components/primitives/Text.stories.svelte +252 -0
  189. package/dist/components/primitives/Text.stories.svelte.d.ts +19 -0
  190. package/dist/components/primitives/Text.svelte +101 -0
  191. package/dist/components/primitives/Text.svelte.d.ts +25 -0
  192. package/dist/components/primitives/index.d.ts +5 -0
  193. package/dist/components/primitives/index.js +5 -0
  194. package/dist/index.d.ts +10 -0
  195. package/dist/index.js +10 -0
  196. package/dist/stores/toast.d.ts +19 -0
  197. package/dist/stores/toast.js +22 -0
  198. package/dist/storybook-utils.d.ts +11 -0
  199. package/dist/storybook-utils.js +29 -0
  200. package/dist/tokens/ColorSwatch.svelte +73 -0
  201. package/dist/tokens/ColorSwatch.svelte.d.ts +10 -0
  202. package/dist/tokens/layout.css +144 -0
  203. package/dist/tokens/patterns.css +281 -0
  204. package/dist/tokens/tokens.css +96 -0
  205. package/dist/tokens/tokens.stories.svelte +107 -0
  206. package/dist/tokens/tokens.stories.svelte.d.ts +18 -0
  207. package/dist/tokens/typography.css +159 -0
  208. package/package.json +62 -0
@@ -0,0 +1,252 @@
1
+ <script module lang="ts">
2
+ import { defineMeta } from "@storybook/addon-svelte-csf";
3
+ import { expect, within } from "storybook/test";
4
+ import Text from "./Text.svelte";
5
+
6
+ const { Story } = defineMeta({
7
+ title: "Primitives/Text",
8
+ component: Text,
9
+ tags: ["autodocs"],
10
+ });
11
+ </script>
12
+
13
+ <!-- AC-4: variant="body" renders <p class="body-text"> -->
14
+ <!-- AC-9: default variant renders body-text -->
15
+ <Story name="Body" args={{ variant: "body" }}
16
+ play={async ({ canvasElement }) => {
17
+ const root = canvasElement.firstElementChild!;
18
+ await expect(root.tagName).toBe("P");
19
+ await expect(root.classList.contains("body-text")).toBe(true);
20
+ }}>
21
+ The quick brown fox jumps over the lazy dog.
22
+ </Story>
23
+
24
+ <!-- AC-5: variant="lede" renders <p class="body-lede"> -->
25
+ <Story name="Lede" args={{ variant: "lede" }}
26
+ play={async ({ canvasElement }) => {
27
+ const root = canvasElement.firstElementChild!;
28
+ await expect(root.tagName).toBe("P");
29
+ await expect(root.classList.contains("body-lede")).toBe(true);
30
+ }}>
31
+ A brief but compelling opening paragraph that sets the stage.
32
+ </Story>
33
+
34
+ <!-- AC-6: variant="mono" renders <span class="mono-label"> -->
35
+ <Story name="Mono" args={{ variant: "mono" }}
36
+ play={async ({ canvasElement }) => {
37
+ const root = canvasElement.firstElementChild!;
38
+ await expect(root.tagName).toBe("SPAN");
39
+ await expect(root.classList.contains("mono-label")).toBe(true);
40
+ await expect(getComputedStyle(root).textTransform).toBe("uppercase");
41
+ }}>
42
+ READ →
43
+ </Story>
44
+
45
+ <!-- AC-7: variant="eyebrow" renders <span class="eyebrow"> -->
46
+ <Story name="Eyebrow" args={{ variant: "eyebrow" }}
47
+ play={async ({ canvasElement }) => {
48
+ const root = canvasElement.firstElementChild!;
49
+ await expect(root.tagName).toBe("SPAN");
50
+ await expect(root.classList.contains("eyebrow")).toBe(true);
51
+ await expect(getComputedStyle(root).textTransform).toBe("uppercase");
52
+ }}>
53
+ Category
54
+ </Story>
55
+
56
+ <!-- AC-10 through AC-14: color prop maps to inline CSS custom properties -->
57
+ <Story name="Colors" args={{ variant: "body" }}
58
+ play={async ({ canvasElement }) => {
59
+ const canvas = within(canvasElement);
60
+
61
+ const inkEl = canvas.getByTestId("color-ink");
62
+ await expect(inkEl.getAttribute("style")).toContain("var(--ink)");
63
+
64
+ const dimEl = canvas.getByTestId("color-dim");
65
+ await expect(dimEl.getAttribute("style")).toContain("var(--ink-dim)");
66
+
67
+ const faintEl = canvas.getByTestId("color-faint");
68
+ await expect(faintEl.getAttribute("style")).toContain("var(--ink-faint)");
69
+
70
+ const amberEl = canvas.getByTestId("color-amber");
71
+ await expect(amberEl.getAttribute("style")).toContain("var(--amber)");
72
+
73
+ const cyanEl = canvas.getByTestId("color-cyan");
74
+ await expect(cyanEl.getAttribute("style")).toContain("var(--cyan)");
75
+
76
+ const okEl = canvas.getByTestId("color-ok");
77
+ await expect(okEl.getAttribute("style")).toContain("var(--ok)");
78
+
79
+ const dangerEl = canvas.getByTestId("color-danger");
80
+ await expect(dangerEl.getAttribute("style")).toContain("var(--danger)");
81
+
82
+ const noColorEl = canvas.getByTestId("color-none");
83
+ const styleAttr = noColorEl.getAttribute("style");
84
+ await expect(!styleAttr || !styleAttr.includes("color:")).toBe(true);
85
+ }}>
86
+ <Text color="ink" data-testid="color-ink">Ink text</Text>
87
+ <Text color="dim" data-testid="color-dim">Dim text</Text>
88
+ <Text color="faint" data-testid="color-faint">Faint text</Text>
89
+ <Text color="amber" data-testid="color-amber">Amber text</Text>
90
+ <Text color="cyan" data-testid="color-cyan">Cyan text</Text>
91
+ <Text color="ok" data-testid="color-ok">OK text</Text>
92
+ <Text color="danger" data-testid="color-danger">Danger text</Text>
93
+ <Text data-testid="color-none">No color</Text>
94
+ </Story>
95
+
96
+ <!-- AC-8: as prop overrides default tag -->
97
+ <Story name="PolymorphicAs" args={{ variant: "body", as: "span" }}
98
+ play={async ({ canvasElement }) => {
99
+ const root = canvasElement.firstElementChild!;
100
+ await expect(root.tagName).toBe("SPAN");
101
+ await expect(root.classList.contains("body-text")).toBe(true);
102
+ }}>
103
+ Inline body text rendered as span.
104
+ </Story>
105
+
106
+ <!-- AC-15: extra class is merged alongside variant class -->
107
+ <!-- AC-16: data attributes are forwarded -->
108
+ <Story name="ClassMerge" args={{ variant: "mono", class: "my-class", "data-testid": "probe" }}
109
+ play={async ({ canvasElement }) => {
110
+ const root = canvasElement.firstElementChild!;
111
+ await expect(root.classList.contains("mono-label")).toBe(true);
112
+ await expect(root.classList.contains("my-class")).toBe(true);
113
+ await expect(root.getAttribute("data-testid")).toBe("probe");
114
+ }}>
115
+ Merged classes
116
+ </Story>
117
+
118
+ <!-- AC-9: no variant prop defaults to body-text on <p> -->
119
+ <Story name="DefaultVariant"
120
+ play={async ({ canvasElement }) => {
121
+ const root = canvasElement.firstElementChild!;
122
+ await expect(root.tagName).toBe("P");
123
+ await expect(root.classList.contains("body-text")).toBe(true);
124
+ }}>
125
+ Default variant text.
126
+ </Story>
127
+
128
+ <!-- B26 AC-3, AC-17: size="xs" on mono → 12px, data-size="xs" present -->
129
+ <Story name="SizeXs" args={{ variant: "mono", size: "xs" }}
130
+ play={async ({ canvasElement }) => {
131
+ const el = canvasElement.firstElementChild!;
132
+ await expect(el.getAttribute("data-size")).toBe("xs");
133
+ await expect(getComputedStyle(el).fontSize).toBe("12px");
134
+ }}>
135
+ Micro label
136
+ </Story>
137
+
138
+ <!-- B26 AC-4: size="sm" on mono → 14px -->
139
+ <Story name="SizeSm" args={{ variant: "mono", size: "sm" }}
140
+ play={async ({ canvasElement }) => {
141
+ const el = canvasElement.firstElementChild!;
142
+ await expect(el.getAttribute("data-size")).toBe("sm");
143
+ await expect(getComputedStyle(el).fontSize).toBe("14px");
144
+ }}>
145
+ Small label
146
+ </Story>
147
+
148
+ <!-- B26 AC-5, AC-41: size="md" on mono → 16px -->
149
+ <Story name="SizeMd" args={{ variant: "mono", size: "md" }}
150
+ play={async ({ canvasElement }) => {
151
+ const el = canvasElement.firstElementChild!;
152
+ await expect(el.getAttribute("data-size")).toBe("md");
153
+ await expect(getComputedStyle(el).fontSize).toBe("16px");
154
+ }}>
155
+ Medium mono text.
156
+ </Story>
157
+
158
+ <!-- B26 AC-6: size="lg" on lede → 19px -->
159
+ <Story name="SizeLg" args={{ variant: "lede", size: "lg" }}
160
+ play={async ({ canvasElement }) => {
161
+ const el = canvasElement.firstElementChild!;
162
+ await expect(el.getAttribute("data-size")).toBe("lg");
163
+ await expect(getComputedStyle(el).fontSize).toBe("19px");
164
+ }}>
165
+ Large lede text.
166
+ </Story>
167
+
168
+ <!-- B26 AC-7, AC-41: size="xl" on body → 24px -->
169
+ <Story name="SizeXl" args={{ variant: "body", size: "xl" }}
170
+ play={async ({ canvasElement }) => {
171
+ const el = canvasElement.firstElementChild!;
172
+ await expect(el.getAttribute("data-size")).toBe("xl");
173
+ await expect(getComputedStyle(el).fontSize).toBe("24px");
174
+ }}>
175
+ Extra-large body text.
176
+ </Story>
177
+
178
+ <!-- B26 AC-8: natural defaults — no size prop → variant's natural font-size -->
179
+ <Story name="NaturalDefaults" args={{ variant: "body" }}
180
+ play={async ({ canvasElement }) => {
181
+ const canvas = within(canvasElement);
182
+ const eyebrow = canvas.getByTestId("natural-eyebrow");
183
+ await expect(getComputedStyle(eyebrow).fontSize).toBe("12px");
184
+ const mono = canvas.getByTestId("natural-mono");
185
+ await expect(getComputedStyle(mono).fontSize).toBe("14px");
186
+ const body = canvas.getByTestId("natural-body");
187
+ await expect(getComputedStyle(body).fontSize).toBe("16px");
188
+ const lede = canvas.getByTestId("natural-lede");
189
+ await expect(getComputedStyle(lede).fontSize).toBe("19px");
190
+ }}>
191
+ <Text variant="eyebrow" data-testid="natural-eyebrow">Eyebrow</Text>
192
+ <Text variant="mono" data-testid="natural-mono">Mono</Text>
193
+ <Text variant="body" data-testid="natural-body">Body</Text>
194
+ <Text variant="lede" data-testid="natural-lede">Lede</Text>
195
+ </Story>
196
+
197
+ <!-- B26 AC-9: size overrides font-size only; other variant properties (letterSpacing, textTransform) preserved -->
198
+ <Story name="SizePreservesVariant" args={{ variant: "eyebrow", size: "lg" }}
199
+ play={async ({ canvasElement }) => {
200
+ const el = canvasElement.firstElementChild!;
201
+ await expect(getComputedStyle(el).fontSize).toBe("19px");
202
+ await expect(getComputedStyle(el).letterSpacing).toBe("2.28px");
203
+ await expect(getComputedStyle(el).textTransform).toBe("uppercase");
204
+ }}>
205
+ Eyebrow at lede size
206
+ </Story>
207
+
208
+ <!-- B26 AC-20, AC-42: case="none" suppresses uppercase on mono -->
209
+ <Story name="CaseNone" args={{ variant: "mono", case: "none" }}
210
+ play={async ({ canvasElement }) => {
211
+ const el = canvasElement.firstElementChild!;
212
+ await expect(el.getAttribute("data-case")).toBe("none");
213
+ await expect(getComputedStyle(el).textTransform).toBe("none");
214
+ }}>
215
+ not uppercase
216
+ </Story>
217
+
218
+ <!-- B26 AC-18, AC-42: case="lower" produces lowercase -->
219
+ <Story name="CaseLower" args={{ variant: "mono", case: "lower" }}
220
+ play={async ({ canvasElement }) => {
221
+ const el = canvasElement.firstElementChild!;
222
+ await expect(el.getAttribute("data-case")).toBe("lower");
223
+ await expect(getComputedStyle(el).textTransform).toBe("lowercase");
224
+ }}>
225
+ lowercase label
226
+ </Story>
227
+
228
+ <!-- B26 AC-19, AC-42: case="upper" produces uppercase on body variant -->
229
+ <Story name="CaseUpper" args={{ variant: "body", case: "upper" }}
230
+ play={async ({ canvasElement }) => {
231
+ const el = canvasElement.firstElementChild!;
232
+ await expect(el.getAttribute("data-case")).toBe("upper");
233
+ await expect(getComputedStyle(el).textTransform).toBe("uppercase");
234
+ }}>
235
+ Uppercased body text.
236
+ </Story>
237
+
238
+ <!-- B26 AC-21: mono and eyebrow default to uppercase; body defaults to none (no case prop) -->
239
+ <Story name="DefaultCase" args={{ variant: "body" }}
240
+ play={async ({ canvasElement }) => {
241
+ const canvas = within(canvasElement);
242
+ const monoEl = canvas.getByTestId("default-case-mono");
243
+ await expect(getComputedStyle(monoEl).textTransform).toBe("uppercase");
244
+ const bodyEl = canvas.getByTestId("default-case-body");
245
+ await expect(getComputedStyle(bodyEl).textTransform).toBe("none");
246
+ const eyebrowEl = canvas.getByTestId("default-case-eyebrow");
247
+ await expect(getComputedStyle(eyebrowEl).textTransform).toBe("uppercase");
248
+ }}>
249
+ <Text variant="mono" data-testid="default-case-mono">Mono default</Text>
250
+ <Text variant="body" data-testid="default-case-body">Body default</Text>
251
+ <Text variant="eyebrow" data-testid="default-case-eyebrow">Eyebrow</Text>
252
+ </Story>
@@ -0,0 +1,19 @@
1
+ import Text from "./Text.svelte";
2
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
+ $$bindings?: Bindings;
5
+ } & Exports;
6
+ (internal: unknown, props: {
7
+ $$events?: Events;
8
+ $$slots?: Slots;
9
+ }): Exports & {
10
+ $set?: any;
11
+ $on?: any;
12
+ };
13
+ z_$$bindings?: Bindings;
14
+ }
15
+ declare const Text: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, {}, string>;
18
+ type Text = InstanceType<typeof Text>;
19
+ export default Text;
@@ -0,0 +1,101 @@
1
+ <script lang="ts">
2
+ import type { ClassValue } from 'svelte/elements'
3
+ import type { Snippet } from 'svelte'
4
+
5
+ type TextVariant = 'body' | 'lede' | 'mono' | 'eyebrow'
6
+ type TextColor = 'ink' | 'dim' | 'faint' | 'amber' | 'cyan' | 'ok' | 'danger'
7
+ type SizeVariant = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
8
+ type CaseVariant = 'upper' | 'lower' | 'none'
9
+
10
+ interface Props {
11
+ /** Typography style to apply. @default 'body' */
12
+ variant?: TextVariant
13
+ /** Text colour mapped to a design token. */
14
+ color?: TextColor
15
+ /** Font size override mapped to a type-scale token. */
16
+ size?: SizeVariant
17
+ /** Text transform override. */
18
+ case?: CaseVariant
19
+ /** HTML element to render as — overrides the variant default. */
20
+ as?: string
21
+ children?: Snippet
22
+ class?: ClassValue | null
23
+ style?: string | null
24
+ [key: string]: unknown
25
+ }
26
+
27
+ const DEFAULT_TAG: Record<TextVariant, string> = {
28
+ body: 'p',
29
+ lede: 'p',
30
+ mono: 'span',
31
+ eyebrow: 'span',
32
+ }
33
+
34
+ const VARIANT_CLASS: Record<TextVariant, string> = {
35
+ body: 'body-text',
36
+ lede: 'body-lede',
37
+ mono: 'mono-label',
38
+ eyebrow: 'eyebrow',
39
+ }
40
+
41
+ const COLOR_MAP: Record<NonNullable<TextColor>, string> = {
42
+ ink: 'ink',
43
+ dim: 'ink-dim',
44
+ faint: 'ink-faint',
45
+ amber: 'amber',
46
+ cyan: 'cyan',
47
+ ok: 'ok',
48
+ danger: 'danger',
49
+ }
50
+
51
+ let { variant = 'body', color, size, case: textCase, as, children, class: klass = '', style, ...rest }: Props = $props()
52
+
53
+ const resolvedAs = $derived(as ?? DEFAULT_TAG[variant])
54
+ const colorStyle = $derived(color ? `color: var(--${COLOR_MAP[color]});` : '')
55
+ const mergedStyle = $derived([colorStyle, style].filter(Boolean).join(' ') || undefined)
56
+ </script>
57
+
58
+ <svelte:element this={resolvedAs} class={[VARIANT_CLASS[variant], klass]} style={mergedStyle} data-size={size || undefined} data-case={textCase || undefined} {...rest}>
59
+ {@render children?.()}
60
+ </svelte:element>
61
+
62
+ <style>
63
+ .body-text {
64
+ font-family: var(--sans);
65
+ font-size: var(--t-body);
66
+ line-height: 1.65;
67
+ }
68
+
69
+ .body-lede {
70
+ font-family: var(--sans);
71
+ font-size: var(--t-lede);
72
+ line-height: 1.55;
73
+ color: var(--ink-dim);
74
+ }
75
+
76
+ .mono-label {
77
+ font-family: var(--mono);
78
+ font-size: var(--t-mono);
79
+ letter-spacing: 0.08em;
80
+ text-transform: uppercase;
81
+ color: var(--ink-dim);
82
+ }
83
+
84
+ .eyebrow {
85
+ font-family: var(--mono);
86
+ font-size: var(--t-micro);
87
+ letter-spacing: 0.12em;
88
+ color: var(--ink-faint);
89
+ text-transform: uppercase;
90
+ }
91
+
92
+ [data-size="xs"] { font-size: var(--t-micro) }
93
+ [data-size="sm"] { font-size: var(--t-mono) }
94
+ [data-size="md"] { font-size: var(--t-body) }
95
+ [data-size="lg"] { font-size: var(--t-lede) }
96
+ [data-size="xl"] { font-size: var(--t-h3) }
97
+
98
+ [data-case="upper"] { text-transform: uppercase }
99
+ [data-case="lower"] { text-transform: lowercase }
100
+ [data-case="none"] { text-transform: none }
101
+ </style>
@@ -0,0 +1,25 @@
1
+ import type { ClassValue } from 'svelte/elements';
2
+ import type { Snippet } from 'svelte';
3
+ type TextVariant = 'body' | 'lede' | 'mono' | 'eyebrow';
4
+ type TextColor = 'ink' | 'dim' | 'faint' | 'amber' | 'cyan' | 'ok' | 'danger';
5
+ type SizeVariant = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
6
+ type CaseVariant = 'upper' | 'lower' | 'none';
7
+ interface Props {
8
+ /** Typography style to apply. @default 'body' */
9
+ variant?: TextVariant;
10
+ /** Text colour mapped to a design token. */
11
+ color?: TextColor;
12
+ /** Font size override mapped to a type-scale token. */
13
+ size?: SizeVariant;
14
+ /** Text transform override. */
15
+ case?: CaseVariant;
16
+ /** HTML element to render as — overrides the variant default. */
17
+ as?: string;
18
+ children?: Snippet;
19
+ class?: ClassValue | null;
20
+ style?: string | null;
21
+ [key: string]: unknown;
22
+ }
23
+ declare const Text: import("svelte").Component<Props, {}, "">;
24
+ type Text = ReturnType<typeof Text>;
25
+ export default Text;
@@ -0,0 +1,5 @@
1
+ export { default as Button } from './Button.svelte';
2
+ export { default as Led } from './Led.svelte';
3
+ export { default as TagPill } from './TagPill.svelte';
4
+ export { default as Text } from './Text.svelte';
5
+ export { default as Heading } from './Heading.svelte';
@@ -0,0 +1,5 @@
1
+ export { default as Button } from './Button.svelte';
2
+ export { default as Led } from './Led.svelte';
3
+ export { default as TagPill } from './TagPill.svelte';
4
+ export { default as Text } from './Text.svelte';
5
+ export { default as Heading } from './Heading.svelte';
@@ -0,0 +1,10 @@
1
+ export { Button, Led, TagPill, Text, Heading } from './components/primitives/index.js';
2
+ export { Stack, Inline, Spread, Grid, Container, Rule, Prose } from './components/layout/index.js';
3
+ export { Card, ProductCard, ProjectCard, NoteCard } from './components/cards/index.js';
4
+ export { Nav, Breadcrumb } from './components/navigation/index.js';
5
+ export { Input, Textarea, Select, InputWrap, Field, Checkbox, Radio, RadioGroup, Switch } from './components/forms/index.js';
6
+ export { Modal, Toast, ToastRegion } from './components/feedback/index.js';
7
+ export { toast } from './stores/toast.js';
8
+ export type { ToastItem, ToastVariant, ToastOptions } from './stores/toast.js';
9
+ export { Alert, CtaBlock, StatCard, KvList, ProgressBar, ActivityRow, SectionHead, SectionFoot, PageHero } from './components/patterns/index.js';
10
+ export { Accordion, AccordionItem, Tabs, Table } from './components/data/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ // Component exports — populated as components are built through the backlog
2
+ export { Button, Led, TagPill, Text, Heading } from './components/primitives/index.js';
3
+ export { Stack, Inline, Spread, Grid, Container, Rule, Prose } from './components/layout/index.js';
4
+ export { Card, ProductCard, ProjectCard, NoteCard } from './components/cards/index.js';
5
+ export { Nav, Breadcrumb } from './components/navigation/index.js';
6
+ export { Input, Textarea, Select, InputWrap, Field, Checkbox, Radio, RadioGroup, Switch } from './components/forms/index.js';
7
+ export { Modal, Toast, ToastRegion } from './components/feedback/index.js';
8
+ export { toast } from './stores/toast.js';
9
+ export { Alert, CtaBlock, StatCard, KvList, ProgressBar, ActivityRow, SectionHead, SectionFoot, PageHero } from './components/patterns/index.js';
10
+ export { Accordion, AccordionItem, Tabs, Table } from './components/data/index.js';
@@ -0,0 +1,19 @@
1
+ export type ToastVariant = "success" | "warning" | "error";
2
+ export interface ToastItem {
3
+ id: string;
4
+ message: string;
5
+ variant: ToastVariant;
6
+ duration: number;
7
+ }
8
+ export interface ToastOptions {
9
+ variant?: ToastVariant;
10
+ duration?: number;
11
+ }
12
+ declare function push(message: string, options?: ToastOptions): string;
13
+ declare function dismiss(id: string): void;
14
+ export declare const toast: {
15
+ subscribe: (this: void, run: import("svelte/store").Subscriber<ToastItem[]>, invalidate?: () => void) => import("svelte/store").Unsubscriber;
16
+ push: typeof push;
17
+ dismiss: typeof dismiss;
18
+ };
19
+ export {};
@@ -0,0 +1,22 @@
1
+ import { writable } from "svelte/store";
2
+ const _store = writable([]);
3
+ let _idCounter = 0;
4
+ function push(message, options) {
5
+ const id = `toast-${++_idCounter}`;
6
+ const item = {
7
+ id,
8
+ message,
9
+ variant: options?.variant ?? "success",
10
+ duration: options?.duration ?? 5000,
11
+ };
12
+ _store.update((items) => [...items, item]);
13
+ return id;
14
+ }
15
+ function dismiss(id) {
16
+ _store.update((items) => items.filter((t) => t.id !== id));
17
+ }
18
+ export const toast = {
19
+ subscribe: _store.subscribe,
20
+ push,
21
+ dismiss,
22
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Resolves a CSS custom property to its computed background-color RGB string.
3
+ * Use for token comparisons that need a background channel
4
+ * (background-color, border-color).
5
+ */
6
+ export declare function resolveTokenColor(token: string): string;
7
+ /**
8
+ * Resolves a CSS custom property to its computed foreground color RGB string.
9
+ * Use for color/border-color comparisons.
10
+ */
11
+ export declare function resolveTokenFgColor(token: string): string;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Resolves a CSS custom property to its computed background-color RGB string.
3
+ * Use for token comparisons that need a background channel
4
+ * (background-color, border-color).
5
+ */
6
+ export function resolveTokenColor(token) {
7
+ const el = document.createElement('div');
8
+ el.style.backgroundColor = `var(${token})`;
9
+ el.style.position = 'absolute';
10
+ el.style.opacity = '0';
11
+ document.body.appendChild(el);
12
+ const value = getComputedStyle(el).backgroundColor;
13
+ document.body.removeChild(el);
14
+ return value;
15
+ }
16
+ /**
17
+ * Resolves a CSS custom property to its computed foreground color RGB string.
18
+ * Use for color/border-color comparisons.
19
+ */
20
+ export function resolveTokenFgColor(token) {
21
+ const el = document.createElement('div');
22
+ el.style.color = `var(${token})`;
23
+ el.style.position = 'absolute';
24
+ el.style.opacity = '0';
25
+ document.body.appendChild(el);
26
+ const value = getComputedStyle(el).color;
27
+ document.body.removeChild(el);
28
+ return value;
29
+ }
@@ -0,0 +1,73 @@
1
+ <script lang="ts">
2
+ interface TokenGroup {
3
+ label: string;
4
+ tokens: string[];
5
+ }
6
+
7
+ interface Props {
8
+ groups: TokenGroup[];
9
+ }
10
+
11
+ let { groups }: Props = $props();
12
+ </script>
13
+
14
+ <div class="swatch-root">
15
+ {#each groups as group}
16
+ <div class="swatch-group">
17
+ <p class="eyebrow">{group.label}</p>
18
+ <div class="swatch-row">
19
+ {#each group.tokens as token}
20
+ <div class="swatch-item">
21
+ <div
22
+ class="swatch-color"
23
+ data-testid={token}
24
+ style="background: var({token})"
25
+ ></div>
26
+ <span class="swatch-name">{token}</span>
27
+ </div>
28
+ {/each}
29
+ </div>
30
+ </div>
31
+ {/each}
32
+ </div>
33
+
34
+ <style>
35
+ .swatch-root {
36
+ padding: var(--u3);
37
+ background: var(--bg);
38
+ display: flex;
39
+ flex-direction: column;
40
+ gap: var(--u4);
41
+ }
42
+
43
+ .swatch-group {
44
+ display: flex;
45
+ flex-direction: column;
46
+ gap: var(--u2);
47
+ }
48
+
49
+ .swatch-row {
50
+ display: flex;
51
+ flex-wrap: wrap;
52
+ gap: var(--u2);
53
+ }
54
+
55
+ .swatch-item {
56
+ display: flex;
57
+ flex-direction: column;
58
+ gap: 6px;
59
+ }
60
+
61
+ .swatch-color {
62
+ width: 80px;
63
+ height: 48px;
64
+ border-radius: var(--radius-card);
65
+ border: 1px solid var(--rule);
66
+ }
67
+
68
+ .swatch-name {
69
+ font-family: var(--mono);
70
+ font-size: 11px;
71
+ color: var(--ink-dim);
72
+ }
73
+ </style>
@@ -0,0 +1,10 @@
1
+ interface TokenGroup {
2
+ label: string;
3
+ tokens: string[];
4
+ }
5
+ interface Props {
6
+ groups: TokenGroup[];
7
+ }
8
+ declare const ColorSwatch: import("svelte").Component<Props, {}, "">;
9
+ type ColorSwatch = ReturnType<typeof ColorSwatch>;
10
+ export default ColorSwatch;