Install it from npm:

npm install boxykit

Import the CSS once, at the root of the app, and use anything on this page:

import "boxykit/css";
import { Button } from "boxykit/react";

<Button>Save</Button>

No React? Pick CSS at the side.

No npm either? Download the whole kit as one file and link it, or copy it into your own:

<link rel="stylesheet"
  href="boxykit-0.4.0.css">

Boxykit · personal UI lib

Desktop-first UI kit I use for my personal projects, so I don’t have to invent it every time.

Tokens · Page

Black on white; the greys for what steps back.

  1. --boxy-bgThe page
  2. --boxy-fgThe text
  3. --boxy-mutedLabels, captions, empty messages
  4. --boxy-ghostFaded headline words
  5. --boxy-lineThe lines that divide the page

Tokens · Accent

The yellow: the main action, the current page, what is chosen. Text on it is --boxy-on-accent.

  1. --boxy-accentThe yellow
  2. --boxy-accent-strongAn accent button under the pointer
  3. --boxy-accent-softSelection, what is under the pointer
  4. --boxy-on-accentText on the yellow

Tokens · Band

The inverted bands: the nav, dark tiles and buttons, toasts.

  1. --boxy-band-bgThe band
  2. --boxy-band-fgText on it
  3. --boxy-band-mutedThe nav numbers, toast titles
  4. --boxy-band-lineLines on the band
  5. --boxy-band-hoverA band link under the pointer

Tokens · Status

The tones of alerts; each -soft one is its background.

  1. --boxy-infoInformation
  2. --boxy-successRight, saved
  3. --boxy-warningClose, careful
  4. --boxy-dangerWrong, errors
  5. --boxy-danger-softBehind an error

Tokens · Type

Each size is --boxy-font-scale (1.5) times the one below it; tiny is the odd one, for the small numbers. Each has its --boxy-line-height-…, a whole number of spaces.

  1. Boxykit--boxy-font-size-tinyTile numbers 01/04
  2. Boxykit--boxy-font-size-smallLabels, buttons, tables, captions
  3. Boxykit--boxy-font-sizeBody text
  4. Boxykit--boxy-font-size-headingTile values
  5. Boxykit--boxy-font-size-displaySection headings
  6. Boxykit--boxy-font-size-headlineHeadlines
  7. Boxykit--boxy-font-size-heroThe hero number

Tokens · Spacing

Multiples of --boxy-space (0.25rem).

  1. --boxy-space
  2. --boxy-space-2
  3. --boxy-space-3
  4. --boxy-space-4
  5. --boxy-space-6
  6. --boxy-space-8
  7. --boxy-space-12
  8. --boxy-space-24

Text · Headline

Big capitals, set tight. ghost adds words set back in grey.

Ship this week

Text · Hero number

The biggest size in the regular weight, its unit at the heading size: the one number a screen is about.

62%

Text · Caption and mono

Small grey capitals spaced wide, for what a block is; mono for IDs, dates and counts.

Progress

TSK-0784 · 2026-10-05

List · Bullets

A small square in front of each item, in the middle of its height.

  • Write the release notes
  • Fix the login redirect
  • Move the old tasks to the archive, then check that nothing links to them

List · Numbered

NumberedList: 01, 02… from a CSS counter, in the middle of the item.

  1. Open a branch
  2. Write the change and its test
  3. Open a pull request and ask for a review

Tag · TagList

Small rectangles: outlined, or look accent or dark for the ones that matter. title shows on hover; icon goes before the label.

P1BugFrontendQ4

Icon · A set

The kit ships no icons: give any line icon (here Lucide) boxy-icon. large doubles it, for empty states and tiles.

Icon · In text

As big as the text around it and in its color; square line ends, to go with the rectangles.

Synced two minutes ago

Due Friday

Icon · With a name

Hidden from screen readers by default; one that says something the words don't gets role="img" and aria-label.

Billing

Board · Main and side

Four cells, the left column twice as wide: the content on the left, its status and actions on the right.

Sprint 14

Release 2.4

  1. 01/0218/24Done
  2. 02/026Open

Next

Fix tests

Board · Quarters

even makes the columns as wide as each other: four cells are four quarters.

62%

Done

23%

In progress

11%

To do

4%

Blocked

Board · Halves

Two cells in an even board: the screen split in two.

Boxy kit

Two halves: put two cells in an even board.

Board · A tall cell

