@lyeve-labs/ui-kit 0.11.2 → 0.13.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 (101) hide show
  1. package/README.md +1 -1
  2. package/dist/components/AccordionItem.svelte +1 -1
  3. package/dist/components/Autocomplete.svelte +191 -125
  4. package/dist/components/Autocomplete.svelte.d.ts +29 -8
  5. package/dist/components/Button.svelte +26 -4
  6. package/dist/components/Card.svelte +61 -3
  7. package/dist/components/Card.svelte.d.ts +24 -2
  8. package/dist/components/Checkbox.svelte +174 -59
  9. package/dist/components/Checkbox.svelte.d.ts +20 -3
  10. package/dist/components/CheckboxGroup.svelte +162 -0
  11. package/dist/components/CheckboxGroup.svelte.d.ts +51 -0
  12. package/dist/components/Collapsible.svelte +142 -0
  13. package/dist/components/Collapsible.svelte.d.ts +32 -0
  14. package/dist/components/CopyButton.svelte +126 -0
  15. package/dist/components/CopyButton.svelte.d.ts +14 -0
  16. package/dist/components/DatePicker.svelte +48 -6
  17. package/dist/components/DateTimePicker.svelte +337 -0
  18. package/dist/components/DateTimePicker.svelte.d.ts +26 -0
  19. package/dist/components/DescriptionList.svelte +78 -0
  20. package/dist/components/DescriptionList.svelte.d.ts +34 -0
  21. package/dist/components/Drawer.svelte +15 -4
  22. package/dist/components/Field.svelte +104 -0
  23. package/dist/components/Field.svelte.d.ts +46 -0
  24. package/dist/components/FileInput.svelte +5 -2
  25. package/dist/components/FormMessage.svelte +85 -0
  26. package/dist/components/FormMessage.svelte.d.ts +11 -0
  27. package/dist/components/Input.svelte +1 -1
  28. package/dist/components/Label.svelte +7 -1
  29. package/dist/components/Label.svelte.d.ts +6 -0
  30. package/dist/components/Modal.svelte +25 -8
  31. package/dist/components/MultiSelect.svelte +199 -109
  32. package/dist/components/MultiSelect.svelte.d.ts +22 -9
  33. package/dist/components/NumberInput.svelte +8 -4
  34. package/dist/components/PageHeader.svelte +37 -4
  35. package/dist/components/PageHeader.svelte.d.ts +15 -0
  36. package/dist/components/PageShell.svelte +85 -0
  37. package/dist/components/PageShell.svelte.d.ts +38 -0
  38. package/dist/components/Pagination.svelte +58 -17
  39. package/dist/components/Panel.svelte +101 -0
  40. package/dist/components/Panel.svelte.d.ts +39 -0
  41. package/dist/components/PasswordInput.svelte +139 -0
  42. package/dist/components/PasswordInput.svelte.d.ts +29 -0
  43. package/dist/components/Radio.svelte +152 -32
  44. package/dist/components/Radio.svelte.d.ts +16 -1
  45. package/dist/components/RadioGroup.svelte +118 -71
  46. package/dist/components/RadioGroup.svelte.d.ts +39 -9
  47. package/dist/components/SectionHeading.svelte +39 -0
  48. package/dist/components/SectionHeading.svelte.d.ts +21 -0
  49. package/dist/components/SegmentedControl.svelte +194 -0
  50. package/dist/components/SegmentedControl.svelte.d.ts +55 -0
  51. package/dist/components/Select.svelte +471 -46
  52. package/dist/components/Select.svelte.d.ts +95 -6
  53. package/dist/components/SidebarNav.svelte +259 -0
  54. package/dist/components/SidebarNav.svelte.d.ts +17 -0
  55. package/dist/components/Stat.svelte +53 -2
  56. package/dist/components/Stat.svelte.d.ts +31 -0
  57. package/dist/components/Textarea.svelte +1 -1
  58. package/dist/components/TimePicker.svelte +480 -0
  59. package/dist/components/TimePicker.svelte.d.ts +23 -0
  60. package/dist/components/Toaster.svelte +9 -2
  61. package/dist/components/Toggle.svelte +5 -1
  62. package/dist/components/Toggle.svelte.d.ts +2 -0
  63. package/dist/components/Toolbar.svelte +39 -0
  64. package/dist/components/Toolbar.svelte.d.ts +26 -0
  65. package/dist/components/Tooltip.svelte +48 -12
  66. package/dist/components/TreeView.svelte +339 -0
  67. package/dist/components/TreeView.svelte.d.ts +37 -0
  68. package/dist/components/dialog/Dialog.svelte +15 -58
  69. package/dist/components/dialog/dialog-manager.svelte.d.ts +2 -2
  70. package/dist/components/dialog/dialog-manager.svelte.js +21 -21
  71. package/dist/index.d.ts +25 -1
  72. package/dist/index.js +20 -1
  73. package/dist/internal/calendar.d.ts +119 -0
  74. package/dist/internal/calendar.js +225 -0
  75. package/dist/internal/choice.d.ts +136 -0
  76. package/dist/internal/choice.js +179 -0
  77. package/dist/internal/field.d.ts +31 -0
  78. package/dist/internal/field.js +42 -1
  79. package/dist/internal/filter.d.ts +80 -0
  80. package/dist/internal/filter.js +80 -0
  81. package/dist/internal/layout.d.ts +119 -0
  82. package/dist/internal/layout.js +132 -0
  83. package/dist/internal/listbox.svelte.d.ts +77 -0
  84. package/dist/internal/listbox.svelte.js +438 -0
  85. package/dist/internal/nav-expansion.svelte.d.ts +36 -0
  86. package/dist/internal/nav-expansion.svelte.js +144 -0
  87. package/dist/internal/nav-tree.d.ts +68 -0
  88. package/dist/internal/nav-tree.js +102 -0
  89. package/dist/internal/overlay.d.ts +25 -0
  90. package/dist/internal/overlay.js +92 -0
  91. package/dist/internal/panel.d.ts +100 -0
  92. package/dist/internal/panel.js +109 -0
  93. package/dist/internal/rollup.d.ts +52 -0
  94. package/dist/internal/rollup.js +67 -0
  95. package/dist/internal/time.d.ts +103 -0
  96. package/dist/internal/time.js +166 -0
  97. package/dist/internal/tree.d.ts +86 -0
  98. package/dist/internal/tree.js +111 -0
  99. package/dist/styles/theme.css +66 -25
  100. package/package.json +4 -2
  101. package/src/lib/styles/theme.css +66 -25
