@teseor/css 1.0.0 → 1.2.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 (73) hide show
  1. package/dist/compiled.css +212 -107
  2. package/dist/index.css +276 -171
  3. package/package.json +1 -1
  4. package/src/00-config/tokens/_variables.scss +39 -25
  5. package/src/00-config/tokens/colors/index.scss +22 -21
  6. package/src/02-base/typography/typography.scss +16 -0
  7. package/src/03-layout/cluster/cluster-visual.png +0 -0
  8. package/src/03-layout/cluster/cluster.visual.spec.ts +15 -0
  9. package/src/03-layout/sidebar/sidebar-visual.png +0 -0
  10. package/src/03-layout/sidebar/sidebar.docs.json +62 -0
  11. package/src/03-layout/sidebar/sidebar.visual.spec.ts +14 -0
  12. package/src/03-layout/sidebar-nav/sidebar-nav.api.json +29 -80
  13. package/src/04-components/accordion/accordion.api.json +5 -1
  14. package/src/04-components/alert/alert.api.json +6 -0
  15. package/src/04-components/alert/index.scss +10 -15
  16. package/src/04-components/avatar/avatar.api.json +5 -0
  17. package/src/04-components/badge/index.scss +12 -9
  18. package/src/04-components/breadcrumb/breadcrumb.api.json +5 -0
  19. package/src/04-components/button/button-visual.png +0 -0
  20. package/src/04-components/button/button.api.json +30 -56
  21. package/src/04-components/button/button.docs.json +75 -0
  22. package/src/04-components/button/index.scss +27 -17
  23. package/src/04-components/button-group/button-group-visual.png +0 -0
  24. package/src/04-components/button-group/button-group.api.json +5 -1
  25. package/src/04-components/button-group/button-group.visual.spec.ts +2 -1
  26. package/src/04-components/checkbox/checkbox-visual.png +0 -0
  27. package/src/04-components/checkbox/checkbox.api.json +1 -1
  28. package/src/04-components/code/code.api.json +6 -1
  29. package/src/04-components/data-list/data-list-visual.png +0 -0
  30. package/src/04-components/data-list/data-list.api.json +16 -1
  31. package/src/04-components/data-list/data-list.visual.spec.ts +2 -1
  32. package/src/04-components/data-list/index.scss +3 -2
  33. package/src/04-components/dialog/dialog.api.json +12 -1
  34. package/src/04-components/disclosure/disclosure.api.json +13 -1
  35. package/src/04-components/divider/divider.api.json +3 -0
  36. package/src/04-components/drawer/drawer.api.json +17 -1
  37. package/src/04-components/field/field.api.json +9 -1
  38. package/src/04-components/form-error/form-error-visual.png +0 -0
  39. package/src/04-components/form-error/form-error.api.json +3 -0
  40. package/src/04-components/icon/icon-visual.png +0 -0
  41. package/src/04-components/icon/icon.api.json +7 -6
  42. package/src/04-components/icon/icon.docs.json +86 -22
  43. package/src/04-components/icon/index.scss +6 -19
  44. package/src/04-components/index.scss +1 -0
  45. package/src/04-components/input/input-visual.png +0 -0
  46. package/src/04-components/input/input.api.json +31 -0
  47. package/src/04-components/label/label.api.json +4 -0
  48. package/src/04-components/link/link-visual.png +0 -0
  49. package/src/04-components/link/link.api.json +6 -0
  50. package/src/04-components/menu/menu.api.json +24 -0
  51. package/src/04-components/modal/modal.api.json +12 -1
  52. package/src/04-components/nav/index.scss +142 -0
  53. package/src/04-components/nav/nav-visual.png +0 -0
  54. package/src/04-components/nav/nav.api.json +55 -0
  55. package/src/04-components/nav/nav.docs.json +242 -0
  56. package/src/04-components/nav/nav.visual.spec.ts +14 -0
  57. package/src/04-components/overlay/overlay.api.json +14 -1
  58. package/src/04-components/pagination/pagination.api.json +22 -1
  59. package/src/04-components/popover/popover.api.json +9 -1
  60. package/src/04-components/progress/progress.api.json +20 -1
  61. package/src/04-components/radio/radio-visual.png +0 -0
  62. package/src/04-components/radio/radio.api.json +1 -1
  63. package/src/04-components/select/select.api.json +3 -0
  64. package/src/04-components/skeleton/skeleton.api.json +8 -1
  65. package/src/04-components/status/status.api.json +14 -1
  66. package/src/04-components/table/table.api.json +8 -1
  67. package/src/04-components/tabs/tabs.api.json +17 -0
  68. package/src/04-components/tag/tag.api.json +4 -0
  69. package/src/04-components/textarea/textarea.api.json +3 -0
  70. package/src/04-components/toast/toast.api.json +22 -1
  71. package/src/04-components/toggle/toggle.api.json +5 -0
  72. package/src/04-components/tooltip/tooltip.api.json +11 -1
  73. package/src/testing/page-setup.ts +25 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teseor/css",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "CSS library - reset, primitives, components, utilities",
