From 73a2d00bf6ff78154adb7614195af23f273db817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaque=20B=C3=B6ck?= Date: Thu, 14 May 2026 12:05:24 -0300 Subject: [PATCH 01/34] feat(pricing-card): use Tag component for popular badge --- .../components/pricing-card/pricing-card.vue | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/webkit/src/components/pricing-card/pricing-card.vue b/packages/webkit/src/components/pricing-card/pricing-card.vue index bf987a6f..e7ed639f 100644 --- a/packages/webkit/src/components/pricing-card/pricing-card.vue +++ b/packages/webkit/src/components/pricing-card/pricing-card.vue @@ -1,6 +1,8 @@ From bcf7cb41c4e34b0e4aae4889bcf1b9d8aa312fd9 Mon Sep 17 00:00:00 2001 From: gab-az Date: Mon, 18 May 2026 10:29:32 -0300 Subject: [PATCH 29/34] chore: inclue blue-alpha to primitive pallete --- .../src/tokens/primitives/colors/alpha.js | 12 ++++++ .../src/tokens/primitives/colors/colors.js | 41 +++++++------------ 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/packages/theme/src/tokens/primitives/colors/alpha.js b/packages/theme/src/tokens/primitives/colors/alpha.js index 3886668f..65956403 100644 --- a/packages/theme/src/tokens/primitives/colors/alpha.js +++ b/packages/theme/src/tokens/primitives/colors/alpha.js @@ -83,6 +83,18 @@ export const alpha = { '800': '#F7BD08CC', '900': '#F7BD08E5', }, + blue: { + '50': '#E5F1FF0D', + '100': '#CCE4FF1A', + '200': '#99C9FF33', + '300': '#66ADFF4D', + '400': '#3392FF66', + '500': '#0072F580', + '600': '#005FCC99', + '700': '#004799B2', + '800': '#003066CC', + '900': '#001833E5', + }, absolute: { black: '#000000E5', white: '#FFFFFFE5', diff --git a/packages/theme/src/tokens/primitives/colors/colors.js b/packages/theme/src/tokens/primitives/colors/colors.js index 0366a648..752fc36a 100644 --- a/packages/theme/src/tokens/primitives/colors/colors.js +++ b/packages/theme/src/tokens/primitives/colors/colors.js @@ -8,6 +8,19 @@ export const primitives = { white: '#FFFFFF', black: '#000000', }, + blue: { + '50': '#E5F1FF', + '100': '#CCE4FF', + '200': '#99C9FF', + '300': '#66ADFF', + '400': '#3392FF', + '500': '#0072F5', + '600': '#005FCC', + '700': '#004799', + '800': '#003066', + '900': '#001833', + '950': '#000C1A', + }, gray: { '50': '#FCFCFC', '100': '#F2F2F2', @@ -21,7 +34,6 @@ export const primitives = { '900': '#1A1A1A', '950': '#0A0A0A', }, - // done violet violet: { '50': '#F6F6FF', '100': '#ECECFF', @@ -87,32 +99,7 @@ export const primitives = { '900': '#0A2916', '950': '#03170B', }, - blue: { - '50': '#EFF6FF', - '100': '#DBEAFE', - '200': '#BFDBFE', - '300': '#93C5FD', - '400': '#60A5FA', - '500': '#3B82F6', - '600': '#2563EB', - '700': '#1D4ED8', - '800': '#1E40AF', - '900': '#1E3A8A', - '950': '#172554', - }, - neutral: { - '50': '#FAFAFA', - '100': '#F5F5F5', - '200': '#E5E5E5', - '300': '#D4D4D4', - '400': '#A3A3A3', - '500': '#737373', - '600': '#525252', - '700': '#404040', - '800': '#262626', - '900': '#171717', - '950': '#0A0A0A', - }, + red: { '50': '#FFE5E5', '100': '#FFCCCC', From c38676ae8014dbe1b43919b92f437af77eb05da2 Mon Sep 17 00:00:00 2001 From: gab-az Date: Mon, 18 May 2026 10:29:58 -0300 Subject: [PATCH 30/34] chore: change bg-canvas on light mode to surface-0 --- packages/theme/src/tokens/theme/background.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/theme/src/tokens/theme/background.js b/packages/theme/src/tokens/theme/background.js index 1c6fca1b..b60d77d9 100644 --- a/packages/theme/src/tokens/theme/background.js +++ b/packages/theme/src/tokens/theme/background.js @@ -2,7 +2,7 @@ import { tokenRef } from '../../scripts/refs.js'; export const background = { light: { - 'bg-canvas': tokenRef('theme.surfaces.surface-100'), + 'bg-canvas': tokenRef('theme.surfaces.surface-0'), 'bg-surface': tokenRef('theme.surfaces.surface-0'), 'bg-surface-raised': tokenRef('theme.surfaces.surface-0'), 'bg-mask': tokenRef('primitives.alpha.black.50'), From 576a4c819ec9b2ed71c78de524f60ca689a647d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaque=20B=C3=B6ck?= Date: Mon, 18 May 2026 12:03:42 -0300 Subject: [PATCH 31/34] feat(theme): expand primitive tokens (typography, effects, shape, animations) - typography: add font-weight, leading, tracking primitives; rewrite font-size to emit --text-* with paired --line-height vars - effects: add drop-shadow, shadow, inset-shadow, perspective primitives - shape: add aspect-video primitive - animations: add ease and animate primitives under new animations group - compile-primitives: register the new groups in refsTree/varsTree so the vars surface at :root - build-tokens: extend the Tailwind v3 preset with fontWeight, dropShadow, lineHeight, and letterSpacing mappings backed by the new vars --- packages/theme/src/scripts/build-tokens.mjs | 18 ++++++++- .../theme/src/scripts/compile-primitives.js | 38 ++++++++++++++++-- .../tokens/primitives/animations/animate.js | 8 ++++ .../src/tokens/primitives/animations/ease.js | 7 ++++ .../tokens/primitives/effects/drop-shadow.js | 10 +++++ .../tokens/primitives/effects/inset-shadow.js | 7 ++++ .../tokens/primitives/effects/perspective.js | 9 +++++ .../src/tokens/primitives/effects/shadow.js | 11 ++++++ .../tokens/primitives/shape/aspect-video.js | 3 ++ .../tokens/primitives/typography/font-size.js | 39 ++++++++++++------- .../primitives/typography/font-weight.js | 13 +++++++ .../tokens/primitives/typography/leading.js | 9 +++++ .../tokens/primitives/typography/tracking.js | 10 +++++ 13 files changed, 165 insertions(+), 17 deletions(-) create mode 100644 packages/theme/src/tokens/primitives/animations/animate.js create mode 100644 packages/theme/src/tokens/primitives/animations/ease.js create mode 100644 packages/theme/src/tokens/primitives/effects/drop-shadow.js create mode 100644 packages/theme/src/tokens/primitives/effects/inset-shadow.js create mode 100644 packages/theme/src/tokens/primitives/effects/perspective.js create mode 100644 packages/theme/src/tokens/primitives/effects/shadow.js create mode 100644 packages/theme/src/tokens/primitives/shape/aspect-video.js create mode 100644 packages/theme/src/tokens/primitives/typography/font-weight.js create mode 100644 packages/theme/src/tokens/primitives/typography/leading.js create mode 100644 packages/theme/src/tokens/primitives/typography/tracking.js diff --git a/packages/theme/src/scripts/build-tokens.mjs b/packages/theme/src/scripts/build-tokens.mjs index d0d304a0..e2583d1c 100644 --- a/packages/theme/src/scripts/build-tokens.mjs +++ b/packages/theme/src/scripts/build-tokens.mjs @@ -189,6 +189,18 @@ const treeToVars = (tree, prefix) => { const buildPresetData = () => { const { refsTree } = buildTrees(); const colors = treeToVars(refsTree.color, '--color'); + const fontWeight = refsTree.typography?.['font-weight'] + ? treeToVars(refsTree.typography['font-weight'], '--font-weight') + : {}; + const dropShadow = refsTree.effects?.['drop-shadow'] + ? treeToVars(refsTree.effects['drop-shadow'], '--drop-shadow') + : {}; + const lineHeight = refsTree.typography?.leading + ? treeToVars(refsTree.typography.leading, '--leading') + : {}; + const letterSpacing = refsTree.typography?.tracking + ? treeToVars(refsTree.typography.tracking, '--tracking') + : {}; const fontSize = {}; for (const [key, bundle] of Object.entries(textsData)) { @@ -200,7 +212,11 @@ const buildPresetData = () => { fontSize[key.replace(/^text-/, '')] = [`var(--${key}-font-size)`, meta]; } - return { theme: { extend: { colors, fontSize } } }; + return { + theme: { + extend: { colors, fontSize, fontWeight, dropShadow, lineHeight, letterSpacing }, + }, + }; }; const emitPresetV3 = () => { diff --git a/packages/theme/src/scripts/compile-primitives.js b/packages/theme/src/scripts/compile-primitives.js index 9135c603..1e3089d5 100644 --- a/packages/theme/src/scripts/compile-primitives.js +++ b/packages/theme/src/scripts/compile-primitives.js @@ -8,11 +8,18 @@ */ import { primitives as colorPrimitives } from '../tokens/primitives/colors/colors.js'; +import { animate } from '../tokens/primitives/animations/animate.js'; +import { ease } from '../tokens/primitives/animations/ease.js'; import { borderWidths } from '../tokens/primitives/border-widths.js'; import { breakpoints } from '../tokens/primitives/breakpoints.js'; import { blur } from '../tokens/primitives/effects/blur.js'; +import { dropShadow } from '../tokens/primitives/effects/drop-shadow.js'; +import { insetShadow } from '../tokens/primitives/effects/inset-shadow.js'; import { opacity } from '../tokens/primitives/effects/opacity.js'; +import { perspective } from '../tokens/primitives/effects/perspective.js'; +import { shadow } from '../tokens/primitives/effects/shadow.js'; import { ringOffset } from '../tokens/primitives/ring-offset.js'; +import { aspectVideo } from '../tokens/primitives/shape/aspect-video.js'; import { container } from '../tokens/primitives/shape/container.js'; import { height } from '../tokens/primitives/shape/height.js'; import { radius } from '../tokens/primitives/shape/radius.js'; @@ -22,7 +29,10 @@ import { spacing } from '../tokens/primitives/shape/spacing.js'; import { width } from '../tokens/primitives/shape/width.js'; import { fontFamily } from '../tokens/primitives/typography/font-family.js'; import { fontSize } from '../tokens/primitives/typography/font-size.js'; +import { fontWeight } from '../tokens/primitives/typography/font-weight.js'; +import { leading } from '../tokens/primitives/typography/leading.js'; import { lineHeight } from '../tokens/primitives/typography/line-height.js'; +import { tracking } from '../tokens/primitives/typography/tracking.js'; import { isTokenRef } from './refs.js'; /** @@ -41,13 +51,33 @@ export const buildTrees = () => { absolute: brand.absolute, }; - const shape = { container, height, radius, size, spacing, width, ...shapeAliases }; + const shape = { + container, + height, + radius, + size, + spacing, + width, + 'aspect-video': aspectVideo, + ...shapeAliases, + }; const typography = { 'font-family': fontFamily, - 'font-size': fontSize, + text: fontSize, + 'font-weight': fontWeight, + leading, 'line-height': lineHeight, + tracking, + }; + const effects = { + blur, + 'drop-shadow': dropShadow, + shadow, + 'inset-shadow': insetShadow, + opacity, + perspective, }; - const effects = { blur, opacity }; + const animations = { ease, animate }; const refsTree = { color, @@ -56,6 +86,7 @@ export const buildTrees = () => { shape, typography, effects, + animations, 'ring-offset': ringOffset['ring-offset'], }; @@ -66,6 +97,7 @@ export const buildTrees = () => { ...shape, ...typography, ...effects, + ...animations, 'ring-offset': ringOffset['ring-offset'], }; diff --git a/packages/theme/src/tokens/primitives/animations/animate.js b/packages/theme/src/tokens/primitives/animations/animate.js new file mode 100644 index 00000000..e678bc91 --- /dev/null +++ b/packages/theme/src/tokens/primitives/animations/animate.js @@ -0,0 +1,8 @@ +export const animate = { + spin: 'spin 1s linear infinite', + ping: 'ping 1s cubic-bezier(0, 0, 0.2, 1) infinite', + pulse: 'pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite', + bounce: 'bounce 1s infinite', +}; + +export default { animate }; diff --git a/packages/theme/src/tokens/primitives/animations/ease.js b/packages/theme/src/tokens/primitives/animations/ease.js new file mode 100644 index 00000000..4f9804ca --- /dev/null +++ b/packages/theme/src/tokens/primitives/animations/ease.js @@ -0,0 +1,7 @@ +export const ease = { + in: 'cubic-bezier(0.4, 0, 1, 1)', + out: 'cubic-bezier(0, 0, 0.2, 1)', + 'in-out': 'cubic-bezier(0.4, 0, 0.2, 1)', +}; + +export default { ease }; diff --git a/packages/theme/src/tokens/primitives/effects/drop-shadow.js b/packages/theme/src/tokens/primitives/effects/drop-shadow.js new file mode 100644 index 00000000..12e52315 --- /dev/null +++ b/packages/theme/src/tokens/primitives/effects/drop-shadow.js @@ -0,0 +1,10 @@ +export const dropShadow = { + xs: '0 1px 1px rgb(0 0 0 / 0.05)', + sm: '0 1px 2px rgb(0 0 0 / 0.15)', + md: '0 3px 3px rgb(0 0 0 / 0.12)', + lg: '0 4px 4px rgb(0 0 0 / 0.15)', + xl: '0 9px 7px rgb(0 0 0 / 0.1)', + '2xl': '0 25px 25px rgb(0 0 0 / 0.15)', +}; + +export default { dropShadow }; diff --git a/packages/theme/src/tokens/primitives/effects/inset-shadow.js b/packages/theme/src/tokens/primitives/effects/inset-shadow.js new file mode 100644 index 00000000..6460f95b --- /dev/null +++ b/packages/theme/src/tokens/primitives/effects/inset-shadow.js @@ -0,0 +1,7 @@ +export const insetShadow = { + '2xs': 'inset 0 1px rgb(0 0 0 / 0.05)', + xs: 'inset 0 1px 1px rgb(0 0 0 / 0.05)', + sm: 'inset 0 2px 4px rgb(0 0 0 / 0.05)', +}; + +export default { insetShadow }; diff --git a/packages/theme/src/tokens/primitives/effects/perspective.js b/packages/theme/src/tokens/primitives/effects/perspective.js new file mode 100644 index 00000000..663622d4 --- /dev/null +++ b/packages/theme/src/tokens/primitives/effects/perspective.js @@ -0,0 +1,9 @@ +export const perspective = { + dramatic: '100px', + near: '300px', + normal: '500px', + midrange: '800px', + distant: '1200px', +}; + +export default { perspective }; diff --git a/packages/theme/src/tokens/primitives/effects/shadow.js b/packages/theme/src/tokens/primitives/effects/shadow.js new file mode 100644 index 00000000..8fe99b6e --- /dev/null +++ b/packages/theme/src/tokens/primitives/effects/shadow.js @@ -0,0 +1,11 @@ +export const shadow = { + '2xs': '0 1px rgb(0 0 0 / 0.05)', + xs: '0 1px 2px 0 rgb(0 0 0 / 0.05)', + sm: '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)', + md: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)', + lg: '0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)', + xl: '0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)', + '2xl': '0 25px 50px -12px rgb(0 0 0 / 0.25)', +}; + +export default { shadow }; diff --git a/packages/theme/src/tokens/primitives/shape/aspect-video.js b/packages/theme/src/tokens/primitives/shape/aspect-video.js new file mode 100644 index 00000000..58ccc68c --- /dev/null +++ b/packages/theme/src/tokens/primitives/shape/aspect-video.js @@ -0,0 +1,3 @@ +export const aspectVideo = '16 / 9'; + +export default { aspectVideo }; diff --git a/packages/theme/src/tokens/primitives/typography/font-size.js b/packages/theme/src/tokens/primitives/typography/font-size.js index 55fd125b..95eb3e29 100644 --- a/packages/theme/src/tokens/primitives/typography/font-size.js +++ b/packages/theme/src/tokens/primitives/typography/font-size.js @@ -1,17 +1,30 @@ export const fontSize = { - xs: '12px', - sm: '14px', - base: '16px', - lg: '18px', - xl: '20px', - '2xl': '24px', - '3xl': '30px', - '4xl': '36px', - '5xl': '48px', - '6xl': '60px', - '7xl': '72px', - '8xl': '96px', - '9xl': '128px', + xs: '0.75rem', + 'xs--line-height': 'calc(1 / 0.75)', + sm: '0.875rem', + 'sm--line-height': 'calc(1.25 / 0.875)', + base: '1rem', + 'base--line-height': 'calc(1.5 / 1)', + lg: '1.125rem', + 'lg--line-height': 'calc(1.75 / 1.125)', + xl: '1.25rem', + 'xl--line-height': 'calc(1.75 / 1.25)', + '2xl': '1.5rem', + '2xl--line-height': 'calc(2 / 1.5)', + '3xl': '1.875rem', + '3xl--line-height': 'calc(2.25 / 1.875)', + '4xl': '2.25rem', + '4xl--line-height': 'calc(2.5 / 2.25)', + '5xl': '3rem', + '5xl--line-height': '1', + '6xl': '3.75rem', + '6xl--line-height': '1', + '7xl': '4.5rem', + '7xl--line-height': '1', + '8xl': '6rem', + '8xl--line-height': '1', + '9xl': '8rem', + '9xl--line-height': '1', }; export default { fontSize }; diff --git a/packages/theme/src/tokens/primitives/typography/font-weight.js b/packages/theme/src/tokens/primitives/typography/font-weight.js new file mode 100644 index 00000000..bc9e0463 --- /dev/null +++ b/packages/theme/src/tokens/primitives/typography/font-weight.js @@ -0,0 +1,13 @@ +export const fontWeight = { + thin: 100, + extralight: 200, + light: 300, + normal: 400, + medium: 500, + semibold: 600, + bold: 700, + extrabold: 800, + black: 900, +}; + +export default { fontWeight }; diff --git a/packages/theme/src/tokens/primitives/typography/leading.js b/packages/theme/src/tokens/primitives/typography/leading.js new file mode 100644 index 00000000..873d94b4 --- /dev/null +++ b/packages/theme/src/tokens/primitives/typography/leading.js @@ -0,0 +1,9 @@ +export const leading = { + tight: 1.25, + snug: 1.375, + normal: 1.5, + relaxed: 1.625, + loose: 2, +}; + +export default { leading }; diff --git a/packages/theme/src/tokens/primitives/typography/tracking.js b/packages/theme/src/tokens/primitives/typography/tracking.js new file mode 100644 index 00000000..26629546 --- /dev/null +++ b/packages/theme/src/tokens/primitives/typography/tracking.js @@ -0,0 +1,10 @@ +export const tracking = { + tighter: '-0.05em', + tight: '-0.025em', + normal: '0em', + wide: '0.025em', + wider: '0.05em', + widest: '0.1em', +}; + +export default { tracking }; From e2a29073a4c05877f4b1c01de7a57ae2fe75208f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaque=20B=C3=B6ck?= Date: Tue, 19 May 2026 10:33:41 -0300 Subject: [PATCH 32/34] refactor(theme): align radius tokens with tailwind naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use Tailwind-style keys (none, sm, DEFAULT, md…) for radius primitives and collapse DEFAULT leaves to the parent CSS var name during flattening. Group font-family under the `font` namespace alongside font-size/weight. --- .../theme/src/scripts/compile-primitives.js | 13 ++++++++++--- packages/theme/src/tests/primitives.html | 3 ++- packages/theme/src/tokens/README.md | 2 +- .../src/tokens/primitives/shape/radius.js | 18 +++++++++--------- .../theme/src/tokens/primitives/shape/shape.js | 8 ++++---- 5 files changed, 26 insertions(+), 18 deletions(-) diff --git a/packages/theme/src/scripts/compile-primitives.js b/packages/theme/src/scripts/compile-primitives.js index 1e3089d5..2d5e6c6a 100644 --- a/packages/theme/src/scripts/compile-primitives.js +++ b/packages/theme/src/scripts/compile-primitives.js @@ -62,7 +62,7 @@ export const buildTrees = () => { ...shapeAliases, }; const typography = { - 'font-family': fontFamily, + font: fontFamily, text: fontSize, 'font-weight': fontWeight, leading, @@ -116,13 +116,20 @@ const resolveRef = (refPath, refsTree) => { return null; }; +// A leaf key of `DEFAULT` collapses to the parent prefix (Tailwind convention), +// so `{ radius: { DEFAULT: '4px' } }` emits `--radius: 4px;`. +const varNameFor = (path) => { + const segments = path[path.length - 1] === 'DEFAULT' ? path.slice(0, -1) : path; + return `--${segments.join('-')}`; +}; + export const flatten = (obj, refsTree, prefix = []) => { const result = {}; Object.entries(obj).forEach(([key, value]) => { const nextPath = [...prefix, key]; if (isTokenRef(value)) { const resolved = resolveRef(value.__ref, refsTree); - result[`--${nextPath.join('-')}`] = resolved ?? value.__ref; + result[varNameFor(nextPath)] = resolved ?? value.__ref; return; } if (value && typeof value === 'object' && !Array.isArray(value)) { @@ -130,7 +137,7 @@ export const flatten = (obj, refsTree, prefix = []) => { return; } if (typeof value === 'string' || typeof value === 'number') { - result[`--${nextPath.join('-')}`] = String(value); + result[varNameFor(nextPath)] = String(value); } }); return result; diff --git a/packages/theme/src/tests/primitives.html b/packages/theme/src/tests/primitives.html index fc43932e..3e8070f3 100644 --- a/packages/theme/src/tests/primitives.html +++ b/packages/theme/src/tests/primitives.html @@ -213,7 +213,8 @@

Full Generated CSS

}); // --- Font family - const fontFamilyEntries = entriesStartingWith('--font-family-'); + const fontFamilyEntries = entriesStartingWith('--font-') + .filter(([name]) => !name.startsWith('--font-weight-')); const fontFamilyEl = document.getElementById('font-family'); fontFamilyEntries.forEach(([name, value]) => { const row = document.createElement('div'); diff --git a/packages/theme/src/tokens/README.md b/packages/theme/src/tokens/README.md index 07124efe..edd2b651 100644 --- a/packages/theme/src/tokens/README.md +++ b/packages/theme/src/tokens/README.md @@ -51,7 +51,7 @@ src/ │ │ ├── shape/ │ │ │ ├── container.js # container-3xs … container-7xl │ │ │ ├── height.js # h-2 … h-96 -│ │ │ ├── radius.js # rounded-none … rounded-3xl, full +│ │ │ ├── radius.js # none, sm, DEFAULT, md … 3xl, full │ │ │ ├── size.js # size-2 … size-96 │ │ │ ├── spacing.js # spacing-1 … spacing-96 │ │ │ └── width.js # w-3xs … w-7xl (alias → container.X) diff --git a/packages/theme/src/tokens/primitives/shape/radius.js b/packages/theme/src/tokens/primitives/shape/radius.js index 26355f6e..97990367 100644 --- a/packages/theme/src/tokens/primitives/shape/radius.js +++ b/packages/theme/src/tokens/primitives/shape/radius.js @@ -1,13 +1,13 @@ export const radius = { - 'rounded-none': '0', - 'rounded-sm': '2px', - 'rounded': '4px', - 'rounded-md': '6px', - 'rounded-lg': '8px', - 'rounded-xl': '12px', - 'rounded-2xl': '16px', - 'rounded-3xl': '24px', - 'rounded-full': '9999px', + none: '0', + sm: '2px', + DEFAULT: '4px', + md: '6px', + lg: '8px', + xl: '12px', + '2xl': '16px', + '3xl': '24px', + full: '9999px', }; export default { radius }; diff --git a/packages/theme/src/tokens/primitives/shape/shape.js b/packages/theme/src/tokens/primitives/shape/shape.js index 9b623e70..7b8067ef 100644 --- a/packages/theme/src/tokens/primitives/shape/shape.js +++ b/packages/theme/src/tokens/primitives/shape/shape.js @@ -2,10 +2,10 @@ import { radius } from './radius.js'; import { borderWidths } from '../border-widths.js'; export const shape = { - 'shape-flat': radius['rounded-none'], - 'shape-card': radius['rounded'], - 'shape-button': radius['rounded'], - 'shape-elements': radius['rounded'], + 'shape-flat': radius.none, + 'shape-card': radius.DEFAULT, + 'shape-button': radius.DEFAULT, + 'shape-elements': radius.DEFAULT, 'border-width-default': borderWidths[1], }; From 9ed4fe0c585d6d558154159c83b3e5615b84187a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaque=20B=C3=B6ck?= Date: Wed, 20 May 2026 16:42:11 -0300 Subject: [PATCH 33/34] fix(theme): restore semantic colors in v3 tailwind build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v3 token build was emitting primitive vars and component classes but never wired in tokens/semantic/colors.js, so dist/v3/globals.css had no --text-*/--background-*/--border-* vars, dist/v3/tailwind.config.js had no textColor/backgroundColor/borderColor extensions, and there was no dark block at all — breaking text-default, bg-surface, border-default and every other semantic utility downstream consumers relied on. - build-tokens.mjs: import semanticColors + createCssVars, emit semantic vars in :root (light), add an @layer base block for [data-theme=dark], .dark, .azion.azion-dark, and extend the v3 preset with textColor/backgroundColor/borderColor. - resolve.js: keep primitives/surfacePrimitives/brandPrimitives nested under their root keys instead of spreading flat, so tokenRef paths like primitives.gray.900 and surfacePrimitives.surface.0 resolve. - semantic/colors.js: rename data key 'bg' → 'background' (css-vars.js and the semanticColors derivation both looked up .background.light and threw on import); rename stale primitives.neutral.* refs to primitives.gray.* (the neutral palette was removed in bcf7cb4). Two refs remain unresolved and emit invalid CSS values pending product decision: primitives.alpha.neutral.25 (bg-backdrop) and primitives.alpha.brand.primary.65 (bg-primary-mask). --- packages/theme/src/scripts/build-tokens.mjs | 35 +++++++++++++++++++- packages/theme/src/scripts/resolve.js | 6 ++-- packages/theme/src/tokens/semantic/colors.js | 14 ++++---- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/packages/theme/src/scripts/build-tokens.mjs b/packages/theme/src/scripts/build-tokens.mjs index e2583d1c..72063073 100644 --- a/packages/theme/src/scripts/build-tokens.mjs +++ b/packages/theme/src/scripts/build-tokens.mjs @@ -33,6 +33,8 @@ import { buildTrees, flatten } from './compile-primitives.js'; import { containersData } from '../tokens/semantic/containers.data.js'; import { spacingsData } from '../tokens/semantic/spacings.data.js'; import { textsData } from '../tokens/semantic/texts.data.js'; +import { semanticColors } from '../tokens/semantic/colors.js'; +import { createCssVars } from './css-vars.js'; const BREAKPOINT_ORDER = ['sm', 'md', 'lg', 'xl', '2xl']; const V3_SELECTOR = ':root, [data-theme=light], .azion.azion-light'; @@ -76,11 +78,22 @@ const flattenBundle = (data) => { return byBp; }; +const SEMANTIC_PREFIXES = ['--text-', '--background-', '--border-']; +const isSemanticVar = (key) => SEMANTIC_PREFIXES.some((p) => key.startsWith(p)); +const pickSemantic = (vars) => + Object.fromEntries(Object.entries(vars).filter(([k]) => isSemanticVar(k))); + +const buildSemanticColorVars = () => { + const { light, dark } = createCssVars(); + return { light: pickSemantic(light), dark: pickSemantic(dark) }; +}; + const buildFlatModel = () => ({ primitives: flattenPrimitives(), containers: flattenSingleValue(containersData, (k) => `--container-${k}`), spacings: flattenSingleValue(spacingsData, (k) => `--${k}`), texts: flattenBundle(textsData), + semanticColors: buildSemanticColorVars(), }); // ─── 3. Shared formatting helpers ────────────────────────────────────────── @@ -127,6 +140,8 @@ const emitMediaBlockV3 = (bp, vars) => ` }`, ].join('\n'); +const V3_DARK_SELECTOR = '[data-theme=dark], .dark, .azion.azion-dark'; + const emitCssV3 = () => { const m = buildFlatModel(); @@ -135,6 +150,7 @@ const emitCssV3 = () => { { title: 'Containers', vars: m.containers._ || {} }, { title: 'Spacings', vars: m.spacings._ || {} }, { title: 'Texts', vars: m.texts._ || {} }, + { title: 'Semantic colors', vars: m.semanticColors.light }, ]; const baseBody = sections @@ -167,6 +183,13 @@ const emitCssV3 = () => { mediaBlocks.join('\n\n'), '}', '', + '@layer base {', + ` ${V3_DARK_SELECTOR} {`, + ` /* ── Semantic colors (dark) ── */`, + formatVars(m.semanticColors.dark, ' '), + ' }', + '}', + '', '@layer components {', emitComponentClasses(), '}', @@ -214,7 +237,17 @@ const buildPresetData = () => { return { theme: { - extend: { colors, fontSize, fontWeight, dropShadow, lineHeight, letterSpacing }, + extend: { + colors, + fontSize, + fontWeight, + dropShadow, + lineHeight, + letterSpacing, + textColor: semanticColors.text, + backgroundColor: semanticColors.background, + borderColor: semanticColors.border, + }, }, }; }; diff --git a/packages/theme/src/scripts/resolve.js b/packages/theme/src/scripts/resolve.js index 4ea1c2d3..c5cb23af 100644 --- a/packages/theme/src/scripts/resolve.js +++ b/packages/theme/src/scripts/resolve.js @@ -33,9 +33,9 @@ const flattenToCssVars = (obj, prefix = []) => { export const resolveRefsToCssVars = (tokens) => { const baseForResolve = { - ...tokens.primitives, - ...tokens.surfacePrimitives, - ...tokens.brandPrimitives, + primitives: tokens.primitives, + surfacePrimitives: tokens.surfacePrimitives, + brandPrimitives: tokens.brandPrimitives, }; const baseForVars = { primitives: tokens.primitives, surfacePrimitives: tokens.surfacePrimitives }; diff --git a/packages/theme/src/tokens/semantic/colors.js b/packages/theme/src/tokens/semantic/colors.js index aab909af..09cd072e 100644 --- a/packages/theme/src/tokens/semantic/colors.js +++ b/packages/theme/src/tokens/semantic/colors.js @@ -21,10 +21,10 @@ import { tokenRef } from '../../scripts/refs.js'; export const semanticColorsData = { text: { light: { - default: tokenRef('primitives.neutral.900'), - muted: tokenRef('primitives.neutral.600'), + default: tokenRef('primitives.gray.900'), + muted: tokenRef('primitives.gray.600'), link: tokenRef('primitives.blue.600'), - code: tokenRef('primitives.neutral.600'), + code: tokenRef('primitives.gray.600'), 'link-hover': tokenRef('primitives.blue.700'), primary: tokenRef('brand.primary.primary-500'), 'primary-hover': tokenRef('brand.primary.primary-600'), @@ -38,10 +38,10 @@ export const semanticColorsData = { warning: tokenRef('primitives.yellow.600'), }, dark: { - default: tokenRef('primitives.neutral.50'), - muted: tokenRef('primitives.neutral.400'), + default: tokenRef('primitives.gray.50'), + muted: tokenRef('primitives.gray.400'), link: tokenRef('primitives.blue.400'), - code: tokenRef('primitives.neutral.400'), + code: tokenRef('primitives.gray.400'), 'link-hover': tokenRef('primitives.blue.300'), primary: tokenRef('brand.primary.primary-500'), 'primary-hover': tokenRef('brand.primary.primary-400'), @@ -55,7 +55,7 @@ export const semanticColorsData = { warning: tokenRef('primitives.yellow.400'), }, }, - 'bg': { + background: { light: { 'surface-raised': tokenRef('brand.surfaces.surface-0'), 'surface-overlay': tokenRef('brand.surfaces.surface-50'), From ad44b05cae40320ee1320c534683eac50f94bede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaque=20B=C3=B6ck?= Date: Wed, 20 May 2026 16:49:53 -0300 Subject: [PATCH 34/34] chore: revert webkit and storybook changes to main state Scope this branch back to packages/theme only. The storybook adjustments live on branch refactoring-tokens-storybook. --- apps/storybook/.storybook/preview.js | 5 +- apps/storybook/src/foundations-data/tokens.js | 76 +++++++++++++++- apps/storybook/src/foundations/data/colors.js | 86 ++++++++++++++++++- .../src/stories/foundations/Colors.stories.js | 2 +- apps/storybook/tailwind.config.js | 25 +++++- .../src/components/overline/overline.vue | 6 +- 6 files changed, 185 insertions(+), 15 deletions(-) diff --git a/apps/storybook/.storybook/preview.js b/apps/storybook/.storybook/preview.js index 633cf490..2aec7e87 100644 --- a/apps/storybook/.storybook/preview.js +++ b/apps/storybook/.storybook/preview.js @@ -2,14 +2,17 @@ import { setup } from '@storybook/vue3' import PrimeVue from 'primevue/config' import Tooltip from 'primevue/tooltip' import { withThemeByClassName } from '@storybook/addon-themes' +import { injectCssVars } from '@aziontech/theme/tokens' import 'primeflex/primeflex.css' -import '@aziontech/theme/v3/globals.css' import '../src/styles/preview.css' import '@aziontech/theme' import '@aziontech/icons' import '@aziontech/webkit/styles/country-flags' +// Inject semantic token CSS variables for light/dark mode +injectCssVars() + setup((app) => { app.use(PrimeVue, { ripple: false diff --git a/apps/storybook/src/foundations-data/tokens.js b/apps/storybook/src/foundations-data/tokens.js index b85792fd..a1203061 100644 --- a/apps/storybook/src/foundations-data/tokens.js +++ b/apps/storybook/src/foundations-data/tokens.js @@ -4,11 +4,81 @@ */ import { + createCssVars, primitives, brandPrimitives, surfacePrimitives, + textSemantic, + backgroundSemantic, + borderSemantic, } from '@aziontech/theme/tokens' +const { light, dark } = createCssVars() + +// ─── Usage descriptions ────────────────────────────────────────────────────── + +const textUsage = { + default: 'Primary text content', + muted: 'Secondary / supporting text', + link: 'Interactive link text', + code: 'Code and monospace text', + linkHover: 'Hovered link text', + primary: 'Brand primary — CTAs and highlights', + primaryHover: 'Hovered primary text', + accent: 'Accent / violet highlight', + accentHover: 'Hovered accent text', + danger: 'Error and destructive states', + dangerHover: 'Hovered danger text', + warning: 'Warning / caution states', + warningHover: 'Hovered warning text', + success: 'Success and positive states', + successHover: 'Hovered success text', +} + +const backgroundUsage = { + surfaceRaised: 'Elevated surface — cards, panels', + surfaceOverlay: 'Floating overlay — tooltips, dropdowns', + surface: 'Base surface — page body', + canvas: 'Outermost page canvas', + primary: 'Brand primary background', + primaryHover: 'Hovered primary background', + danger: 'Error / danger background', + dangerHover: 'Hovered danger background', + warning: 'Warning background', + warningHover: 'Hovered warning background', + success: 'Success background', + successHover: 'Hovered success background', + backdrop: 'Modal / dialog backdrop overlay', +} + +const borderUsage = { + default: 'Standard divider border', + subtle: 'Subtle / low-contrast border', + strong: 'High-contrast border', + primary: 'Brand primary border', + primaryHover: 'Hovered primary border', + accent: 'Accent brand border', + accentHover: 'Hovered accent border', + danger: 'Error / destructive border', + dangerHover: 'Hovered danger border', + warning: 'Warning border', + warningHover: 'Hovered warning border', + success: 'Success border', + successHover: 'Hovered success border', +} + +// ─── Helpers ───────────────────────────────────────────────────────────────── + +function buildSemanticRows(semanticMap, cssVarPrefix, tailwindPrefix, usageMap) { + return Object.keys(semanticMap.light).map((key) => ({ + name: `${tailwindPrefix}${key}`, + cssVar: `--${cssVarPrefix}${key}`, + tailwindClass: `${tailwindPrefix}${key}`, + lightValue: light[`--${cssVarPrefix}${key}`] ?? 'N/A', + darkValue: dark[`--${cssVarPrefix}${key}`] ?? 'N/A', + usage: usageMap[key] ?? '', + })) +} // ─── Primitive color groups ─────────────────────────────────────────────────── // Ordered for display (most commonly used first) @@ -72,16 +142,16 @@ export const semanticColorGroups = [ { group: 'Text', description: 'Consumed via Tailwind as `text-{name}`. Controls font color.', - rows: [], + rows: buildSemanticRows(textSemantic, 'text-', 'text-', textUsage), }, { group: 'Background', description: 'Consumed via Tailwind as `bg-{name}`. Controls background color.', - rows: [], + rows: buildSemanticRows(backgroundSemantic, 'background-', 'bg-', backgroundUsage), }, { group: 'Border', description: 'Consumed via Tailwind as `border-{name}`. Controls border color.', - rows: [], + rows: buildSemanticRows(borderSemantic, 'border-', 'border-', borderUsage), }, ] diff --git a/apps/storybook/src/foundations/data/colors.js b/apps/storybook/src/foundations/data/colors.js index 634f59b3..63768767 100644 --- a/apps/storybook/src/foundations/data/colors.js +++ b/apps/storybook/src/foundations/data/colors.js @@ -9,8 +9,22 @@ import { primitives, surfacePrimitives, brandPrimitives, + textSemantic, + backgroundSemantic, + borderSemantic, + resolveRefsToCssVars, } from '@aziontech/theme/tokens'; +// Resolve all token refs to concrete hex values for both modes +const { light: lightVars, dark: darkVars } = resolveRefsToCssVars({ + primitives, + surfacePrimitives, + brandPrimitives, + textSemantic, + backgroundSemantic, + borderSemantic, +}); + // ─── Primitive Colors ───────────────────────────────────────────────────────── const SHADES = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]; @@ -40,6 +54,72 @@ export const primitiveColors = PRIMITIVE_FAMILIES.map(({ name, label, role }) => })), })); -export const backgroundTokens = []; -export const textTokens = []; -export const borderTokens = []; +// ─── Semantic Tokens ────────────────────────────────────────────────────────── + +const TOKEN_DESCRIPTIONS = { + background: { + surface: 'Main content areas — cards, panels, sidebars', + surfaceRaised: 'Elevated surfaces — modals, dropdowns, tooltips', + surfaceOverlay: 'Overlay panel backgrounds', + canvas: 'Page / app root background', + primary: 'Brand primary interactive fill', + primaryHover: 'Primary fill hover state', + danger: 'Error / destructive state fill', + dangerHover: 'Danger hover state', + warning: 'Warning state fill', + warningHover: 'Warning hover state', + success: 'Success state fill', + successHover: 'Success hover state', + backdrop: 'Modal / overlay backdrop', + }, + text: { + default: 'Primary text content', + muted: 'Secondary / supporting text', + link: 'Interactive link text', + linkHover: 'Link hover state', + code: 'Code / monospace text', + primary: 'Brand-colored text', + primaryHover: 'Brand text hover', + accent: 'Accent (violet) text', + accentHover: 'Accent hover state', + danger: 'Error / destructive text', + dangerHover: 'Danger text hover', + warning: 'Warning text', + warningHover: 'Warning hover', + success: 'Success text', + successHover: 'Success hover', + }, + border: { + default: 'Standard borders and dividers', + subtle: 'Lightweight / low-contrast borders', + strong: 'High-contrast borders', + primary: 'Brand-colored borders', + primaryHover: 'Primary border hover', + accent: 'Accent-colored borders', + accentHover: 'Accent border hover', + danger: 'Error state borders', + dangerHover: 'Danger border hover', + warning: 'Warning state borders', + warningHover: 'Warning border hover', + success: 'Success state borders', + successHover: 'Success border hover', + }, +}; + +/** + * Build a resolved token data array for a semantic category. + * Tailwind class names match the semantic-colors-plugin (no camelCase → kebab conversion). + */ +const buildTokens = (semanticLight, category, tailwindPrefix) => + Object.keys(semanticLight).map((key) => ({ + name: key, + cssVar: `--${category}-${key}`, + tailwindClass: `${tailwindPrefix}-${key}`, + description: TOKEN_DESCRIPTIONS[category]?.[key] ?? '', + lightHex: lightVars[`--${category}-${key}`] ?? null, + darkHex: darkVars[`--${category}-${key}`] ?? null, + })); + +export const backgroundTokens = buildTokens(backgroundSemantic.light, 'background', 'bg'); +export const textTokens = buildTokens(textSemantic.light, 'text', 'text'); +export const borderTokens = buildTokens(borderSemantic.light, 'border', 'border'); diff --git a/apps/storybook/src/stories/foundations/Colors.stories.js b/apps/storybook/src/stories/foundations/Colors.stories.js index 6ff7bec8..9ab081c8 100644 --- a/apps/storybook/src/stories/foundations/Colors.stories.js +++ b/apps/storybook/src/stories/foundations/Colors.stories.js @@ -157,7 +157,7 @@ export const Backgrounds = {
- +
diff --git a/apps/storybook/tailwind.config.js b/apps/storybook/tailwind.config.js index ad9394bb..88451808 100644 --- a/apps/storybook/tailwind.config.js +++ b/apps/storybook/tailwind.config.js @@ -1,10 +1,13 @@ import typography from '@tailwindcss/typography' -import themePreset from '@aziontech/theme/tailwind-preset/v3' +import { theme } from '@aziontech/theme/tailwind/tailwind-theme' +import semanticColors from '@aziontech/theme/tailwind/semantic-colors-plugin' +import semanticTexts from '@aziontech/theme/tailwind/semantic-texts-plugin' +import semanticSpacing from '@aziontech/theme/tailwind/semantic-spacing-plugin' +import semanticAnimations from '@aziontech/theme/tailwind/semantic-animations-plugin' /** @type {import('tailwindcss').Config} */ export default { important: true, - presets: [themePreset], content: [ './src/**/*.{vue,js,ts,jsx,tsx}', '../../packages/webkit/src/**/*.{vue,js,ts,jsx,tsx}' @@ -12,22 +15,30 @@ export default { // Dark mode configuration // Use `.dark` on an ancestor (Storybook uses `withThemeByClassName` to toggle it) darkMode: ['class'], + // Merge base theme with primitives theme: { + ...theme, fontFamily: { + ...(theme.fontFamily ?? {}), sans: ['Sora'], mono: ['Proto Mono'], code: ['Roboto Mono'] }, listStyleType: { + ...(theme.listStyleType ?? {}), none: 'none', disc: 'disc', decimal: 'decimal', square: 'square', roman: 'upper-roman' }, + // Properly merge the theme's extend with local extend extend: { - // Storybook-specific color extensions (merged on top of the theme preset) + // Import colors from theme (brand, base, surface, primitives) + ...(theme.extend ?? {}), + // Storybook-specific color extensions colors: { + ...(theme.extend?.colors ?? {}), header: '#111111', 'header-button-enabled': '#ffffff32', 'header-button-hover': '#f5f5f516', @@ -67,5 +78,11 @@ export default { } } }, - plugins: [typography] + plugins: [ + typography, + semanticColors(), + semanticTexts(), + semanticSpacing(), + semanticAnimations(), + ] } diff --git a/packages/webkit/src/components/overline/overline.vue b/packages/webkit/src/components/overline/overline.vue index 4f9d712b..dae6b095 100644 --- a/packages/webkit/src/components/overline/overline.vue +++ b/packages/webkit/src/components/overline/overline.vue @@ -30,20 +30,20 @@ > {{ prefix }}