@lyeve-labs/ui-kit 0.28.0 → 0.30.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.
@@ -257,7 +257,7 @@
257
257
  role="menu"
258
258
  use:placePanel
259
259
  transition:motion.popover|global
260
- class="{PANEL_SURFACE} min-w-36 {align === 'right' ? 'end-0' : 'start-0'}"
260
+ class="{PANEL_SURFACE} w-max min-w-36 max-w-xs {align === 'right' ? 'end-0' : 'start-0'}"
261
261
  >
262
262
  <div class={PANEL_LIST} data-panel-list>
263
263
  {#each items as item, index}
@@ -267,7 +267,7 @@
267
267
  disabled={item.disabled}
268
268
  tabindex={index === active ? 0 : -1}
269
269
  onclick={() => handleItemClick(item)}
270
- class="{TOUCH_GROW} flex w-full items-center gap-2.5 rounded-lg px-2 py-2 text-sm transition-colors
270
+ class="{TOUCH_GROW} flex w-full items-center gap-2.5 rounded-lg px-2 py-2 text-start text-sm whitespace-nowrap transition-colors
271
271
  outline-none focus-visible:ring-2 focus-visible:ring-inset
272
272
  focus-visible:ring-brand disabled:cursor-not-allowed disabled:opacity-40
273
273
  {item.variant === 'danger' ? 'text-danger hover:bg-danger/10' : 'hover:bg-surface-2'}"
@@ -31,6 +31,12 @@
31
31
  required?: boolean;
32
32
  id?: string;
33
33
  name?: string;
34
+ /**
35
+ * Monospace for the control alone: a slug, a key, a locale tag. Passing
36
+ * `font-mono` as a class reached the wrapper, so the label and the hint
37
+ * turned monospace with it.
38
+ */
39
+ mono?: boolean;
34
40
  class?: string;
35
41
  }
36
42
 
@@ -44,6 +50,7 @@
44
50
  disabled = false,
45
51
  required = false,
46
52
  id = undefined,
53
+ mono = false,
47
54
  class: klass = '',
48
55
  ...rest
49
56
  }: Props = $props();
@@ -67,7 +74,7 @@
67
74
  bind:value
68
75
  aria-invalid={error ? 'true' : undefined}
69
76
  aria-describedby={describedBy(fieldId, error, hint)}
70
- class="{CONTROL_BASE} {controlBorder(!!error)}"
77
+ class="{CONTROL_BASE} {controlBorder(!!error)} {mono ? 'font-mono' : ''}"
71
78
  {...rest}
72
79
  />
73
80
 
@@ -16,6 +16,12 @@ interface Props extends Forwarded {
16
16
  required?: boolean;
17
17
  id?: string;
18
18
  name?: string;
19
+ /**
20
+ * Monospace for the control alone: a slug, a key, a locale tag. Passing
21
+ * `font-mono` as a class reached the wrapper, so the label and the hint
22
+ * turned monospace with it.
23
+ */
24
+ mono?: boolean;
19
25
  class?: string;
20
26
  }
21
27
  declare const Input: import("svelte").Component<Props, {}, "value">;
@@ -11,9 +11,11 @@
11
11
  * drew a near-black column on a dark surface. There is no media query here
12
12
  * for that reason, and none belongs here.
13
13
  *
14
- * The neutral faces come from currentColor and the lit faces from the brand
15
- * ramp, so every face answers the same tokens as the rest of the page and a
16
- * palette change reaches the mark with everything else.
14
+ * Every face and the wordmark paint from the mark-* tokens, which carry the
15
+ * brand book's colours per theme: the same lockup the documentation site
16
+ * ships as a static file. They are separate from the brand ramp because that
17
+ * ramp darkens for text contrast in the light theme and inverts the mark's
18
+ * lighting there.
17
19
  */
18
20
 
19
21
  type Size = 'sm' | 'md' | 'lg';
@@ -47,10 +49,7 @@
47
49
  const px = $derived(marks[size]);
48
50
  </script>
49
51
 
50
- <!-- text-fg is stated here rather than inherited. The mark is usually wrapped
51
- in a link that carries no colour of its own, so currentColor would
52
- otherwise be whatever that ancestor happened to hold. -->
53
- <span class="inline-flex items-center gap-2 text-fg {klass}">
52
+ <span class="inline-flex items-center gap-2 {klass}">
54
53
  <span class="inline-flex shrink-0 items-center justify-center">
