Refine settings, archive, and check-in styling
This commit is contained in:
29
src/components/design-system/WorkspacePanel.tsx
Normal file
29
src/components/design-system/WorkspacePanel.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { useId, type ReactNode } from "react";
|
||||
import { X } from "lucide-react";
|
||||
import { Button } from "./primitives";
|
||||
|
||||
/** Shared flat panel for secondary workspace flows. */
|
||||
export function WorkspacePanel({ id, eyebrow, title, description, children, onClose, closeLabel = "Close panel" }: {
|
||||
id: string; eyebrow: string; title: string; description?: string; children: ReactNode; onClose?: () => void; closeLabel?: string;
|
||||
}) {
|
||||
return <section id={id} className="ds-workspace-panel" aria-label={title}>
|
||||
<header className="ds-panel-heading">
|
||||
<div><p className="ds-eyebrow">{eyebrow}</p><h2>{title}</h2>{description && <p className="ds-panel-description">{description}</p>}</div>
|
||||
{onClose && <Button variant="text" className="ds-panel-close" onClick={onClose} aria-label={closeLabel} title={closeLabel}><X size={20} aria-hidden="true" /></Button>}
|
||||
</header>
|
||||
{children}
|
||||
</section>;
|
||||
}
|
||||
|
||||
/** Consistent label, explanation and control columns for preference forms. */
|
||||
export function SettingRow({ title, description, children }: { title: string; description: ReactNode; children: ReactNode }) {
|
||||
const id = useId();
|
||||
return <section className="ds-setting-row" aria-labelledby={id}>
|
||||
<header className="ds-setting-heading"><h3 id={id}>{title}</h3><div>{description}</div></header>
|
||||
<div className="ds-setting-controls">{children}</div>
|
||||
</section>;
|
||||
}
|
||||
|
||||
export function FormMessage({ children, error = false }: { children: ReactNode; error?: boolean }) {
|
||||
return <p className={`ds-form-message${error ? " ds-form-message--error" : ""}`} role={error ? "alert" : "status"}>{children}</p>;
|
||||
}
|
||||
Reference in New Issue
Block a user