@@ -36,6 +36,12 @@
36
36
  --color-surface: #101a2b;
37
37
  --color-surface-2: #162233;
38
38
  --color-line: #1e2d40;
39
+ /* line reads 1.25:1 against surface. That is fine for a divider, which
40
+ * carries no information, and fails SC 1.4.11 for anything whose boundary
41
+ * is the only thing identifying it as a control. Inputs, selects,
42
+ * checkboxes, radios and toggles use line-strong, which clears 3:1 on
43
+ * every surface in the palette. */
44
+ --color-line-strong: #616d80;
39
45
  --color-fg: #e6e8ee;
40
46
  --color-muted: #9aa1ad;
41
47
  /* #525866 failed WCAG AA against surface/ink (~2.5:1); every caption and
@@ -46,13 +52,24 @@
46
52
  --color-brand: #00d4ff;
47
53
  --color-brand-light: #5fd9f4;
48
54
  --color-brand-deep: #0099c4;
49
- --color-violet: #7c6aef;
55
+ /* #7c6aef reads 4.29:1 on surface and 3.83:1 inside its own bg-violet/10
56
+ * badge, both under the 4.5:1 floor. #9587f2 clears every surface the kit
57
+ * paints it on and the badge as well. */
58
+ --color-violet: #9587f2;
50
59
 
51
60
  /* #15803d and #b45309 sit at ~3.7:1 on ink, below the 4.5:1 AA floor
52
61
  * for the text-size status labels that use them. */
53
62
  --color-success: #22c55e;
54
63
  --color-warn: #f59e0b;
