diff --git a/src/components/composed/BuildInfoFooter/BuildInfoFooter.stories.tsx b/src/components/composed/BuildInfoFooter/BuildInfoFooter.stories.tsx new file mode 100644 index 00000000..e213c711 --- /dev/null +++ b/src/components/composed/BuildInfoFooter/BuildInfoFooter.stories.tsx @@ -0,0 +1,48 @@ +import { expect, within } from "storybook/test"; + +import { BuildInfoFooter } from "./BuildInfoFooter"; + +import type { Meta, StoryObj } from "@storybook/react-vite"; + +const meta = { + title: "Design Patterns/Build Info Footer", + component: BuildInfoFooter, + parameters: { + layout: "fullscreen", + zephyr: { testCaseId: "" }, + }, + tags: ["autodocs"], + args: { + version: "1.4.2", + commitSha: "a1b2c3d", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +/** App version + commit SHA. */ +export const Default: Story = { + parameters: { + zephyr: { testCaseId: "SW-T5653" }, + }, + play: async ({ canvasElement, step }) => { + const canvas = within(canvasElement); + + await step("renders the version and commit", async () => { + expect(canvasElement.querySelector('[data-slot="build-info-footer"]')).toBeInTheDocument(); + expect(canvas.getByText("v1.4.2")).toBeVisible(); + expect(canvas.getByText("a1b2c3d")).toBeVisible(); + }); + }, +}; + +/** Only what you pass renders — here just the version. */ +export const VersionOnly: Story = { + args: { + commitSha: undefined, + }, + parameters: { + zephyr: { testCaseId: "SW-T5654" }, + }, +}; diff --git a/src/components/composed/BuildInfoFooter/BuildInfoFooter.tsx b/src/components/composed/BuildInfoFooter/BuildInfoFooter.tsx new file mode 100644 index 00000000..f863fc19 --- /dev/null +++ b/src/components/composed/BuildInfoFooter/BuildInfoFooter.tsx @@ -0,0 +1,49 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +export interface BuildInfoFooterProps + extends Omit, "children"> { + /** Application version (rendered as `v{version}`) */ + version?: string; + /** Short commit SHA */ + commitSha?: string; +} + +/** + * A subtle full-width footer bar for application build metadata — the app + * version and commit SHA. Both fields are optional and only render when + * provided. Meant to sit at the bottom of a page/app. + */ +export function BuildInfoFooter({ + version, + commitSha, + className, + ...props +}: BuildInfoFooterProps) { + const meta = [version && `v${version}`, commitSha].filter( + (x): x is string => Boolean(x) + ); + + return ( + + ); +} diff --git a/src/components/composed/BuildInfoFooter/index.ts b/src/components/composed/BuildInfoFooter/index.ts new file mode 100644 index 00000000..91c9b861 --- /dev/null +++ b/src/components/composed/BuildInfoFooter/index.ts @@ -0,0 +1,2 @@ +export { BuildInfoFooter } from "./BuildInfoFooter"; +export type { BuildInfoFooterProps } from "./BuildInfoFooter"; diff --git a/src/index.ts b/src/index.ts index d39194ac..fceab49c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,6 +3,7 @@ import "@/index.css"; // Composed export * from "@/components/composed/AppShellSimple"; +export * from "@/components/composed/BuildInfoFooter"; export * from "@/components/composed/FormPatterns"; export * from "@/components/composed/StatCard"; export * from "@/components/composed/DataAppShell";