tall takes the whole left column; end puts a cell's content on the line below it.

TSK-0412

  1. StatusIn review
  2. OwnerMia

Step 2 of 4

Board · A tool page, under a Nav

fit makes rows as tall as their content. A side cell sits in the right column even when it comes first; sticky keeps its content in view. Right under a Nav the board is shorter by the Nav's height.

Inputs

Net, a month

2 940 €

Breakdown

Gross
4 000 €
Tax
−1 060 €

Stack · Basic

Children one under another, --boxy-space-4 between them.

Sprint 14

Release 2.4

Stack · Gaps

gap names another spacing step: 2, 3, 6 or 8. Stacks nest: a wide gap between groups, a narrow one inside them.

Gap 2

TSK-0410TSK-0411

Gap 3

TSK-0412TSK-0413

Gap 6

TSK-0414TSK-0415

Box · Outlined

A rounded outline around any content: the cards of an invoice, a summary.

From

Northwind Oy

Helsinki

Bill to

Mia Laine

Tampere

Section · Basic

A SectionHeading and the content under it.

Settings

The content under the heading.

Table · Plain

Columns with a header each.

TaskOwnerStatus
Fix the login formMiaIn review
Export to CSVLeoIn progress
Dark modeAnaDone

Table · Clickable rows

onRowClick makes rows clickable (Enter and Space too); expanded draws a full-width row under an open one.

TaskOwner
Fix the login formMia
Safari drops the password on submit.
Export to CSVLeo

Table · Numbers and a total

numeric on a column puts it on the right, digits as wide as each other, on one line. foot is the rows of totals, under a dark line.

ItemHoursAmount
Design12,51 000,00 €
Development403 600,00 €
Review3270,00 €
Total55,54 870,00 €

LabelRows · Label and value

The row form of a LabelTile, a <dl>: the label small and mono on the left, the value on the right. accent fills the row that sums up.

Subtotal
1 200,00 €
VAT 25.5%
306,00 €
Total
1 506,00 €

Tile · Value

Outlined: the place 04/04 at the top, the value and its label at the bottom.

  1. 04/04845Total

Tile · Accent and dark

look fills the tile with the accent (the first or the main number) or dark (the others).

  1. 01/0312Projects
  2. 02/03845Tasks
  3. 03/034Teams

Tile · With a ring

A ring at the top right shows a share: shareRing(part, whole, of) makes it with its title.

  1. 01/0337% of all tasks312Done
  2. 02/0314% of all tasks120In progress
  3. 03/0349% of all tasks413Bugs

Tile · Wide

wide makes the tile two squares wide and as tall as one: the tile that leads a row.

  1. 01/0214% of all tasks120/845Showing
  2. 02/0249% of all tasks413Bugs

Tile · Out of

outOf adds the whole, small after the value: 3/10.

  1. 01/022/4Step
  2. 02/0220% of this sprint done3/10Task

Tile · Corner text

corner puts a text such as a date where the place goes; icon puts an icon where a ring goes.

  1. 08.1014°Wed
  2. 09.1019°Thu

Tile · Label only

A tile whose label says it all has no value.

  1. 04/04Bugs

Tile · Clickable

With onClick the whole tile is a button and its label ends in →; disabled fades it.

Tile · SelectableTiles

Tiles that work like radio buttons: the chosen one accent, the others dark. children adds tiles after them.

Tile · TileIndex

A place in small mono numbers, 01/04; without of just 01. The tiles draw it themselves.

01/0403

LabelTile · Label over value

An outlined square, the label small at the top and the value at the bottom.

  1. StatusIn review
  2. OwnerMia

LabelTile · Long values

The square keeps its size: lines break between words, evenly.

  1. ReviewerDesign team
  2. MilestonePublic beta launch
  3. Blocked byDatabase migration

LabelTile · Wide

wide makes it two squares wide and at least as tall as one, for values longer than a word.

  1. ProjectsWebsite redesign
    Mobile app

LabelTile · Missing

An empty field or list: a dashed outline and a faded value.

  1. AssigneeNone yet
  2. LabelsNone yet

LabelTile · With a ring

The label can hold more than text: here a ProgressRing next to it.

  1. Progress2 of 3 skills passed2/3

Button · Looks

Accent is the default; dark goes on the accent; outline takes the text color, so it works on any background.

Button · Sizes

As tall as the field of the same size: normal beside a normal field, small unless told otherwise, tiny in table rows and next to lists.

