Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions apps/frontend/src/components/AppShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,10 @@ function NavItemLink({
title={collapsed ? label : undefined}
className={({ isActive }) =>
cn(
// W13 — pill nav items match the AIS button shape; the active
// bg-primary/10 + text-primary tint then reads exactly like the
// AIS selected-nav state. Hover/active transitions stay on the
// W11 150 ms ease-out-soft tokens.
"flex items-center rounded-full py-2 text-sm font-medium transition-colors duration-fast ease-out-soft",
// W11-F polish — sidebar nav hover/active transitions land on the
// W11-A 150 ms ease-out-soft tokens for parity with every other
// hoverable affordance (buttons, dropdown items, tabs).
"flex items-center rounded-md py-2 text-sm font-medium transition-colors duration-fast ease-out-soft",
collapsed ? "justify-center px-2" : "gap-2 px-3",
"hover:bg-accent hover:text-accent-foreground",
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
Expand Down
8 changes: 4 additions & 4 deletions apps/frontend/src/components/ui/badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,17 @@
// critical text-red-700 → 5.54:1
// high text-orange-800 → 6.47:1
// medium text-yellow-800 → 5.91:1
// low text-teal-800 → 6.59:1 (W13 — token moved to
// teal-700, text follows the hue)
// low text-blue-700 → 5.83:1
// info text-slate-600 → 6.41:1
//
// The dot indicators (SeverityBadge / DependencyScopeBadge / chart
// legends) still use `bg-risk-X` raw so the brand colour stays
// recognisable — only the text shade is darkened.
// recognisable — only the text shade is darkened. Token values in
// `index.css` are NOT changed (W11 prohibition: "Severity 색 변경 0").
critical: "border-transparent bg-risk-critical/10 text-red-700",
high: "border-transparent bg-risk-high/10 text-orange-800",
medium: "border-transparent bg-risk-medium/15 text-yellow-800",
low: "border-transparent bg-risk-low/10 text-teal-800",
low: "border-transparent bg-risk-low/10 text-blue-700",
info: "border-transparent bg-risk-info/15 text-slate-600",
success: "border-transparent bg-emerald-100 text-emerald-700",
},
Expand All @@ -86,4 +86,4 @@
);
Badge.displayName = "Badge";

export { badgeVariants };

Check warning on line 89 in apps/frontend/src/components/ui/badge.tsx

View workflow job for this annotation

GitHub Actions / lint (frontend)

Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
33 changes: 16 additions & 17 deletions apps/frontend/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,25 @@
import { cn } from "@/lib/utils";

/**
* Button — W13 AIS adoption (pill shape) on top of the W11-A polish.
* Button — W11-A polish.
*
* - `rounded-full` pills are the Google AI Studio button shape. This is
* deliberately NOT driven by the --radius token — raising the token to
* a pill value would full-round cards/dialogs via the tailwind.config
* calc() derivations. Inputs keep the token radius on purpose.
* - `transition-all duration-fast ease-out-soft` — 150 ms eased hover /
* focus transition (W11 Linear polish, retained).
* - Focus ring `ring-2` + `ring-offset-2` (matches --ring, now the blue
* primary, for a coherent focus signal).
* - shadow-sm on default/destructive/outline resolves to a zero-alpha
* no-op under W13 tokens (AIS keeps in-flow surfaces flat); kept in
* the class lists so a future token change re-enables elevation
* without touching this file.
* Changes vs. previous baseline:
* - `transition-colors` → `transition-all duration-fast ease-out-soft` so
* hover/focus is a 150 ms eased transition (Linear polish) covering
* background AND shadow.
* - Focus ring kept at `ring-2` + `ring-offset-2` (matches new --ring token
* which now lines up with --primary for a coherent focus signal).
* - Default variant picks up `shadow-sm` so the primary CTA reads as a
* raised affordance against the off-white page background (Vercel
* deployments-1 "Visit" button reference).
* - Outline variant gets `shadow-sm` too — light elevation, no border
* contrast bump needed.
*
* The hex colors themselves are NOT in this file — they flow from the
* tokens declared in `src/index.css` (W13).
* tokens declared in `src/index.css` (W11-A).
*/
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-sm font-medium ring-offset-background transition-all duration-fast ease-out-soft focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-all duration-fast ease-out-soft focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
Expand All @@ -41,8 +40,8 @@
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 px-3 text-xs",
lg: "h-10 px-6",
sm: "h-8 rounded-md px-3 text-xs",
lg: "h-10 rounded-md px-6",
icon: "h-9 w-9",
},
},
Expand Down Expand Up @@ -73,4 +72,4 @@
);
Button.displayName = "Button";

export { buttonVariants };

Check warning on line 75 in apps/frontend/src/components/ui/button.tsx