55
- --color-danger: #b91c1c;
64
+ /* #b91c1c reads 2.85:1 on ink and 2.61:1 inside bg-danger/10, so every
65
+ * form error message and every validation hint failed AA. A dark red
66
+ * cannot work as a foreground on a dark surface.
67
+ *
68
+ * One token serves both roles because it inverts with `ink`. As text on a
69
+ * dark surface #f87171 reads 6.30:1; as the fill behind a `text-ink` label
70
+ * on a filled destructive button it reads 6.67:1. The light palette does
71
+ * the same in reverse with a dark red and a near-white ink. */
72
+ --color-danger: #f87171;
56
73
 
57
74
  /* ── Radius ─────────────────────────────────────────────────── */
58
75
  --radius-xs: 4px;
@@ -80,13 +97,13 @@
80
97
  * Caption 13px 1.50 0 400 Labels, metadata *
81
98
  * Mono 18px 1.50 0 500 Code, eyebrows *
82
99
  * */
83
- --font-size-display: 4rem; /* 64px */
84
- --font-size-h1: 2.75rem; /* 44px */
85
- --font-size-h2: 2rem; /* 32px */
86
- --font-size-h3: 1.375rem; /* 22px */
87
- --font-size-body: 1rem; /* 16px */
88
- --font-size-caption: 0.8125rem; /* 13px */
89
- --font-size-mono: 1.125rem; /* 18px */
100
+ --text-display: 4rem; /* 64px */
101
+ --text-h1: 2.75rem; /* 44px */
102
+ --text-h2: 2rem; /* 32px */
103
+ --text-h3: 1.375rem; /* 22px */
104
+ --text-body: 1rem; /* 16px */
105
+ --text-caption: 0.8125rem; /* 13px */
106
+ --text-mono: 1.125rem; /* 18px */
90
107
 
91
108
  --leading-display: 1.05;
92
109
  --leading-h1: 1.1;
@@ -105,16 +122,24 @@
105
122
  * Tailwind's default 0.25rem (4px) grid is unchanged. *
106
123
  * These tokens add named slots for common component spacing. */
107
124
  --spacing-page-x: 1.5rem; /* 24px - page horizontal gutter */
108
- --spacing-page-y: 2rem; /* 32px - page vertical gutter */
109
- --spacing-card: 1.5rem; /* 24px - card inner padding */
125
+ --spacing-page-y: 1.5rem; /* 24px - page vertical gutter. Equal to page-x because no page
126
+ * measured renders an asymmetric gutter; the two names stay
127
+ * separate so one axis can move without dragging the other. */
128
+ --spacing-card: 1.25rem; /* 20px - card inner padding. 24px matched none of the card
129
+ * surfaces in use; 20px is their measured mode and Card's own md. */
110
130
  --spacing-card-sm: 1rem; /* 16px - compact card padding */
111
- --spacing-section: 3rem; /* 48px - section gap */
131
+ --spacing-section: 2rem; /* 32px - section gap. 48px matched nothing anywhere; 32px is the
132
+ * gap the pages that set one already use, and PageHeader's own. */
112
133
  --spacing-input-x: 0.75rem; /* 12px - input horizontal padding */
113
134
  --spacing-input-y: 0.5rem; /* 8px - input vertical padding */
114
135
  /* 38px - the height of every single-line control. Stated once so an Input,
115
136
  * a Select and a NumberInput sitting in the same row line up. Derived from
116
137
  * the 13px/1.25 control text plus input-y padding and a 1px border. */
117
138
  --spacing-control: 2.375rem;
139
+ --spacing-panel-max: 15rem; /* 240px - the scroll cap on a floating option list */
140
+ --spacing-nav-indent: 0.875rem; /* 14px - one level of sidebar nesting */
141
+ --spacing-nav-rail: 3.5rem; /* 56px - the collapsed icon rail */
142
+ --spacing-sidebar: 14rem; /* 224px - the expanded sidebar */
118
143
  --spacing-stack: 1rem; /* 16px - default vertical stack gap */
119
144
  --spacing-inline: 0.5rem; /* 8px - default inline gap */
120
145
  }