5
5
  "license": "MIT",
6
6
  "author": "letanure",
@@ -1,3 +1,5 @@
1
+ @use 'sass:map';
2
+
1
3
  // SCSS Variables - Source of truth for fallback values
2
4
  // These are the computed values that CSS custom properties resolve to.
3
5
  // Import this file in components that need standalone fallbacks.
@@ -23,6 +25,20 @@ $space-4: $unit * 4;
23
25
  $space-6: $unit * 6;
24
26
  $space-8: $unit * 8;
25
27
 
28
+ // T-shirt sizes map for looping
29
+ $sizes: (
30
+ xs: $unit, // 8px
31
+ sm: $unit * 1.5, // 12px
32
+ md: $unit * 2, // 16px
33
+ lg: $unit * 2.5, // 20px
34
+ xl: $unit * 3 // 24px
35
+ );
36
+
37
+ // Helper function to get size value
38
+ @function size($name) {
39
+ @return map.get($sizes, $name);
40
+ }
41
+
26
42
  // Typography - Font families
27
43
  $font-sans: "Noto Sans", system-ui, -apple-system, sans-serif;
28
44
  $font-mono: "Noto Sans Mono", ui-monospace, "Cascadia Code", monospace;
@@ -76,31 +92,29 @@ $border-width-sm: $unit * 0.125; // 1px
76
92
  $border-width-md: $unit * 0.25; // 2px
77
93
  $border-width-lg: $unit * 0.5; // 4px
78
94
 
79
- // Color primitives
80
- $hue-primary: 220;
81
- $hue-success: 142;
82
- $hue-warning: 38;
83
- $hue-danger: 0;
84
-
85
- $color-neutral-50: hsl($hue-primary 10% 98%);
86
- $color-neutral-100: hsl($hue-primary 10% 96%);
87
- $color-neutral-200: hsl($hue-primary 10% 90%);
88
- $color-neutral-300: hsl($hue-primary 10% 80%);
89
- $color-neutral-400: hsl($hue-primary 10% 60%);
90
- $color-neutral-500: hsl($hue-primary 10% 45%);
91
- $color-neutral-600: hsl($hue-primary 10% 35%);
92
- $color-neutral-700: hsl($hue-primary 10% 25%);
93
- $color-neutral-800: hsl($hue-primary 10% 15%);
94
- $color-neutral-900: hsl($hue-primary 10% 10%);
95
-
96
- $color-primary-light: hsl($hue-primary 85% 65%);
97
- $color-primary: hsl($hue-primary 85% 50%);
98
- $color-primary-dark: hsl($hue-primary 85% 40%);
99
-
100
- $color-success: hsl($hue-success 70% 45%);
101
- $color-warning: hsl($hue-warning 90% 50%);
102
- $color-danger: hsl($hue-danger 70% 50%);
103
- $color-danger-dark: hsl($hue-danger 70% 40%);
95
+ // Base colors - OKLCH for perceptual uniformity
96
+ // These are fallback values; CSS custom properties take precedence
97
+ $color-primary: oklch(55% 0.22 250);
98
+ $color-success: oklch(60% 0.18 145);
99
+ $color-warning: oklch(75% 0.18 70);
100
+ $color-danger: oklch(60% 0.22 25);
101
+ $color-neutral: oklch(50% 0.02 250);
102
+
103
+ // Neutral scale - approximated from color-mix in oklch
104
+ $color-neutral-50: hsl(220 10% 98%);
105
+ $color-neutral-100: hsl(220 10% 96%);
106
+ $color-neutral-200: hsl(220 10% 90%);
107
+ $color-neutral-300: hsl(220 10% 80%);
108
+ $color-neutral-400: hsl(220 10% 60%);
109
+ $color-neutral-500: hsl(220 10% 45%);
110
+ $color-neutral-600: hsl(220 10% 35%);
111
+ $color-neutral-700: hsl(220 10% 25%);
112
+ $color-neutral-800: hsl(220 10% 15%);
113
+ $color-neutral-900: hsl(220 10% 10%);
114
+
115
+ // Primary shades - fallbacks (CSS uses color-mix)
116
+ $color-primary-light: oklch(75% 0.15 250);
117
+ $color-primary-dark: oklch(40% 0.18 250);
104
118
 
