Skip to content
buttery

v1.0.0

Source on GitHub

Version 1.0.0

Spacing and sizing

The 4px spacing scale, the control heights that change with density, and the widths pages and panels keep to.

buttery's spacing is a scale of steps on a 4px grid, from 0.5 (2px) to 32 (128px). Use a step for every gap and padding, and the space around things stays in proportion from one screen to the next.

Spacing steps

Layout props take a step, not a length: gap={3} is 12px and pad={4} is 16px. Half steps are numbers too, such as gap={1.5} for 6px, and any step can also be written as a string, such as padX="0.5".

tsx

import type { ReactElement } from "react";
import { Inline, Stack, Surface, Text } from "@butteryui/core";
import { Button } from "@butteryui/react";

export function PayoutCard(): ReactElement {
  return (
    <Surface level="card" pad={5}>
      <Stack gap={3}>
        <Text variant="title-sm">Next payout</Text>
        <Text variant="body-sm" tone="secondary">
          $1,280.40 arrives on Friday.
        </Text>
        <Inline gap={2}>
          <Button size="sm">View payouts</Button>
        </Inline>
      </Stack>
    </Surface>
  );
}

Every step, with its variable and its length:

--bt-space-0 路 0px
--bt-space-1 路 4px
--bt-space-2 路 8px
--bt-space-3 路 12px
--bt-space-4 路 16px
--bt-space-5 路 20px
--bt-space-6 路 24px
--bt-space-8 路 32px
--bt-space-10 路 40px
--bt-space-12 路 48px
--bt-space-16 路 64px
--bt-space-24 路 96px
--bt-space-32 路 128px
--bt-space-0_5 路 2px
--bt-space-1_5 路 6px

In CSS the steps are variables, --bt-space-<step>, with an underscore for a half step: var(--bt-space-0_5).

Do

css

.toolbar {
  gap: var(--bt-space-2);
}

A step from the scale: 8px, the same space as gap={2}.

Don't

css

.toolbar {
  gap: 10px;
}

A length off the scale, which buttery's stylelint config fails.

Control heights

Every control is one of a few heights, so buttons, fields and segmented controls line up in a row. Each height has a comfortable value and a compact one, and ButteryProvider's density picks between them for the whole app.

badge 路 20 / 18
sm 路 28 / 28
control 路 34 / 30
button 路 36 / 32
cta 路 48 / 40
row 路 50 / 42
row-split 路 64 / 56
header 路 56 / 48
nav-bar 路 64 / 64
sub-nav 路 48 / 48
table-row 路 36 / 32

Components take their height from these tokens on their own. In your own CSS, read them as var(--bt-h-control) and the like.

Widths

Fixed widths for the parts that have one, such as the sidebar, a dialog or a page's content. Anything else takes its width from its container.

--bt-w-shell-max
1380px
--bt-w-inspector
340px
--bt-w-sidebar
240px
--bt-w-sidebar-rail
56px
--bt-w-app-page
1280px
--bt-w-app-page-md
960px
--bt-w-app-page-sm
820px
--bt-w-aside
320px
--bt-w-search
360px
--bt-w-search-open
600px
--bt-w-side-panel
360px
--bt-w-side-panel-wide
560px
--bt-w-dialog
400px
--bt-w-auth
360px
--bt-w-dialog-md
560px
--bt-w-dialog-lg
880px
--bt-w-menu-min
200px
--bt-w-row-control
160px
--bt-w-page
1200px
--bt-w-prose
720px
--bt-bento-row
320px
--bt-nav-panel-min
200px
--bt-inset-titlebar
84px
--bt-focus-width
2px
--bt-focus-offset
2px
--bt-icon-sm
16px
--bt-icon-md
20px
--bt-blur-scrim
10px
  • The layout contract

    The 13 rules every buttery screen follows, so nothing overlaps, overflows or shifts, and how they're checked.

  • Radius

    The corner radius scale, and how nested surfaces keep their corners concentric.