Button · Expand and collapse

An outline button that shows and hides a block, with aria-expanded.

Button · Pending

While what it started is under way: disabled but not faded, a Spinner after the label. SubmitButton swaps its label too.

Button · Disabled

Faded and without the press effect, in every look.

Button · A link as a button

buttonClass() gives any link the button look, so any router works.

Button · Tiny links in a row

An accent link with an outlined one next to it, under a list.

Input · Basic

Outlined, as wide as its container.

Input · Muted, with a label and an icon

No line, a light fill: for filters and search in toolbars. Field puts a label over any control; icon goes inside on the left.

Input · Invalid

invalid sets aria-invalid, which the CSS marks.

Input · Sizes

size="small" and "tiny": the small text in less padding, for toolbars and table rows. An icon follows the size.

Fields · Stacked

A group of Fields, one under another.

Fields · Columns

layout="columns": two across from sm, one under another below it. full on a Field takes both.

Fields · Row

layout="row": side by side on one line, the controls and a button on one bottom line; they wrap when the line is short.

Fields · Labels aside

layout="aside": from sm the labels in a column as wide as the longest, the controls lined up in a second one.

Textarea · Basic

The Input's look over several lines; it grows taller by hand. invalid works as on Input.

Select · Basic

The native select in the Input's look. Where the browser allows (Chrome), the open list is styled too.

Select · Sizes

size="small" and "tiny", as on Input.

Dropdown · Search

A field that opens a rounded box: a search on top, the options under it split by lines. Arrows move, Enter picks, Esc closes.

Dropdown · Numbered, with rings

numbered puts 01, 02… before the options, and each keeps its number while searching. ring on an option adds a ProgressRing.

Dropdown · No search

search={false} for a short list; icon on an option shows in the box and in the field. name adds a hidden input, so it goes with a form.

Checkbox, Radio and Switch · Checkbox

Rows like an InteractiveList, in a ChoiceList: the square fills when on; indeterminate half-fills it.

Checklist

Checkbox, Radio and Switch · Radio · Numbered

One name for one question; the circle fills. numbered puts 01, 02… in front.

Plan

Checkbox, Radio and Switch · Switch

On or off at once, no Save: YES ■ | □ NO at the end of the row, the side it is on in the accent.

Notifications

NumberInput · Min and max

A slider under the field: drag the small square along the line, min and max at its ends. Type, or step with the arrow keys; it stays inside.

112

NumberInput · From and to

from and to only set the line's ends: the slider runs over them, nothing shows at the ends, and a typed number can go past.

NumberInput · Just the field

No range, no slider. step holds everywhere: typing snaps to it when you leave the field, and the arrow keys move by it.

NumberInput · With a unit

unit shows small at the right end of the field: €, %, kg. It stays out of the label.

€/year

NumberInput · Sizes

size="small" and "tiny", as on Input; the unit shrinks with them.

ToggleGroup · One of a few

The chosen cell is the accent.

ProgressRing and Spinner · ProgressRing

Filled clockwise to a 0–1 value; title says what it means.

0% done40% done100% done

ProgressRing and Spinner · Large

size="large" for a ring that stands alone, e.g. in a table cell.

15% done40% done85% done

ProgressRing and Spinner · Spinner

The ring with a quarter running round it: something is under way.

LoadingLoading

Alert and Empty · Tones

Dark like a Toast: a dot in the tone top right, an optional title in the tone on top. Danger and warning are announced right away (role="alert"), the others politely.

InfoYour progress syncs every minute.
SavedAll 12 tasks are up to date.
No title, just the dot.

Alert and Empty · Light

look="light": the page's colors, outlined.

SavedAll 12 tasks are up to date.

Alert and Empty · Empty

A dashed box, grey and centered, instead of an empty list or table.

No tasks yet.

Toast · Notice

The title small at the top, then the content. Show toast puts it in the corner for 3 seconds.

Saved

TSK-0412 moved to Done

Toast · With a count

count goes at the right of the title.

Uploading3

report.pdf, logo.svg, notes.md

Toast · With actions

A toast that waits for an answer (role="alertdialog"): it goes only when a button hides it.

Delete 3 tasks?

This can’t be undone.

Modal · Over the page

The title small at the top, the content, the actions at the bottom. Esc, ✕ and a click on the dim close it.

TSK-0412

  1. StatusIn review
  2. OwnerMia
  3. TitleFix the login form on Safari