View workflow job for this annotation

GitHub Actions / lint (frontend)

Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
145 changes: 67 additions & 78 deletions apps/frontend/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,24 @@
/* ---------------------------------------------------------------------------
* TRUSCA — design tokens
*
* W13 (2026-06-12) — Google AI Studio light tone, adopted from the dev
* prototype (PR #394) after user review. Supersedes the W11-A Vercel +
* Linear palette; the W11 typography hierarchy, focus ring, and motion
* polish are retained unchanged.
* W11-A (2026-05-27) — Vercel base + Linear polish (option C, light single).
* SoT: docs/ux/design-philosophy-evolution-plan-2026-05-27.md §4.
*
* Tone reference — Google AI Studio (light):
* - plain white canvas, grey panel tint, #dadce0 hairline borders
* - Google-blue primary CTA + tonal (light-blue) secondary
* - pill buttons (see button.tsx) and flat cards (border + tone, no
* shadow); shadows are reserved for floating surfaces
* - fonts stay Inter + JetBrains Mono (Google Sans is proprietary)
* Tone reference:
* - Vercel light deployments / domains / deployment detail
* → background / surface / border / sidebar tint / dense rows / primary
* near-black button
* - Linear feature / dashboard
* → typography hierarchy (heading semibold), focus ring (visible 2 + 2
* offset), hover transitions (150 ms ease-out), elevation shadows,
* dropdown polish. Dark variant intentionally NOT absorbed — Linear
* is dark-native, we re-interpret only the polish layer in light.
*
* Layout invariants (unchanged):
* sidebar 224 px · header 48 px · table row 40 px · Inter + JetBrains Mono.
* Density is kept — only the skin changed.
*
* Risk severity colors:
* Critical / High / Medium / Info unchanged. Low moved blue-600 → teal-700
* in W13 (user decision): the old blue collided with the new Google-blue
* primary, making Low badges read like CTAs / links.
* Risk severity colors (unchanged — domain semantics fixed):
* Critical / High / Medium / Low / Info.
*
* Forward-compat note:
* Dark mode tokens are NOT defined in this phase (2026-05-27 user decision).
Expand All @@ -36,83 +34,79 @@
@layer base {
:root {
/* -------------------------------------------------------------------
* shadcn/ui base tokens — Google AI Studio light palette (W13).
* shadcn/ui base tokens — re-tuned to Vercel light palette.
*
* HSL is shadcn convention. Hex equivalents are noted for review;
* never reference the hex directly in components (use the CSS var or
* the Tailwind utility — e.g. `bg-background`, `text-foreground`).
* ----------------------------------------------------------------- */

/* Page background — plain white canvas (AIS). Cards sit flush on it
* and separate via border + tone, not elevation. */
--background: 0 0% 100%; /* #ffffff */
--foreground: 0 0% 12%; /* #1f1f1fGoogle grey-900 */
/* Page background — slight off-white so elevated surfaces (cards,
* popovers) read as raised. Vercel uses ~#fafafa for the canvas. */
--background: 0 0% 98%; /* #fafafa */
--foreground: 240 6% 10%; /* #18181bwarm near-black (was #0f172a navy) */

/* Surfaces share the white canvas; --muted carries the grey panel /
* table-header tint instead. */
/* Elevated surfaces sit on top of --background. Pure white reads as
* "card on page" against the off-white canvas. */
--card: 0 0% 100%; /* #ffffff */
--card-foreground: 0 0% 12%;
--card-foreground: 240 6% 10%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 12%;
--popover-foreground: 240 6% 10%;

/* Muted = table header / sidebar tint / placeholder fill. */
--muted: 210 17% 98%; /* #f8f9fa */
--muted-foreground: 213 5% 39%; /* #5f6368Google grey-700, passes AA */

/* Border / input outline — the AIS standard hairline. */
--border: 220 9% 87%; /* #dadce0 */
--input: 220 9% 87%;

/* Primary CTA — Google blue. Hover flows through `bg-primary/90`. */
--primary: 217 90% 43%; /* #0b57d0 */
--primary-foreground: 0 0% 100%;

/* Secondary = Google "tonal" button (light-blue fill, deep-blue text);
* accent = the faint blue-grey tint AIS uses on hover rows and ghost
* surfaces. */
--secondary: 217 91% 91%; /* #d3e3fd */
--secondary-foreground: 217 90% 15%; /* #041e49 */
--accent: 213 43% 96%; /* #f0f4f9 */
--accent-foreground: 0 0% 12%;

/* Destructive — Google red. Near risk-critical (#dc2626) so destructive
* buttons still share the visual language of a Critical badge. */
--destructive: 4 71% 50%; /* #d93025 */
--destructive-foreground: 0 0% 100%;

