59 lines
1.8 KiB
TypeScript
59 lines
1.8 KiB
TypeScript
import { useId } from "react";
|
|
import type { ReactNode } from "react";
|
|
import type { UiDashboardPreview } from "../types";
|
|
import { ModuleCard } from "./ModuleCard";
|
|
import { ServicePanel } from "./ServicePanel";
|
|
import { StatusStrip } from "./StatusStrip";
|
|
import { TelemetryGrid } from "./TelemetryGrid";
|
|
|
|
export interface DashboardFrameProps {
|
|
actions?: ReactNode;
|
|
dashboard: UiDashboardPreview;
|
|
titleId?: string;
|
|
}
|
|
|
|
export function DashboardFrame({
|
|
actions,
|
|
dashboard,
|
|
titleId,
|
|
}: DashboardFrameProps) {
|
|
const generatedTitleId = useId();
|
|
const resolvedTitleId = titleId || `${generatedTitleId}-title`;
|
|
|
|
return (
|
|
<main className="dashboard-frame" aria-labelledby={resolvedTitleId}>
|
|
<header className="dashboard-frame__header console-header">
|
|
<div className="dashboard-frame__title">
|
|
<div className="dashboard-frame__title-copy">
|
|
{dashboard.eyebrow ? <p>{dashboard.eyebrow}</p> : null}
|
|
<h1 id={resolvedTitleId}>{dashboard.title}</h1>
|
|
{dashboard.subtitle ? <span>{dashboard.subtitle}</span> : null}
|
|
</div>
|
|
{actions ? (
|
|
<div className="dashboard-frame__actions">{actions}</div>
|
|
) : null}
|
|
</div>
|
|
{dashboard.modules.length ? (
|
|
<div className="dashboard-frame__modules">
|
|
{dashboard.modules.map((module) => (
|
|
<ModuleCard key={module.id} module={module} />
|
|
))}
|
|
</div>
|
|
) : null}
|
|
</header>
|
|
|
|
<TelemetryGrid cards={dashboard.telemetry} />
|
|
|
|
<section className="dashboard-frame__panels" aria-label="Service groups">
|
|
{dashboard.serviceGroups.map((group) => (
|
|
<ServicePanel key={group.id} group={group} />
|
|
))}
|
|
</section>
|
|
|
|
<StatusStrip
|
|
id={dashboard.statusStripId}
|
|
items={dashboard.statusItems}
|
|
/>
|
|
</main>
|
|
);
|
|
}
|