55
54
  <svg
56
55
  width={px}
@@ -60,18 +59,24 @@
60
59
  aria-hidden="true"
61
60
  >
62
61
  <g transform="translate(6 4)">
63
- <polygon class="fill-current" points="0,14 14,7 14,40 0,47" />
64
- <polygon class="fill-current opacity-50" points="0,47 14,40 14,54 0,61" />
65
- <polygon class="fill-current opacity-75" points="14,40 28,33 28,47 14,54" />
66
- <polygon class="fill-brand-light" points="14,54 28,47 56,33 42,40" />
67
- <polygon class="fill-brand-deep" points="42,40 56,33 56,47 42,54" />
68
- <polygon class="fill-brand" points="14,54 28,61 42,54 28,47" />
69
- <polygon class="fill-brand" points="28,47 42,54 56,47 42,40" />
62
+ <polygon class="fill-mark-ink" points="0,14 14,7 14,40 0,47" />
63
+ <polygon class="fill-mark-foot" points="0,47 14,40 14,54 0,61" />
64
+ <polygon class="fill-mark-step" points="14,40 28,33 28,47 14,54" />
65
+ <polygon class="fill-mark-top" points="14,54 28,47 56,33 42,40" />
66
+ <polygon class="fill-mark-side" points="42,40 56,33 56,47 42,54" />
67
+ <polygon class="fill-mark-face" points="14,54 28,61 42,54 28,47" />
68
+ <polygon class="fill-mark-face" points="28,47 42,54 56,47 42,40" />
70
69
  </g>
71
70
  </svg>
72
71
  </span>
73
72
 
