feat(ui): introduce Control Rail design system and shell

This commit is contained in:
NuklearRabbit
2026-08-02 03:27:00 +02:00
parent 73e361002d
commit d0f34e6933
5 changed files with 526 additions and 296 deletions
+85
View File
@@ -0,0 +1,85 @@
import type { ReactNode } from "react";
import { Icon, type IconName } from "./Icons";
export function PageHeader({
eyebrow,
title,
description,
actions,
}: {
eyebrow: string;
title: string;
description?: string;
actions?: ReactNode;
}) {
return (
<header className="page-header">
<div>
<p className="page-eyebrow">{eyebrow}</p>
<h1>{title}</h1>
{description && <p className="page-description">{description}</p>}
</div>
{actions && <div className="page-actions">{actions}</div>}
</header>
);
}
export function SectionHeading({
title,
description,
action,
}: {
title: string;
description?: string;
action?: ReactNode;
}) {
return (
<div className="section-heading">
<div>
<h2>{title}</h2>
{description && <p>{description}</p>}
</div>
{action}
</div>
);
}
export function LoadingState({ label = "Loading workspace…" }: { label?: string }) {
return (
<div className="state-panel" role="status">
<span className="spinner" aria-hidden="true" />
<p>{label}</p>
</div>
);
}
export function ErrorState({ message }: { message: string }) {
return (
<div className="state-panel state-error" role="alert">
<Icon name="alert" />
<div><strong>We couldnt load this workspace.</strong><p>{message}</p></div>
</div>
);
}
export function EmptyState({
icon = "check",
title,
detail,
}: {
icon?: IconName;
title: string;
detail: string;
}) {
return (
<div className="state-panel state-empty">
<Icon name={icon} />
<div><strong>{title}</strong><p>{detail}</p></div>
</div>
);
}
export function IntegrationMark({ kind }: { kind: "n8n" | "rag" | "mcp" }) {
const labels = { n8n: "n8n", rag: "RA", mcp: "MC" };
return <span className={`integration-mark integration-${kind}`} aria-hidden="true">{labels[kind]}</span>;
}