/* Focus ring — matches the blue primary so the 2 px outline reads as
* "the same thing this button is". */
--ring: 217 90% 43%;
--muted: 240 5% 96%; /* #f4f4f5 */
--muted-foreground: 240 4% 46%; /* #71717a — passes AA on --muted */

/* Border / input outline — softer than slate-200, more neutral. */
--border: 240 5% 91%; /* #e5e5ea */
--input: 240 5% 91%;

/* Primary CTA — Vercel-style warm near-black instead of navy.
* Reads as "important action" without leaning blue. */
--primary: 240 6% 10%; /* #18181b */
--primary-foreground: 0 0% 98%;

/* Secondary / accent share the muted tint — used for ghost-style
* surfaces and hover row backgrounds. */
--secondary: 240 5% 96%;
--secondary-foreground: 240 6% 10%;
--accent: 240 5% 96%;
--accent-foreground: 240 6% 10%;

/* Destructive — aligned with risk-critical hex so destructive
* buttons share the visual language of a Critical severity badge. */
--destructive: 0 72% 51%; /* ~#dc2626 */
--destructive-foreground: 0 0% 98%;

/* Focus ring — matches primary tone so the 2 px outline reads as
* "the same thing this button is", per Linear polish. */
--ring: 240 6% 10%;

/* -------------------------------------------------------------------
* Radius hierarchy (W13 — one step rounder than W11 across the board).
* Radius hierarchy (Linear polish — different sizes for different
* affordances so depth reads at a glance).
*
* --radius-sm 6 px — small inputs, badges, chips
* --radius 8 px — cards, inputs, table chrome (DEFAULT)
* --radius-lg 10 px — drawer, large surfaces
* --radius-xl 14 px — modals, dialogs
* --radius-sm 4 px — small inputs, badges, chips
* --radius 6 px — buttons, cards, table chrome (DEFAULT)
* --radius-lg 8 px — drawer, large surfaces
* --radius-xl 12 px — modals, dialogs
*
* Buttons are pills (rounded-full in button.tsx), NOT derived from
* this token — raising --radius to a pill value would full-round
* cards and dialogs via the calc() derivations in tailwind.config.ts.
* shadcn convention reads `--radius` as the card default; smaller /
* larger variants derive via `calc()` in tailwind.config.ts.
* ----------------------------------------------------------------- */
--radius: 0.5rem;
--radius: 0.375rem;

/* -------------------------------------------------------------------
* Elevation — AIS keeps in-flow surfaces flat (cards/buttons separate
* via border + tone), so shadow-sm is a zero-alpha no-op. It must stay
* a VALID box-shadow value (consumers do `box-shadow: var(--shadow-sm)`
* and an empty string / `none` inside a list breaks them). md / lg
* follow the Google elevation-1 / -2 recipes for floating surfaces
* (dropdown / popover / drawer / dialog).
* Elevation — subtle, Vercel-style. Light shadows only; no glow.
* Used by Card (sm), Dropdown / Popover (md), Drawer / Dialog (lg).
* ----------------------------------------------------------------- */
--shadow-sm: 0 0 0 0 rgb(0 0 0 / 0);
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.04);
--shadow-md:
0 1px 2px 0 rgb(60 64 67 / 0.3),
0 1px 3px 1px rgb(60 64 67 / 0.15);
0 2px 8px -2px rgb(0 0 0 / 0.08),
0 1px 2px 0 rgb(0 0 0 / 0.04);
--shadow-lg:
0 1px 3px 0 rgb(60 64 67 / 0.3),
0 4px 8px 3px rgb(60 64 67 / 0.15);
0 10px 28px -8px rgb(0 0 0 / 0.12),
0 3px 8px -3px rgb(0 0 0 / 0.06);

/* -------------------------------------------------------------------
* Motion (Linear polish) — short, ease-out. Three steps cover the
Expand All @@ -128,19 +122,14 @@
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);

/* -------------------------------------------------------------------
* Risk severity — domain meaning is fixed.
* Risk severity (unchanged — domain meaning is fixed).
* Used directly by recharts / lucide as raw hex, also exposed as
* Tailwind `text-risk-critical` / `bg-risk-high/10` etc.
*
* W13: --risk-low moved blue-600 (#2563eb) → teal-700 (#0f766e) so Low
* badges no longer share a hue with the Google-blue primary CTA.
* Contrast (WCAG): 5.47:1 on white, 4.76:1 on its own 10 % tint —
* both clear AA, slightly better than the old blue (5.17 / 4.49).
* ----------------------------------------------------------------- */
--risk-critical: #dc2626;
--risk-high: #ea580c;
--risk-medium: #ca8a04;
--risk-low: #0f766e;
--risk-low: #2563eb;
--risk-info: #71717a;

