SpareThought design system
SpareThought is a handwritten journal, ToDo list and calendar for Android, built for two devices that share one theme and one set of components: an e-ink tablet (the main device, BOOX-class, 702 × 936 dp portrait) and a colour phone companion (411 × 869 dp, down to 360 dp). Everything here is implemented in Jetpack Compose. The colours are fixed; what this system governs is layout, hierarchy, spacing and behaviour.
Principles
- Paper first. The writing surface is the product. Chrome is white, quiet and thin; the user's ink is the only thing with weight.
- Works in grayscale. Every screen must read on an e-ink panel. Selection, state and urgency are never carried by colour alone: they are always paired with a check, a 2 dp outline, Bold, an icon or a word. Check every design against the
einktheme. - No depth, no motion on e-ink. No shadows or elevation anywhere (
elevation-none). On the tablet there is no scrim, no dim layer and no animation. The phone's bottom sheet is the single exception (see Motion). - One component, two form factors. A ToDo row, dialog frame or picker is built once and parameterised per device (
WindowSizeClassor the app's device check). Never fork phone and tablet copies. - Anchor to the trigger. A menu or popover opens from the control that summoned it and says what it belongs to. If the user can't see what a popup refers to, it is in the wrong place.
Content fundamentals
Write in plain, human English, in sentence case, addressing the user as "you" only when necessary. No emoji.
- Name things the way people see them. "Days with writing", not "dates with strokes"; "This device", not a device ID.
- Never show raw data. No hex codes ("#3399BB" → "Blue"), no minute counts ("1440 minutes" → "1 day before"), no internal states ("SYNC_PENDING" → "Waiting to sync").
- Titles say what the dialog is for. "Go to date", "Due date", "Calendar color". Never "Options", "Select", or a title borrowed from another picker.
- A field shows its label once. The label sits above the field; an empty, focused field shows only a cursor, not the label again as a placeholder.
- Empty states are one plain line, optionally with one line of how to fill it: "No meeting notes yet. Open a meeting in your calendar to start a note." No illustrations, icons or skeletons. Search with no hits shows only "No results".
- Buttons say what happens. "Copy pages", "Convert to text", "Sign out". Destructive confirmations name the thing and the consequence: "Delete “kubernetes”? Its 1 page of writing will be permanently deleted."
- Don't explain the obvious. If the selected swatch is already marked, don't also print "Red selected".
- Dates follow the user's Date format setting (default
05.04.2026); in navigation use the short form "Thu 5 Nov".
Visual foundations
Colour
surfaceis the only surface. Putinktext on it,mutedfor secondary text.forestis the accent: primary buttons (withon-foresttext), selected outlines, the focus ring, text buttons. Use it sparingly — one primary action per view.- Selected state =
sage-selectedfill and a 2 dpforestoutline and/or a check icon and Bold. Never fill alone. sageis a quiet fill (disabled buttons, time boxes, preview tiles), never a selection.urgentis for overdue items, errors and destructive actions, always with Bold and "!" or an icon. Destructive buttons are outlinedurgentin lists and filledurgentonly inside the confirmation dialog.upcomingmarks future due dates on ToDo rows.meeting-fillfills meeting cards; the left rail takes the calendar's colour (calendar-railby default, else acal-*token).- Pen, calendar and theme colour choices come only from the 11
cal-*tokens (the app's fixed palette; grayscale panels offer only black, gray and light gray).cal-yellow,cal-light-grayandcal-grayare always drawn inside a 1 dpdividerborder.
Type
- Phone: Material 3 roles in Roboto (
phone-*styles). Titles of sheets usephone-title-large; body copyphone-body-medium; metadataphone-body-small. - Tablet: its own larger sp scale (
tablet-*styles). Dialog titlestablet-title(24 sp Medium); body and rowstablet-body(18 sp); metadatatablet-label(16 sp); button labelstablet-button. - Never reuse a phone size on the tablet. Every tablet mockup is drawn at 2 px = 1 dp: halve every pixel value.
- Use tabular numerals wherever digits line up: times, page labels ("2/3"), counters, zoom levels.
ink-sample(Caveat) only stands in for real ink in mockups.
Spacing, shape and lines
- Spacing steps are
space-14,space-28,space-312,space-416,space-624. Use 4 dp only between an icon and its label. - Phone screen edge:
space-4. Tablet dialog padding:space-6(24 / 24 / 16 heading; 16 top, 24 start, 32 end with the scrollbar lane in the body; 16 / 24 / 24 footer). - Corners are
radius-md(8 dp) everywhere;radius-fullonly for pills, toggles, key badges and the selected day. - Outlines are
stroke-hairlineinoutline; dividersstroke-hairlineindivider. Dialogs, popovers and menus get astroke-frame(2 dp)inkframe — the heavier line is what lifts them off the page instead of a shadow. - One divider between sections, never stacked dividers.
Sizes and touch
- Every target is at least
target-min(48 dp). Icons are 24 dp. Chips are 40 dp visual inside 48 dp targets. - A selected tool is a
selected-tool-box(36 dp) ofsage-selectedwith a 2 dpforestoutline, centred in its 48 dp target. - Whenever content scrolls, show the persistent scrollbar in its 16 dp lane (1 dp
dividertrack, 6 dpoutlinethumb).
Motion
- Tablet: none. Dialogs and popovers appear and disappear instantly.
- Phone bottom sheet only:
scrimwith a 6 dp backdrop blur (API 31+, plain scrim below), a 300 ms slide-up on cubic-bezier(.05,.7,.1,1), a 200 ms scrim fade, a 32 × 4 drag handle and swipe-down to dismiss. Respect reduced motion and the animator-duration setting.
Containers: which one to use
| Need | Phone | Tablet |
|---|---|---|
| A task with a decision (edit, create, confirm) | Bottom sheet, footer with Cancel + primary | Centred dialog, dialog-standard (editors dialog-editor) |
| Pick one value (date, time, colour, preset) | Bottom sheet or small centred dialog | Centred dialog, dialog-narrow (400 dp) |
| Confirm something destructive | Small centred dialog | Small centred dialog |
| A list to browse (Topics, Saved meeting notes, Settings) | Bottom sheet | Centred dialog, 800 dp tall, search and count in the heading |
| Actions on one item | Menu hanging from that item's ⋮; the row shows as active | Same |
| A value tied to a control (journal date, meeting details, pen presets) | Sheet | Popover anchored under the control |
| More editing tools | » tray: icon strip above the bottom tool bar (two rows) | » tray: one icon row under the app bar |
- Footers only for decisions. Dialogs with nothing to confirm (Settings, libraries, About) have no footer and no Close button — × in the heading, system Back and tapping outside all dismiss.
- Cancel is outlined and always comes before the filled
forestprimary. With Cancel + Save, ×, Back and tapping outside all act as Cancel. - No labelled dropdown menus for tools. Tools are icons in the bar or the » tray; values that step (zoom) use − / value / + inside the tray.
- Size pickers to their content. A date or colour picker is a compact
dialog-narrow, never a full-width dialog. - Use the platform where it exists. Time is the Material 3 TimePicker (dial on the phone; TimeInput by default on e-ink, with the dial one tap away), themed with these tokens.
Iconography
Stroke icons on a 24 viewBox, 1.75 stroke, round caps and joins, currentColor. In code, use the closest Material Symbols Outlined glyph: notebook (saved meeting notes), calendar_month, search, cloud with a status mark (sync), settings (standard cog), check_box (ToDos), sell (topics), edit, ink_eraser, lasso_select, undo/redo, chevrons, more_vert, delete, lock / lock_open, zoom_in. Icons sit in 48 dp targets; icon-only buttons always carry a content description ("Page 2 of 3", "More actions for kubernetes").
Accessibility
- Text meets 4.5:1 on its ground (see each colour's usage note).
mutedonsage-selectedis only 4.3:1: useinkfor secondary text inside selected rows. - Layouts hold at font scale 1.3 and, on the phone, at 360 dp width.
- Selected tools are exposed as
Role.Tab/ selected; toggles as switches; option groups as radio groups.