feat(web): indigo brand token + status tokens + Badge success/warning variants (#49)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-07 14:08:08 +02:00
parent 67e486df46
commit 04ed0c50e2
6 changed files with 50 additions and 17 deletions
+8
View File
@@ -27,6 +27,14 @@ export const Destructive: Story = {
args: { variant: 'destructive', children: 'Error' },
}
export const Success: Story = {
args: { variant: 'success', children: 'Public' },
}
export const Warning: Story = {
args: { variant: 'warning', children: 'Internal' },
}
export const Outline: Story = {
args: { variant: 'outline', children: 'Draft' },
}
+2
View File
@@ -14,6 +14,8 @@ const badgeVariants = cva(
"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
destructive:
"bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
success: "bg-success/10 text-success [a]:hover:bg-success/20",
warning: "bg-warning/10 text-warning [a]:hover:bg-warning/20",
outline:
"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
ghost:
+28 -4
View File
@@ -18,6 +18,12 @@
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-success: var(--success);
--color-success-foreground: var(--success-foreground);
--color-warning: var(--warning);
--color-warning-foreground: var(--warning-foreground);
--color-highlight: var(--highlight);
--color-highlight-foreground: var(--highlight-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
@@ -35,7 +41,7 @@
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary: oklch(0.511 0.262 276.966);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
@@ -44,9 +50,15 @@
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--success: oklch(0.627 0.194 149.214);
--success-foreground: oklch(0.985 0 0);
--warning: oklch(0.666 0.179 58.318);
--warning-foreground: oklch(0.985 0 0);
--highlight: oklch(0.905 0.182 98.111);
--highlight-foreground: oklch(0.205 0 0);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--ring: oklch(0.511 0.262 276.966);
--radius: 0.625rem;
}
@@ -57,7 +69,7 @@
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.985 0 0);
--primary: oklch(0.673 0.182 276.935);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
@@ -66,9 +78,15 @@
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--success: oklch(0.723 0.192 149.579);
--success-foreground: oklch(0.205 0 0);
--warning: oklch(0.769 0.188 70.08);
--warning-foreground: oklch(0.205 0 0);
--highlight: oklch(0.852 0.199 91.936);
--highlight-foreground: oklch(0.205 0 0);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
--ring: oklch(0.673 0.182 276.935);
}
@layer base {
@@ -80,3 +98,9 @@
@apply bg-background text-foreground font-sans;
}
}
@layer components {
.label-caption {
@apply text-xs font-medium uppercase tracking-wide text-muted-foreground;
}
}
+6 -5
View File
@@ -26,16 +26,17 @@ export const Draft: Story = {
args: { visibility: 'draft' },
}
// The single project-wide CssCheck. VisibilityBadge applies `bg-green-100` for
// the `public` visibility (see STYLES in visibility-badge.tsx). A concrete
// resolved background colour proves the shared preview actually loaded the app's
// Tailwind stylesheet — an unstyled badge would report a transparent background.
// The single project-wide CssCheck. VisibilityBadge applies the `success`
// variant for the `public` visibility (`bg-success/10`, see VARIANT in
// visibility-badge.tsx). A concrete resolved background colour proves the shared
// preview actually loaded the app's Tailwind stylesheet — an unstyled badge
// would report a transparent background.
export const CssCheck: Story = {
args: { visibility: 'public' },
play: async ({ canvas }) => {
const badge = canvas.getByText('Public')
await expect(getComputedStyle(badge).backgroundColor).toBe(
'oklch(0.962 0.044 156.743)',
'oklab(0.627 -0.166662 0.0992956 / 0.1)',
)
},
}
+5 -7
View File
@@ -5,18 +5,16 @@ import { Badge } from "@/components/ui/badge";
type Visibility = components["schemas"]["Visibility"];
const STYLES: Record<Visibility, string> = {
draft: "bg-neutral-100 text-neutral-600",
internal: "bg-amber-100 text-amber-800",
public: "bg-green-100 text-green-800",
const VARIANT: Record<Visibility, "secondary" | "warning" | "success"> = {
draft: "secondary",
internal: "warning",
public: "success",
};
export function VisibilityBadge({ visibility }: { visibility: Visibility }) {
const { t } = useTranslation();
return (
<Badge variant="outline" className={STYLES[visibility]}>
{t(`visibility.${visibility}`)}
</Badge>
<Badge variant={VARIANT[visibility]}>{t(`visibility.${visibility}`)}</Badge>
);
}
+1 -1
View File
@@ -31,7 +31,7 @@ export function Highlight({ text }: { text: string }) {
}
nodes.push(
<mark key={key++} className="bg-yellow-200">
<mark key={key++} className="bg-highlight text-highlight-foreground">
{rest.slice(start + PRE.length, end)}
</mark>,
);