Paper and ink

Ponjo's design system. The page is quiet so the writing and the buddies stand out: a warm grey ramp, one ink, and colour only where it means something.

This page is rendered with the app's own web/app.css. Change the system there and here together.

Rules for changing the UI

For anyone, person or agent, who changes how the app looks.

  1. Reuse before adding. Use an existing class (.pj-primary, .pj-secondary, .pj-icon-btn, .pj-input, .pj-segmented, .pj-switch, .pj-radio, .pj-panel…) before writing a new rule.
  2. Colours are tokens. No hex, rgb(), oklch(), black or white outside the token blocks at the top of app.css. A colour with a new meaning gets a token there, and a line on this page, first.
  3. Colour means something. Grey for the UI; ink for the one primary action and for what is on or selected; a buddy's own colour only for that buddy; red for danger and deletions (a buddy's deletions are grey); green for insertions and online; yellow for commented text; blue only for focus, text selection and links.
  4. Sizes come from the scales. Font sizes 11, 12, 13, 14, 16, 20, 24px; weights 400, 500, 600; radii 0, 4, 6, 10, 14px or full; spacing 2, 4, 6, 8, 12, 16, 24, 32, 48px; control heights 24, 28, 32px (36 and 40 for bars and big buttons).
  5. One of each control. Icon buttons are .pj-icon-btn: 28px, 32 in the header, 24 inside a row. Menu and list rows share one size, set once in app.css: 28px tall, 8px side padding, radius 6, 13px; grey on hover, --active when selected or current.
  6. One primary button per view. Everything else is secondary, ghost or a link button.
  7. Sentence case. Labels and headings are never all caps.
  8. Both themes. Check light and dark; tokens flip on their own, so a change that needs a dark-only override is usually using the wrong token.

Colour

Surfaces and ink

--canvasWindow, page
--bgPopovers, dialogs, active card
--bg-softToolbar, sidebar, cards, code
--hoverHover wash
--activeSelected, pressed, current
--border / -strongHairlines, outlines
--text-faintPlaceholders, meta
--text-softSecondary text, icons
--textInk: text, primary fill

Colours that mean something

--highlightCommented text
--highlight-activeThe open or hovered comment's text
--accentFocus, selection, links only
--redDanger, errors, deletions
--greenInsertions, online

Buddies

Each buddy has its own colour, the one in its face (see Avatars). It is set as --buddy on whatever belongs to that buddy: its @chip, edits, flag and the card it is working on. A run's edits show in the text as a revision: new text in its colour, removed text grey and struck through where it was.

Type

Inter for the UI, with each platform's own Chinese font behind it (PingFang SC, Microsoft YaHei UI, Noto Sans CJK SC; Songti SC, Noto Serif CJK SC for serif). The Markdown editor's page font (sans, serif or mono, set in that view) and its sizes in em are the writer's, not the UI's. A text file that is not Markdown shows as it is, in --mono at 14px by default (a size from 12 to 20 in its plugin).

24 / 600Display
20 / 600Large heading
16 / 600Section heading
14 / 400Comment text, menus, the base size
13 / 500Buttons, controls, settings
12 / 400Names, times, hints, small headings
11 / 500Badges, keys, flags

Shape and depth

4 chips, keys
6 controls, rows
10 cards, menus
14 dialogs
full faces
--shadowResting cards
--shadow-raisedAnything floating

Components

Buttons

Toolbar: pressed is ink on grey

A doc that cannot be edited here (a teammate who can only read) shows no formatting tools and no Comment bubble, rather than tools that do nothing; what only reads stays: the outline, the word count, comments and history. For a teammate who can only read, the comments have no reply box, Resolve, Reopen or Undo, and history has no Restore.

Fields and choices

14 px

A stepper is a .pj-segmented with .pj-stepper: − value +, for a whole number in a range. A view's or rule's settings are rows of a switch, a segmented choice or a stepper; the first row of a group has a heading, .pj-setting-group: 12px, semibold, faint.

Settings with a page of their own

A group of settings with its own page, such as a view or a rule, is a row in a list: its name, what it is and whether it is on, the whole row one button with a chevron. Its page starts with .pj-back, the same Back as the history's.

One of several, with its settings

When exactly one of several is picked, such as the agent that runs every buddy, each is a row of .pj-choices: a .pj-radio (ink when picked), its name and what it is, the whole row its label. The picked one shows its settings under it, in .pj-choice-detail, lined up with its name; the others stay closed.

Lists: current is ink on grey

A file or folder git ignores (build output, installed packages) is dimmed to --text-faint, not hidden; a filter leaves it out.

A sidebar is resized by dragging its edge: the cursor turns to col-resize and the edge shows a 2px --text-faint line; double-click the edge for the default width back.

Team panel

The Team button opens an .pj-panel, 360px: a head with its title and, for the owner of a project, Invite link and New link (both secondary); then .pj-people-rows in groups headed .pj-setting-group: you, Teammates, AI buddies, ending with New AI buddy. A request to join is the first teammate: its row says Asks to join, and under it Read or Edit (a .pj-segmented, Edit to start), Deny (secondary) and Allow, the panel's one primary button. A teammate's row says Can read or Can edit; its card has the same Read or Edit and Remove from this project (secondary, red). A teammate's page in a browser first asks their name in a card in the middle of the page.

Status bar

The plain view has a status bar under the page: .pj-statusbar, 28px, 12px text in --text-soft on --bg-soft, a hairline --border on top. The caret's place is on the left; on the right text buttons, 22px, grey on hover and ink on grey while pressed or open, and a menu above them in the .pj-block-menu style. Line numbers, whitespace marks (dots for spaces, arrows for tabs) are --text-faint; indent guides are --border-strong.

Ln 12, Col 8 · 24 selected

Text: comments, buddy edits, links, tasks

We ship the beta to fifty design partners in March, then open the waitlist once the beta is solidonboarding is stable. See the checklist.

A task list item has a box in place of its bullet: a .pj-radio's outline, square (radius 4); ink with a check when done. Clicking it ticks it.

A thread

Fan2m
Too vague. @Clippy can you make it concrete? cc @Sam
Clippy is working on it

Tooltip and keys

Undo ⌘Z ⌘⇧Z