/* Layout density (unchanged). */
Expand Down
32 changes: 15 additions & 17 deletions apps/frontend/src/pages/dev/DesignSystemPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@
* Design System Preview — W11-A, expanded into a living reference in W12-E.
*
* Dev-only sample page. Originally the visual confirm gate for the W11-A
* token redefinition; W12-E grew it into a living component reference + a
* manual review / visual-regression surface covering the W12 primitives.
* W13 (2026-06-12) re-skinned the token set to the Google AI Studio light
* tone (white canvas, blue primary, pill buttons) after the PR #394
* prototype review.
* token redefinition (Vercel base + Linear polish, light single-theme); W12-E
* grew it into a living component reference + a manual review / visual-
* regression surface covering the W12 primitives.
*
* Routing:
* - Mounted at `/dev/design-preview` (see router.tsx).
Expand Down Expand Up @@ -107,17 +105,17 @@ export function DesignSystemPreview() {
Design system · living reference (dev only)
</Eyebrow>
<h1 className="text-3xl font-semibold tracking-tight">
TRUSCA — Google AI Studio light
Vercel base + Linear polish
</h1>
<p className="max-w-2xl text-sm text-muted-foreground">
Living sample of the W13 token set (adopted 2026-06-12): white
canvas, Google-blue primary, tonal secondary, pill buttons, flat
cards. The rest of the app uses these same tokens — walk a few
pages after this to spot any regressions.
Sample of the new token set applied to two foundational
components. The rest of the app still uses these same tokens —
walk a few pages after this to spot any regressions before we
green-light Phase B.
</p>
</header>

<Section title="Color tokens" description="Light single-theme. Severity: Low moved to teal-700 in W13 so it no longer collides with the blue primary.">
<Section title="Color tokens" description="Light single-theme. Severity tokens unchanged.">
<div className="grid grid-cols-2 gap-4 md:grid-cols-3">
<Swatch token="background" varName="--background" />
<Swatch token="foreground" varName="--foreground" />
Expand Down Expand Up @@ -150,7 +148,7 @@ export function DesignSystemPreview() {
</div>
</Section>

<Section title="Buttons" description="Pill shape (W13) — Google-blue primary, tonal secondary; hover transitions at 150 ms ease-out.">
<Section title="Buttons" description="Primary near-black + subtle shadow; hover transitions at 150 ms ease-out.">
<div className="flex flex-wrap items-center gap-3">
<Button>Deploy</Button>
<Button variant="secondary">Cancel</Button>
Expand All @@ -169,7 +167,7 @@ export function DesignSystemPreview() {
</div>
</Section>

<Section title="Card" description="White canvas + flat card — separation comes from the border, not elevation (AIS).">
<Section title="Card" description="Off-white canvas + white card + subtle shadow. Vercel domains pattern.">
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
<Card>
<CardHeader>
Expand Down Expand Up @@ -263,16 +261,16 @@ export function DesignSystemPreview() {
</div>
<div className="grid grid-cols-4 gap-4">
<div className="flex h-16 items-center justify-center rounded-sm border border-border bg-card text-xs">
rounded-sm · 6px
rounded-sm · 4px
</div>
<div className="flex h-16 items-center justify-center rounded-md border border-border bg-card text-xs">
rounded-md · 8px
rounded-md · 6px
</div>
<div className="flex h-16 items-center justify-center rounded-lg border border-border bg-card text-xs">
rounded-lg · 10px
rounded-lg · 8px
</div>
<div className="flex h-16 items-center justify-center rounded-xl border border-border bg-card text-xs">
rounded-xl · 14px
rounded-xl · 12px
</div>
</div>
<p className="text-xs text-muted-foreground">
Expand Down
13 changes: 5 additions & 8 deletions apps/frontend/tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,12 @@ const config: Config = {
row: "var(--table-row)",
},
borderRadius: {
// W13 — radius hierarchy, one step rounder than W11 (--radius 8px).
// W11-A — radius hierarchy. Different sizes for different affordances.
//
// sm 6 px — chips / small inputs
// md 8 px — cards / inputs / table chrome (= --radius default)
// lg 10 px — drawer, large panels
// xl 14 px — modals, dialogs
//
// Buttons are pills (`rounded-full` in button.tsx), not part of
// this scale.
// sm 4 px — chips / small inputs
// md 6 px — buttons / cards / table chrome (= --radius default)
// lg 8 px — drawer, large panels
// xl 12 px — modals, dialogs
//
// shadcn's older `rounded-lg`/`rounded-md`/`rounded-sm` mapping
// (lg = --radius, md = lg-2, sm = lg-4) still works for existing
Expand Down
Loading
Loading