@@ -125,20 +150,30 @@ html[data-theme='light'] {
125
150
  --color-surface: #ffffff;
126
151
  --color-surface-2: #e6e8ee;
127
152
  --color-line: #d6d9e0;
153
+ --color-line-strong: #767d8e;
128
154
  --color-fg: #111827;
129
155
  --color-muted: #525866;
130
- /* #9aa1ad on white is ~3.1:1, below the 4.5:1 AA floor; #6b7280 sits
131
- * at ~4.8:1 while staying visually tertiary. */
132
- --color-faint: #6b7280;
133
-
134
- --color-brand: #007ea6;
135
- --color-brand-light: #00b4dd;
136
- --color-brand-deep: #006a8a;
137
- --color-violet: #6b5cdf;
138
-
139
- --color-success: #15803d;
140
- --color-warn: #b45309;
141
- --color-danger: #b91c1c;
156
+ /* Every value below is the lightest colour on its own hue that clears
157
+ * 4.5:1 against the worst background the kit actually paints it on. That
158
+ * worst case is rarely the bare canvas: status text and brand chips sit
159
+ * inside a tint of their own token (bg-warn/10 text-warn), and the tint
160
+ * drags the background toward the text. Values chosen against white alone
161
+ * fail inside the tint and on surface-2. */
162
+ --color-faint: #616774;
163
+
164
+ --color-brand: #005a77;
165
+ /* brand-light is the hover step for brand links and for the filled brand
166
+ * button. In a light theme emphasis reads as deeper, not lighter, so it
167
+ * sits below brand here and brand-deep below that. The names describe
168
+ * their place in the default dark ramp. #00b4dd put near-white text at
169
+ * 2.45:1 on the primary button's hover state. */
170
+ --color-brand-light: #004f69;
171
+ --color-brand-deep: #00455c;
172
+ --color-violet: #5544da;
173
+
174
+ --color-success: #126c34;
175
+ --color-warn: #904207;
176
+ --color-danger: #ab1a1a;
142
177
  }
143
178
 
144
179
  @layer base {
@@ -163,8 +198,14 @@ html[data-theme='light'] {
163
198
  background-color: color-mix(in srgb, var(--color-brand) 30%, transparent);
164
199
  }
165
200
 
201
+ /*
202
+ * SC 1.4.11 puts a 3:1 floor on the focus indicator. Mixing brand down to
203
+ * 60% alpha left it at 2.39:1 on the light palette, so the one affordance a
204
+ * keyboard user has for locating themselves was the element that failed.
205
+ * Solid brand reads 9.85:1 on dark and 7.70:1 on light.
206
+ */
166
207
  :focus-visible {
167
- outline: 2px solid color-mix(in srgb, var(--color-brand) 60%, transparent);
208
+ outline: 2px solid var(--color-brand);
168
209
  outline-offset: 2px;
169
210
  }
170
211
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyeve-labs/ui-kit",
3
- "version": "0.11.2",
3
+ "version": "0.13.0",
4
4
  "description": "A clean, accessible, palette-aware Svelte 5 component library. The design system behind LyEve.",
5
5
  "license": "MIT",
6
6
  "author": "LyEve Labs <hello@lyeve.com>",
@@ -23,7 +23,7 @@
23
23
  ],
24
24
  "type": "module",
25
25
  "sideEffects": false,
26
- "packageManager": "pnpm@10.33.4",
26
+ "packageManager": "pnpm@11.25.0",
27
27
  "engines": {
28
28
  "node": ">=20"
29
29
  },
@@ -37,6 +37,8 @@
37
37
  "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
38
38
  "test": "vitest run",
39
39
  "test:watch": "vitest",
40
+ "test:coverage": "vitest run --coverage",
41
+ "test:ct": "playwright test --config playwright-ct.config.ts",
40
42
  "format": "prettier --write .",
41
43
  "format:check": "prettier --check ."
42
44
  },
@@ -36,6 +36,12 @@
36
36
  --color-surface: #101a2b;
37
37
  --color-surface-2: #162233;
38
38
  --color-line: #1e2d40;
