@lerianstudio/sindarian-ui 2.0.0-beta.5 → 2.0.0-beta.7

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.
@@ -1,12 +1,5 @@
1
1
  import * as React from 'react';
2
2
  import { type VariantProps } from 'class-variance-authority';
3
- /**
4
- * `credit` is the accounting reading of a credit amount, NOT an alias of
5
- * `destructive` (an error/alarm). The credit role is a tint-and-ink pair:
6
- * `--credit-foreground` mirrors `--credit` by contract, so the red carries the
7
- * role as text over a tinted surface. Do not "fix" this into a solid
8
- * `bg-credit` fill — that renders red-on-red and is invisible.
9
- */
10
3
  /**
11
4
  * `gap-1` is load-bearing, not decoration: a badge holding a label AND an
12
5
  * element child (`ID<code>ctx-123</code>`) has nothing between them otherwise —
@@ -14,6 +7,17 @@ import { type VariantProps } from 'class-variance-authority';
14
7
  * anonymous flex item — so the screen reads `IDctx-123`. Consumers were pasting
15
8
  * `className="gap-1"` per call site; `cn` runs tailwind-merge, so an explicit
16
9
  * `gap-2` still wins. Single-child badges are unaffected: gap needs two items.
10
+ *
11
+ * `whitespace-nowrap` keeps the pill a pill. `rounded-full` draws the ends as
12
+ * semicircles sized to ONE line box, so a label that wraps stretches those caps
13
+ * over two lines and the shape reads as a rounded blob, not a token. It bit a
14
+ * consumer table whose column was sized to its content: `min-content` on
15
+ * wrappable text resolves to the WIDEST WORD, so a three-word group name landed
16
+ * at 112px wide and 46px tall against the 26px of a single-line badge. Nowrap
17
+ * also pins `min-content` to the full label, which is what lets a caller cap the
18
+ * box with `max-w-*` plus a truncating child and get an ellipsis. A caller that
19
+ * genuinely wants a wrapping badge passes `whitespace-normal`; tailwind-merge
20
+ * lets it win.
17
21
  */
