@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,54 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte'
3
+ import Stack from '../layout/Stack.svelte'
4
+ import Inline from '../layout/Inline.svelte'
5
+ import Text from '../primitives/Text.svelte'
6
+ import Heading from '../primitives/Heading.svelte'
7
+
8
+ interface Props {
9
+ /** Small mono label shown above the heading. */
10
+ eyebrow?: string
11
+ /** Primary section heading. */
12
+ heading: string
13
+ /** Secondary label shown inline after the heading. */
14
+ sublabel?: string
15
+ children?: Snippet
16
+ [key: string]: unknown
17
+ }
18
+
19
+ let {
20
+ eyebrow,
21
+ heading,
22
+ sublabel,
23
+ children,
24
+ ...rest
25
+ }: Props = $props()
26
+ </script>
27
+
28
+ <section class="section-head" {...rest}>
29
+ <Stack gap="xs">
30
+ {#if eyebrow}
31
+ <Text variant="eyebrow">{eyebrow}</Text>
32
+ {/if}
33
+ <Inline gap="sm" align="baseline">
34
+ <Heading level={2} variant="h3">{heading}</Heading>
35
+ {#if sublabel}
36
+ <span class="sublabel"><Text variant="mono">{sublabel}</Text></span>
37
+ {/if}
38
+ </Inline>
39
+ {#if children}
40
+ {@render children()}
41
+ {/if}
42
+ </Stack>
43
+ </section>
44
+
45
+ <style>
46
+ .section-head {
47
+ padding: 40px 0 12px;
48
+ border-bottom: 1px solid var(--rule);
49
+ }
50
+
51
+ .sublabel {
52
+ margin-left: auto;
53
+ }
54
+ </style>
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ /** Small mono label shown above the heading. */
4
+ eyebrow?: string;
5
+ /** Primary section heading. */
6
+ heading: string;
7
+ /** Secondary label shown inline after the heading. */
8
+ sublabel?: string;
9
+ children?: Snippet;
10
+ [key: string]: unknown;
11
+ }
12
+ declare const SectionHead: import("svelte").Component<Props, {}, "">;
13
+ type SectionHead = ReturnType<typeof SectionHead>;
14
+ export default SectionHead;
@@ -0,0 +1,59 @@
1
+ <script module lang="ts">
2
+ import { defineMeta } from "@storybook/addon-svelte-csf";
3
+ import { expect, within } from "storybook/test";
4
+ import StatCard from "./StatCard.svelte";
5
+ import { resolveTokenFgColor } from "../../storybook-utils.js";
6
+
7
+ const { Story } = defineMeta({
8
+ title: "Patterns/StatCard",
9
+ component: StatCard,
10
+ tags: ["autodocs"],
11
+ });
12
+ </script>
13
+
14
+ <Story name="Default" args={{ label: "Modules", value: "12", sublabel: "across 2 cases" }}
15
+ play={async ({ canvasElement }) => {
16
+ const canvas = within(canvasElement);
17
+ const root = canvasElement.firstElementChild;
18
+ await expect(root).toBeVisible();
19
+ await expect(canvas.getByText("12")).toBeVisible();
20
+ await expect(canvas.getByText(/modules/i)).toBeVisible();
21
+ await expect(canvas.getByText(/across 2 cases/i)).toBeVisible();
22
+ const inkColor = resolveTokenFgColor("--ink");
23
+ await expect(getComputedStyle(canvas.getByText("12")).color).toBe(inkColor);
24
+ }} />
25
+
26
+ <Story name="Ok Color" args={{ label: "+12V draw", value: "68%", color: "ok", sublabel: "2.04A / 3.0A" }}
27
+ play={async ({ canvasElement }) => {
28
+ const canvas = within(canvasElement);
29
+ const okColor = resolveTokenFgColor("--ok");
30
+ await expect(getComputedStyle(canvas.getByText("68%")).color).toBe(okColor);
31
+ }} />
32
+
33
+ <Story name="Amber Color" args={{ label: "Orders open", value: "2", color: "amber", sublabel: "awaiting shipment" }}
34
+ play={async ({ canvasElement }) => {
35
+ const canvas = within(canvasElement);
36
+ const amberColor = resolveTokenFgColor("--amber");
37
+ await expect(getComputedStyle(canvas.getByText("2")).color).toBe(amberColor);
38
+ }} />
39
+
40
+ <Story name="Danger Color" args={{ label: "Thermal", value: "97%", color: "danger" }}
41
+ play={async ({ canvasElement }) => {
42
+ const canvas = within(canvasElement);
43
+ const dangerColor = resolveTokenFgColor("--danger");
44
+ await expect(getComputedStyle(canvas.getByText("97%")).color).toBe(dangerColor);
45
+ }} />
46
+
47
+ <Story name="No Sublabel" args={{ label: "Projects", value: "5" }}
48
+ play={async ({ canvasElement }) => {
49
+ await expect(canvasElement.querySelector(".stat-sub")).toBeNull();
50
+ }} />
51
+
52
+ <!-- B27 AC-17: Stack inside StatCard must have no style="padding: 16px 20px" attribute -->
53
+ <Story name="No Inline Padding Style" args={{ label: "Modules", value: "12" }}
54
+ play={async ({ canvasElement }) => {
55
+ // The Stack root inside the card carries style="padding: 16px 20px;" before B27.
56
+ // After B27 the padding moves to scoped CSS; the Stack must have no style= attribute.
57
+ const stackRoot = canvasElement.querySelector(".stack") as HTMLElement;
58
+ await expect(stackRoot.getAttribute("style")).toBeNull();
59
+ }} />
@@ -0,0 +1,19 @@
1
+ import StatCard from "./StatCard.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 StatCard: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, {}, string>;
18
+ type StatCard = InstanceType<typeof StatCard>;
19
+ export default StatCard;
@@ -0,0 +1,57 @@
1
+ <script lang="ts">
2
+ import Card from '../cards/Card.svelte'
3
+ import Stack from '../layout/Stack.svelte'
4
+ import Text from '../primitives/Text.svelte'
5
+
6
+ type StatColor = 'default' | 'ok' | 'amber' | 'danger'
7
+
8
+ interface Props {
9
+ /** Metric label shown above the value. */
10
+ label: string
11
+ /** Primary value string displayed large. */
12
+ value: string
13
+ /** Secondary label shown below the value. */
14
+ sublabel?: string
15
+ /** Colour accent applied to the value. @default 'default' */
16
+ color?: StatColor
17
+ [key: string]: unknown
18
+ }
19
+
20
+ let {
21
+ label,
22
+ value,
23
+ sublabel,
24
+ color = 'default',
25
+ ...rest
26
+ }: Props = $props()
27
+ </script>
28
+
29
+ <Card class="stat-card" {...rest}>
30
+ <div class="stat-card-body">
31
+ <Stack gap="xs">
32
+ <Text variant="mono" color="faint" size="xs">{label}</Text>
33
+ <span class="stat-value stat-value--{color}">{value}</span>
34
+ {#if sublabel}
35
+ <Text variant="mono" color="faint" size="xs">{sublabel}</Text>
36
+ {/if}
37
+ </Stack>
38
+ </div>
39
+ </Card>
40
+
41
+ <style>
42
+ .stat-card-body {
43
+ padding: 16px 20px;
44
+ }
45
+
46
+ .stat-value {
47
+ font-family: var(--mono);
48
+ font-size: 32px;
49
+ letter-spacing: -0.02em;
50
+ line-height: 1;
51
+ color: var(--ink);
52
+ }
53
+
54
+ .stat-value--ok { color: var(--ok); }
55
+ .stat-value--amber { color: var(--amber); }
56
+ .stat-value--danger { color: var(--danger); }
57
+ </style>
@@ -0,0 +1,15 @@
1
+ type StatColor = 'default' | 'ok' | 'amber' | 'danger';
2
+ interface Props {
3
+ /** Metric label shown above the value. */
4
+ label: string;
5
+ /** Primary value string displayed large. */
6
+ value: string;
7
+ /** Secondary label shown below the value. */
8
+ sublabel?: string;
9
+ /** Colour accent applied to the value. @default 'default' */
10
+ color?: StatColor;
11
+ [key: string]: unknown;
12
+ }
13
+ declare const StatCard: import("svelte").Component<Props, {}, "">;
14
+ type StatCard = ReturnType<typeof StatCard>;
15
+ export default StatCard;
@@ -0,0 +1,9 @@
1
+ export { default as Alert } from './Alert.svelte';
2
+ export { default as CtaBlock } from './CtaBlock.svelte';
3
+ export { default as StatCard } from './StatCard.svelte';
4
+ export { default as KvList } from './KvList.svelte';
5
+ export { default as ProgressBar } from './ProgressBar.svelte';
6
+ export { default as ActivityRow } from './ActivityRow.svelte';
7
+ export { default as SectionHead } from './SectionHead.svelte';
8
+ export { default as SectionFoot } from './SectionFoot.svelte';
9
+ export { default as PageHero } from './PageHero.svelte';
@@ -0,0 +1,9 @@
1
+ export { default as Alert } from './Alert.svelte';
2
+ export { default as CtaBlock } from './CtaBlock.svelte';
3
+ export { default as StatCard } from './StatCard.svelte';
4
+ export { default as KvList } from './KvList.svelte';
5
+ export { default as ProgressBar } from './ProgressBar.svelte';
6
+ export { default as ActivityRow } from './ActivityRow.svelte';
7
+ export { default as SectionHead } from './SectionHead.svelte';
8
+ export { default as SectionFoot } from './SectionFoot.svelte';
9
+ export { default as PageHero } from './PageHero.svelte';
@@ -0,0 +1,132 @@
1
+ <script module lang="ts">
2
+ import { defineMeta } from "@storybook/addon-svelte-csf";
3
+ import { expect, within } from "storybook/test";
4
+ import Button from "./Button.svelte";
5
+ import { resolveTokenColor, resolveTokenFgColor } from "../../storybook-utils.js";
6
+
7
+ const { Story } = defineMeta({
8
+ title: "Primitives/Button",
9
+ component: Button,
10
+ tags: ["autodocs"],
11
+ });
12
+ </script>
13
+
14
+ <Story name="Primary" args={{ variant: "primary" }}
15
+ play={async ({ canvasElement }) => {
16
+ const canvas = within(canvasElement);
17
+ const btn = canvas.getByRole("button");
18
+ await expect(btn).toBeVisible();
19
+ await expect(btn).toBeEnabled();
20
+ const amberColor = resolveTokenColor("--amber");
21
+ const bgColor = resolveTokenColor("--bg");
22
+ await expect(getComputedStyle(btn).backgroundColor).toBe(amberColor);
23
+ await expect(getComputedStyle(btn).color).toBe(bgColor);
24
+ await expect(getComputedStyle(btn).textTransform).toBe("uppercase");
25
+ }}>
26
+ Order Now
27
+ </Story>
28
+
29
+ <Story name="Primary Disabled" args={{ variant: "primary", disabled: true }}
30
+ play={async ({ canvasElement }) => {
31
+ const canvas = within(canvasElement);
32
+ const btn = canvas.getByRole("button");
33
+ await expect(btn).toBeVisible();
34
+ await expect(btn).toBeDisabled();
35
+ await expect(getComputedStyle(btn).opacity).toBe("0.5");
36
+ await expect(getComputedStyle(btn).cursor).toBe("not-allowed");
37
+ }}>
38
+ Disabled
39
+ </Story>
40
+
41
+ <Story name="CTA" args={{ variant: "cta" }}
42
+ play={async ({ canvasElement }) => {
43
+ const canvas = within(canvasElement);
44
+ const btn = canvas.getByRole("button");
45
+ await expect(btn).toBeVisible();
46
+ await expect(btn).toBeEnabled();
47
+ const amberColor = resolveTokenColor("--amber");
48
+ await expect(getComputedStyle(btn).color).toBe(amberColor);
49
+ await expect(getComputedStyle(btn).borderColor).toBe(amberColor);
50
+ }}>
51
+ View Project →
52
+ </Story>
53
+
54
+ <Story name="CTA Disabled" args={{ variant: "cta", disabled: true }}
55
+ play={async ({ canvasElement }) => {
56
+ const canvas = within(canvasElement);
57
+ const btn = canvas.getByRole("button");
58
+ await expect(btn).toBeVisible();
59
+ await expect(btn).toBeDisabled();
60
+ await expect(getComputedStyle(btn).opacity).toBe("0.5");
61
+ }}>
62
+ Disabled
63
+ </Story>
64
+
65
+ <Story name="Ghost" args={{ variant: "ghost" }}
66
+ play={async ({ canvasElement }) => {
67
+ const canvas = within(canvasElement);
68
+ const btn = canvas.getByRole("button");
69
+ await expect(btn).toBeVisible();
70
+ await expect(btn).toBeEnabled();
71
+ await expect(getComputedStyle(btn).backgroundColor).toBe("rgba(0, 0, 0, 0)");
72
+ const amberColor = resolveTokenColor("--amber");
73
+ await expect(getComputedStyle(btn).color).toBe(amberColor);
74
+ }}>
75
+ View All Hardware →
76
+ </Story>
77
+
78
+ <Story name="Back" args={{ variant: "back" }}
79
+ play={async ({ canvasElement }) => {
80
+ const canvas = within(canvasElement);
81
+ const btn = canvas.getByRole("button");
82
+ await expect(btn).toBeVisible();
83
+ await expect(btn).toBeEnabled();
84
+ const inkFaintColor = resolveTokenColor("--ink-faint");
85
+ await expect(getComputedStyle(btn).color).toBe(inkFaintColor);
86
+ }}>
87
+ ← Back to Catalogue
88
+ </Story>
89
+
90
+ <Story name="Del" args={{ variant: "del" }}
91
+ play={async ({ canvasElement }) => {
92
+ const canvas = within(canvasElement);
93
+ const btn = canvas.getByRole("button");
94
+ await expect(btn).toBeVisible();
95
+ await expect(btn).toBeEnabled();
96
+ await expect(getComputedStyle(btn).borderStyle).not.toBe("none");
97
+ const inkFaintColor = resolveTokenColor("--ink-faint");
98
+ await expect(getComputedStyle(btn).color).toBe(inkFaintColor);
99
+ }}>
100
+ Remove
101
+ </Story>
102
+
103
+ <Story name="As Link" args={{ as: "a", href: "#demo", variant: "ghost" }}
104
+ play={async ({ canvasElement }) => {
105
+ const canvas = within(canvasElement);
106
+ const link = canvas.getByRole("link");
107
+ await expect(link).toBeVisible();
108
+ await expect(link).toHaveAttribute("href", "#demo");
109
+ await expect(link.tagName).toBe("A");
110
+ }}>
111
+ View Demo →
112
+ </Story>
113
+
114
+ <!-- AC-B28-1 (2,3,4) -->
115
+ <Story name="Nav Variant" args={{ variant: "nav" }}
116
+ play={async ({ canvasElement }) => {
117
+ const canvas = within(canvasElement);
118
+ const btn = canvas.getByRole("button");
119
+ await expect(btn).toBeVisible();
120
+
121
+ // AC-2: element has class btn-nav
122
+ await expect(btn.classList.contains("btn-nav")).toBe(true);
123
+
124
+ // AC-3: computed color matches --ink-faint
125
+ const inkFaintColor = resolveTokenFgColor("--ink-faint");
126
+ await expect(getComputedStyle(btn).color).toBe(inkFaintColor);
127
+
128
+ // AC-4: background-color is transparent
129
+ await expect(getComputedStyle(btn).backgroundColor).toBe("rgba(0, 0, 0, 0)");
130
+ }}>
131
+
132
+ </Story>
@@ -0,0 +1,19 @@
1
+ import Button from "./Button.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 Button: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, {}, string>;
18
+ type Button = InstanceType<typeof Button>;
19
+ export default Button;
@@ -0,0 +1,142 @@
1
+ <script lang="ts">
2
+ import type { HTMLButtonAttributes } from 'svelte/elements'
3
+ import type { Snippet } from 'svelte'
4
+
5
+ type ButtonVariant = 'primary' | 'cta' | 'ghost' | 'back' | 'del' | 'nav'
6
+
7
+ interface Props extends HTMLButtonAttributes {
8
+ /** HTML element or component to render as. @default 'button' */
9
+ as?: string
10
+ /** Visual style variant. @default 'primary' */
11
+ variant?: ButtonVariant
12
+ children?: Snippet
13
+ /** URL — pass to render as an `<a>` (set `as="a"` too). */
14
+ href?: string
15
+ [key: string]: unknown
16
+ }
17
+
18
+ let { as = 'button', variant = 'primary', children, class: klass = '', ...rest }: Props = $props()
19
+ </script>
20
+
21
+ <svelte:element this={as} class={['btn', `btn-${variant}`, klass]} {...rest}>
22
+ {@render children?.()}
23
+ </svelte:element>
24
+
25
+ <style>
26
+ .btn {
27
+ font-family: var(--mono);
28
+ text-transform: uppercase;
29
+ cursor: pointer;
30
+ white-space: nowrap;
31
+ transition:
32
+ background var(--transition),
33
+ color var(--transition),
34
+ border-color var(--transition);
35
+ border: none;
36
+ background: transparent;
37
+ display: inline-block;
38
+ text-decoration: none;
39
+ }
40
+
41
+ /* primary */
42
+ .btn-primary {
43
+ background: var(--amber);
44
+ color: var(--bg);
45
+ padding: 10px 16px;
46
+ font-size: 14px;
47
+ letter-spacing: 0.1em;
48
+ }
49
+
50
+ .btn-primary:hover {
51
+ background: var(--ink);
52
+ }
53
+
54
+ .btn-primary:disabled,
55
+ .btn-primary[disabled],
56
+ .btn-primary[aria-disabled="true"] {
57
+ opacity: 0.5;
58
+ cursor: not-allowed;
59
+ }
60
+
61
+ /* cta */
62
+ .btn-cta {
63
+ color: var(--amber);
64
+ border: 1px solid var(--amber);
65
+ border-radius: var(--radius);
66
+ background: transparent;
67
+ padding: 9px 20px;
68
+ font-size: 14px;
69
+ letter-spacing: 0.1em;
70
+ }
71
+
72
+ .btn-cta:hover {
73
+ background: var(--amber);
74
+ color: var(--bg);
75
+ }
76
+
77
+ .btn-cta:disabled,
78
+ .btn-cta[disabled],
79
+ .btn-cta[aria-disabled="true"] {
80
+ opacity: 0.5;
81
+ cursor: not-allowed;
82
+ }
83
+
84
+ /* ghost */
85
+ .btn-ghost {
86
+ color: var(--amber);
87
+ background: transparent;
88
+ border: none;
89
+ font-size: 14px;
90
+ letter-spacing: 0.08em;
91
+ }
92
+
93
+ .btn-ghost:hover {
94
+ color: var(--ink);
95
+ }
96
+
97
+ /* back */
98
+ .btn-back {
99
+ color: var(--ink-faint);
100
+ background: transparent;
101
+ border: none;
102
+ font-size: 14px;
103
+ letter-spacing: 0.08em;
104
+ }
105
+
106
+ .btn-back:hover {
107
+ color: var(--amber);
108
+ }
109
+
110
+ /* del */
111
+ .btn-del {
112
+ color: var(--ink-faint);
113
+ border: 1px solid var(--rule-strong);
114
+ border-radius: var(--radius);
115
+ background: transparent;
116
+ padding: 3px 7px;
117
+ font-size: 12px;
118
+ letter-spacing: 0.1em;
119
+ }
120
+
121
+ .btn-del:hover {
122
+ color: var(--danger);
123
+ border-color: var(--danger);
124
+ }
125
+
126
+ /* nav */
127
+ .btn-nav {
128
+ color: var(--ink-faint);
129
+ background: transparent;
130
+ border: none;
131
+ border-bottom: 1px solid transparent;
132
+ font-size: var(--t-body);
133
+ line-height: 1;
134
+ padding: 0 0 2px 0;
135
+ letter-spacing: 0;
136
+ }
137
+
138
+ .btn-nav:hover {
139
+ color: var(--ink);
140
+ border-bottom-color: var(--amber);
141
+ }
142
+ </style>
@@ -0,0 +1,16 @@
1
+ import type { HTMLButtonAttributes } from 'svelte/elements';
2
+ import type { Snippet } from 'svelte';
3
+ type ButtonVariant = 'primary' | 'cta' | 'ghost' | 'back' | 'del' | 'nav';
4
+ interface Props extends HTMLButtonAttributes {
5
+ /** HTML element or component to render as. @default 'button' */
6
+ as?: string;
7
+ /** Visual style variant. @default 'primary' */
8
+ variant?: ButtonVariant;
9
+ children?: Snippet;
10
+ /** URL — pass to render as an `<a>` (set `as="a"` too). */
11
+ href?: string;
12
+ [key: string]: unknown;
13
+ }
14
+ declare const Button: import("svelte").Component<Props, {}, "">;
15
+ type Button = ReturnType<typeof Button>;
16
+ export default Button;