74
73
  {#if wordmark}
75
- <span class="font-semibold tracking-tight {words[size]}">LyEve</span>
74
+ <!-- The accent splits the word across two elements, which some screen
75
+ readers announce letter group by letter group, so the painted word is
76
+ hidden and the name is given once as plain text. -->
77
+ <span class="font-bold tracking-tight text-mark-ink {words[size]}">
78
+ <span aria-hidden="true">Ly<span class="text-mark-accent">E</span>ve</span>
79
+ <span class="sr-only">LyEve</span>
80
+ </span>
76
81
  {/if}
77
82
  </span>
@@ -10,9 +10,11 @@
10
10
  * drew a near-black column on a dark surface. There is no media query here
11
11
  * for that reason, and none belongs here.
12
12
  *
13
- * The neutral faces come from currentColor and the lit faces from the brand
14
- * ramp, so every face answers the same tokens as the rest of the page and a
15
- * palette change reaches the mark with everything else.
13
+ * Every face and the wordmark paint from the mark-* tokens, which carry the
14
+ * brand book's colours per theme: the same lockup the documentation site
15
+ * ships as a static file. They are separate from the brand ramp because that
16
+ * ramp darkens for text contrast in the light theme and inverts the mark's
17
+ * lighting there.
16
18
  */
17
19
  type Size = 'sm' | 'md' | 'lg';
18
20
  interface Props {
@@ -199,7 +199,7 @@
199
199
  'inline-flex items-center justify-center rounded-md outline-none transition-colors focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-brand disabled:cursor-not-allowed ' +
200
200
  SIZES[size].segment +
201
201
  (selected
202
- ? ' bg-surface text-fg shadow-sm'
202
+ ? ' bg-surface text-brand shadow-sm ring-1 ring-inset ring-brand/40'
203
203
  : ' text-muted hover:text-fg active:bg-surface active:text-fg')}
204
204
  {#snippet content()}
205
205
  {#if Icon}
@@ -26,6 +26,7 @@
26
26
  resize = true,
27
27
  error,
28
28
  hint,
29
+ mono = false,
29
30
  class: cls = '',
30
31
  oninput,
31
32
  onblur,
@@ -43,6 +44,12 @@
43
44
  resize?: boolean;
44
45
  error?: string;
45
46
  hint?: string;
47
+ /**
48
+ * Monospace for the control alone: code, JSON, a key. Passing `font-mono`
49
+ * as a class reached the wrapper, so the label and the hint turned
50
+ * monospace with it.
51
+ */
52
+ mono?: boolean;
46
53
  class?: string;
47
54
  oninput?: (e: TAE) => void;
48
55
  onblur?: (e: FocusEvent & { currentTarget: TA }) => void;
@@ -69,7 +76,7 @@
69
76
  {placeholder}
70
77
  aria-invalid={error ? 'true' : undefined}
71
78
  aria-describedby={describedBy(fieldId, error, hint)}
72
- class="{CONTROL_MULTILINE} {controlBorder(!!error)} {resize ? 'resize-y' : 'resize-none'}"
79
+ class="{CONTROL_MULTILINE} {controlBorder(!!error)} {resize ? 'resize-y' : 'resize-none'} {mono ? 'font-mono' : ''}"
73
80
  bind:value
74
81
  {oninput}
75
82
  {onblur}
@@ -16,6 +16,12 @@ type $$ComponentProps = {
16
16
  resize?: boolean;
17
17
  error?: string;
18
18
  hint?: string;
19
+ /**
20
+ * Monospace for the control alone: code, JSON, a key. Passing `font-mono`
21
+ * as a class reached the wrapper, so the label and the hint turned
22
+ * monospace with it.
23
+ */
24
+ mono?: boolean;
19
25
  class?: string;
20
26
  oninput?: (e: TAE) => void;
21
27
  onblur?: (e: FocusEvent & {
package/dist/index.d.ts CHANGED
@@ -93,4 +93,4 @@ export { cn, type ClassValue } from './utils/cn.js';
93
93
  export { getTheme, getThemePreference, nextThemePreference, resolveTheme, setTheme, setThemePreference, systemTheme, themeBootScript, toggleTheme, watchSystemTheme, THEME_PREFERENCES, type Theme, type ThemePreference, } from './utils/theme.js';
94
94
  export * as motion from './motion.js';
95
95
  export type { Rung as MotionRung, Curve as MotionCurve } from './motion.js';
96
- export declare const VERSION = "0.28.0";
96
+ export declare const VERSION = "0.30.0";
package/dist/index.js CHANGED
@@ -103,4 +103,4 @@ export * as motion from './motion.js';
103
103
  // ── Version ────────────────────────────────────────────────────────────────
104
104
  // Generated from package.json by `pnpm version:sync`. Bump package.json, never
105
105
  // this line; the build and the test suite fail when the two disagree.
106
- export const VERSION = '0.28.0';
106
+ export const VERSION = '0.30.0';
@@ -57,6 +57,19 @@
57
57
  * paints it on and the badge as well. */
58
58
  --color-violet: #9587f2;
59
59
 
60
+ /* The product mark's faces, at the brand book's values. They are their own
61
+ * tokens because the brand ramp above is tuned for text contrast: in the
62
+ * light theme it darkens to #005a77 and brand-light sits below brand, so a
63
+ * mark painted from it inverts its lighting. A logotype is exempt from the
64
+ * contrast floor, so these keep the published colours instead. */
65
+ --color-mark-ink: #ffffff;
66
+ --color-mark-foot: #9aa1ad;
67
+ --color-mark-step: #c5cad3;
68
+ --color-mark-top: #00d4ff;
69
+ --color-mark-side: #0099c4;
70
+ --color-mark-face: #00b4dd;
71
+ --color-mark-accent: #00d4ff;
72
+
60
73
  /* #15803d and #b45309 sit at ~3.7:1 on ink, below the 4.5:1 AA floor
61
74
  * for the text-size status labels that use them. */
62
75
  --color-success: #22c55e;
@@ -396,12 +409,33 @@ html[data-theme='light'] {
396
409
  --color-brand-light: #004f69;
397
410
  --color-brand-deep: #00455c;
398
411
  --color-violet: #5544da;
412
+ --color-mark-ink: #0a0e14;
413
+ --color-mark-foot: #9aa1ad;
414
+ --color-mark-step: #c5cad3;
415
+ --color-mark-top: #0099c4;
416
+ --color-mark-side: #006a8a;
417
+ --color-mark-face: #007ea6;
418
+ --color-mark-accent: #00d4ff;
399
419
 
400
420
  --color-success: #126c34;
401
421
  --color-warn: #904207;
402
422
  --color-danger: #ab1a1a;
403
423
  }
404
424
 
425
+ /*
426
+ * A forced-colors scheme repaints the page but not a fill named in hex, so the
427
+ * mark's white column vanished on a white high-contrast canvas. Its neutral
428
+ * faces take the system colours there; the cyan faces keep their shape.
429
+ */
430
+ @media (forced-colors: active) {
431
+ :root,
432
+ html[data-theme='light'] {
433
+ --color-mark-ink: CanvasText;
434
+ --color-mark-foot: GrayText;
435
+ --color-mark-step: GrayText;
436
+ }
437
+ }
438
+
405
439
  /*
406
440
  * The four durations as utilities. A --duration-* token generates nothing
407
441
  * (see the motion section of the @theme block), so each is declared here the
@@ -552,6 +586,13 @@ html[data-theme='light'] {
552
586
  --color-brand-light: #000000;
553
587
  --color-brand-deep: #000000;
554
588
  --color-violet: #000000;
589
+ /* The mark keeps its light-theme faces: in black every face is one
590
+ * shape and the L is gone. Printing from the dark theme would otherwise
591
+ * put a white column on white paper. */
592
+ --color-mark-ink: #0a0e14;
593
+ --color-mark-top: #0099c4;
594
+ --color-mark-side: #006a8a;
595
+ --color-mark-face: #007ea6;
555
596
  --color-success: #000000;
556
597
  --color-warn: #000000;
557
598
  --color-danger: #000000;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyeve-labs/ui-kit",
3
- "version": "0.28.0",
3
+ "version": "0.30.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>",
@@ -57,6 +57,19 @@
57
57
  * paints it on and the badge as well. */
58
58
  --color-violet: #9587f2;
59
59
 
60
+ /* The product mark's faces, at the brand book's values. They are their own
61
+ * tokens because the brand ramp above is tuned for text contrast: in the
62
+ * light theme it darkens to #005a77 and brand-light sits below brand, so a
63
+ * mark painted from it inverts its lighting. A logotype is exempt from the
64
+ * contrast floor, so these keep the published colours instead. */
65
+ --color-mark-ink: #ffffff;
66
+ --color-mark-foot: #9aa1ad;
67
+ --color-mark-step: #c5cad3;
68
+ --color-mark-top: #00d4ff;
69
+ --color-mark-side: #0099c4;
70
+ --color-mark-face: #00b4dd;
71
+ --color-mark-accent: #00d4ff;
72
+
60
73
  /* #15803d and #b45309 sit at ~3.7:1 on ink, below the 4.5:1 AA floor
61
74
  * for the text-size status labels that use them. */
62
75
  --color-success: #22c55e;
@@ -396,12 +409,33 @@ html[data-theme='light'] {
396
409
  --color-brand-light: #004f69;
397
410
  --color-brand-deep: #00455c;
398
411
  --color-violet: #5544da;
412
+ --color-mark-ink: #0a0e14;
413
+ --color-mark-foot: #9aa1ad;
414
+ --color-mark-step: #c5cad3;
415
+ --color-mark-top: #0099c4;
416
+ --color-mark-side: #006a8a;
417
+ --color-mark-face: #007ea6;
418
+ --color-mark-accent: #00d4ff;
399
419
 
400
420
  --color-success: #126c34;
401
421
  --color-warn: #904207;
402
422
  --color-danger: #ab1a1a;
403
423
  }
404
424
 
425
+ /*
426
+ * A forced-colors scheme repaints the page but not a fill named in hex, so the
427
+ * mark's white column vanished on a white high-contrast canvas. Its neutral
428
+ * faces take the system colours there; the cyan faces keep their shape.
429
+ */
430
+ @media (forced-colors: active) {
431
+ :root,
432
+ html[data-theme='light'] {
433
+ --color-mark-ink: CanvasText;
434
+ --color-mark-foot: GrayText;
435
+ --color-mark-step: GrayText;
436
+ }
437
+ }
438
+
405
439
  /*
406
440
  * The four durations as utilities. A --duration-* token generates nothing
407
441
  * (see the motion section of the @theme block), so each is declared here the
@@ -552,6 +586,13 @@ html[data-theme='light'] {
552
586
  --color-brand-light: #000000;
553
587
  --color-brand-deep: #000000;
554
588
  --color-violet: #000000;
589
+ /* The mark keeps its light-theme faces: in black every face is one
590
+ * shape and the L is gone. Printing from the dark theme would otherwise
591
+ * put a white column on white paper. */
592
+ --color-mark-ink: #0a0e14;
593
+ --color-mark-top: #0099c4;
594
+ --color-mark-side: #006a8a;
595
+ --color-mark-face: #007ea6;
555
596
  --color-success: #000000;
556
597
  --color-warn: #000000;
557
598
  --color-danger: #000000;