105
119
  // Semantic colors (light theme defaults)
106
120
  $color-text: $color-neutral-900;
@@ -1,25 +1,26 @@
1
1
  :root {
2
- --ui-hue-primary: 220;
3
- --ui-hue-success: 142;
4
- --ui-hue-warning: 38;
5
- --ui-hue-danger: 0;
2
+ // Base colors - override these to customize the design system
3
+ --ui-color-primary: oklch(55% 0.22 250);
4
+ --ui-color-success: oklch(60% 0.18 145);
5
+ --ui-color-warning: oklch(75% 0.18 70);
6
+ --ui-color-danger: oklch(60% 0.22 25);
7
+ --ui-color-neutral: oklch(50% 0.02 250);
6
8
 
7
- --ui-color-neutral-50: hsl(var(--ui-hue-primary) 10% 98%);
8
- --ui-color-neutral-100: hsl(var(--ui-hue-primary) 10% 96%);
9
- --ui-color-neutral-200: hsl(var(--ui-hue-primary) 10% 90%);
10
- --ui-color-neutral-300: hsl(var(--ui-hue-primary) 10% 80%);
11
- --ui-color-neutral-400: hsl(var(--ui-hue-primary) 10% 60%);
12
- --ui-color-neutral-500: hsl(var(--ui-hue-primary) 10% 45%);
13
- --ui-color-neutral-600: hsl(var(--ui-hue-primary) 10% 35%);
14
- --ui-color-neutral-700: hsl(var(--ui-hue-primary) 10% 25%);
15
- --ui-color-neutral-800: hsl(var(--ui-hue-primary) 10% 15%);
16
- --ui-color-neutral-900: hsl(var(--ui-hue-primary) 10% 10%);
9
+ // Primary shades - auto-generated via color-mix
10
+ --ui-color-primary-light: color-mix(in oklch, var(--ui-color-primary) 50%, white);
11
+ --ui-color-primary-dark: color-mix(in oklch, var(--ui-color-primary) 75%, black);
12
+ --ui-color-primary-subtle: color-mix(in oklch, var(--ui-color-primary) 12%, white);
13
+ --ui-color-primary-hover: color-mix(in oklch, var(--ui-color-primary) 85%, black);
17
14
 
18
- --ui-color-primary-light: hsl(var(--ui-hue-primary) 85% 65%);
19
- --ui-color-primary: hsl(var(--ui-hue-primary) 85% 50%);
20
- --ui-color-primary-dark: hsl(var(--ui-hue-primary) 85% 40%);
21
-
22
- --ui-color-success: hsl(var(--ui-hue-success) 70% 45%);
23
- --ui-color-warning: hsl(var(--ui-hue-warning) 90% 50%);
24
- --ui-color-danger: hsl(var(--ui-hue-danger) 70% 50%);
15
+ // Neutral scale - auto-generated via color-mix
16
+ --ui-color-neutral-50: color-mix(in oklch, var(--ui-color-neutral) 3%, white);
17
+ --ui-color-neutral-100: color-mix(in oklch, var(--ui-color-neutral) 6%, white);
18
+ --ui-color-neutral-200: color-mix(in oklch, var(--ui-color-neutral) 12%, white);
19
+ --ui-color-neutral-300: color-mix(in oklch, var(--ui-color-neutral) 25%, white);
20
+ --ui-color-neutral-400: color-mix(in oklch, var(--ui-color-neutral) 50%, white);
21
+ --ui-color-neutral-500: var(--ui-color-neutral);
22
+ --ui-color-neutral-600: color-mix(in oklch, var(--ui-color-neutral) 85%, black);
23
+ --ui-color-neutral-700: color-mix(in oklch, var(--ui-color-neutral) 70%, black);
24
+ --ui-color-neutral-800: color-mix(in oklch, var(--ui-color-neutral) 50%, black);
25
+ --ui-color-neutral-900: color-mix(in oklch, var(--ui-color-neutral) 35%, black);
25
26
  }