18
22
  declare const badgeVariants: (props?: ({
19
23
  variant?: "default" | "secondary" | "outline" | "destructive" | "alert" | "success" | "active" | "inactive" | "credit" | "error" | "info" | "purple" | null | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/badge/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAKjE;;;;;;GAMG;AACH;;;;;;;GAOG;AACH,QAAA,MAAM,aAAa;;;8EA6ClB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,GACnD,YAAY,CAAC,OAAO,aAAa,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAE5D,iBAAS,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,UAAU,qBAsBzE;AAED,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/badge/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAKjE;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,aAAa;;;8EAqDlB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,GACnD,YAAY,CAAC,OAAO,aAAa,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAE5D,iBAAS,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,UAAU,qBAsBzE;AAED,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAA"}
@@ -6,13 +6,6 @@ const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const class_variance_authority_1 = require("class-variance-authority");
7
7
  const utils_1 = require("../../../lib/utils");
8
8
  const react_slot_1 = require("@radix-ui/react-slot");
9
- /**
10
- * `credit` is the accounting reading of a credit amount, NOT an alias of
11
- * `destructive` (an error/alarm). The credit role is a tint-and-ink pair:
12
- * `--credit-foreground` mirrors `--credit` by contract, so the red carries the
13
- * role as text over a tinted surface. Do not "fix" this into a solid
14
- * `bg-credit` fill — that renders red-on-red and is invisible.
15
- */
16
9
  /**
17
10
  * `gap-1` is load-bearing, not decoration: a badge holding a label AND an
18
11
  * element child (`ID<code>ctx-123</code>`) has nothing between them otherwise —
@@ -20,8 +13,19 @@ const react_slot_1 = require("@radix-ui/react-slot");
20
13
  * anonymous flex item — so the screen reads `IDctx-123`. Consumers were pasting
21
14
  * `className="gap-1"` per call site; `cn` runs tailwind-merge, so an explicit
22
15
  * `gap-2` still wins. Single-child badges are unaffected: gap needs two items.
16
+ *
17
+ * `whitespace-nowrap` keeps the pill a pill. `rounded-full` draws the ends as
18
+ * semicircles sized to ONE line box, so a label that wraps stretches those caps
19
+ * over two lines and the shape reads as a rounded blob, not a token. It bit a
20
+ * consumer table whose column was sized to its content: `min-content` on
21
+ * wrappable text resolves to the WIDEST WORD, so a three-word group name landed
22
+ * at 112px wide and 46px tall against the 26px of a single-line badge. Nowrap
23
+ * also pins `min-content` to the full label, which is what lets a caller cap the
24
+ * box with `max-w-*` plus a truncating child and get an ellipsis. A caller that
25
+ * genuinely wants a wrapping badge passes `whitespace-normal`; tailwind-merge
26
+ * lets it win.
23
27
  */
24
- const badgeVariants = (0, class_variance_authority_1.cva)('inline-flex items-center gap-1 rounded-full border border-border px-2.5 py-0.5 text-sm font-medium transition-colors focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2', {
28
+ const badgeVariants = (0, class_variance_authority_1.cva)('inline-flex items-center gap-1 whitespace-nowrap rounded-full border border-border px-2.5 py-0.5 text-sm font-medium transition-colors focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2', {
25
29
  variants: {
26
30
  variant: {
27
31
  default: 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
@@ -29,6 +33,14 @@ const badgeVariants = (0, class_variance_authority_1.cva)('inline-flex items-cen
29
33
  inactive: 'bg-muted text-foreground border-muted-foreground/40 py-[2px] px-3',
30
34
  secondary: 'border-transparent bg-muted-foreground text-white dark:text-black',
31
35
  destructive: 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
36
+ /**
37
+ * The accounting reading of a credit amount, NOT an alias of
38
+ * `destructive` (an error/alarm). The credit role is a tint-and-ink
39
+ * pair: `--credit-foreground` mirrors `--credit` by contract, so the
40
+ * red carries the role as text over a tinted surface. Do not "fix"
41
+ * this into a solid `bg-credit` fill — that renders red-on-red and is
42
+ * invisible.
43
+ */
32
44
  credit: 'border-credit/30 bg-credit/10 text-credit-foreground px-[10px] py-1',
33
45
  error: 'border-system-error-border bg-system-error-surface text-system-error-text px-[10px] py-1',
34
46
  success: 'border-system-success-border bg-system-success-surface text-system-success-text px-[10px] py-1',
@@ -1,12 +1,5 @@
1
1
  import * as React from 'react';
2
2
  import { type VariantProps } from 'class-variance-authority';
3
- /**
4
- * `credit` is the accounting reading of a credit amount, NOT an alias of
5
- * `destructive` (an error/alarm). The credit role is a tint-and-ink pair:
6
- * `--credit-foreground` mirrors `--credit` by contract, so the red carries the
7
- * role as text over a tinted surface. Do not "fix" this into a solid
8
- * `bg-credit` fill — that renders red-on-red and is invisible.
9
- */
10
3
  /**
11
4
  * `gap-1` is load-bearing, not decoration: a badge holding a label AND an
12
5
  * element child (`ID<code>ctx-123</code>`) has nothing between them otherwise —
@@ -14,6 +7,17 @@ import { type VariantProps } from 'class-variance-authority';
14
7
  * anonymous flex item — so the screen reads `IDctx-123`. Consumers were pasting
15
8
  * `className="gap-1"` per call site; `cn` runs tailwind-merge, so an explicit
16
9
  * `gap-2` still wins. Single-child badges are unaffected: gap needs two items.
10
+ *
11
+ * `whitespace-nowrap` keeps the pill a pill. `rounded-full` draws the ends as
12
+ * semicircles sized to ONE line box, so a label that wraps stretches those caps
13
+ * over two lines and the shape reads as a rounded blob, not a token. It bit a
14
+ * consumer table whose column was sized to its content: `min-content` on
15
+ * wrappable text resolves to the WIDEST WORD, so a three-word group name landed
16
+ * at 112px wide and 46px tall against the 26px of a single-line badge. Nowrap
17
+ * also pins `min-content` to the full label, which is what lets a caller cap the
18
+ * box with `max-w-*` plus a truncating child and get an ellipsis. A caller that
19
+ * genuinely wants a wrapping badge passes `whitespace-normal`; tailwind-merge
20
+ * lets it win.
17
21
  */
18
22
  declare const badgeVariants: (props?: ({
19
23
  variant?: "default" | "secondary" | "outline" | "destructive" | "alert" | "success" | "active" | "inactive" | "credit" | "error" | "info" | "purple" | null | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/badge/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAKjE;;;;;;GAMG;AACH;;;;;;;GAOG;AACH,QAAA,MAAM,aAAa;;;8EA6ClB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,GACnD,YAAY,CAAC,OAAO,aAAa,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAE5D,iBAAS,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,UAAU,qBAsBzE;AAED,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/badge/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAKjE;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,aAAa;;;8EAqDlB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,GACnD,YAAY,CAAC,OAAO,aAAa,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAE5D,iBAAS,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,UAAU,qBAsBzE;AAED,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAA"}
@@ -2,13 +2,6 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cva } from 'class-variance-authority';
3
3
  import { cn } from '../../../lib/utils.js';
4
4
  import { Slot } from '@radix-ui/react-slot';
5
- /**
6
- * `credit` is the accounting reading of a credit amount, NOT an alias of
7
- * `destructive` (an error/alarm). The credit role is a tint-and-ink pair:
8
- * `--credit-foreground` mirrors `--credit` by contract, so the red carries the
9
- * role as text over a tinted surface. Do not "fix" this into a solid
10
- * `bg-credit` fill — that renders red-on-red and is invisible.
11
- */
12
5
  /**
13
6
  * `gap-1` is load-bearing, not decoration: a badge holding a label AND an
14
7
  * element child (`ID<code>ctx-123</code>`) has nothing between them otherwise —
@@ -16,8 +9,19 @@ import { Slot } from '@radix-ui/react-slot';
16
9
  * anonymous flex item — so the screen reads `IDctx-123`. Consumers were pasting
17
10
  * `className="gap-1"` per call site; `cn` runs tailwind-merge, so an explicit
18
11
  * `gap-2` still wins. Single-child badges are unaffected: gap needs two items.
12
+ *
13
+ * `whitespace-nowrap` keeps the pill a pill. `rounded-full` draws the ends as
14
+ * semicircles sized to ONE line box, so a label that wraps stretches those caps
15
+ * over two lines and the shape reads as a rounded blob, not a token. It bit a
16
+ * consumer table whose column was sized to its content: `min-content` on
17
+ * wrappable text resolves to the WIDEST WORD, so a three-word group name landed
18
+ * at 112px wide and 46px tall against the 26px of a single-line badge. Nowrap
19
+ * also pins `min-content` to the full label, which is what lets a caller cap the
20
+ * box with `max-w-*` plus a truncating child and get an ellipsis. A caller that
21
+ * genuinely wants a wrapping badge passes `whitespace-normal`; tailwind-merge
22
+ * lets it win.
19
23
  */
20
- const badgeVariants = cva('inline-flex items-center gap-1 rounded-full border border-border px-2.5 py-0.5 text-sm font-medium transition-colors focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2', {
24
+ const badgeVariants = cva('inline-flex items-center gap-1 whitespace-nowrap rounded-full border border-border px-2.5 py-0.5 text-sm font-medium transition-colors focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2', {
21
25
  variants: {
22
26
  variant: {
23
27
  default: 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
@@ -25,6 +29,14 @@ const badgeVariants = cva('inline-flex items-center gap-1 rounded-full border bo
25
29
  inactive: 'bg-muted text-foreground border-muted-foreground/40 py-[2px] px-3',
26
30
  secondary: 'border-transparent bg-muted-foreground text-white dark:text-black',
27
31
  destructive: 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
32
+ /**
33
+ * The accounting reading of a credit amount, NOT an alias of
34
+ * `destructive` (an error/alarm). The credit role is a tint-and-ink
35
+ * pair: `--credit-foreground` mirrors `--credit` by contract, so the
36
+ * red carries the role as text over a tinted surface. Do not "fix"
37
+ * this into a solid `bg-credit` fill — that renders red-on-red and is
38
+ * invisible.
39
+ */
28
40
  credit: 'border-credit/30 bg-credit/10 text-credit-foreground px-[10px] py-1',
29
41
  error: 'border-system-error-border bg-system-error-surface text-system-error-text px-[10px] py-1',
30
42
  success: 'border-system-success-border bg-system-success-surface text-system-success-text px-[10px] py-1',
package/dist/globals.css CHANGED
@@ -541,7 +541,7 @@
541
541
  }
542
542
  }
543
543
 
544
- /* Sonner toast overrides — solid bold backgrounds (Radix parity) */
544
+ /* Sonner toast overrides — tinted surfaces from the system token families */
545
545
  [data-sonner-toaster] {
546
546
  --width: 420px;
547
547
  pointer-events: auto !important;
@@ -559,41 +559,41 @@
559
559
  }
560
560
 
561
561
  /*
562
- Type fills come from the system token families, so a toast themes with the
563
- rest of the app. All three coloured types take ONE ink, --accent-foreground:
564
- a solid system fill is bright enough to need near-black ink in BOTH themes,
565
- and that token is the only one in this sheet that is near-black in both.
566
-
567
- It replaced the per-family reasoning that stood here, which routed success
568
- and error through --primary-foreground because that token inverts (white in
569
- light, base/800 in dark). Inverting was the bug: white ink on the LIGHT
570
- fills measured 3.35:1 on --system-success and 3.78:1 on --system-error,
571
- both under AA, and no token value can fix that from the white side — the
572
- light green/600 and red/500 fills sit mid-luminance, so white caps at ~3.8
573
- while near-black reaches 5.9 and 5.3. Ratios now, ink over fill:
574
- light 5.93 / 5.25 / 11.17 and dark 11.39 / 7.23 / 13.00
575
- (success / error / warning). The dark pairs were already passing at
576
- 8.51 / 5.41 / 13.00 and only gained. `toast ink` in
577
- src/__tests__/tokens-contract.test.ts recomputes all six from these
578
- declarations, so the next token edit that drops a pair under 4.5 fails
579
- instead of shipping.
562
+ Each coloured type paints the `surface` + `text` + `border` trio of its own
563
+ family — the pairing every other tinted component in the kit already uses
564
+ (`components/ui/badge/index.tsx`, `enterprise/alert-banner/index.tsx`).
565
+ `surface` is the only slot in a system family built to sit BEHIND content: it
566
+ darkens on the dark canvas, while `base` and `h1a` are fill and ink slots
567
+ that INVERT between themes (`--system-success-h1a` is #166534 in light and
568
+ #BBF7D0 in dark). Grounding toast text on either of those forces a different
569
+ ink per theme, and the toast stops tracking the family it names.
570
+
571
+ Ink over ground, light / dark: success 6.81 / 10.62, error 7.60 / 8.51,
572
+ warning 6.62 / 11.70 — every half clear of the 4.5 floor by more than two
573
+ points. `system text tokens` in `src/__tests__/tokens-contract.test.ts`
574
+ already measures this pair for all five families, so the toast is covered by
575
+ the gate that guards the pills rather than by a rule written for it alone;
576
+ `sonner toast ink` there reads whichever pair these rules declare.
577
+
578
+ `info` stays neutral on `--card`: an informational toast is the unstyled
579
+ case, not a fourth colour.
580
580
  */
581
581
  [data-sonner-toast][data-type='success'] {
582
- --normal-bg: hsl(var(--system-success));
583
- --normal-text: hsl(var(--accent-foreground));
584
- --normal-border: transparent;
582
+ --normal-bg: hsl(var(--system-success-surface));
583
+ --normal-text: hsl(var(--system-success-text));
584
+ --normal-border: hsl(var(--system-success-border));
585
585
  }
586
586
 
587
587
  [data-sonner-toast][data-type='error'] {
588
- --normal-bg: hsl(var(--system-error));
589
- --normal-text: hsl(var(--accent-foreground));
590
- --normal-border: transparent;
588
+ --normal-bg: hsl(var(--system-error-surface));
589
+ --normal-text: hsl(var(--system-error-text));
590
+ --normal-border: hsl(var(--system-error-border));
591
591
  }
592
592
 
593
593
  [data-sonner-toast][data-type='warning'] {
594
- --normal-bg: hsl(var(--system-alert));
595
- --normal-text: hsl(var(--accent-foreground));
596
- --normal-border: transparent;
594
+ --normal-bg: hsl(var(--system-alert-surface));
595
+ --normal-text: hsl(var(--system-alert-text));
596
+ --normal-border: hsl(var(--system-alert-border));
597
597
  }
598
598
 
599
599
  [data-sonner-toast][data-type='info'] {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lerianstudio/sindarian-ui",
3
- "version": "2.0.0-beta.5",
3
+ "version": "2.0.0-beta.7",
4
4
  "description": "Sindarian UI - A UI library for Midaz Console",
5
5
  "license": "ISC",
6
6
  "author": {