@hardlydifficult/storybook-components
v0.0.37
Published
Opinionated React components for internal tools. The goal is expressive client code, not maximum flexibility.
Readme
@hardlydifficult/storybook-components
Opinionated React components for internal tools. The goal is expressive client code, not maximum flexibility.
Installation
npm install @hardlydifficult/storybook-componentsDesign Principles
- Layout components use the same header vocabulary:
title,description,actions. - Tables are row-first. If rows already look like table data, they should render without extra wiring.
- Defaults should match the obvious case. Extra props exist to clarify intent, not to make every decision configurable.
Quick Start
import {
Badge,
Button,
DataTable,
Page,
Section,
Stack,
} from "@hardlydifficult/storybook-components";
const team = [
{ id: "1", name: "Alice", role: "Engineer", status: "Active" },
{ id: "2", name: "Bob", role: "Designer", status: "Away" },
];
export function Example() {
return (
<Page
title="Team"
description="The page shell handles spacing and header layout."
actions={<Button size="sm">Invite</Button>}
>
<Stack gap="md">
<Section
title="Members"
description="`Section` uses the same header prop names as `Page`."
>
<DataTable
rows={team}
columns={[
"name",
"role",
{
key: "status",
cell: (member) => (
<Badge
variant={member.status === "Active" ? "success" : "default"}
>
{String(member.status)}
</Badge>
),
},
]}
/>
</Section>
</Stack>
</Page>
);
}Components
Page
Use Page for the outer app shell.
<Page
title="Deployments"
description="Recent production activity"
actions={<Button size="sm">Ship</Button>}
>
{content}
</Page>Section
Use Section to group related content inside a page.
<Section
title="Queue"
description="Last 30 minutes"
actions={
<Button variant="ghost" size="sm">
Refresh
</Button>
}
>
{content}
</Section>DataTable
DataTable assumes rows have an id. Columns are optional:
- Omit
columnsto infer them from the first row. - Use string keys for straightforward columns.
- Use
{ key, label?, cell? }when one column needs custom rendering. - Selection callbacks return the selected rows, not just their ids.
<DataTable rows={rows} />
<DataTable
rows={rows}
columns={[
"name",
"role",
{ key: "status", cell: (row) => <Badge>{String(row.status)}</Badge> },
]}
selectable
onSelectionChange={(selectedRows) => {
console.log(selectedRows);
}}
/>Local Development
npm install
npm --workspace @hardlydifficult/storybook-components run storybookBuild
npm --workspace @hardlydifficult/storybook-components run build
npm --workspace @hardlydifficult/storybook-components run lint