feat(tokens): sync espresso v2 from Figma + rebuild foundations docs#727
Open
netchampfaris wants to merge 22 commits into
Open
feat(tokens): sync espresso v2 from Figma + rebuild foundations docs#727netchampfaris wants to merge 22 commits into
netchampfaris wants to merge 22 commits into
Conversation
84b44f7 to
280a01a
Compare
3 tasks
…ndations docs
Generator
- tailwind/figma-tokens-to-theme.js reads the W3C DTCG token JSON
exported from Figma (espresso-v2-design-tokens/) and emits
tailwind/generated/{colors,radius,typography}.json
- Run with `yarn sync-tokens`
- Preserves legacy semantic names (surface-cards, surface-white,
ink-gray-9, outline-gray-modals, …) via alias + legacy-entry maps
so existing src/ and docs/ usage keeps working through the rename
Tailwind
- tailwind/colors.json refreshed from Figma; adds *.950 shades,
gray-alpha and red-alpha ramps, surface/ink/outline updates
- tailwind/plugin.js now consumes radius.json + typography.json
instead of hardcoded scales; exposes new sizes (tiny, 4xl..15xl)
and the full numeric radius scale (rounded-0..9) alongside the
named aliases
Docs
- New /docs/foundations/* pages replacing /docs/design-system/*:
Colours — Base, Colours — Semantic, Typography, Corner Radius,
Drop Shadow
- Components in docs/components/foundations/ read directly from
the generated JSON; light/dark TabButtons toggle; click-to-copy
- Layout.vue respects `outline: false` frontmatter (custom
OnThisPage was previously unconditional)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
transformerStyleToClass only flushes its CSS at buildEnd, so in dev the generated shiki.css stays empty and code blocks lose their syntax highlighting. Skip the transformer in dev and let shiki emit inline --shiki-light/dark styles directly. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add text-{size}-medium utilities (ADR-0004) for Figma's named
typography styles; Button md/lg adopt them for exact tracking parity
- Switch Button focus ring to ring-2 to match Figma's 2px shadow (ADR-0005)
- Adopt numbered radius tokens as canonical (ADR-0006); Button migrates
from named aliases; named aliases flagged for migration
- Add spec/foundations.md covering typography, focus, radius, themes,
code-only extensions, and the Figma verification process
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Delete Variants/Themes/Sizes/Icons stories; the API table already covers prop variations - Add 6 contextual stories matching the Button Figma file: section controls, section action, selection toolbar, inline actions, stacked actions, and a live-class card - Add a Playground builder (TabButtons + Switch knobs) with live preview and dynamically generated Vue snippet; registered globally as <ButtonBuilder> in the VitePress theme Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Wire the Figma token pipeline to emit elevation/focus effects, expose them as CSS variables, and register `shadow-*` / `ring-*` utilities that resolve to the new variables. Replace the standalone drop-shadow docs page with a broader elevation page that previews both stacks. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Consolidates the lucide / feather / emoji / Vue-component icon-rendering pattern that's currently duplicated across Button, Dropdown, Dialog, and OptionIcon into one small component, so new call sites have one obvious choice. Falsy values render nothing; fallthrough attrs go to the rendered root. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A compact tab item used by TabButtons (and reusable on its own). The `icon` prop renders an icon-only pill — any `label` is exposed only to assistive tech. `iconLeft` / `iconRight` are accent icons rendered next to a visible label, matching Button's semantics. Variants cover the segmented, outline, underline, and browser-tab looks. Icon rendering goes through the shared `<Icon>` component. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…wrap TabButtons no longer wraps `<Button>` internally — each tab is now a native `<button>`, `<a href>`, or `<RouterLink>` rendering a `<Pill>` for its visual treatment. BREAKING CHANGE: per-option `theme`, `variant`, `size`, `loading`, `hideLabel` and `tooltip`-as-popover are no longer honored. Use the shared `<Button>` directly if any of these matter, or supply richer content via the `prefix` / `suffix` slots. Migration notes added to `TabButtons.md`. New: `route` and `href` per option render the tab as a RouterLink or anchor respectively. The internal v-model fallback chain (`value ?? label ?? index`) is preserved for back-compat with consumers that bound to a label string. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Picks up the new Pill and Icon components in the auto-resolved declaration file, drops stale Rating story entries, and absorbs incidental type-union reordering in Divider/Popover/Tooltip api docs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace the four duplicated *Builder.vue files (~180 lines each, 90% identical chrome) with a shared ComponentPlayground that takes a knob schema + #preview slot + code(values) fn. Each per-component builder shrinks to ~30-80 lines of pure config. Code preview matches story preview visuals exactly: runtime shiki highlighting with the same tokyo-night/github-light themes, .shiki sizing and bg, and the global .copy button style. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previously the active indicator was a 3px rounded bar floating 3px outboard of the rail, with full pill height. Read as a text caret next to the label rather than a tab marker. Now: 1px-wide square segment positioned at right:-2px (overlapping the column rail), label-height via inset-y-1.5. Active label gets font-medium on underline variant so the label itself signals selection. Adds pr-2 to vertical underline pills so short labels don't sit flush against the indicator. Also cleans up a stray </content> tag at the end of Pill.vue and TabButtons.vue (left over from prior commits, broke SFC parsing). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Swap the per-site focus-visible:ring-* + ring-outline-gray-* patterns
for the new focus-ring / focus-ring-{theme} utilities backed by the
--focus-* design tokens. Button maps theme → themed focus-ring
(blue/green/red); other components use the default gray focus-ring.
Triggers in Select / shared selection / MultiSelect TagsTrigger also
adopt focus-ring on data-[state=open] so the open ring matches the
focus ring exactly. Intentional suppression sites (Sidebar item, ghost
input variants) left unchanged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace generic Tab/Tab placeholder options with Home/Task/Contact/Others nav and an icon-only ghost sidebar, inspired by the Figma showcase. Use distinct iconLeft icons per option and switch the Sizes / PrefixSuffix demos to view-switcher and Inbox/Comments patterns. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The docs render the stories/ snippets directly; this orphan Histoire-style file isn't referenced anywhere. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Sidebar/page renames: "Colours — Base" → "Base Colors", "Colours — Semantic" → "Semantic Colors", "Corner Radius" → "Radius" (file renamed to foundations/radius.md, URL paths for colours unchanged). - SemanticPage rewritten as a flat row list per token: swatch, name, → reference, and resolved value — no surrounding box, no hover. - PalettePage: drop the per-swatch inset 1px ring and the p-2 wrappers around the overlay sections; each overlay swatch now layers its translucent color over its own bg-ink-gray-9 / bg-surface-white backdrop via a linear-gradient. - New docs/composables/useTheme.ts watches the <html data-theme> attribute (set by Navbar.vue) so the local Light/Dark switchers on both foundations pages follow global theme toggles in real time. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Espresso 2.0's Figma dark-mode page applies elevation/light/* shadows
universally — never the elevation/dark/* set. Match that: emit
--elevation-{sm..2xl} from :root only, so shadow-* resolves to the same
value in both themes. The Figma dark set is still exposed as
--dark-elevation-* / shadow-dark-* for opt-in heavier shadows.
Pill: raised active state now uses bg-surface-gray-2-contrast shadow-base
+ text-ink-gray-8, matching the Figma dark-mode active pill (lighter
surface over container, subtle light shadow with inner highlight, less
glaring label).
TabButtons: clip the container so the active pill's shadow doesn't
overflow the rounded corners.
Docs: elevation page copy reflects the single-shadow-set model;
ElevationPreview switcher uses TabButtons and syncs with the global
theme toggle (same pattern as Palette/Semantic pages).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Pass defaultColor: false to Shiki's codeToHtml so both themes are emitted as CSS variables (--shiki-light / --shiki-dark) instead of inline color on the light theme. The [data-theme="dark"] .shiki span rule in docs/css/style.css can then flip tokens at runtime — previously the light theme's inline color won by specificity and snippets stayed light even in dark mode. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Radius: collapse the numeric and named-alias sections into one divided list (one row per scale step). Each row shows the rounded-N class + --radius-N CSS variable, with aliases like `rounded`, `rounded-sm` rendered as inline chips on the numeric row they map to. Swatches enlarged so adjacent steps (e.g. 2 → 3 = 5px → 6px) are distinguishable. Plumb --radius-* CSS variables through tailwind/plugin.js so the docs aren't lying: borderRadius now resolves via var(--radius-N), with `DEFAULT` reusing the numeric var that shares its value. Values unchanged. Typography: display line-height as a unitless ratio (lh / size) instead of the raw px value from Figma — closer to how designers reason about leading.
…values PR #720 on main extracted borderRadius/boxShadow/fontSize into tokens.js as a public sub-path export. Our branch already replaced those values with Figma-generated tokens in plugin.js. After the rebase, tokens.js still exported the legacy hardcoded values, drifting from what the plugin actually emits. Source from ./generated/* so external consumers match the plugin output. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
56a53c7 to
002efa1
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
yarn sync-tokens). Refreshestailwind/colors.json(new*.950shades,gray-alpha/red-alpharamps, semantic surface/ink/outline) and replaces hardcodedborderRadius/fontSizeinplugin.jswith the generated JSON.rounded-0..rounded-9numeric radii (incl. 5px / 6px previously only reachable via arbitrary values) alongside the existing named aliases, plus typography sizes up totext-15xl./docs/foundations/*and read directly from the generated JSON.surface-cards,surface-white,ink-gray-9,outline-gray-modals, etc.) via alias + legacy-entry maps in the generator — no churn for existingsrc/ordocs/usage.Files of interest
tailwind/figma-tokens-to-theme.js— the generatortailwind/colors.json,tailwind/generated/{radius,typography}.json— synced outputstailwind/plugin.js— now consumes JSON instead of hardcoded scalesdocs/components/foundations/*.vue— new docs pages with light/darkTabButtonstoggle + click-to-copydocs/components/Layout.vue— customOnThisPagenow respectsoutline: falsefrontmatterTest plan
yarn sync-tokensregenerates JSON without errorsyarn buildpassesyarn testpasses (39/39 locally)/docs/foundations/colours/base— palette renders, light/dark toggle swaps values/docs/foundations/colours/semantic— surface/ink/outline tokens grouped by subfamily, 4-column responsive grid/docs/foundations/corner-radius— both numeric and named tile grids visible/docs/foundations/typography— text + display sizes render with metadatasurface-cardslegacy alias)bg-surface-*,text-ink-*,border-outline-*,rounded-*look unchanged in light modeDocs preview: https://ui.frappe.io/pr-preview/pr-727/
Coverage: 48.92% (±0.00% vs
main)