39
+ /* line reads 1.25:1 against surface. That is fine for a divider, which
40
+ * carries no information, and fails SC 1.4.11 for anything whose boundary
41
+ * is the only thing identifying it as a control. Inputs, selects,
42
+ * checkboxes, radios and toggles use line-strong, which clears 3:1 on
43
+ * every surface in the palette. */
44
+ --color-line-strong: #616d80;
39
45
  --color-fg: #e6e8ee;
40
46
  --color-muted: #9aa1ad;
41
47
  /* #525866 failed WCAG AA against surface/ink (~2.5:1); every caption and
@@ -46,13 +52,24 @@
46
52
  --color-brand: #00d4ff;
47
53
  --color-brand-light: #5fd9f4;
48
54
  --color-brand-deep: #0099c4;
49
- --color-violet: #7c6aef;
55
+ /* #7c6aef reads 4.29:1 on surface and 3.83:1 inside its own bg-violet/10
56
+ * badge, both under the 4.5:1 floor. #9587f2 clears every surface the kit
57
+ * paints it on and the badge as well. */
58
+ --color-violet: #9587f2;
50
59
 
51
60
  /* #15803d and #b45309 sit at ~3.7:1 on ink, below the 4.5:1 AA floor
52
61
  * for the text-size status labels that use them. */
53
62
  --color-success: #22c55e;
54
63
  --color-warn: #f59e0b;
55
- --color-danger: #b91c1c;
64
+ /* #b91c1c reads 2.85:1 on ink and 2.61:1 inside bg-danger/10, so every
65
+ * form error message and every validation hint failed AA. A dark red
66
+ * cannot work as a foreground on a dark surface.
67
+ *
68
+ * One token serves both roles because it inverts with `ink`. As text on a
69
+ * dark surface #f87171 reads 6.30:1; as the fill behind a `text-ink` label
70
+ * on a filled destructive button it reads 6.67:1. The light palette does
71
+ * the same in reverse with a dark red and a near-white ink. */
72
+ --color-danger: #f87171;
56
73
 
57
74
  /* ── Radius ─────────────────────────────────────────────────── */
58
75
  --radius-xs: 4px;
@@ -80,13 +97,13 @@
80
97
  * Caption 13px 1.50 0 400 Labels, metadata *
81
98
  * Mono 18px 1.50 0 500 Code, eyebrows *
82
99
  * */
83
- --font-size-display: 4rem; /* 64px */
84
- --font-size-h1: 2.75rem; /* 44px */
85
- --font-size-h2: 2rem; /* 32px */
86
- --font-size-h3: 1.375rem; /* 22px */
87
- --font-size-body: 1rem; /* 16px */
88
- --font-size-caption: 0.8125rem; /* 13px */
89
- --font-size-mono: 1.125rem; /* 18px */
100
+ --text-display: 4rem; /* 64px */
101
+ --text-h1: 2.75rem; /* 44px */
102
+ --text-h2: 2rem; /* 32px */
103
+ --text-h3: 1.375rem; /* 22px */
104
+ --text-body: 1rem; /* 16px */
105
+ --text-caption: 0.8125rem; /* 13px */
106
+ --text-mono: 1.125rem; /* 18px */
90
107
 
91
108
  --leading-display: 1.05;
92
109
  --leading-h1: 1.1;
@@ -105,16 +122,24 @@
105
122
  * Tailwind's default 0.25rem (4px) grid is unchanged. *
106
123
  * These tokens add named slots for common component spacing. */
107
124
  --spacing-page-x: 1.5rem; /* 24px - page horizontal gutter */
108
- --spacing-page-y: 2rem; /* 32px - page vertical gutter */
109
- --spacing-card: 1.5rem; /* 24px - card inner padding */
125
+ --spacing-page-y: 1.5rem; /* 24px - page vertical gutter. Equal to page-x because no page
126
+ * measured renders an asymmetric gutter; the two names stay
127
+ * separate so one axis can move without dragging the other. */
128
+ --spacing-card: 1.25rem; /* 20px - card inner padding. 24px matched none of the card
129
+ * surfaces in use; 20px is their measured mode and Card's own md. */
110
130
  --spacing-card-sm: 1rem; /* 16px - compact card padding */