@@ -103,6 +103,22 @@
103
103
  background: none;
104
104
  }
105
105
 
106
+ // Links - inherit design system colors
107
+ a {
108
+ text-decoration: underline;
109
+ color: var(--ui-color-primary);
110
+
111
+ transition: color var(--ui-duration-fast) var(--ui-ease-default);
112
+
113
+ &:hover {
114
+ color: var(--ui-color-primary-hover);
115
+ }
116
+
117
+ &:visited {
118
+ color: var(--ui-color-primary);
119
+ }
120
+ }
121
+
106
122
  // ==========================================================================
107
123
  // RESPONSIVE BREAKPOINTS
108
124
  // ==========================================================================
@@ -0,0 +1,15 @@
1
+ import { resolve } from 'node:path';
2
+ import { expect, test } from '@playwright/test';
3
+ import { saveForLostPixel, setupVisualTestFromDocs } from '../../testing';
4
+
5
+ const DOCS_PATH = resolve(__dirname, 'cluster.docs.json');
6
+
7
+ test.describe('cluster visual regression', () => {
8
+ test('all variations', async ({ page }) => {
9
+ await setupVisualTestFromDocs(page, DOCS_PATH);
10
+ // skip validateGridRhythm: cluster is a layout primitive that
11
+ // controls gap/alignment, not child height
12
+ await saveForLostPixel(page, 'cluster');
13
+ await expect(page.locator('body')).toHaveScreenshot('cluster.visual.png');
14
+ });
15
+ });
@@ -0,0 +1,62 @@
1
+ {
2
+ "id": "sidebar",
3
+ "type": "primitive",
4
+ "title": "Sidebar",
5
+ "description": "Fixed-position sidebar for app layouts with adjustable widths and positioning.",
6
+ "api": "./sidebar.api.json",
7
+ "sections": [
8
+ {
9
+ "title": "Basic",
10
+ "description": "Default sidebar positioned on the start side. Use inside an app-shell layout.",
11
+ "examples": [
12
+ {
13
+ "code": "<aside class=\"ui-sidebar\">\n <p>Sidebar content</p>\n</aside>"
14
+ }
15
+ ]
16
+ },
17
+ {
18
+ "title": "Widths",
19
+ "description": "Three width options via size modifiers.",
20
+ "examples": [
21
+ {
22
+ "layout": "stack",
23
+ "items": [
24
+ {
25
+ "tag": "div",
26
+ "class": "ui-cluster",
27
+ "children": [
28
+ { "tag": "code", "text": "--sm" },
29
+ { "tag": "span", "text": "192px (24 units)" }
30
+ ]
31
+ },
32
+ {
33
+ "tag": "div",
34
+ "class": "ui-cluster",
35
+ "children": [
36
+ { "tag": "code", "text": "--md" },
37
+ { "tag": "span", "text": "240px (30 units, default)" }
38
+ ]
39
+ },
40
+ {
41
+ "tag": "div",
42
+ "class": "ui-cluster",
43
+ "children": [
44
+ { "tag": "code", "text": "--lg" },
45
+ { "tag": "span", "text": "320px (40 units)" }
46
+ ]
47
+ }
48
+ ]
49
+ }
50
+ ]
51
+ },
52
+ {
53
+ "title": "End Position",
54
+ "description": "Position sidebar on the end side with --end modifier.",
55
+ "examples": [
56
+ {
57
+ "code": "<aside class=\"ui-sidebar ui-sidebar--end\">\n <p>End sidebar</p>\n</aside>"
58
+ }
59
+ ]
60
+ }
61
+ ]
62
+ }
@@ -0,0 +1,14 @@
1
+ import { resolve } from 'node:path';
2
+ import { expect, test } from '@playwright/test';
3
+ import { saveForLostPixel, setupVisualTestFromDocs, validateGridRhythm } from '../../testing';
4
+
5
+ const DOCS_PATH = resolve(__dirname, 'sidebar.docs.json');
6
+
7
+ test.describe('sidebar visual regression', () => {
8
+ test('all variations', async ({ page }) => {
9
+ await setupVisualTestFromDocs(page, DOCS_PATH);
10
+ await validateGridRhythm(page, 'sidebar');
11
+ await saveForLostPixel(page, 'sidebar');
12
+ await expect(page.locator('body')).toHaveScreenshot('sidebar.visual.png');
13
+ });
14
+ });
@@ -1,115 +1,64 @@
1
1
  {
2
2
  "name": "sidebar-nav",
3
- "baseClass": "sidebar-nav",
4
3
  "element": "nav",
5
- "description": "Navigation component for sidebars with support for groups, nested items, icons, and badges",
6
4
  "modifiers": {
7
5
  "collapsed": {
8
- "type": "boolean",
9
- "description": "Icon-only mode, hides labels and badges"
6
+ "type": "boolean"
10
7
  }
11
8
  },
12
9
  "elements": {
13
- "header": {
14
- "element": "div",
15
- "description": "Sticky header section"
16
- },
17
- "content": {
18
- "element": "div",
19
- "description": "Scrollable content area"
20
- },
21
- "footer": {
22
- "element": "div",
23
- "description": "Sticky footer section"
24
- },
25
- "group": {
26
- "element": "div",
27
- "description": "Navigation group container"
28
- },
29
- "group-label": {
30
- "element": "span",
31
- "description": "Group section heading"
32
- },
33
- "group-items": {
34
- "element": "ul",
35
- "description": "List of nav items in a group"
36
- },
37
- "subgroup-label": {
38
- "element": "span",
39
- "description": "Nested subgroup heading"
40
- },
10
+ "header": {},
11
+ "content": {},
12
+ "footer": {},
13
+ "group": {},
14
+ "group-label": {},
15
+ "group-items": {},
16
+ "subgroup-label": {},
41
17
  "item": {
42
- "element": "a",
43
- "description": "Navigation link",
44
18
  "modifiers": {
45
19
  "active": {
46
- "type": "boolean",
47
- "description": "Current/active page state"
20
+ "type": "boolean"
48
21
  },
49
22
  "disabled": {
50
- "type": "boolean",
51
- "description": "Non-interactive item"
23
+ "type": "boolean"
52
24
  },
53
25
  "nested": {
54
- "type": "boolean",
55
- "description": "Indented nested item"
26
+ "type": "boolean"
56
27
  }
57
28
  }
58
29
  },
59
- "icon": {
60
- "element": "span",
61
- "description": "Icon container"
62
- },
63
- "label": {
64
- "element": "span",
65
- "description": "Text label"
66
- },
67
- "badge": {
68
- "element": "span",
69
- "description": "Badge or count indicator"
70
- }
71
- },
72
- "accessibility": {
73
- "role": "navigation",
74
- "aria-label": "Required - descriptive label for the navigation",
75
- "aria-current": "Use 'page' on active item link",
76
- "keyboard": "Tab navigation between focusable items"
30
+ "icon": {},
31
+ "label": {},
32
+ "badge": {}
77
33
  },
78
- "customization": [
34
+ "cssVars": [
79
35
  {
80
- "token": "--ui-sidebar-nav-width",
81
- "default": "calc(var(--ui-unit) * 30)",
82
- "description": "Default sidebar width"
36
+ "name": "--ui-sidebar-nav-width",
37
+ "default": "calc(var(--ui-unit) * 30)"
83
38
  },
84
39
  {
85
- "token": "--ui-sidebar-nav-width-collapsed",
86
- "default": "var(--ui-row-3)",
87
- "description": "Width in collapsed/icon-only mode"
40
+ "name": "--ui-sidebar-nav-width-collapsed",
41
+ "default": "var(--ui-row-3)"
88
42
  },
89
43
  {
90
- "token": "--ui-sidebar-nav-bg",
91
- "default": "var(--ui-color-bg-subtle)",
92
- "description": "Background color"
44
+ "name": "--ui-sidebar-nav-bg",
45
+ "default": "var(--ui-color-bg-subtle)"
93
46
  },
94
47
  {
95
- "token": "--ui-sidebar-nav-item-height",
96
- "default": "var(--ui-row-2)",
97
- "description": "Nav item height"
48
+ "name": "--ui-sidebar-nav-item-height",
49
+ "default": "var(--ui-row-2)"
98
50
  },
99
51
  {
100
- "token": "--ui-sidebar-nav-item-hover-bg",
101
- "default": "var(--ui-color-bg-muted)",
102
- "description": "Item hover background"
52
+ "name": "--ui-sidebar-nav-item-hover-bg",
53
+ "default": "var(--ui-color-bg-muted)"
103
54
  },
104
55
  {
105
- "token": "--ui-sidebar-nav-item-active-bg",
106
- "default": "var(--ui-color-primary-subtle)",
107
- "description": "Active item background"
56
+ "name": "--ui-sidebar-nav-item-active-bg",
57
+ "default": "var(--ui-color-primary-subtle)"
108
58
  },
109
59
  {
110
- "token": "--ui-sidebar-nav-item-active-color",
111
- "default": "var(--ui-color-primary)",
112
- "description": "Active item text color"
60
+ "name": "--ui-sidebar-nav-item-active-color",
61
+ "default": "var(--ui-color-primary)"
113
62
  }
114
63
  ]
115
64
  }
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "name": "accordion",
3
3
  "element": "div",
4
- "modifiers": {},
4
+ "modifiers": {
5
+ "separated": {
6
+ "type": "boolean"
7
+ }
8
+ },
5
9
  "cssVars": [
6
10
  {
7
11
  "name": "--ui-accordion-border-color",
@@ -6,6 +6,12 @@
6
6
  "values": ["info", "success", "warning", "danger"]
7
7
  }
8
8
  },
9
+ "elements": {
10
+ "content": {},
11
+ "title": {},
12
+ "description": {},
13
+ "icon": {}
14
+ },
9
15
  "cssVars": [
10
16
  {
11
17
  "name": "--ui-alert-padding",
@@ -5,39 +5,34 @@
5
5
 
6
6
  @layer components.tokens {
7
7
  .alert {
8
+ // Single accent color - variants override, bg/border derived via color-mix
9
+ --_accent: var(--ui-alert-accent, var(--ui-color-border, #{t.$color-border}));
10
+
8
11
  --_padding: var(--ui-alert-padding, var(--ui-space-2, #{t.$space-2}));
9
12
  --_border-width: var(--ui-alert-border-width, var(--ui-border-width-sm, #{t.$border-width-sm}));
10
13
  --_gap: var(--ui-alert-gap, var(--ui-space-1, #{t.$space-1}));
11
14
  --_radius: var(--ui-alert-radius, var(--ui-radius-md, #{t.$radius-md}));
12
- --_bg: var(--ui-alert-bg, var(--ui-color-bg-subtle, #{t.$color-bg-subtle}));
13
- --_border-color: var(--ui-alert-border-color, var(--ui-color-border, #{t.$color-border}));
15
+ --_bg: color-mix(in oklch, var(--_accent) 8%, white);
16
+ --_border-color: var(--_accent);
14
17
  --_color: var(--ui-alert-color, var(--ui-color-text, #{t.$color-text}));
15
- --_icon-color: var(--ui-alert-icon-color, currentcolor);
18
+ --_icon-color: var(--_accent);
16
19
  }
17
20
 
18
21
  // @modifier variant
19
22
  .alert--info {
20
- --_bg: var(--ui-alert-info-bg, var(--ui-color-bg-subtle, #{t.$color-bg-subtle}));
21
- --_border-color: var(--ui-alert-info-border, var(--ui-color-primary, #{t.$color-primary}));
22
- --_icon-color: var(--ui-alert-info-icon, var(--ui-color-primary, #{t.$color-primary}));
23
+ --_accent: var(--ui-color-primary, #{t.$color-primary});
23
24
  }
24
25
 
25
26
  .alert--success {
26
- --_bg: var(--ui-alert-success-bg, var(--ui-color-bg-subtle, #{t.$color-bg-subtle}));
27
- --_border-color: var(--ui-alert-success-border, var(--ui-color-success, #{t.$color-success}));
28
- --_icon-color: var(--ui-alert-success-icon, var(--ui-color-success, #{t.$color-success}));
27
+ --_accent: var(--ui-color-success, #{t.$color-success});
29
28
  }
30
29
 
31
30
  .alert--warning {
32
- --_bg: var(--ui-alert-warning-bg, var(--ui-color-bg-subtle, #{t.$color-bg-subtle}));
33
- --_border-color: var(--ui-alert-warning-border, var(--ui-color-warning, #{t.$color-warning}));
34
- --_icon-color: var(--ui-alert-warning-icon, var(--ui-color-warning, #{t.$color-warning}));
31
+ --_accent: var(--ui-color-warning, #{t.$color-warning});
35
32
  }
36
33
 
37
34
  .alert--danger {
38
- --_bg: var(--ui-alert-danger-bg, var(--ui-color-bg-subtle, #{t.$color-bg-subtle}));
39
- --_border-color: var(--ui-alert-danger-border, var(--ui-color-danger, #{t.$color-danger}));
40
- --_icon-color: var(--ui-alert-danger-icon, var(--ui-color-danger, #{t.$color-danger}));
35
+ --_accent: var(--ui-color-danger, #{t.$color-danger});
41
36
  }
42
37
  }
43
38
 
@@ -9,6 +9,11 @@
9
9
  "type": "boolean"
10
10
  }
11
11
  },
12
+ "elements": {
13
+ "fallback": {},
14
+ "image": {}
15
+ },
16
+ "relatedComponents": ["avatar-group"],
12
17
  "cssVars": [
13
18
  {
14
19
  "name": "--ui-avatar-size",
@@ -5,12 +5,15 @@
5
5
 
6
6
  @layer components.tokens {
7
7
  .badge {
8
+ // Single accent color - variants override this
9
+ --_accent: var(--ui-badge-accent, var(--ui-color-bg-muted, #{t.$color-bg-muted}));
10
+
8
11
  --_height: var(--ui-badge-height, calc(var(--ui-row, #{t.$row}) * 1.25));
9
12
  --_padding-x: var(--ui-badge-padding-x, var(--ui-space-1, #{t.$space-1}));
10
13
  --_font-size: var(--ui-badge-font-size, var(--ui-font-size-xs, #{t.$font-size-xs}));
11
14
  --_font-weight: var(--ui-badge-font-weight, var(--ui-weight-medium, #{t.$weight-medium}));
12
15
  --_radius: var(--ui-badge-radius, var(--ui-radius-full, #{t.$radius-full}));
13
- --_bg: var(--ui-badge-bg, var(--ui-color-bg-muted, #{t.$color-bg-muted}));
16
+ --_bg: var(--_accent);
14
17
  --_text: var(--ui-badge-text, var(--ui-color-text, #{t.$color-text}));
15
18
  }
16
19
 
@@ -23,23 +26,23 @@
23
26
 
24
27
  // @modifier variant
25
28
  .badge--primary {
26
- --_bg: var(--ui-badge-primary-bg, var(--ui-color-primary, #{t.$color-primary}));
27
- --_text: var(--ui-badge-primary-text, var(--ui-color-text-inverse, #{t.$color-text-inverse}));
29
+ --_accent: var(--ui-color-primary, #{t.$color-primary});
30
+ --_text: var(--ui-color-text-inverse, #{t.$color-text-inverse});
28
31
  }
29
32
 
30
33
  .badge--success {
31
- --_bg: var(--ui-badge-success-bg, var(--ui-color-success, #{t.$color-success}));
32
- --_text: var(--ui-badge-success-text, var(--ui-color-text-inverse, #{t.$color-text-inverse}));
34
+ --_accent: var(--ui-color-success, #{t.$color-success});
35
+ --_text: var(--ui-color-text-inverse, #{t.$color-text-inverse});
33
36
  }
34
37
 
35
38
  .badge--warning {
36
- --_bg: var(--ui-badge-warning-bg, var(--ui-color-warning, #{t.$color-warning}));
37
- --_text: var(--ui-badge-warning-text, var(--ui-color-text, #{t.$color-text}));
39
+ --_accent: var(--ui-color-warning, #{t.$color-warning});
40
+ --_text: var(--ui-color-text, #{t.$color-text});
38
41
  }
39
42
 
40
43
  .badge--danger {
41
- --_bg: var(--ui-badge-danger-bg, var(--ui-color-danger, #{t.$color-danger}));
42
- --_text: var(--ui-badge-danger-text, var(--ui-color-text-inverse, #{t.$color-text-inverse}));
44
+ --_accent: var(--ui-color-danger, #{t.$color-danger});
45
+ --_text: var(--ui-color-text-inverse, #{t.$color-text-inverse});
43
46
  }
44
47
  }
45
48
 
@@ -2,6 +2,11 @@
2
2
  "name": "breadcrumb",
3
3
  "element": "div",
4
4
  "modifiers": {},
5
+ "elements": {
6
+ "item": {},
7
+ "link": {},
8
+ "current": {}
9
+ },
5
10
  "cssVars": [
6
11
  {
7
12
  "name": "--ui-breadcrumb-height",