Component Showcase

Inkwell — every component, both modes

A live tour of Inkwell with its default Indigo & Cloud palette. Use the toggle in the top-right to flip between auto / light / dark. Open tokens.css for the source, DESIGN_SYSTEM.md for the docs, index.html for a starter template.

01

Color

12 tokens
#F4F4F0--ivory
#FFFFFF--paper
#13141B--slate
#3B4A8C--accent
#DDDCDF--oat
#788C5D--olive
#B04A3F--rust
#C78E3F--warning
#EDEDEA--gray-100
#CFCFCC--gray-300
#6F6F75--gray-500
#3A3B41--gray-700

Hex labels show light-mode values. Toggle to dark to see the lifted equivalents (e.g., --accent shifts to #7A8AD1 periwinkle).

02

Typography

10 styles
Plan the week ahead
Plan the week ahead
Plan the week ahead
Plan the week ahead

A deck paragraph sits between the headline and the body — serif italic, twenty pixels, comfortable line-length.

Body copy at 16/1.55, sans, weight 430. Long-form prose lives here — captions, descriptions, paragraphs of explanation.
Small at 14/1.5 — meta information, secondary copy.
Caption · updated 2 hours ago
Eyebrow label
Editorial kicker
03

Buttons & controls

03b

Button states & a11y utilities

2.1.0
InvoiceStatusAmountIssuedDue
INV-0041Paid$1,280.00May 2May 16
INV-0042Open$640.00May 9May 23

.tbl-scroll wrapper — the table scrolls instead of crushing columns on narrow viewports. .sr-only and .skip-link ship for screen-reader and keyboard flows; pair aria-busy="true" with disabled from JS (CSS only blocks pointer events, not keyboard activation).

04

Badges, pills & chips

Draft In review Done Overdue Failed
SEV-2 Resolved Duration 42m
auth/session.ts queue/dispatch.ts migrations/0042.sql
05

Stat cards

23
Shipped
▲ 4 vs last week
5
Open PRs
— flat
2
Slipped
▼ needs attention
98%
Test coverage
▲ 1.2pp
06

Dark callout (auto-inverts in dark mode)

TL;DR

Elevated 502 errors on /sync for 27 minutes. Root cause: a stale connection pool after the deploy at 14:02 UTC. Mitigated by rolling restart; permanent fix tracked in INC-2025-0412.

07

Table

ItemOwnerStatusDue
Revamp planner sidebarAveryDoneMon
Migrate auth to OAuth2JordanIn reviewWed
Rate-limit retriesSamAt riskFri
08

Timeline

14:02 UTC
Deploy of v3.4.1 lands
Routine release of the planner refactor — no flags toggled.
14:09 UTC
First 502s observed
Pager fires. Error rate climbs from baseline 0.01% to 4.2% within 90 seconds.
14:29 UTC
Mitigated
Rolling restart applied; error rate returns to baseline within 4 minutes.
09

Card grid (link cards)

Three code approaches
Side-by-side comparison of three ways to solve the same problem.
01-exploration.html
Visual design directions
A handful of layout and palette options rendered live.
02-visual.html
Implementation plan
Milestones on a timeline, data-flow diagram, risk table.
16-plan.html
10

Avatars

monogram circles
AC JD SM VC RT

Default uses --oat background with the 1.5px hairline. Tinted variants reuse --accent-tint / --olive-tint to stay on-palette without introducing new colors.

11

Table of contents (pill nav)

linkable
12

Form fields

.field · states · textarea · select
Shown to teammates and on shared links.
Slugs cannot contain spaces.
13

Radio & switch

.radio · .switch
14

Keyboard chips

native <kbd>
Save with S Command palette K Toggle theme T Submit Enter
15

Alerts

4 severities

Heads up

Your workspace will move to the new billing model on the first of next month.

Settings saved

Changes are live for everyone in this workspace.

Approaching plan limit

You've used 87% of your monthly seat allocation.

Sync failed

Last attempt at 14:02 returned a 502. Retrying in 5 minutes.

16

Code block

multi-line <pre><code>
const dialog = document.querySelector('#confirm');
document.querySelector('#open').addEventListener('click', () => {
  dialog.showModal();
});
17

Dialog

native <dialog>
Native focus trap, ESC-to-close, styled ::backdrop.

Archive this workspace?

Members lose access immediately. The data is retained for 30 days, then permanently deleted.

18

Tabs

aria-selected · .is-active

Tab panels are unstyled containers — show the panel matching the active tab and hide the rest with [hidden].

19

Tooltip

[data-tooltip]
auth/session.ts

Hover or focus to reveal. Pair with aria-label for screen-reader users — the visual bubble is decorative.

20

Breadcrumbs

<ol> · aria-current
21

Pagination

aria-current="page"
  1. 1
  2. 2
  3. 3
  4. 4
  5. 12
22

Skeleton

.is-text · .is-title · .is-block · .is-circle

Animation respects prefers-reduced-motion; the gradient lives between --gray-100 and --gray-200 so it stays warm in dark mode.

23

Empty state

icon · headline · body · action

No results found

Try a broader query, or remove a filter. Searches match component names, token names, documentation headings, and inline code.

24

Editorial primitives

dropcap · pullquote · byline · figure
Volume IV · Issue 02

The case for hairlines

Why a 1.5-pixel border is the most opinionated decision a design system can make — and the one that ages best.

Every design system makes a wager about borders. Most pick one pixel, because that is the default in every framework and the cheapest line the browser knows how to draw. Inkwell picks one-and-a-half. The half-pixel is a small concession to the era of retina screens, and a deliberate signal that this system was tuned for the era it ships in, not the one CSS was first specified for.

The half-pixel is the system's most opinionated decision — and the easiest one to defend.

On a 2× display, a 1.5-pixel border renders as three device pixels. That is the smallest unit that reliably reads as a drawn line rather than an artifact of antialiasing. One-pixel borders, on the same screen, often disappear under shadows and tinted backgrounds. Two-pixel borders read as frames around posters — fine for art, wrong for product UI.

The accent and olive tints, side by side under the same 1.5px frame. The border is what makes them feel like a pair instead of two unrelated swatches.

Pair this with sparing color and the system stops shouting. That, more than any single token, is what Inkwell is for.

25

Segmented control

aria-pressed · .is-active

Made with hairlines and serifs by Vinny Carpenter. The 1.5px is on purpose.