Template
- tokens.css: full token layer (type scale rem-based, palette, spacing, radii) - App.css rebuilt token-driven; zero hardcoded colors/px font sizes - readability preset: --root-font-size 112%; button matrix scrolls when narrow - App.tsx split into real components (Hero, CodeSample, RightRail + reflow) - light theme via [data-theme=light] overrides; topbar sun/moon toggle persisted - scripts/check-tokens.mjs + npm run check (lint, token guard, tsc, build) - AGENTS.md: token contract, check gate, preview workflow
18 lines
568 B
TypeScript
18 lines
568 B
TypeScript
import type { ButtonHTMLAttributes, ReactNode } from 'react'
|
|
|
|
export type ButtonVariant = 'primary' | 'secondary' | 'danger' | 'ghost'
|
|
|
|
type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
variant?: ButtonVariant
|
|
children: ReactNode
|
|
}
|
|
|
|
/** Shared action primitive. Visual variants stay in App.css so themes can override them. */
|
|
export function Button({ variant = 'secondary', className = '', children, ...props }: ButtonProps) {
|
|
return (
|
|
<button className={`button ${variant} ${className}`.trim()} {...props}>
|
|
{children}
|
|
</button>
|
|
)
|
|
}
|