feat: Implement foundational UI components (Button, Card) and layout components (Section, Container), updating design tokens, styling, and documentation.

This commit is contained in:
1elle1
2026-02-01 14:13:39 +01:00
parent f7ac3d6a99
commit 643231b7b0
12 changed files with 357 additions and 55 deletions

45
components/ui/Button.tsx Normal file
View File

@@ -0,0 +1,45 @@
import type { ButtonHTMLAttributes, ReactNode } from "react";
type ButtonVariant = "primary" | "secondary" | "ghost";
type ButtonSize = "sm" | "md" | "lg";
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children: ReactNode;
variant?: ButtonVariant;
size?: ButtonSize;
}
const baseClasses =
"inline-flex items-center justify-center font-medium rounded-[var(--radius-md)] transition-all duration-[var(--duration-normal)] ease-[var(--easing-default)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--color-primary)] disabled:pointer-events-none disabled:opacity-50";
const variantClasses: Record<ButtonVariant, string> = {
primary:
"bg-[var(--color-primary)] text-[color:var(--color-background)] hover:opacity-90",
secondary:
"bg-[var(--color-muted)] text-[color:var(--color-foreground)] border border-[color:var(--color-border)] hover:opacity-80",
ghost:
"bg-transparent text-[color:var(--color-foreground)] hover:bg-[var(--color-muted)]",
};
const sizeClasses: Record<ButtonSize, string> = {
sm: "px-[var(--spacing-sm)] py-[var(--spacing-xs)] text-[length:var(--font-size-sm)]",
md: "px-[var(--spacing-md)] py-[var(--spacing-sm)] text-[length:var(--font-size-base)]",
lg: "px-[var(--spacing-lg)] py-[var(--spacing-md)] text-[length:var(--font-size-lg)]",
};
export function Button({
children,
variant = "primary",
size = "md",
className = "",
...props
}: ButtonProps) {
return (
<button
className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]} ${className}`.trim()}
{...props}
>
{children}
</button>
);
}

21
components/ui/Card.tsx Normal file
View File

@@ -0,0 +1,21 @@
import type { ElementType, ReactNode } from "react";
interface CardProps {
children: ReactNode;
className?: string;
as?: ElementType;
}
export function Card({
children,
className = "",
as: Tag = "div",
}: CardProps) {
return (
<Tag
className={`rounded-[var(--radius-md)] border border-[color:var(--color-border)] shadow-[var(--shadow-sm)] p-[var(--spacing-lg)] ${className}`.trim()}
>
{children}
</Tag>
);
}