111
- --spacing-section: 3rem; /* 48px - section gap */
131
+ --spacing-section: 2rem; /* 32px - section gap. 48px matched nothing anywhere; 32px is the
132
+ * gap the pages that set one already use, and PageHeader's own. */
112
133
  --spacing-input-x: 0.75rem; /* 12px - input horizontal padding */
113
134
  --spacing-input-y: 0.5rem; /* 8px - input vertical padding */
114
135
  /* 38px - the height of every single-line control. Stated once so an Input,
115
136
  * a Select and a NumberInput sitting in the same row line up. Derived from
116
137
  * the 13px/1.25 control text plus input-y padding and a 1px border. */
117
138
  --spacing-control: 2.375rem;
139
+ --spacing-panel-max: 15rem; /* 240px - the scroll cap on a floating option list */
140
+ --spacing-nav-indent: 0.875rem; /* 14px - one level of sidebar nesting */
141
+ --spacing-nav-rail: 3.5rem; /* 56px - the collapsed icon rail */
142
+ --spacing-sidebar: 14rem; /* 224px - the expanded sidebar */
118
143
  --spacing-stack: 1rem; /* 16px - default vertical stack gap */
119
144
  --spacing-inline: 0.5rem; /* 8px - default inline gap */
120
145
  }
@@ -125,20 +150,30 @@ html[data-theme='light'] {
125
150
  --color-surface: #ffffff;
126
151
  --color-surface-2: #e6e8ee;
127
152
  --color-line: #d6d9e0;
153
+ --color-line-strong: #767d8e;
128
154
  --color-fg: #111827;
129
155
  --color-muted: #525866;
130
- /* #9aa1ad on white is ~3.1:1, below the 4.5:1 AA floor; #6b7280 sits
131
- * at ~4.8:1 while staying visually tertiary. */
132
- --color-faint: #6b7280;
133
-
134
- --color-brand: #007ea6;
135
- --color-brand-light: #00b4dd;
136
- --color-brand-deep: #006a8a;
137
- --color-violet: #6b5cdf;
138
-
139
- --color-success: #15803d;
140
- --color-warn: #b45309;
141
- --color-danger: #b91c1c;
156
+ /* Every value below is the lightest colour on its own hue that clears
157
+ * 4.5:1 against the worst background the kit actually paints it on. That
158
+ * worst case is rarely the bare canvas: status text and brand chips sit
159
+ * inside a tint of their own token (bg-warn/10 text-warn), and the tint
160
+ * drags the background toward the text. Values chosen against white alone
161
+ * fail inside the tint and on surface-2. */
162
+ --color-faint: #616774;
163
+
164
+ --color-brand: #005a77;
165
+ /* brand-light is the hover step for brand links and for the filled brand
166
+ * button. In a light theme emphasis reads as deeper, not lighter, so it
167
+ * sits below brand here and brand-deep below that. The names describe
168
+ * their place in the default dark ramp. #00b4dd put near-white text at
169
+ * 2.45:1 on the primary button's hover state. */
170
+ --color-brand-light: #004f69;
171
+ --color-brand-deep: #00455c;
172
+ --color-violet: #5544da;
173
+
174
+ --color-success: #126c34;
175
+ --color-warn: #904207;
176
+ --color-danger: #ab1a1a;
142
177
  }
143
178
 
144
179
  @layer base {
@@ -163,8 +198,14 @@ html[data-theme='light'] {
163
198
  background-color: color-mix(in srgb, var(--color-brand) 30%, transparent);
164
199
  }
165
200
 
201
+ /*
202
+ * SC 1.4.11 puts a 3:1 floor on the focus indicator. Mixing brand down to
203
+ * 60% alpha left it at 2.39:1 on the light palette, so the one affordance a
204
+ * keyboard user has for locating themselves was the element that failed.
205
+ * Solid brand reads 9.85:1 on dark and 7.70:1 on light.
206
+ */
166
207
  :focus-visible {
167
- outline: 2px solid color-mix(in srgb, var(--color-brand) 60%, transparent);
208
+ outline: 2px solid var(--color-brand);
168
209
  outline-offset: 2px;
169
210
  }
170
211