ui-foundations 0.3.2 → 0.4.1

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 (69) hide show
  1. package/README.md +179 -36
  2. package/dist/assets/icons/checkmark.svg +1 -0
  3. package/dist/core/index.css +7 -7
  4. package/dist/macros/ui.njk +142 -0
  5. package/dist/main.css +465 -173
  6. package/dist/react/badge.js +41 -0
  7. package/dist/react/button.js +15 -6
  8. package/dist/react/checkbox.js +30 -0
  9. package/dist/react/icon.js +19 -1
  10. package/dist/react/index.js +2 -0
  11. package/dist/react/label.js +1 -1
  12. package/dist/react/radio.js +62 -0
  13. package/dist/react/switch.js +18 -0
  14. package/dist/tokens/css/{appearance-(modes).tokens.mode-dark.css → appearance-modes.tokens.mode-dark.css} +1 -1
  15. package/dist/tokens/css/{appearance-(modes).tokens.mode-light.css → appearance-modes.tokens.mode-light.css} +1 -1
  16. package/dist/tokens/css/{components-(ui).tokens.css → components-ui.tokens.css} +46 -3
  17. package/dist/tokens/css/{core-(primitives).tokens.css → core-primitives.tokens.css} +61 -19
  18. package/dist/tokens/css/{semantics-(roles).tokens.css → semantics-roles.tokens.css} +1 -1
  19. package/dist/tokens/css/themes-brands.tokens.brand-a.css +22 -0
  20. package/dist/tokens/css/{themes-(brands).tokens.brand-b.css → themes-brands.tokens.brand-b.css} +9 -9
  21. package/dist/tokens/json/appearance-modes.tokens.mode-dark.json +121 -0
  22. package/dist/tokens/json/appearance-modes.tokens.mode-light.json +121 -0
  23. package/dist/tokens/json/components-ui.tokens.json +715 -0
  24. package/dist/tokens/json/{core-(primitives).tokens.json → core-primitives.tokens.json} +227 -413
  25. package/dist/tokens/json/semantics-roles.tokens.json +141 -0
  26. package/dist/tokens/json/themes-brands.tokens.brand-a.json +81 -0
  27. package/dist/tokens/json/themes-brands.tokens.brand-b.json +81 -0
  28. package/dist/tokens/missing-tokens.json +43 -0
  29. package/dist/tokens/tokens.yaml +1254 -149
  30. package/dist/tokens/ts/{appearance-(modes).tokens.mode-dark.ts → appearance-modes.tokens.mode-dark.ts} +1 -1
  31. package/dist/tokens/ts/{appearance-(modes).tokens.mode-light.ts → appearance-modes.tokens.mode-light.ts} +1 -1
  32. package/dist/tokens/ts/{components-(ui).tokens.ts → components-ui.tokens.ts} +47 -4
  33. package/dist/tokens/ts/{core-(primitives).tokens.ts → core-primitives.tokens.ts} +62 -20
  34. package/dist/tokens/ts/{semantics-(roles).tokens.ts → semantics-roles.tokens.ts} +1 -1
  35. package/dist/tokens/ts/{themes-(brands).tokens.brand-a.ts → themes-brands.tokens.brand-a.ts} +9 -9
  36. package/dist/tokens/ts/{themes-(brands).tokens.brand-b.ts → themes-brands.tokens.brand-b.ts} +9 -9
  37. package/dist/ui/index.css +2 -0
  38. package/dist/ui/patterns/badge.css +49 -0
  39. package/dist/ui/patterns/checkbox.css +71 -22
  40. package/dist/ui/patterns/radio.css +109 -0
  41. package/docs/README.md +38 -0
  42. package/docs/agentic/README.md +34 -0
  43. package/docs/agentic/assistant-behavior-rules.md +48 -0
  44. package/docs/agentic/skills/ux-writing-coach.md +116 -0
  45. package/docs/foundations/README.md +31 -0
  46. package/docs/foundations/foundation-001-token-layering.md +6 -0
  47. package/docs/foundations/foundation-002-naming-and-grouping.md +6 -0
  48. package/docs/foundations/foundation-003-color-semantics-and-status.md +6 -0
  49. package/docs/foundations/foundation-004-typography-scale-and-line-height.md +6 -0
  50. package/docs/foundations/foundation-005-responsive-breakpoints-and-containers.md +6 -0
  51. package/docs/foundations/foundation-006-z-index-layering.md +6 -0
  52. package/docs/foundations/foundation-007-typography-selectors-and-specificity.md +6 -0
  53. package/docs/foundations/foundation-008-mode-activation-and-consumer-control.md +6 -0
  54. package/docs/foundations/foundation-009-component-boundaries-and-utility.md +6 -0
  55. package/docs/foundations/foundation-010-implementation-and-pipeline-workflow.md +6 -0
  56. package/docs/foundations/foundation-011-branching-and-release-governance.md +6 -0
  57. package/docs/foundations/foundation-012-minimal-markup-and-composition.md +6 -0
  58. package/package.json +15 -11
  59. package/dist/tokens/css/themes-(brands).tokens.brand-a.css +0 -22
  60. package/dist/tokens/json/appearance-(modes).tokens.mode-dark.json +0 -182
  61. package/dist/tokens/json/appearance-(modes).tokens.mode-light.json +0 -182
  62. package/dist/tokens/json/components-(ui).tokens.json +0 -739
  63. package/dist/tokens/json/semantics-(roles).tokens.json +0 -203
  64. package/dist/tokens/json/themes-(brands).tokens.brand-a.json +0 -115
  65. package/dist/tokens/json/themes-(brands).tokens.brand-b.json +0 -115
  66. package/docs/agentic/skills/README.md +0 -51
  67. package/docs/agentic/skills/design-ops-specialist/SKILL.md +0 -60
  68. package/docs/agentic/skills/design-system-architect/SKILL.md +0 -106
  69. package/docs/agentic/team-ai-playbook.md +0 -226
