On margins
The unit is 8px.
Every gap, padding and control height is a multiple of it. --kb-space-8
Rules
- Controls on one row share one height.
- Muted text clears 4.5:1 or becomes ink.
Reference
Import from @kasane/design/react. Every class a component emits exists in the CSS. The check runs on every commit.
Covers the root, bands, column, and chrome
The root. Scopes every style and paints the page ground. One per page, in the root layout.
<Kasane>
<ToastProvider>{children}</ToastProvider>
</Kasane>| Prop | Type | Note |
|---|---|---|
lang | string | default 'en' |
className | string |
Scroll sideways for more columns.
A full-bleed band. Content goes in a Col.
<Band tone="deep" id="notes" labelledBy="notes-title">
<Col>
<Head title="Notes" id="notes-title" />
</Col>
</Band>| Prop | Type | Note |
|---|---|---|
tone | 'hero' | 'tone' | 'deep' | 'beni' | omit for the page ground |
as | ElementType | default 'section' |
labelledBy | string | id of the heading inside |
Scroll sideways for more columns.
The 1200px column.
| Prop | Type | Note |
|---|---|---|
className | string |
Scroll sideways for more columns.
A section head. Title left, aside right.
6 projects
| Prop | Type | Note |
|---|---|---|
title | ReactNode | |
aside | ReactNode | |
id | string | |
level | 1 | 2 | 3 | 4 | 5 | 6 | default 2 |
Scroll sideways for more columns.
A surface block. On the deep band in the light theme it takes the light theme.
A panel.
| Prop | Type | Note |
|---|---|---|
as | ElementType | default 'div' |
className | string |
Scroll sideways for more columns.
The main landmark.
| Prop | Type | Note |
|---|---|---|
id | string | default 'main' |
Scroll sideways for more columns.
First in the page. Visible on focus.
| Prop | Type | Note |
|---|---|---|
href | string | default '#main' |
label | string | default 'Skip to content' |
Scroll sideways for more columns.
The fixed pill bar holds the brand, section links, and children at the end. Put a ThemeSwitch there.
<Bar brand={{ name: 'Kasane', href: '/' }} items={items} link={Link}>
<ThemeSwitch />
</Bar>| Prop | Type | Note |
|---|---|---|
brand | { name, domain?, href } | |
items | NavItem[] | { href, label, current? } |
label | string | nav label, default 'Primary' |
link | LinkComponent | 'a' | next/link or a plain anchor |
Scroll sideways for more columns.
One button that says the theme and flips it. useTheme() gives [theme, setTheme]. themeScript is the head snippet.
| Prop | Type | Note |
|---|---|---|
className | string | default 'kb-bar__theme' |
Scroll sideways for more columns.
A block in the opposite theme of the page.
| Prop | Type | Note |
|---|---|---|
className | string |
Scroll sideways for more columns.
Covers the hero, tiles, stats, and long-form blocks
The opening band. Renders its own Band.
| Prop | Type | Note |
|---|---|---|
title | ReactNode | |
name | ReactNode | |
intro | ReactNode | |
id | string | heading id, default 'hero-title' |
Scroll sideways for more columns.
A whole-tile link, inside Tiles.
| Prop | Type | Note |
|---|---|---|
href | string | |
kind | ReactNode | |
year | ReactNode | |
title | ReactNode | |
level | HeadingLevel | default 3 |
small | boolean | |
link | LinkComponent | 'a' | next/link or a plain anchor |
children | ReactNode | the description |
Scroll sideways for more columns.
A big number, inside Stats. direction draws the arrow. sentiment colours it.
| Prop | Type | Note |
|---|---|---|
value | ReactNode | |
label | ReactNode | |
delta | ReactNode | |
direction | 'up' | 'down' | |
sentiment | 'good' | 'bad' | 'neutral' | default 'neutral' |
Scroll sideways for more columns.
The beni band. Renders its own Band.
| Prop | Type | Note |
|---|---|---|
title | ReactNode | |
text | ReactNode | |
actions | ReactNode | |
id | string | heading id, default 'cta-title' |
Scroll sideways for more columns.
Long-form headings, lists, figures, tables, and code get their margins back. Article puts a Prose and a Toc side by side.
The unit is 8px.
Every gap, padding and control height is a multiple of it. --kb-space-8
| Prop | Type | Note |
|---|---|---|
as | ElementType | default 'article' |
className | string |
Scroll sideways for more columns.
On this page, as a panel.
| Prop | Type | Note |
|---|---|---|
items | { href, label }[] | |
label | string | default 'On this page' |
link | LinkComponent | 'a' | next/link or a plain anchor |
Scroll sideways for more columns.
A note in a box. err is an alert.
| Prop | Type | Note |
|---|---|---|
kind | 'neutral' | 'notice' | 'ok' | 'warn' | 'err' | default 'neutral' |
title | ReactNode |
Scroll sideways for more columns.
An empty state.
No deployments yet. Push to main to create one.
Rows of surface, one per family, each with a caps label. SheetRow takes label and id.
Covers buttons, words, identity, and layout
Passes every button attribute through. ButtonLink is the same look on an anchor. LinkButton is a button drawn as a link.
| Prop | Type | Note |
|---|---|---|
variant | 'secondary' | 'primary' | 'accent' | 'danger' | default 'secondary' |
size | 'sm' | 'md' | 'lg' | 32, 40, 48px |
icon | boolean | a square button holding one icon, needs aria-label |
tip | string | tooltip on hover and focus |
push | boolean | margin-left: auto |
Scroll sideways for more columns.
A pill holding a segmented set. Buttons inside carry aria-pressed.
| Prop | Type | Note |
|---|---|---|
label | string | |
role | 'group' | 'tablist' | default 'group' |
Scroll sideways for more columns.
A word in its colour.
| Prop | Type | Note |
|---|---|---|
kind | 'neutral' | 'ok' | 'warn' | 'err' | default 'neutral' |
Scroll sideways for more columns.
Keys, inline code, a code block.
--kb-space-8: 8px.card {
border-radius: var(--kb-radius-block);
}Initials in a circle. With a name it is an image. Without one it is hidden, because the control around it carries the name. AvatarStack overlaps them.
| Prop | Type | Note |
|---|---|---|
initials | ReactNode | |
name | string | |
size | 'md' | 'lg' |
Scroll sideways for more columns.
Breadcrumb. The last entry has no href and is the page.
| Prop | Type | Note |
|---|---|---|
trail | { href?, label }[] | |
link | LinkComponent | 'a' | next/link or a plain anchor |
Scroll sideways for more columns.
Page numbers. A null entry is a gap.
| Prop | Type | Note |
|---|---|---|
pages | ({ href, label, current? } | null)[] | |
prev | string | |
next | string | |
label | string | default 'Pagination' |
push | boolean | |
link | LinkComponent | 'a' | next/link or a plain anchor |
Scroll sideways for more columns.
A progressbar. Skeleton is one shimmering line.
| Prop | Type | Note |
|---|---|---|
value | number | |
max | number | default 100 |
label | string |
Scroll sideways for more columns.
Cluster is a wrapping row. Stack is a column. Row puts fields side by side, 2 or 3 columns. Split makes two halves. Divider is a hairline.
| Prop | Type | Note |
|---|---|---|
Cluster gap | 'tight' | 'wide' | |
Cluster push | boolean | |
Cluster as | ElementType | |
Stack tight | boolean | |
Row cols | 2 | 3 | default 2 |
Scroll sideways for more columns.
Covers field wiring, inputs, choices, and the dropdown
Hands the control its id, aria-describedby and aria-invalid through a render prop. Form and Fieldset wrap. FormActions is the button row.
| Prop | Type | Note |
|---|---|---|
id | string | generated when omitted |
label | ReactNode | |
hint | ReactNode | |
error | ReactNode | marks the field invalid |
required | boolean | |
wide | boolean | spans the row |
children | (wiring) => ReactNode |
Scroll sideways for more columns.
Native inputs with the system's look. Every attribute passes through.
| Prop | Type | Note |
|---|---|---|
size | 'sm' | 'md' | Input only, 32 or 40px |
Scroll sideways for more columns.
An input with a fixed word before or after it, in one pill.
| Prop | Type | Note |
|---|---|---|
before | ReactNode | |
after | ReactNode | |
size | 'sm' | 'md' |
Scroll sideways for more columns.
A native select for forms and a button plus listbox drawn by the system. Arrows, Home, End, typeahead, Escape. Flips up when there is no room below.
| Prop | Type | Note |
|---|---|---|
options | { value, label, disabled? }[] | |
value | string | controlled |
defaultValue | string | |
onChange | (value: string) => void | |
size | 'sm' | 'md' | |
name | string | |
disabled | boolean |
Scroll sideways for more columns.
Checkbox, radio and switch, drawn by the CSS. The switch says On or Off.
| Prop | Type | Note |
|---|---|---|
type | 'checkbox' | 'radio' | Choice only |
label | ReactNode | |
description | ReactNode | small type under the label |
on, off | string | Switch words, default 'On' / 'Off' |
Scroll sideways for more columns.
A row of small controls above a table. HiddenLabel names a control the layout already explains.
Tables and tabs
TableWrap scrolls sideways inside its block and shows a hint only when columns are hidden. Th and Td take a priority. Columns drop as the block narrows, low then mid then narrow. RowTitle folds the status word under the name when the status column has gone.
| Project | Environment | Status | Requests | p95 | Updated | Actions |
|---|---|---|---|---|---|---|
| apiHealthy | production | Healthy | 1,204,553 | 182 ms | 2 min ago | |
| webDegraded | staging | Degraded | 48,210 | 640 ms | 14 min ago | |
| storageFailed | production | Failed | 0 | — | 3 h ago |
Scroll sideways for more columns.
| Prop | Type | Note |
|---|---|---|
TableWrap label | string | names the scroll region |
TableWrap hint | ReactNode | |
TableWrap prose | boolean | inside long-form |
Th, Td priority | 'low' | 'mid' | 'narrow' | |
Th, Td num | boolean | right-aligned, tabular digits |
Td muted | boolean | |
RowTitle status | { kind?, label } |
Scroll sideways for more columns.
ARIA tabs. Arrows, Home and End move and select. The list is a tray. The selected tab is a filled pill.
All eight deployments.
Five in production.
| Prop | Type | Note |
|---|---|---|
label | string | |
items | { id?, label, count?, children }[] | |
initial | number | default 0 |
onChange | (index: number) => void |
Scroll sideways for more columns.
Dialogs and toasts
Native dialog. Open it with ref.current.showModal(). The cross and any button with data-kb-close close it. useTypedConfirm(word) gives inputProps and confirmed for a destructive dialog.
| Prop | Type | Note |
|---|---|---|
id | string | |
title | ReactNode | |
actions | ReactNode | the foot |
ref | Ref<HTMLDialogElement> | |
closeLabel | string | default 'Close' |
Scroll sideways for more columns.
ToastProvider renders the list at the viewport corner. useToast() returns toast(message, kind?). At most three, five seconds each, paused while hovered.
| Prop | Type | Note |
|---|---|---|
kind | 'ok' | 'err' | optional |
Scroll sideways for more columns.
All of the above, combined on one page.