@getvitops/generator 0.6.0 → 0.7.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,86 @@
1
+ # @getvitops/generator
2
+
3
+ ## 0.7.0
4
+
5
+ ### Patch Changes
6
+
7
+ - @getvitops/utils@0.7.0
8
+
9
+ ## 0.6.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 2cc847d: Package-resident agent skill + `vitops docs`:
14
+ - `@getvitops/cli` now ships the `vitops-design-system` agent skill inside the package
15
+ (`skill/SKILL.md`). `vitops agents` no longer emits a generated skill into the repo — it
16
+ symlinks `.agents/skills/` and `.claude/skills/` entries to the installed package (logical
17
+ `node_modules/@getvitops/cli/skill` target, surviving version bumps) and writes the
18
+ AGENTS.md pointer block. Old generated-skill directories are migrated automatically;
19
+ `--docs-dir` keeps the emit-files layout.
20
+ - New `vitops docs [topic]` command prints reference docs to stdout, rendered live from the
21
+ project's `design-system.json` (topics: classes, authoring, formats, color, scales,
22
+ patterns, elements; `--all` concatenates).
23
+ - `renderSkill()` removed from `@getvitops/generator` (superseded by the packaged skill).
24
+
25
+ ### Patch Changes
26
+
27
+ - @getvitops/utils@0.6.0
28
+
29
+ ## 0.5.0
30
+
31
+ ### Minor Changes
32
+
33
+ - Ship design-system context to downstream agents:
34
+ - JSON Schema descriptions: every `design-system.json` and site-config field now carries a
35
+ `description` (authored in the zod schemas via `desc()`), emitted into `schema.json` /
36
+ `site.schema.json` for editor hovers and agent consumption.
37
+ - New generated OKF docs: `authoring.md` (field reference walked from the JSON Schema),
38
+ `formats.md` (tailwind vs css vs bricks, including the TW_CLASH utilities Tailwind
39
+ provides natively), and `concepts/{color,scales,patterns}.md` (seeded OKLCH colour
40
+ system, fluid modular scales, pattern token cascade + override hooks).
41
+ - `vitops agents` now emits a generated `vitops-design-system` agent skill into
42
+ `.agents/skills/vitops-design-system/` (SKILL.md + the docs bundle as `references/`,
43
+ with an idempotent `.claude/skills/` symlink) and writes a compact pointer block into
44
+ `AGENTS.md`. Pass `--docs-dir` for the legacy docs-only layout.
45
+ - `TW_CLASH` and `BASE_HOOK` are exported from `@getvitops/generator`.
46
+
47
+ ### Patch Changes
48
+
49
+ - @getvitops/utils@0.5.0
50
+
51
+ ## 0.4.0
52
+
53
+ ### Patch Changes
54
+
55
+ - Updated dependencies [d7e6491]
56
+ - @getvitops/utils@0.4.0
57
+
58
+ ## 0.3.0
59
+
60
+ ### Patch Changes
61
+
62
+ - Updated dependencies
63
+ - @getvitops/utils@0.3.0
64
+
65
+ ## 0.2.1
66
+
67
+ ### Patch Changes
68
+
69
+ - d28aae7: Fix Tailwind output: the `.centered > *` default (`grid-column: measure`) was emitted unlayered,
70
+ which in Tailwind v4 outranks every layer — so track utilities (`.spotlight`/`.breakout`/
71
+ `.fullbleed`) never overrode it and all `.centered` children fell back to `measure`. Emit the
72
+ structural rules (and the animation engine + patterns) in `@layer components` so the track/spacing
73
+ `@utility` classes (utilities layer) win.
74
+ - @getvitops/utils@0.2.1
75
+
76
+ ## 0.2.0
77
+
78
+ ### Minor Changes
79
+
80
+ - Redesign the colour system: seeded OKLCH tonal scales plus functional semantic tokens
81
+ (`bg`/`text`/`solid`/`on-solid`, `muted`/`bold`), with named-alias back-compat. Updates the
82
+ framework CSS, the schema, and the generated docs to the new token model.
83
+
84
+ ### Patch Changes
85
+
86
+ - @getvitops/utils@0.2.0
package/README.md CHANGED
@@ -33,3 +33,9 @@ await generate({
33
33
  | `bricks` | `styles.min.css`, `bricks-colors-*.json`, `bricks-variables.json`, `tokens.json`, JS, `bricks/`, `docs/` |
34
34
 
35
35
  See the [`design-system.json` schema](./schema.json) for the config shape.
36
+
37
+ ## Changelog
38
+
39
+ This package's history: [`CHANGELOG.md`](./CHANGELOG.md) (shipped in the npm tarball, so it
40
+ also reads from `node_modules/@getvitops/generator/CHANGELOG.md`). `@getvitops/core`, `generator`,
41
+ `utils`, `cli`, `vite` and `astro` share one version and are released together.
@@ -3,10 +3,10 @@
3
3
  * Consumes the generated token cascade (src/css/generated/tokens.css).
4
4
  */
5
5
 
6
- /* ── Inline code chip — prose <code> that isn't inside a <pre>. Element-level at
7
- zero specificity (like the schema-generated button/link patterns) so bare
6
+ /* ── Inline code — prose <code> that isn't inside a <pre>. Element-level at
7
+ zero specificity (like the schema-generated btn/link patterns) so bare
8
8
  <code> needs no class and any explicit class overrides it. .font-code styles
9
- type only; this adds the chip. ── */
9
+ type only; this adds the boxed treatment. ── */
10
10
  :where(:not(pre) > code) {
11
11
  font-family: var(--font-mono);
12
12
  font-size: 0.85em;
@@ -3,7 +3,7 @@
3
3
  * Consumes the generated token cascade (src/css/generated/tokens.css).
4
4
  */
5
5
 
6
- /* ── List family — base list, facets, filtered search, virtual, chips ─────── */
6
+ /* ── List family — base list, facets, filtered search, virtual, tag list ──── */
7
7
  .list {
8
8
  --_p: var(--p-list, var(--p-list-group, var(--p-default)));
9
9
  --_b: var(--b-list, var(--b-list-group, var(--b-default)));
@@ -216,11 +216,15 @@
216
216
  }
217
217
  }
218
218
 
219
- .chip-list {
220
- --_p: var(--p-chip-list, var(--p-control, var(--p-default)));
221
- --_b: var(--b-chip-list, var(--b-control, var(--b-default)));
222
- --_br: var(--br-chip-list, var(--br-control, var(--br-default)));
223
- --_fs: var(--fs-chip-list, var(--fs-control, var(--fs-default)));
219
+ /* ── Tag list — a bordered field of dismissable tags plus a free-text input.
220
+ Items are the generated `.tag` pattern (+ `.tag__remove` from tag.css): a tag is
221
+ the editable/dismissable label, a badge is the static one — so this needs no
222
+ parallel item styling of its own. ── */
223
+ .tag-list {
224
+ --_p: var(--p-tag-list, var(--p-control, var(--p-default)));
225
+ --_b: var(--b-tag-list, var(--b-control, var(--b-default)));
226
+ --_br: var(--br-tag-list, var(--br-control, var(--br-default)));
227
+ --_fs: var(--fs-tag-list, var(--fs-control, var(--fs-default)));
224
228
 
225
229
  display: flex;
226
230
  flex-wrap: wrap;
@@ -232,31 +236,7 @@
232
236
  align-items: center;
233
237
  font-size: var(--_fs);
234
238
 
235
- .chip-list__chip {
236
- display: inline-flex;
237
- align-items: center;
238
- gap: 0.25rem;
239
- padding: 0.25rem 0.5rem;
240
- border-radius: var(--br-chip, var(--br-tag, 0.25rem));
241
- font-size: 0.875rem;
242
- background: var(--color-surface-muted);
243
- }
244
-
245
- .chip-list__chip-remove {
246
- padding: 0;
247
- background: transparent;
248
- border: none;
249
- cursor: pointer;
250
- opacity: 0.6;
251
- line-height: 1;
252
- transition: opacity 0.15s ease;
253
-
254
- &:hover {
255
- opacity: 1;
256
- }
257
- }
258
-
259
- .chip-list__input {
239
+ .tag-list__input {
260
240
  flex: 1;
261
241
  min-inline-size: 6rem;
262
242
  border: none;
@@ -266,7 +246,7 @@
266
246
  }
267
247
 
268
248
  &:focus-within {
269
- outline: 2px solid var(--chip-list-focus-color, var(--color-brand-primary-muted));
249
+ outline: 2px solid var(--tag-list-focus-color, var(--color-brand-primary-muted));
270
250
  outline-offset: 2px;
271
251
  }
272
252
  }
package/dist/index.d.mts CHANGED
@@ -58,6 +58,7 @@ declare const DesignSystemSchema: z.ZodMiniObject<{
58
58
  overrides: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniString<string>>>;
59
59
  element: z.ZodMiniOptional<z.ZodMiniString<string>>;
60
60
  class: z.ZodMiniOptional<z.ZodMiniString<string>>;
61
+ fill: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
61
62
  default_role: z.ZodMiniOptional<z.ZodMiniString<string>>;
62
63
  base: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniString<string>>>;
63
64
  states: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnknown>>>;
@@ -147,6 +148,7 @@ declare const jsonSchema: {
147
148
  overrides: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniString<string>>>;
148
149
  element: z.ZodMiniOptional<z.ZodMiniString<string>>;
149
150
  class: z.ZodMiniOptional<z.ZodMiniString<string>>;
151
+ fill: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
150
152
  default_role: z.ZodMiniOptional<z.ZodMiniString<string>>;
151
153
  base: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniString<string>>>;
152
154
  states: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnknown>>>;
@@ -278,8 +280,9 @@ declare function generateDocs(ds: DesignSystem, assetsDir: string): Record<strin
278
280
  */
279
281
  /**
280
282
  * Pattern base geometry props → per-pattern override-hook shorthand. Each hook
281
- * wraps the authored value (`padding: var(--p-button, 0.6em 1.2em)`) so a
282
- * consumer restyles one pattern by setting one variable.
283
+ * wraps the authored value (`padding: var(--p-btn, 0.4em 0.8em)`) so a
284
+ * consumer restyles one pattern by setting one variable. The hook is named after
285
+ * the pattern's key, not its class.
283
286
  */
284
287
  declare const BASE_HOOK: Record<string, string>;
285
288
  /**
@@ -497,6 +500,7 @@ declare const SiteConfigSchema: z.ZodMiniObject<{
497
500
  overrides: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniString<string>>>;
498
501
  element: z.ZodMiniOptional<z.ZodMiniString<string>>;
499
502
  class: z.ZodMiniOptional<z.ZodMiniString<string>>;
503
+ fill: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
500
504
  default_role: z.ZodMiniOptional<z.ZodMiniString<string>>;
501
505
  base: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniString<string>>>;
502
506
  states: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnknown>>>;
@@ -992,6 +996,7 @@ declare const siteJsonSchema: {
992
996
  overrides: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniString<string>>>;
993
997
  element: z.ZodMiniOptional<z.ZodMiniString<string>>;
994
998
  class: z.ZodMiniOptional<z.ZodMiniString<string>>;
999
+ fill: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
995
1000
  default_role: z.ZodMiniOptional<z.ZodMiniString<string>>;
996
1001
  base: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniString<string>>>;
997
1002
  states: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnknown>>>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/schema.ts","../src/generate.ts","../src/docs.ts","../src/shared.ts","../src/site.ts","../src/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/schema.ts","../src/generate.ts","../src/docs.ts","../src/shared.ts","../src/site.ts","../src/index.ts"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -62,7 +62,8 @@ const Pattern = desc(z.object({
62
62
  group: desc(z.optional(z.string()), "Token-cascade group this pattern belongs to (e.g. tag / control / panel); base declarations resolve through `--<prop>-<group>` before `--<prop>-default`."),
63
63
  overrides: z.optional(desc(CssDecls, "Per-pattern token overrides, emitted as `--<prop>-<name>-group` values.")),
64
64
  element: desc(z.optional(z.string()), "Style at element level via zero-specificity `:where(<element>)` (instead of, or alongside, a class)."),
65
- class: desc(z.optional(z.string()), "Class name to emit (defaults to the pattern's key)."),
65
+ class: desc(z.optional(z.string()), "Class name to emit (defaults to the pattern's key when no `element` is set). Combined with `element`, the pattern emits one zero-specificity `:where(<element>, .<class>)` rule so the class works on any tag and any explicit class overrides it."),
66
+ fill: desc(z.optional(z.boolean()), "Whether this pattern is colour-filled (states/roles drive `background-color` + `on-solid` text) or text-coloured (they drive `color`). Defaults to true when `base` declares a background."),
66
67
  default_role: desc(z.optional(z.string()), "Semantic colour role applied to the bare/default variant."),
67
68
  base: z.optional(desc(CssDecls, "Base CSS declarations. Geometry properties (padding, border-radius, border, box-shadow, font-size) are wrapped in per-pattern override hooks (`--p-<name>`, `--br-<name>`, `--b-<name>`, `--ds-<name>`, `--fs-<name>`) so consumers can restyle one pattern by setting one variable.")),
68
69
  states: desc(z.optional(z.record(z.string(), z.record(z.string(), z.unknown()))), "Interaction states (hover / active / focus-visible), each a map of shortcuts: `step` (intensify fills/text by n emphasis stops), `scale` (transform scale), `lift` (translateY + shadow), `shadow` (a shadow name → drop-shadow(var(--shadow-<name>)), or true → lift shadow), `ring` (focus ring), or raw `css` declarations. Hover rules are wrapped in `@media (hover: hover)`."),
@@ -159,8 +160,9 @@ function validate(input) {
159
160
  */
160
161
  /**
161
162
  * Pattern base geometry props → per-pattern override-hook shorthand. Each hook
162
- * wraps the authored value (`padding: var(--p-button, 0.6em 1.2em)`) so a
163
- * consumer restyles one pattern by setting one variable.
163
+ * wraps the authored value (`padding: var(--p-btn, 0.4em 0.8em)`) so a
164
+ * consumer restyles one pattern by setting one variable. The hook is named after
165
+ * the pattern's key, not its class.
164
166
  */
165
167
  const BASE_HOOK = {
166
168
  padding: "p",
@@ -1012,9 +1014,10 @@ pattern CSS is assembled — token cascade, \`--p-<pattern>\`-style override hoo
1012
1014
  shortcuts — is explained in [/concepts/patterns.md](../concepts/patterns.md).)
1013
1015
 
1014
1016
  - Patterns: ${code(patterns)}.
1015
- - Roles (for coloured patterns like \`badge\`, \`tag\`, \`status\`, \`button\`):
1016
- ${code(patternRoles)} — e.g. \`badge-success\`, \`button-danger\`. The default (unsuffixed)
1017
- variant uses the brand-primary role.
1017
+ - Roles (for coloured patterns — \`badge\`, \`tag\`, \`status\`, \`cta\`, \`btn\`, …):
1018
+ ${code(patternRoles)} — e.g. \`badge-success\`, \`cta-danger\`. A pattern that also styles an
1019
+ element accepts the bare role class too (\`<button class="danger">\`). The default
1020
+ (unsuffixed) variant uses the pattern's \`default_role\`.
1018
1021
  - Shape primitives: \`--br-<name>\` radii — ${code(radii)}.
1019
1022
  `;
1020
1023
  }
@@ -1343,16 +1346,25 @@ Shared geometry resolves through a variable chain, most-specific first:
1343
1346
 
1344
1347
  ## 2 — Base declarations & override hooks
1345
1348
 
1346
- Each pattern's \`base\` block is emitted on its selector — a class (\`.<class ?? name>\`) or,
1347
- with \`element\`, a **zero-specificity** \`:where(<element>)\` rule so author CSS can always
1348
- override it. Geometry properties are wrapped in a **per-pattern override hook**:
1349
+ Each pattern's \`base\` block is emitted on its selector:
1350
+
1351
+ - \`class\` only → \`.<class ?? name>\`, at normal class specificity.
1352
+ - \`element\` only → a **zero-specificity** \`:where(<element>)\` rule, so author CSS can always
1353
+ override it.
1354
+ - **both** → one \`:where(<element>, .<class>)\` rule (e.g. \`:where(button, .btn)\`). The element
1355
+ gets the styling with no class needed, the class carries it to any other tag, and — because the
1356
+ whole thing sits at zero specificity — any explicit class wins, including a louder pattern
1357
+ (\`.cta\`) or a component's own rule (\`.dialog__close\`).
1358
+
1359
+ Geometry properties are wrapped in a **per-pattern override hook**:
1349
1360
 
1350
1361
  | base property | hook variable |
1351
1362
  | --- | --- |
1352
1363
  ${hookTable}
1353
1364
 
1354
- e.g. \`padding: var(--p-button, 0.6em 1.2em)\` — a consumer restyles every button by setting
1355
- \`--p-button\` on \`:root\`, without touching the pattern.
1365
+ e.g. \`padding: var(--p-btn, 0.4em 0.8em)\` — a consumer restyles every button by setting
1366
+ \`--p-btn\` on \`:root\`, without touching the pattern. The hook is named after the pattern's
1367
+ **key**, not its class.
1356
1368
 
1357
1369
  ## 3 — States
1358
1370
 
@@ -1374,7 +1386,10 @@ rules are wrapped in \`@media (hover: hover)\` so touch devices never stick.
1374
1386
  ## 4 — Role variants
1375
1387
 
1376
1388
  \`roles\` lists semantic colour variants: class patterns emit \`.<pattern>-<role>\`
1377
- (\`.badge-success\`), element patterns emit \`<element>.<role>\` (\`button.danger\`). Fill
1389
+ (\`.badge-success\`). A pattern with an \`element\` emits both the bare role class on the
1390
+ element and the \`-<role>\` form (\`:where(button, .btn).danger, .btn-danger\`), so the same
1391
+ variant works on a non-element host — both at class specificity, so neither outranks a
1392
+ plain class. Fill
1378
1393
  patterns set \`background-color: var(--<role>-solid)\` + \`color: var(--<role>-on-solid)\`;
1379
1394
  text patterns use the role's \`bold\` emphasis stop. \`default_role\` colours the bare,
1380
1395
  unsuffixed pattern. States re-apply per variant with the variant's role.
@@ -1704,6 +1719,7 @@ function build(ds, format, assetsDir) {
1704
1719
  generated["typography.css"] = typo;
1705
1720
  }
1706
1721
  const stateRules = (sel, role, states, colorProp = "background-color") => {
1722
+ const sels = Array.isArray(sel) ? sel : [sel];
1707
1723
  let out = "";
1708
1724
  for (const [state, spec] of Object.entries(states)) {
1709
1725
  const body = [];
@@ -1721,7 +1737,8 @@ function build(ds, format, assetsDir) {
1721
1737
  }
1722
1738
  if (spec.css && typeof spec.css === "object") for (const [k, v] of Object.entries(spec.css)) body.push(`${k}: ${v};`);
1723
1739
  if (!body.length) continue;
1724
- const rule = `${sel}${state === "hover" ? ":hover" : state === "active" ? ":active" : state === "focus-visible" ? ":focus-visible" : `:${state}`} {\n ${body.join("\n ")}\n}\n`;
1740
+ const pseudo = state === "hover" ? ":hover" : state === "active" ? ":active" : state === "focus-visible" ? ":focus-visible" : `:${state}`;
1741
+ const rule = `${sels.map((s) => `${s}${pseudo}`).join(",\n")} {\n ${body.join("\n ")}\n}\n`;
1725
1742
  out += state === "hover" ? `@media (hover: hover) {\n${rule}}\n` : rule;
1726
1743
  }
1727
1744
  return out;
@@ -1731,11 +1748,12 @@ function build(ds, format, assetsDir) {
1731
1748
  for (const [pname, p] of Object.entries(patterns?.items ?? {})) {
1732
1749
  if (!p.base) continue;
1733
1750
  const states = p.states ?? {};
1734
- const isElement = !!p.element;
1735
- const defaultSel = isElement ? `:where(${p.element})` : `.${p.class ?? pname}`;
1751
+ const cls = p.class ?? (p.element ? void 0 : pname);
1752
+ const elementSel = (extra = "") => `:where(${[p.element, cls && `.${cls}`].filter(Boolean).join(", ")})${extra}`;
1753
+ const defaultSel = p.element ? elementSel() : `.${cls}`;
1736
1754
  const defaultRole = p.default_role ?? null;
1737
1755
  const base = { ...p.base };
1738
- const fills = pname === "button" || pname === "badge" || base["background-color"] != null || base["background"] != null;
1756
+ const fills = p.fill ?? (pname === "button" || pname === "badge" || base["background-color"] != null || base["background"] != null);
1739
1757
  const colorProp = fills ? "background-color" : "color";
1740
1758
  pat += `${defaultSel} {\n`;
1741
1759
  if (Object.keys(states).length > 0) {
@@ -1753,10 +1771,10 @@ function build(ds, format, assetsDir) {
1753
1771
  pat += decls(wrappedBase) + "\n}\n";
1754
1772
  pat += stateRules(defaultSel, defaultRole, states, colorProp);
1755
1773
  for (const role of p.roles ?? []) {
1756
- const variantSel = isElement ? `${p.element}.${role}` : `.${p.class ?? pname}-${role}`;
1774
+ const variantSels = p.element ? [elementSel(`.${role}`), ...cls ? [`.${cls}-${role}`] : []] : [`.${cls}-${role}`];
1757
1775
  const variantColorDecl = fills ? `background-color: var(--${role}-solid); color: var(--${role}-on-solid)` : `color: var(--color-${role}-bold)`;
1758
- pat += `${variantSel} { ${variantColorDecl}; }\n`;
1759
- pat += stateRules(variantSel, role, states, colorProp);
1776
+ pat += `${variantSels.join(",\n")} { ${variantColorDecl}; }\n`;
1777
+ pat += stateRules(variantSels, role, states, colorProp);
1760
1778
  }
1761
1779
  pat += "\n";
1762
1780
  }
@@ -1992,7 +2010,7 @@ function build(ds, format, assetsDir) {
1992
2010
  reverseIndex
1993
2011
  }, null, 2);
1994
2012
  })(),
1995
- tailwind: emitTailwind({
2013
+ tailwind: format !== "tailwind" ? "" : emitTailwind({
1996
2014
  ds,
1997
2015
  expandedPalette,
1998
2016
  scaleRoles,
@@ -3087,21 +3105,73 @@ function defaultConfig() {
3087
3105
  top: 1e3
3088
3106
  },
3089
3107
  items: {
3090
- button: {
3108
+ btn: {
3091
3109
  group: "control",
3092
3110
  element: "button",
3111
+ class: "btn",
3112
+ fill: false,
3113
+ overrides: {
3114
+ b: "1px solid transparent",
3115
+ fs: "inherit"
3116
+ },
3117
+ base: {
3118
+ display: "inline-flex",
3119
+ "align-items": "center",
3120
+ "justify-content": "center",
3121
+ gap: "0.4em",
3122
+ padding: "var(--p-btn-group)",
3123
+ "border-radius": "var(--br-btn-group)",
3124
+ border: "var(--b-btn-group)",
3125
+ "box-shadow": "var(--ds-btn-group)",
3126
+ background: "transparent",
3127
+ color: "inherit",
3128
+ "font-family": "inherit",
3129
+ "font-size": "var(--fs-btn-group)",
3130
+ "font-weight": "inherit",
3131
+ "text-decoration": "none",
3132
+ cursor: "pointer"
3133
+ },
3134
+ states: {
3135
+ hover: {
3136
+ step: 1,
3137
+ css: { "background-color": "var(--color-surface-muted)" }
3138
+ },
3139
+ "focus-visible": { ring: true }
3140
+ },
3141
+ roles: []
3142
+ },
3143
+ cta: {
3144
+ group: "control",
3145
+ class: "cta",
3146
+ fill: true,
3093
3147
  default_role: "brand-primary",
3148
+ overrides: {
3149
+ p: "0.75em 1.5em",
3150
+ b: "none",
3151
+ ds: "var(--shadow-sm)",
3152
+ fs: "inherit"
3153
+ },
3094
3154
  base: {
3095
- padding: "0.6em 1.2em",
3096
- "border-radius": "var(--br-control, 0.25rem)",
3097
- border: "none",
3155
+ display: "inline-flex",
3156
+ "align-items": "center",
3157
+ "justify-content": "center",
3158
+ gap: "0.5em",
3159
+ padding: "var(--p-cta-group)",
3160
+ "border-radius": "var(--br-cta-group)",
3161
+ border: "var(--b-cta-group)",
3162
+ "font-family": "inherit",
3163
+ "font-size": "var(--fs-cta-group)",
3098
3164
  "font-weight": "600",
3099
- color: "#fff",
3165
+ "text-decoration": "none",
3100
3166
  cursor: "pointer",
3101
- "box-shadow": "var(--shadow-sm)"
3167
+ color: "var(--brand-primary-on-solid)",
3168
+ "box-shadow": "var(--ds-cta-group)"
3102
3169
  },
3103
3170
  states: {
3104
- hover: { step: 1 },
3171
+ hover: {
3172
+ step: 1,
3173
+ lift: "1px"
3174
+ },
3105
3175
  active: { scale: .97 },
3106
3176
  "focus-visible": { ring: true }
3107
3177
  },