@@ -0,0 +1,41 @@
1
+ import React from "react";
2
+ import { Icon } from "./icon.js";
3
+
4
+ export function Badge({
5
+ children,
6
+ text,
7
+ variant = "default",
8
+ size = "md",
9
+ startIcon,
10
+ className = "",
11
+ ...props
12
+ }) {
13
+ const content = children ?? text;
14
+ const classes = ["badge"];
15
+
16
+ if (variant && variant !== "default") classes.push(variant);
17
+ if (size === "sm") classes.push("sm");
18
+ if (className) classes.push(className);
19
+
20
+ const iconElement =
21
+ startIcon && typeof startIcon === "string"
22
+ ? React.createElement(Icon, {
23
+ name: startIcon,
24
+ decorative: true,
25
+ })
26
+ : startIcon && React.isValidElement(startIcon)
27
+ ? startIcon
28
+ : null;
29
+
30
+ return React.createElement(
31
+ "span",
32
+ {
33
+ className: classes.join(" "),
34
+ ...props,
35
+ },
36
+ iconElement,
37
+ content != null
38
+ ? React.createElement("span", { className: "badge__text" }, content)
39
+ : null,
40
+ );
41
+ }
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { LabelContent } from "./label.js";
2
+ import { LabelContent, hasTextContent } from "./label.js";
3
3
 
