Refactor site header, heroes, and design system
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
import { AppCard } from "@/components/ui/app-card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export function WorkspaceHero({
|
||||
eyebrow,
|
||||
title,
|
||||
description,
|
||||
aside,
|
||||
}: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
description: string;
|
||||
aside?: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<AppCard level={3}>
|
||||
<CardContent className="flex flex-col gap-4 p-6 lg:flex-row lg:items-end lg:justify-between lg:p-8">
|
||||
<div className="space-y-2">
|
||||
<p className="text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground">
|
||||
{eyebrow}
|
||||
</p>
|
||||
<h2 className="text-2xl font-semibold text-foreground">{title}</h2>
|
||||
<p className="max-w-3xl text-sm text-muted-foreground">{description}</p>
|
||||
</div>
|
||||
{aside ? <div className="flex flex-wrap gap-2">{aside}</div> : null}
|
||||
</CardContent>
|
||||
</AppCard>
|
||||
);
|
||||
}
|
||||
|
||||
export function WorkspaceSidebarPanel({
|
||||
title,
|
||||
children,
|
||||
}: {
|
||||
title: string;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<AppCard level={2}>
|
||||
<CardHeader className="pb-4">
|
||||
<CardTitle className="text-base">{title}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">{children}</CardContent>
|
||||
</AppCard>
|
||||
);
|
||||
}
|
||||
|
||||
export function WorkspaceStepButton({
|
||||
active,
|
||||
completed,
|
||||
index,
|
||||
label,
|
||||
eyebrow,
|
||||
onClick,
|
||||
completeIcon,
|
||||
}: {
|
||||
active: boolean;
|
||||
completed: boolean;
|
||||
index: number;
|
||||
label: string;
|
||||
eyebrow: string;
|
||||
onClick: () => void;
|
||||
completeIcon?: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
className={cn(
|
||||
"flex w-full items-start gap-3 rounded-surface border px-4 py-3 text-left transition-colors",
|
||||
active
|
||||
? "border-input bg-accent/40"
|
||||
: "border-input bg-background hover:bg-accent/20",
|
||||
)}
|
||||
>
|
||||
<div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-pill border border-input bg-background text-sm font-semibold text-foreground">
|
||||
{completed ? completeIcon ?? "OK" : index + 1}
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<p className="text-xs font-semibold uppercase tracking-[0.12em] text-muted-foreground">
|
||||
{eyebrow}
|
||||
</p>
|
||||
<p className="mt-1 text-sm font-medium text-foreground">{label}</p>
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export function WorkspaceLocaleCard({
|
||||
title,
|
||||
hint,
|
||||
children,
|
||||
}: {
|
||||
title: string;
|
||||
hint: string;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<AppCard level={2}>
|
||||
<CardHeader className="pb-4">
|
||||
<CardTitle className="text-lg">{title}</CardTitle>
|
||||
<CardDescription>{hint}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">{children}</CardContent>
|
||||
</AppCard>
|
||||
);
|
||||
}
|
||||
|
||||
export function WorkspaceStatusBadge({
|
||||
done,
|
||||
doneLabel = "Ready",
|
||||
openLabel = "Open",
|
||||
}: {
|
||||
done: boolean;
|
||||
doneLabel?: string;
|
||||
openLabel?: string;
|
||||
}) {
|
||||
return <Badge variant={done ? "success" : "warning"}>{done ? doneLabel : openLabel}</Badge>;
|
||||
}
|
||||
Reference in New Issue
Block a user