;
+
+export const Default: Story = {};
diff --git a/src/lib/ui/stories/FocusPreview.svelte b/src/lib/ui/stories/FocusPreview.svelte
deleted file mode 100644
index 514691f..0000000
--- a/src/lib/ui/stories/FocusPreview.svelte
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
- {@render children?.()}
-
-
-
diff --git a/src/lib/ui/stories/FooterCell.stories.svelte b/src/lib/ui/stories/FooterCell.stories.svelte
deleted file mode 100644
index cb4a08e..0000000
--- a/src/lib/ui/stories/FooterCell.stories.svelte
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/FooterCell.stories.tsx b/src/lib/ui/stories/FooterCell.stories.tsx
new file mode 100644
index 0000000..3ba26c7
--- /dev/null
+++ b/src/lib/ui/stories/FooterCell.stories.tsx
@@ -0,0 +1,21 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { FooterCell } from "../components/FooterCell";
+import { statusItems } from "./story-data";
+
+const meta = {
+ title: "UI/FooterCell",
+ component: FooterCell,
+ args: {
+ item: statusItems.ok,
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Operational: Story = {};
+export const Linked: Story = {
+ args: {
+ item: statusItems.action,
+ },
+};
diff --git a/src/lib/ui/stories/FooterStatusCell.stories.svelte b/src/lib/ui/stories/FooterStatusCell.stories.svelte
deleted file mode 100644
index 578cb11..0000000
--- a/src/lib/ui/stories/FooterStatusCell.stories.svelte
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/FooterStatusCell.stories.tsx b/src/lib/ui/stories/FooterStatusCell.stories.tsx
new file mode 100644
index 0000000..8097ba3
--- /dev/null
+++ b/src/lib/ui/stories/FooterStatusCell.stories.tsx
@@ -0,0 +1,16 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { FooterStatusCell } from "../components/FooterStatusCell";
+import { statusItems } from "./story-data";
+
+const meta = {
+ title: "UI/FooterStatusCell",
+ component: FooterStatusCell,
+ args: {
+ item: statusItems.degraded,
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Warning: Story = {};
diff --git a/src/lib/ui/stories/GridFrame.stories.svelte b/src/lib/ui/stories/GridFrame.stories.svelte
deleted file mode 100644
index d8be595..0000000
--- a/src/lib/ui/stories/GridFrame.stories.svelte
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/GridFrame.stories.tsx b/src/lib/ui/stories/GridFrame.stories.tsx
new file mode 100644
index 0000000..a43ad22
--- /dev/null
+++ b/src/lib/ui/stories/GridFrame.stories.tsx
@@ -0,0 +1,25 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { GridFrame } from "../components/GridFrame";
+import { ModuleCard } from "../components/ModuleCard";
+import { moduleBlocks } from "./story-data";
+
+const meta = {
+ title: "UI/GridFrame",
+ component: GridFrame,
+ render: (args) => (
+
+
+
+
+
+ ),
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Dense: Story = {
+ args: {
+ density: "dense",
+ },
+};
diff --git a/src/lib/ui/stories/IconButton.stories.svelte b/src/lib/ui/stories/IconButton.stories.svelte
deleted file mode 100644
index faa05b6..0000000
--- a/src/lib/ui/stories/IconButton.stories.svelte
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/IconButton.stories.tsx b/src/lib/ui/stories/IconButton.stories.tsx
new file mode 100644
index 0000000..35b58b9
--- /dev/null
+++ b/src/lib/ui/stories/IconButton.stories.tsx
@@ -0,0 +1,16 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { IconButton } from "../components/IconButton";
+
+const meta = {
+ title: "UI/IconButton",
+ component: IconButton,
+ args: {
+ icon: "mdi:refresh",
+ label: "Refresh status",
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {};
diff --git a/src/lib/ui/stories/IconGlyph.stories.svelte b/src/lib/ui/stories/IconGlyph.stories.svelte
deleted file mode 100644
index 043e7b3..0000000
--- a/src/lib/ui/stories/IconGlyph.stories.svelte
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/IconGlyph.stories.tsx b/src/lib/ui/stories/IconGlyph.stories.tsx
new file mode 100644
index 0000000..3f1715a
--- /dev/null
+++ b/src/lib/ui/stories/IconGlyph.stories.tsx
@@ -0,0 +1,17 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { IconGlyph } from "../components/IconGlyph";
+
+const meta = {
+ title: "UI/IconGlyph",
+ component: IconGlyph,
+ args: {
+ name: "mdi:server-network",
+ label: "Generic service",
+ size: "md",
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {};
diff --git a/src/lib/ui/stories/LineChart.stories.svelte b/src/lib/ui/stories/LineChart.stories.svelte
deleted file mode 100644
index ef1ad22..0000000
--- a/src/lib/ui/stories/LineChart.stories.svelte
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
diff --git a/src/lib/ui/stories/LineChart.stories.tsx b/src/lib/ui/stories/LineChart.stories.tsx
new file mode 100644
index 0000000..bbf8690
--- /dev/null
+++ b/src/lib/ui/stories/LineChart.stories.tsx
@@ -0,0 +1,17 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { LineChart } from "../components/LineChart";
+
+const meta = {
+ title: "UI/LineChart",
+ component: LineChart,
+ args: {
+ values: [12, 18, 24, 20, 36, 44],
+ severity: "ok",
+ label: "Generic trend",
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Trend: Story = {};
diff --git a/src/lib/ui/stories/ModuleCard.stories.svelte b/src/lib/ui/stories/ModuleCard.stories.svelte
deleted file mode 100644
index 890a3ca..0000000
--- a/src/lib/ui/stories/ModuleCard.stories.svelte
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
diff --git a/src/lib/ui/stories/ModuleCard.stories.tsx b/src/lib/ui/stories/ModuleCard.stories.tsx
new file mode 100644
index 0000000..3366a55
--- /dev/null
+++ b/src/lib/ui/stories/ModuleCard.stories.tsx
@@ -0,0 +1,21 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { ModuleCard } from "../components/ModuleCard";
+import { moduleBlocks } from "./story-data";
+
+const meta = {
+ title: "UI/ModuleCard",
+ component: ModuleCard,
+ args: {
+ module: moduleBlocks.compact,
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Compact: Story = {};
+export const Long: Story = {
+ args: {
+ module: moduleBlocks.long,
+ },
+};
diff --git a/src/lib/ui/stories/Panel.stories.svelte b/src/lib/ui/stories/Panel.stories.svelte
deleted file mode 100644
index c3d3a80..0000000
--- a/src/lib/ui/stories/Panel.stories.svelte
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
- Reusable panel content.
-
-
-
-
- Compact repeated content.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/Panel.stories.tsx b/src/lib/ui/stories/Panel.stories.tsx
new file mode 100644
index 0000000..730c2d9
--- /dev/null
+++ b/src/lib/ui/stories/Panel.stories.tsx
@@ -0,0 +1,23 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { Panel } from "../components/Panel";
+import { ServiceRow } from "../components/ServiceRow";
+import { serviceRows } from "./story-data";
+
+const meta = {
+ title: "UI/Panel",
+ component: Panel,
+ render: (args) => (
+
+
+
+
+ ),
+ args: {
+ title: "Generic Panel",
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Dense: Story = {};
diff --git a/src/lib/ui/stories/ProgressMeter.stories.svelte b/src/lib/ui/stories/ProgressMeter.stories.svelte
deleted file mode 100644
index 861009f..0000000
--- a/src/lib/ui/stories/ProgressMeter.stories.svelte
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/ProgressMeter.stories.tsx b/src/lib/ui/stories/ProgressMeter.stories.tsx
new file mode 100644
index 0000000..d3bfdac
--- /dev/null
+++ b/src/lib/ui/stories/ProgressMeter.stories.tsx
@@ -0,0 +1,17 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { ProgressMeter } from "../components/ProgressMeter";
+
+const meta = {
+ title: "UI/ProgressMeter",
+ component: ProgressMeter,
+ args: {
+ value: 72,
+ severity: "ok",
+ label: "Capacity",
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Filled: Story = {};
diff --git a/src/lib/ui/stories/ScanlineField.stories.svelte b/src/lib/ui/stories/ScanlineField.stories.svelte
deleted file mode 100644
index cc993f7..0000000
--- a/src/lib/ui/stories/ScanlineField.stories.svelte
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/ScanlineField.stories.tsx b/src/lib/ui/stories/ScanlineField.stories.tsx
new file mode 100644
index 0000000..89e554e
--- /dev/null
+++ b/src/lib/ui/stories/ScanlineField.stories.tsx
@@ -0,0 +1,16 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { ScanlineField } from "../components/ScanlineField";
+
+const meta = {
+ title: "UI/ScanlineField",
+ component: ScanlineField,
+ args: {
+ tone: "accent",
+ intensity: "medium",
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {};
diff --git a/src/lib/ui/stories/Separator.stories.svelte b/src/lib/ui/stories/Separator.stories.svelte
deleted file mode 100644
index 3f2f6e3..0000000
--- a/src/lib/ui/stories/Separator.stories.svelte
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
- Generic section one
-
- Generic section two
-
-
diff --git a/src/lib/ui/stories/Separator.stories.tsx b/src/lib/ui/stories/Separator.stories.tsx
new file mode 100644
index 0000000..e261f52
--- /dev/null
+++ b/src/lib/ui/stories/Separator.stories.tsx
@@ -0,0 +1,15 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { Separator } from "../components/Separator";
+
+const meta = {
+ title: "UI/Separator",
+ component: Separator,
+ args: {
+ orientation: "horizontal",
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Horizontal: Story = {};
diff --git a/src/lib/ui/stories/ServiceGroupPanel.stories.svelte b/src/lib/ui/stories/ServiceGroupPanel.stories.svelte
deleted file mode 100644
index 51c48bd..0000000
--- a/src/lib/ui/stories/ServiceGroupPanel.stories.svelte
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/ServiceGroupPanel.stories.tsx b/src/lib/ui/stories/ServiceGroupPanel.stories.tsx
new file mode 100644
index 0000000..7183771
--- /dev/null
+++ b/src/lib/ui/stories/ServiceGroupPanel.stories.tsx
@@ -0,0 +1,16 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { ServiceGroupPanel } from "../components/ServiceGroupPanel";
+import { serviceGroups } from "./story-data";
+
+const meta = {
+ title: "UI/ServiceGroupPanel",
+ component: ServiceGroupPanel,
+ args: {
+ group: serviceGroups.mixed,
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Mixed: Story = {};
diff --git a/src/lib/ui/stories/ServicePanel.stories.svelte b/src/lib/ui/stories/ServicePanel.stories.svelte
deleted file mode 100644
index 059b63b..0000000
--- a/src/lib/ui/stories/ServicePanel.stories.svelte
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/ServicePanel.stories.tsx b/src/lib/ui/stories/ServicePanel.stories.tsx
new file mode 100644
index 0000000..750c428
--- /dev/null
+++ b/src/lib/ui/stories/ServicePanel.stories.tsx
@@ -0,0 +1,16 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { ServicePanel } from "../components/ServicePanel";
+import { serviceGroups } from "./story-data";
+
+const meta = {
+ title: "UI/ServicePanel",
+ component: ServicePanel,
+ args: {
+ group: serviceGroups.long,
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const LongList: Story = {};
diff --git a/src/lib/ui/stories/ServiceRow.stories.svelte b/src/lib/ui/stories/ServiceRow.stories.svelte
deleted file mode 100644
index 7be9f19..0000000
--- a/src/lib/ui/stories/ServiceRow.stories.svelte
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/ServiceRow.stories.tsx b/src/lib/ui/stories/ServiceRow.stories.tsx
new file mode 100644
index 0000000..9513d2c
--- /dev/null
+++ b/src/lib/ui/stories/ServiceRow.stories.tsx
@@ -0,0 +1,21 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { ServiceRow } from "../components/ServiceRow";
+import { serviceRows } from "./story-data";
+
+const meta = {
+ title: "UI/ServiceRow",
+ component: ServiceRow,
+ args: {
+ service: serviceRows.normal,
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Normal: Story = {};
+export const Warning: Story = {
+ args: {
+ service: serviceRows.degraded,
+ },
+};
diff --git a/src/lib/ui/stories/SignalTrace.stories.svelte b/src/lib/ui/stories/SignalTrace.stories.svelte
deleted file mode 100644
index 0130817..0000000
--- a/src/lib/ui/stories/SignalTrace.stories.svelte
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/SignalTrace.stories.tsx b/src/lib/ui/stories/SignalTrace.stories.tsx
new file mode 100644
index 0000000..ae8785b
--- /dev/null
+++ b/src/lib/ui/stories/SignalTrace.stories.tsx
@@ -0,0 +1,16 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { SignalTrace } from "../components/SignalTrace";
+
+const meta = {
+ title: "UI/SignalTrace",
+ component: SignalTrace,
+ args: {
+ tone: "accent",
+ orientation: "horizontal",
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Horizontal: Story = {};
diff --git a/src/lib/ui/stories/Sparkline.stories.svelte b/src/lib/ui/stories/Sparkline.stories.svelte
deleted file mode 100644
index 62744bd..0000000
--- a/src/lib/ui/stories/Sparkline.stories.svelte
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/Sparkline.stories.tsx b/src/lib/ui/stories/Sparkline.stories.tsx
new file mode 100644
index 0000000..efecfbd
--- /dev/null
+++ b/src/lib/ui/stories/Sparkline.stories.tsx
@@ -0,0 +1,16 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { Sparkline } from "../components/Sparkline";
+
+const meta = {
+ title: "UI/Sparkline",
+ component: Sparkline,
+ args: {
+ values: [8, 14, 12, 24, 18, 30],
+ severity: "ok",
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {};
diff --git a/src/lib/ui/stories/StatusBadge.stories.svelte b/src/lib/ui/stories/StatusBadge.stories.svelte
deleted file mode 100644
index 1429ceb..0000000
--- a/src/lib/ui/stories/StatusBadge.stories.svelte
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/StatusBadge.stories.tsx b/src/lib/ui/stories/StatusBadge.stories.tsx
new file mode 100644
index 0000000..4513a08
--- /dev/null
+++ b/src/lib/ui/stories/StatusBadge.stories.tsx
@@ -0,0 +1,16 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { StatusBadge } from "../components/StatusBadge";
+
+const meta = {
+ title: "UI/StatusBadge",
+ component: StatusBadge,
+ args: {
+ label: "Ready",
+ severity: "ok",
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Ready: Story = {};
diff --git a/src/lib/ui/stories/StatusStrip.stories.svelte b/src/lib/ui/stories/StatusStrip.stories.svelte
deleted file mode 100644
index 7b6d22d..0000000
--- a/src/lib/ui/stories/StatusStrip.stories.svelte
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/StatusStrip.stories.tsx b/src/lib/ui/stories/StatusStrip.stories.tsx
new file mode 100644
index 0000000..7b808fa
--- /dev/null
+++ b/src/lib/ui/stories/StatusStrip.stories.tsx
@@ -0,0 +1,17 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { StatusStrip } from "../components/StatusStrip";
+import { mixedStatusStrip } from "./story-data";
+
+const meta = {
+ title: "UI/StatusStrip",
+ component: StatusStrip,
+ args: {
+ id: "generic-status",
+ items: mixedStatusStrip,
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Mixed: Story = {};
diff --git a/src/lib/ui/stories/SystemState.stories.svelte b/src/lib/ui/stories/SystemState.stories.svelte
deleted file mode 100644
index 0e28282..0000000
--- a/src/lib/ui/stories/SystemState.stories.svelte
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/SystemState.stories.tsx b/src/lib/ui/stories/SystemState.stories.tsx
new file mode 100644
index 0000000..585540e
--- /dev/null
+++ b/src/lib/ui/stories/SystemState.stories.tsx
@@ -0,0 +1,18 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { SystemState } from "../components/SystemState";
+
+const meta = {
+ title: "UI/SystemState",
+ component: SystemState,
+ args: {
+ title: "Loading Dashboard",
+ detail: "Fetching active model",
+ severity: "loading",
+ icon: "mdi:progress-clock",
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Loading: Story = {};
diff --git a/src/lib/ui/stories/TelemetryCard.stories.svelte b/src/lib/ui/stories/TelemetryCard.stories.svelte
deleted file mode 100644
index 004f47b..0000000
--- a/src/lib/ui/stories/TelemetryCard.stories.svelte
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/TelemetryCard.stories.tsx b/src/lib/ui/stories/TelemetryCard.stories.tsx
new file mode 100644
index 0000000..dbdf301
--- /dev/null
+++ b/src/lib/ui/stories/TelemetryCard.stories.tsx
@@ -0,0 +1,21 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { TelemetryCard } from "../components/TelemetryCard";
+import { telemetryCards } from "./story-data";
+
+const meta = {
+ title: "UI/TelemetryCard",
+ component: TelemetryCard,
+ args: {
+ card: telemetryCards.percent,
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Percent: Story = {};
+export const Danger: Story = {
+ args: {
+ card: telemetryCards.danger,
+ },
+};
diff --git a/src/lib/ui/stories/TelemetryGrid.stories.svelte b/src/lib/ui/stories/TelemetryGrid.stories.svelte
deleted file mode 100644
index 8054cc9..0000000
--- a/src/lib/ui/stories/TelemetryGrid.stories.svelte
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
diff --git a/src/lib/ui/stories/TelemetryGrid.stories.tsx b/src/lib/ui/stories/TelemetryGrid.stories.tsx
new file mode 100644
index 0000000..6b0166e
--- /dev/null
+++ b/src/lib/ui/stories/TelemetryGrid.stories.tsx
@@ -0,0 +1,21 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { TelemetryGrid } from "../components/TelemetryGrid";
+import { eightTelemetryCards, sixteenTelemetryCards } from "./story-data";
+
+const meta = {
+ title: "UI/TelemetryGrid",
+ component: TelemetryGrid,
+ args: {
+ cards: eightTelemetryCards,
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const EightCards: Story = {};
+export const SixteenCards: Story = {
+ args: {
+ cards: sixteenTelemetryCards,
+ },
+};
diff --git a/src/lib/ui/stories/TelemetryStrip.stories.svelte b/src/lib/ui/stories/TelemetryStrip.stories.svelte
deleted file mode 100644
index 5eb01b5..0000000
--- a/src/lib/ui/stories/TelemetryStrip.stories.svelte
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
diff --git a/src/lib/ui/stories/TelemetryStrip.stories.tsx b/src/lib/ui/stories/TelemetryStrip.stories.tsx
new file mode 100644
index 0000000..76fc983
--- /dev/null
+++ b/src/lib/ui/stories/TelemetryStrip.stories.tsx
@@ -0,0 +1,16 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { TelemetryStrip } from "../components/TelemetryStrip";
+import { eightTelemetryCards } from "./story-data";
+
+const meta = {
+ title: "UI/TelemetryStrip",
+ component: TelemetryStrip,
+ args: {
+ cards: eightTelemetryCards,
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {};
diff --git a/src/lib/ui/stories/WeatherModule.stories.svelte b/src/lib/ui/stories/WeatherModule.stories.svelte
deleted file mode 100644
index de86e73..0000000
--- a/src/lib/ui/stories/WeatherModule.stories.svelte
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
diff --git a/src/lib/ui/stories/WeatherModule.stories.tsx b/src/lib/ui/stories/WeatherModule.stories.tsx
new file mode 100644
index 0000000..6429de2
--- /dev/null
+++ b/src/lib/ui/stories/WeatherModule.stories.tsx
@@ -0,0 +1,16 @@
+import type { Meta, StoryObj } from "@storybook/react-vite";
+import { WeatherModule } from "../components/WeatherModule";
+import { moduleBlocks } from "./story-data";
+
+const meta = {
+ title: "UI/WeatherModule",
+ component: WeatherModule,
+ args: {
+ module: moduleBlocks.compact,
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {};
diff --git a/src/lib/ui/storybook.test.ts b/src/lib/ui/storybook.test.ts
index 172526e..1b524ed 100644
--- a/src/lib/ui/storybook.test.ts
+++ b/src/lib/ui/storybook.test.ts
@@ -7,35 +7,36 @@ const componentsDir = join(root, "src/lib/ui/components");
const storiesDir = join(root, "src/lib/ui/stories");
const requiredStoryFiles = [
- "Badge.stories.svelte",
- "Button.stories.svelte",
- "DashboardFrame.stories.svelte",
- "DashboardHeader.stories.svelte",
- "DashboardOnePager.stories.svelte",
- "CornerBracketFrame.stories.svelte",
- "DiagonalStripeField.stories.svelte",
- "FooterCell.stories.svelte",
- "FooterStatusCell.stories.svelte",
- "GridFrame.stories.svelte",
- "IconButton.stories.svelte",
- "IconGlyph.stories.svelte",
- "ModuleCard.stories.svelte",
- "Panel.stories.svelte",
- "ProgressMeter.stories.svelte",
- "Separator.stories.svelte",
- "ServiceGroupPanel.stories.svelte",
- "ServicePanel.stories.svelte",
- "ServiceRow.stories.svelte",
- "SignalTrace.stories.svelte",
- "Sparkline.stories.svelte",
- "StatusBadge.stories.svelte",
- "StatusStrip.stories.svelte",
- "SystemState.stories.svelte",
- "ScanlineField.stories.svelte",
- "TelemetryCard.stories.svelte",
- "TelemetryGrid.stories.svelte",
- "TelemetryStrip.stories.svelte",
- "WeatherModule.stories.svelte",
+ "Badge.stories.tsx",
+ "Button.stories.tsx",
+ "DashboardFrame.stories.tsx",
+ "DashboardHeader.stories.tsx",
+ "DashboardOnePager.stories.tsx",
+ "CornerBracketFrame.stories.tsx",
+ "DiagonalStripeField.stories.tsx",
+ "FooterCell.stories.tsx",
+ "FooterStatusCell.stories.tsx",
+ "GridFrame.stories.tsx",
+ "IconButton.stories.tsx",
+ "IconGlyph.stories.tsx",
+ "LineChart.stories.tsx",
+ "ModuleCard.stories.tsx",
+ "Panel.stories.tsx",
+ "ProgressMeter.stories.tsx",
+ "Separator.stories.tsx",
+ "ServiceGroupPanel.stories.tsx",
+ "ServicePanel.stories.tsx",
+ "ServiceRow.stories.tsx",
+ "SignalTrace.stories.tsx",
+ "Sparkline.stories.tsx",
+ "StatusBadge.stories.tsx",
+ "StatusStrip.stories.tsx",
+ "SystemState.stories.tsx",
+ "ScanlineField.stories.tsx",
+ "TelemetryCard.stories.tsx",
+ "TelemetryGrid.stories.tsx",
+ "TelemetryStrip.stories.tsx",
+ "WeatherModule.stories.tsx",
] as const;
const forbiddenStoryContent = [
@@ -64,8 +65,8 @@ describe("Storybook inventory", () => {
test("keeps component and story files paired as the UI inventory changes", () => {
const componentStoryFiles = readdirSync(componentsDir)
- .filter((filename) => filename.endsWith(".svelte"))
- .map((filename) => filename.replace(".svelte", ".stories.svelte"));
+ .filter((filename) => filename.endsWith(".tsx") && !filename.endsWith(".test.tsx"))
+ .map((filename) => filename.replace(".tsx", ".stories.tsx"));
for (const filename of componentStoryFiles) {
expect(existsSync(join(storiesDir, filename)), `${filename} is missing`).toBe(true);
@@ -74,7 +75,7 @@ describe("Storybook inventory", () => {
test("keeps Storybook fixtures generic and content-free", () => {
const storyText = readdirSync(storiesDir)
- .filter((filename) => filename.endsWith(".svelte") || filename.endsWith(".ts"))
+ .filter((filename) => filename.endsWith(".tsx") || filename.endsWith(".ts"))
.map((filename) => readFileSync(join(storiesDir, filename), "utf8").toLowerCase())
.join("\n");
@@ -90,12 +91,12 @@ describe("Storybook inventory", () => {
"ScanlineField",
"SignalTrace",
]) {
- expect(existsSync(join(componentsDir, `${component}.svelte`)), `${component} is missing`).toBe(
+ expect(existsSync(join(componentsDir, `${component}.tsx`)), `${component} is missing`).toBe(
true,
);
expect(
- existsSync(join(storiesDir, `${component}.stories.svelte`)),
- `${component}.stories.svelte is missing`,
+ existsSync(join(storiesDir, `${component}.stories.tsx`)),
+ `${component}.stories.tsx is missing`,
).toBe(true);
}
});
@@ -107,7 +108,7 @@ describe("Storybook inventory", () => {
"ScanlineField",
"SignalTrace",
]) {
- const source = readFileSync(join(componentsDir, `${component}.svelte`), "utf8");
+ const source = readFileSync(join(componentsDir, `${component}.tsx`), "utf8");
expect(source).toContain('aria-hidden="true"');
}
@@ -115,8 +116,16 @@ describe("Storybook inventory", () => {
test("does not add deferred form/navigation primitives", () => {
for (const component of ["Input", "ToggleGroup", "ScrollArea"]) {
- expect(existsSync(join(root, `src/lib/ui/components/${component}.svelte`))).toBe(false);
- expect(existsSync(join(storiesDir, `${component}.stories.svelte`))).toBe(false);
+ expect(existsSync(join(root, `src/lib/ui/components/${component}.tsx`))).toBe(false);
+ expect(existsSync(join(storiesDir, `${component}.stories.tsx`))).toBe(false);
}
});
+
+ test("does not keep Svelte stories in the React Storybook inventory", () => {
+ const svelteStories = readdirSync(storiesDir).filter((filename) =>
+ filename.endsWith(".stories.svelte"),
+ );
+
+ expect(svelteStories).toEqual([]);
+ });
});