4
4
  function normalizeOrientation(value) {
5
5
  return value === "vertical" ? "vertical" : "horizontal";
@@ -9,6 +9,18 @@ function normalizeJustify(value) {
9
9
  return value === "stretch" ? "stretch" : "start";
10
10
  }
11
11
 
12
+ function warnDev(message) {
13
+ if (
14
+ typeof process !== "undefined" &&
15
+ process.env &&
16
+ process.env.NODE_ENV === "production"
17
+ ) {
18
+ return;
19
+ }
20
+
21
+ console.warn(message);
22
+ }
23
+
12
24
  export function Button({
13
25
  variant = "solid",
14
26
  className = "",
@@ -28,10 +40,7 @@ export function Button({
28
40
  if (className) classes.push(className);
29
41
 
30
42
  const content = children ?? label;
31
- const hasReadableLabel =
32
- typeof content === "string"
33
- ? content.trim().length > 0
34
- : content !== null && content !== undefined && content !== false;
43
+ const hasReadableLabel = hasTextContent(content);
35
44
  const resolvedIconOnly = iconOnly ?? !hasReadableLabel;
36
45
  const iconStart = resolvedIconOnly ? startIcon || endIcon : startIcon;
37
46
  const iconEnd = resolvedIconOnly ? undefined : endIcon;
@@ -49,7 +58,7 @@ export function Button({
49
58
  }
50
59
 
51
60
  if (resolvedIconOnly && !buttonProps["aria-label"]) {
52
- console.warn(
61
+ warnDev(
53
62
  "[ui-foundations] iconOnly Button should include `ariaLabel` or `aria-label`.",
54
63
  );
55
64
  }
@@ -7,25 +7,55 @@ function hasLabelContent(value) {
7
7
  return true;
8
8
  }
9
9
 
10
+ function warnDev(message) {
11
+ if (
12
+ typeof process !== "undefined" &&
13
+ process.env &&
14
+ process.env.NODE_ENV === "production"
15
+ ) {
16
+ return;
17
+ }
18
+
19
+ console.warn(message);
20
+ }
21
+
10
22
  export function Checkbox({
11
23
  className = "",
12
24
  wrapperClassName = "",
13
25
  label,
14
26
  children,
27
+ indeterminate = false,
15
28
  ...props
16
29
  }) {
17
30
  const classes = ["checkbox"];
31
+ if (indeterminate) classes.push("is-indeterminate");
18
32
  if (className) classes.push(className);
19
33
 
20
34
  const content = children ?? label;
21
35
  const hasLabel = hasLabelContent(content);
22
36
  const disabled = Boolean(props.disabled);
37
+ const inputRef = React.useRef(null);
38
+
39
+ React.useEffect(() => {
40
+ if (!inputRef.current) return;
41
+ inputRef.current.indeterminate = Boolean(indeterminate);
42
+ }, [indeterminate]);
43
+
23
44
  const input = React.createElement("input", {
24
45
  type: "checkbox",
25
46
  className: classes.join(" "),
47
+ "aria-checked":
48
+ props["aria-checked"] ?? (indeterminate ? "mixed" : undefined),
49
+ ref: inputRef,
26
50
  ...props,
27
51
  });
28
52
 
53
+ if (!hasLabel && !props["aria-label"] && !props["aria-labelledby"]) {
54
+ warnDev(
55
+ "[ui-foundations] Checkbox should include visible label content or `aria-label`/`aria-labelledby`.",
56
+ );
57
+ }
58
+
29
59
  if (!hasLabel) return input;
30
60
 
31
61
  const wrapperClasses = ["checkbox-field"];
@@ -11,6 +11,18 @@ function humanizeName(name) {
11
11
  .trim();
12
12
  }
13
13
 
14
+ function warnDev(message) {
15
+ if (
16
+ typeof process !== "undefined" &&
17
+ process.env &&
18
+ process.env.NODE_ENV === "production"
19
+ ) {
20
+ return;
21
+ }
22
+
23
+ console.warn(message);
24
+ }
25
+
14
26
  export function Icon({
15
27
  name,
16
28
  src,
@@ -37,8 +49,14 @@ export function Icon({
37
49
  if (isDecorative) {
38
50
  accessibilityProps["aria-hidden"] = true;
39
51
  } else {
52
+ const accessibleLabel = label || humanizeName(name);
53
+ if (!accessibleLabel) {
54
+ warnDev(
55
+ "[ui-foundations] Non-decorative Icon should include a readable `label` or `name`.",
56
+ );
57
+ }
40
58
  accessibilityProps.role = "img";
41
- accessibilityProps["aria-label"] = label || humanizeName(name);
59
+ accessibilityProps["aria-label"] = accessibleLabel;
42
60
  }
43
61
 
44
62
  return React.createElement("span", {
@@ -3,4 +3,6 @@ export { Checkbox } from "./checkbox.js";
3
3
  export { Icon } from "./icon.js";
4
4
  export { Input } from "./input.js";
5
5
  export { LabelContent, FieldLabel } from "./label.js";
6
+ export { Radio } from "./radio.js";
6
7
  export { Switch } from "./switch.js";
8
+ export { Badge } from "./badge.js";
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { Icon } from "./icon.js";
3
3
 
4
- function hasTextContent(value) {
4
+ export function hasTextContent(value) {
5
5
  if (value === null || value === undefined || value === false) return false;
6
6
  if (typeof value === "string") return value.trim().length > 0;
7
7
  if (Array.isArray(value)) return value.some(hasTextContent);
@@ -0,0 +1,62 @@
1
+ import React from "react";
2
+
3
+ function hasLabelContent(value) {
4
+ if (value === null || value === undefined || value === false) return false;
5
+ if (typeof value === "string") return value.trim().length > 0;
6
+ if (Array.isArray(value)) return value.some(hasLabelContent);
7
+ return true;
8
+ }
9
+
10
+ function warnDev(message) {
11
+ if (
12
+ typeof process !== "undefined" &&
13
+ process.env &&
14
+ process.env.NODE_ENV === "production"
15
+ ) {
16
+ return;
17
+ }
18
+
19
+ console.warn(message);
20
+ }
21
+
22
+ export function Radio({
23
+ className = "",
24
+ wrapperClassName = "",
25
+ label,
26
+ children,
27
+ ...props
28
+ }) {
29
+ const classes = ["radio"];
30
+ if (className) classes.push(className);
31
+
32
+ const content = children ?? label;
33
+ const hasLabel = hasLabelContent(content);
34
+ const disabled = Boolean(props.disabled);
35
+
36
+ const input = React.createElement("input", {
37
+ type: "radio",
38
+ className: classes.join(" "),
39
+ ...props,
40
+ });
41
+
42
+ if (!hasLabel && !props["aria-label"] && !props["aria-labelledby"]) {
43
+ warnDev(
44
+ "[ui-foundations] Radio should include visible label content or `aria-label`/`aria-labelledby`.",
45
+ );
46
+ }
47
+
48
+ if (!hasLabel) return input;
49
+
50
+ const wrapperClasses = ["radio-field"];
51
+ if (disabled) wrapperClasses.push("is-disabled");
52
+ if (wrapperClassName) wrapperClasses.push(wrapperClassName);
53
+
54
+ return React.createElement(
55
+ "label",
56
+ {
57
+ className: wrapperClasses.join(" "),
58
+ },
59
+ input,
60
+ React.createElement("span", { className: "radio-field__text" }, content),
61
+ );
62
+ }
@@ -7,6 +7,18 @@ function hasLabelContent(value) {
7
7
  return true;
8
8
  }
9
9
 
10
+ function warnDev(message) {
11
+ if (
12
+ typeof process !== "undefined" &&
13
+ process.env &&
14
+ process.env.NODE_ENV === "production"
15
+ ) {
16
+ return;
17
+ }
18
+
19
+ console.warn(message);
20
+ }
21
+
10
22
  export function Switch({
11
23
  className = "",
12
24
  wrapperClassName = "",
@@ -28,6 +40,12 @@ export function Switch({
28
40
  ...props,
29
41
  });
30
42
 
43
+ if (!hasLabel && !props["aria-label"] && !props["aria-labelledby"]) {
44
+ warnDev(
45
+ "[ui-foundations] Switch should include visible label content or `aria-label`/`aria-labelledby`.",
46
+ );
47
+ }
48
+
31
49
  if (!hasLabel) return input;
32
50
 
33
51
  const wrapperClasses = ["switch-field"];
@@ -1,5 +1,5 @@
1
1
  /* Auto-generated design tokens from Figma */
2
- /* Generated on 2026-03-31T20:27:09.721Z */
2
+ /* Generated on 2026-04-28T09:23:28.554Z */
3
3
 
4
4
  :root[data-mode="dark"] {
5
5
  --color-text-default: var(--color-neutral-800);
@@ -1,5 +1,5 @@
1
1
  /* Auto-generated design tokens from Figma */
2
- /* Generated on 2026-03-31T20:27:09.718Z */
2
+ /* Generated on 2026-04-28T09:23:28.552Z */
3
3
 
4
4
  :root {
5
5
  --color-text-default: var(--color-neutral-800);
@@ -1,5 +1,5 @@
1
1
  /* Auto-generated design tokens from Figma */
2
- /* Generated on 2026-03-31T20:27:09.724Z */
2
+ /* Generated on 2026-04-28T09:23:28.559Z */
3
3
 
4
4
  :root {
5
5
  --button-border-size-hover: var(--size-border-100);
@@ -92,18 +92,41 @@
92
92
  --input-overlay-active: var(--color-transparent);
93
93
  --input-height: 2.5rem;
94
94
  --input-checkbox-text-color-default: var(--color-text-default);
95
- --input-checkbox-text-color-hover: var(--color-text-default);
95
+ --input-checkbox-text-color-hover: var(--color-text-strong);
96
96
  --input-checkbox-text-color-active: var(--color-text-inverse);
97
97
  --input-checkbox-border-color-default: var(--color-border-subtle);
98
- --input-checkbox-border-color-hover: var(--color-border-brand);
98
+ --input-checkbox-border-color-hover: var(--color-border-strong);
99
99
  --input-checkbox-border-color-active: var(--color-border-brand);
100
100
  --input-checkbox-border-color-focus: var(--color-border-brand);
101
101
  --input-checkbox-border-color-invalid: var(--color-border-danger);
102
102
  --input-checkbox-border-color-valid: var(--color-border-strong);
103
+ --input-checkbox-border-color-disabled: var(--color-border-disabled);
103
104
  --input-checkbox-container-background-default: var(--color-fill-surface);
104
105
  --input-checkbox-container-background-hover: var(--color-fill-surface);
105
106
  --input-checkbox-container-background-focus: var(--color-fill-surface);
106
107
  --input-checkbox-container-background-active: var(--color-fill-brand);
108
+ --input-checkbox-container-background-disabled: var(--color-fill-disabled);
109
+ --input-checkbox-text-color-disabled: var(--color-text-disabled);
110
+ --checkbox-border-size-hover: var(--size-border-200);
111
+ --checkbox-border-size-disabled: var(--size-border-000);
112
+ --checkbox-border-size-default: var(--size-border-100);
113
+ --input-radio-text-color-default: var(--color-text-default);
114
+ --input-radio-text-color-hover: var(--color-text-strong);
115
+ --input-radio-text-color-active: var(--color-text-inverse);
116
+ --input-radio-text-color-disabled: var(--color-text-disabled);
117
+ --input-radio-border-color-default: var(--color-border-subtle);
118
+ --input-radio-border-color-hover: var(--color-border-strong);
119
+ --input-radio-border-color-active: var(--color-border-brand);
120
+ --input-radio-border-color-focus: var(--color-border-brand);
121
+ --input-radio-border-color-disabled: var(--color-border-disabled);
122
+ --input-radio-container-background-default: var(--color-fill-surface);
123
+ --input-radio-container-background-hover: var(--color-fill-surface);
124
+ --input-radio-container-background-focus: var(--color-fill-surface);
125
+ --input-radio-container-background-active: var(--color-fill-brand);
126
+ --input-radio-container-background-disabled: var(--color-fill-disabled);
127
+ --radio-border-size-default: var(--size-border-100);
128
+ --radio-border-size-hover: var(--size-border-200);
129
+ --radio-border-size-disabled: var(--size-border-000);
107
130
  --form-group-gap: var(--size-spacing-400);
108
131
  --form-group-title-color: var(--color-text-default);
109
132
  --form-padding-inline: var(--size-spacing-400);
@@ -116,4 +139,24 @@
116
139
  --form-container-background: var(--color-fill-surface);
117
140
  --form-container-border-color: var(--color-border-subtle);
118
141
  --form-border-size: var(--size-border-100);
142
+ --badge-default-container-background: var(--color-fill-subtle);
143
+ --badge-default-text-color: var(--color-text-default);
144
+ --badge-brand-container-background: var(--color-fill-brand);
145
+ --badge-brand-text-color: var(--color-text-inverse);
146
+ --badge-success-container-background: var(--color-fill-success);
147
+ --badge-success-text-color: var(--color-text-inverse);
148
+ --badge-danger-container-background: var(--color-fill-danger);
149
+ --badge-danger-text-color: var(--color-text-inverse);
150
+ --badge-border-radius: var(--size-radius-full);
151
+ --badge-font-family: var(--typography-label-font-family);
152
+ --badge-font-weight: var(--font-weight-700);
153
+ --badge-font-size-sm: var(--font-size-xs);
154
+ --badge-font-size-md: var(--font-size-sm);
155
+ --badge-line-height-sm: var(--line-height-xs);
156
+ --badge-line-height-md: var(--line-height-sm);
157
+ --badge-padding-inline-sm: var(--size-spacing-200);
158
+ --badge-padding-inline-md: var(--size-spacing-300);
159
+ --badge-padding-block-sm: var(--size-spacing-000);
160
+ --badge-padding-block-md: var(--size-spacing-100);
161
+ --badge-gap: var(--size-spacing-100);
119
162
  }
@@ -1,5 +1,5 @@
1
1
  /* Auto-generated design tokens from Figma */
2
- /* Generated on 2026-03-31T20:27:09.731Z */
2
+ /* Generated on 2026-04-28T09:23:28.563Z */
3
3
 
4
4
  :root {
5
5
  --color-neutral-100: rgb(230 230 230);
@@ -23,25 +23,67 @@
23
23
  --color-neutral-alpha-900: rgba(0 0 0 / 0.9);
24
24
  --color-neutral-alpha-000: rgba(0 0 0 / 0);
25
25
  --color-neutral-000: rgb(255 255 255);
26
- --color-brand-a-purple-200: rgb(222 192 255);
27
- --color-brand-a-purple-600: rgb(151 71 255);
28
- --color-brand-a-purple-800: rgb(85 26 139);
29
- --color-brand-a-blue-200: rgb(226 244 253);
30
- --color-brand-a-blue-500: rgb(112 203 244);
31
- --color-brand-a-blue-700: rgb(12 75 243);
32
- --color-brand-a-blue-800: rgb(27 17 92);
33
- --color-brand-a-green: rgb(19 174 92);
34
- --color-brand-a-red: rgb(255 0 0);
35
- --color-brand-b-purple-200: rgb(196 143 255);
36
- --color-brand-b-purple-600: rgb(122 20 255);
37
- --color-brand-b-purple-800: rgb(58 18 95);
38
- --color-brand-b-blue-200: rgb(179 226 250);
39
- --color-brand-b-blue-500: rgb(66 186 240);
40
- --color-brand-b-blue-700: rgb(10 60 194);
41
- --color-brand-b-blue-800: rgb(14 9 47);
42
- --color-brand-b-red: rgb(204 0 0);
43
- --color-brand-b-green: rgb(14 129 68);
26
+ --color-brand-b-purple-200: rgb(222 192 255);
27
+ --color-brand-b-purple-300: rgb(196 143 255);
28
+ --color-brand-b-purple-600: rgb(151 71 255);
29
+ --color-brand-b-purple-700: rgb(122 20 255);
30
+ --color-brand-b-purple-800: rgb(85 26 139);
31
+ --color-brand-b-purple-900: rgb(58 18 95);
32
+ --color-brand-b-blue-100: rgb(206 219 253);
33
+ --color-brand-b-blue-200: rgb(158 183 250);
34
+ --color-brand-b-blue-300: rgb(109 147 248);
35
+ --color-brand-b-blue-400: rgb(61 111 245);
36
+ --color-brand-b-blue-500: rgb(12 75 243);
37
+ --color-brand-b-blue-600: rgb(10 60 194);
38
+ --color-brand-b-blue-700: rgb(7 45 146);
39
+ --color-brand-b-blue-800: rgb(5 30 97);
40
+ --color-brand-b-blue-900: rgb(2 15 49);
41
+ --color-brand-b-red-100: rgb(255 255 255);
42
+ --color-brand-b-red-200: rgb(255 204 204);
43
+ --color-brand-b-red-300: rgb(255 153 153);
44
+ --color-brand-b-red-400: rgb(255 102 102);
45
+ --color-brand-b-red-500: rgb(255 51 51);
46
+ --color-brand-b-red-600: rgb(255 0 0);
47
+ --color-brand-b-red-700: rgb(153 0 0);
48
+ --color-brand-b-red-800: rgb(102 0 0);
49
+ --color-brand-b-red-900: rgb(51 0 0);
50
+ --color-brand-b-green-100: rgb(246 254 250);
51
+ --color-brand-b-green-200: rgb(200 249 223);
52
+ --color-brand-b-green-300: rgb(154 244 196);
53
+ --color-brand-b-green-400: rgb(108 239 170);
54
+ --color-brand-b-green-500: rgb(62 234 143);
55
+ --color-brand-b-green-600: rgb(19 174 92);
56
+ --color-brand-b-green-700: rgb(14 129 68);
57
+ --color-brand-b-green-800: rgb(8 69 36);
58
+ --color-brand-b-green-900: rgb(4 37 19);
44
59
  --color-transparent: rgba(0 0 0 / 0);
60
+ --color-brand-a-green-100: rgb(243 246 233);
61
+ --color-brand-a-green-200: rgb(223 231 197);
62
+ --color-brand-a-green-300: rgb(207 219 169);
63
+ --color-brand-a-green-400: rgb(191 207 140);
64
+ --color-brand-a-green-500: rgb(175 195 111);
65
+ --color-brand-a-green-600: rgb(159 183 82);
66
+ --color-brand-a-green-700: rgb(137 158 66);
67
+ --color-brand-a-green-800: rgb(112 129 54);
68
+ --color-brand-a-green-900: rgb(81 93 39);
69
+ --color-brand-a-red-100: rgb(254 251 251);
70
+ --color-brand-a-red-200: rgb(250 224 230);
71
+ --color-brand-a-red-300: rgb(244 179 195);
72
+ --color-brand-a-red-400: rgb(238 135 160);
73
+ --color-brand-a-red-500: rgb(231 90 124);
74
+ --color-brand-a-red-600: rgb(225 46 89);
75
+ --color-brand-a-red-700: rgb(191 28 67);
76
+ --color-brand-a-red-800: rgb(147 21 52);
77
+ --color-brand-a-red-900: rgb(102 15 36);
78
+ --color-brand-a-sand-100: rgb(240 240 229);
79
+ --color-brand-a-sand-200: rgb(221 222 197);
80
+ --color-brand-a-sand-300: rgb(192 193 172);
81
+ --color-brand-a-sand-400: rgb(164 165 147);
82
+ --color-brand-a-sand-500: rgb(136 137 122);
83
+ --color-brand-a-sand-600: rgb(108 109 97);
84
+ --color-brand-a-sand-700: rgb(80 81 72);
85
+ --color-brand-a-sand-800: rgb(52 52 47);
86
+ --color-brand-a-sand-900: rgb(24 24 22);
45
87
  --font-size-md: 1rem;
46
88
  --font-size-xs: .75rem;
47
89
  --font-size-sm: .875rem;
@@ -1,5 +1,5 @@
1
1
  /* Auto-generated design tokens from Figma */
2
- /* Generated on 2026-03-31T20:27:09.733Z */
2
+ /* Generated on 2026-04-28T09:23:28.564Z */
3
3
 
4
4
  :root {
5
5
  --typography-heading-font-family: var(--brand-font-lead);
@@ -0,0 +1,22 @@
1
+ /* Auto-generated design tokens from Figma */
2
+ /* Generated on 2026-04-28T09:23:28.565Z */
3
+
4
+ :root[data-brand="a"] {
5
+ --brand-color-functional-success: var(--color-brand-a-green-600);
6
+ --brand-color-functional-danger: var(--color-brand-a-red-600);
7
+ --brand-color-functional-base: var(--color-brand-a-green-700);
8
+ --brand-color-functional-base-dark: var(--color-brand-a-green-900);
9
+ --brand-color-primary: var(--color-brand-a-sand-700);
10
+ --brand-color-accent: var(--color-brand-a-green-400);
11
+ --brand-color-primary-dark: var(--color-brand-a-sand-900);
12
+ --brand-color-accent-dark: var(--color-brand-a-green-600);
13
+ --brand-color-subtle: var(--color-neutral-500);
14
+ --brand-color-subtle-dark: var(--color-neutral-800);
15
+ --brand-color-subtle-light: var(--color-neutral-200);
16
+ --brand-font-base: var(--font-family-sans);
17
+ --brand-font-lead: var(--font-family-serif);
18
+ --brand-corner-button: var(--size-radius-700);
19
+ --brand-corner-card: var(--size-radius-200);
20
+ --brand-corner-modal: var(--size-radius-400);
21
+ --brand-corner-input: var(--size-radius-200);
22
+ }
@@ -1,15 +1,15 @@
1
1
  /* Auto-generated design tokens from Figma */
2
- /* Generated on 2026-03-31T20:27:09.734Z */
2
+ /* Generated on 2026-04-28T09:23:28.567Z */
3
3
 
4
4
  :root[data-brand="b"] {
5
- --brand-color-functional-success: var(--color-brand-b-green);
6
- --brand-color-functional-danger: var(--color-brand-b-red);
7
- --brand-color-functional-base: var(--color-brand-b-purple-600);
8
- --brand-color-functional-base-dark: var(--color-brand-b-purple-800);
9
- --brand-color-primary: var(--color-brand-b-blue-500);
10
- --brand-color-accent: var(--color-brand-b-purple-600);
11
- --brand-color-primary-dark: var(--color-brand-b-blue-700);
12
- --brand-color-accent-dark: var(--color-brand-b-purple-800);
5
+ --brand-color-functional-success: var(--color-brand-b-green-600);
6
+ --brand-color-functional-danger: var(--color-brand-b-red-600);
7
+ --brand-color-functional-base: var(--color-brand-b-purple-700);
8
+ --brand-color-functional-base-dark: var(--color-brand-b-purple-900);
9
+ --brand-color-primary: var(--color-brand-b-purple-600);
10
+ --brand-color-accent: var(--color-brand-b-green-400);
11
+ --brand-color-primary-dark: var(--color-brand-b-purple-800);
12
+ --brand-color-accent-dark: var(--color-brand-b-green-800);
13
13
  --brand-color-subtle: var(--color-neutral-500);
14
14
  --brand-color-subtle-dark: var(--color-neutral-800);
15
15
  --brand-color-subtle-light: var(--color-neutral-200);
@@ -0,0 +1,121 @@
1
+ {
2
+ "$schema": "https://www.designtokens.org/schemas/2025.10/format.json",
3
+ "Color": {
4
+ "Text": {
5
+ "Default": {
6
+ "$type": "color",
7
+ "$value": "{Color.Neutral.800}"
8
+ },
9
+ "Inverse": {
10
+ "$type": "color",
11
+ "$value": "{Color.Neutral.000}"
12
+ },
13
+ "Disabled": {
14
+ "$type": "color",
15
+ "$value": "{Color.Neutral.600}"
16
+ },
17
+ "Brand": {
18
+ "$type": "color",
19
+ "$value": "{Brand.Color.Primary}"
20
+ },
21
+ "Subtle": {
22
+ "$type": "color",
23
+ "$value": "{Brand.Color.Subtle}"
24
+ },
25
+ "Strong": {
26
+ "$type": "color",
27
+ "$value": "{Color.Neutral.1000}"
28
+ },
29
+ "Danger": {
30
+ "$type": "color",
31
+ "$value": "{Brand.Color.Functional.Danger}"
32
+ },
33
+ "Success": {
34
+ "$type": "color",
35
+ "$value": "{Brand.Color.Functional.Success}"
36
+ }
37
+ },
38
+ "Fill": {
39
+ "Surface": {
40
+ "$type": "color",
41
+ "$value": "{Color.Neutral.000}"
42
+ },
43
+ "Disabled": {
44
+ "$type": "color",
45
+ "$value": "{Color.Neutral.300}"
46
+ },
47
+ "Hover": {
48
+ "$type": "color",
49
+ "$value": "{Color.Neutral.Alpha.500}"
50
+ },
51
+ "Brand": {
52
+ "$type": "color",
53
+ "$value": "{Brand.Color.Primary}"
54
+ },
55
+ "Subtle": {
56
+ "$type": "color",
57
+ "$value": "{Brand.Color.Subtle Light}"
58
+ },
59
+ "Active": {
60
+ "$type": "color",
61
+ "$value": "{Brand.Color.Accent}"
62
+ },
63
+ "Danger": {
64
+ "$type": "color",
65
+ "$value": "{Brand.Color.Functional.Danger}"
66
+ },
67
+ "Success": {
68
+ "$type": "color",
69
+ "$value": "{Brand.Color.Functional.Success}"
70
+ }
71
+ },
72
+ "Border": {
73
+ "Default": {
74
+ "$type": "color",
75
+ "$value": "{Color.Neutral.800}"
76
+ },
77
+ "Subtle": {
78
+ "$type": "color",
79
+ "$value": "{Brand.Color.Subtle}"
80
+ },
81
+ "Strong": {
82
+ "$type": "color",
83
+ "$value": "{Color.Neutral.1000}"
84
+ },
85
+ "Brand": {
86
+ "$type": "color",
87
+ "$value": "{Brand.Color.Primary}"
88
+ },
89
+ "Disabled": {
90
+ "$type": "color",
91
+ "$value": "{Color.Neutral.500}"
92
+ },
93
+ "Danger": {
94
+ "$type": "color",
95
+ "$value": "#ff0000"
96
+ }
97
+ },
98
+ "Overlay": {
99
+ "Backdrop": {
100
+ "$type": "color",
101
+ "$value": "{Color.Neutral.Alpha.400}"
102
+ },
103
+ "Hover": {
104
+ "$type": "color",
105
+ "$value": "{Color.Neutral.Alpha.200}"
106
+ },
107
+ "Active": {
108
+ "$type": "color",
109
+ "$value": "{Color.Neutral.Alpha.400}"
110
+ },
111
+ "Selected": {
112
+ "$type": "color",
113
+ "$value": "{Color.Neutral.Alpha.600}"
114
+ }
115
+ },
116
+ "Focus": {
117
+ "$type": "color",
118
+ "$value": "{Brand.Color.Primary}"
119
+ }
120
+ }
121
+ }