Back to work

Design System · PeopleDesk v1.0

A design system for numbers
people have to trust.

PeopleDesk is a white-label HR, payroll and finance platform. Its system is built around one question: can the person running payroll tell, from the interface alone, what they are allowed to see, what will stop them, and what cannot be undone?

Role
Sole designer
Library and documentation
Client
Devlights
Built to resell white-label
Scope
Tokens, components, patterns
Written documentation
Platform
Web, desktop first
Dark-only interface
Colour foundations of the PeopleDesk design system: primitive ramps and semantic surfaces
149tokens across three tiers
17components with states, anatomy and accessibility notes
10primitives a reseller changes to rebrand the product

Context

Built while designing. Written down after.

I designed PeopleDesk end to end and built its component library in Figma as the screens took shape. The library worked, but its rules lived only in my head: why a contractor badge is amber, why one alert blocks a payroll run and another does not, why a hidden field shows a lock instead of a blank.

A white-label product is handed to teams that will never talk to its designer, so I turned that library into a documented system. This page walks through it the way a reseller's team would meet it: foundations first, then behaviour, then the components, then the rules that hold it together.

Every specimen below is live code built from the system's own tokens.

01Tokens

Three tiers. Ten values to rebrand.

Primitives hold raw values, semantic tokens give them a job, and component tokens scope that job to one element. Components may only reference the second and third tier. A hard-coded hex or a primitive inside a component is a review blocker.

One colour, three tiers
1 · Primitive--pd-violet-500

A raw value with no meaning attached. Owned by the system.

2 · Semantic--pd-action-primary

A role in the interface. The only tier a reseller may repoint.

3 · Component--pd-btn-primary-bg

Scoped to one component, so it can be retuned without touching the rest.

Live preview · example tenant themes
Payroll · June 202532 employees · 1 alert pending
Recurring Ready No hours
66%

Repoint, don't repaint

A reseller swaps the ten --pd-violet-* primitives and the logo mark. Every action, focus ring and brand badge follows, including the translucent states, which are mixed from violet-500 instead of written as fixed values.

Status never moves

Green, amber, red and blue stay fixed in every tenant. In the preview the Ready and No hours badges keep their colour, because green has to mean success no matter whose logo is on top.

Named by job, not by pixel

The grammar is --pd-{family}-{role}-{variant}. --pd-status-critical-bg is readable without the file open. --pd-red-light-2 breaks the moment the hue changes.

02Color

Dark by default. Color never works alone.

Depth comes from surface steps, not shadows, because on a dark canvas a shadow reads as a smudge. Violet is reserved for action and brand. Status colours always travel with an icon and a text label, so no meaning depends on hue alone.

Brand ramp · the only ramp a tenant replaces
Semantic tokens
TokenValueUsed for
surface-canvas#0F0F11The page. Never pure black
surface-raised#17171ACards, tables, alert rows
surface-overlay#1F1F24Modals and menus above the page
text-primary#F0EEEABody copy and figures. Warm, not white
text-secondary#9896A0Meta lines and helper text
action-primaryviolet-500The one primary action per view
action-dangerred-500Destructive actions only
surface-activeviolet-500 · 14%Selected nav item and row
Status triplets · foreground, background, border
Ready Overtime Missing bank New Recurring Intern

03Typography

One family. Numbers that line up.

Inter across the whole product, in ten steps. Most of the interface lives between 11 and 14 pixels, because HR and finance users scan dozens of rows per session. Anything above 20 is a page title or a figure meant to be read from across a desk.

Scale · size / line height / weight
Display40 / 1.15 / 700
$184,200.00
Title32 / 1.15 / 700
Finance Overview
Heading24 / 1.2 / 700
Payroll · June 2025
Subheading20 / 1.3 / 600
Review before running
Body14 / 1.55 / 400
Hourly employee · Period has no approved timesheet.
Body small13 / 1.5 / 400
34 employees · 2 alerts pending
Micro11 / 1.4 / 500
Resolved 2 min ago
Label10 / 1.3 / 700
Total payroll
Numerals · the same three amounts
Tabular, right-aligned
$8,500.00
$142,500.00
$3,200.00
Proportional, left-aligned
$8,500.00
$142,500.00
$3,200.00

Money is always tabular

Currency and counts use tabular-nums, right-aligned. The decimal points stack, so a scan down the column is enough to spot an outlier, and a changing digit never shifts the layout.

Large figures are tightened

Display and title sizes carry -0.02em tracking so a six-figure total reads as one number instead of a row of drifting digits.

04Spacing & Layout

4px base. Dense on purpose.

An 8px rhythm on a 4px base. The two smallest steps exist only for icon-to-label gaps and badge padding. Whitespace is spent separating groups, not padding individual items, because the people using this are operators, not visitors.

Spacing scale
space-24px
space-38px
row-pad11px
space-412px
space-516px
space-724px
space-832px
space-1048px
space-1164px
space-1280px

The one off-grid value. Table rows use 11px vertical padding to hold a 42px row at 13px type. It is tokenised so it cannot spread by accident.

App shell
240Sidebar, px
64Icon rail, px
56Top bar, px
24Gutter, px
12Columns
1440Content max, px
Breakpoints
390Stacked cards
768Two-up stats
1100Icon rail
1280Full sidebar
1600Content caps

Tables reflow, they never scroll sideways

Below 1100px the payroll table becomes one card per employee. Horizontal scroll would hide the status column, which is the column that blocks a run.

Never truncate amount or status

Project and role may wrap. The amount and the status are the reason the table exists, so they are always shown in full.

Radius shows nesting

Badges 3px, controls 6px, cards 12px, modals 20px. A child is always one step less round than its parent, never equal.

05Behaviour

Severity has consequences. Friction is spent once.

A problem's severity is defined by what happens if it is ignored, not by how serious it sounds. Each of the three severities maps to a different interaction, and only one action in the payroll flow earns a confirmation gate.

Alert rows · three severities, three behaviours
Pablo G. · No hours logged
Hourly employee · Period has no approved timesheet
Julián M. · Overtime detected
Logged 52h this period, 12h over standard. Confirm if intentional.
Renata L. · Bank account added
Contractor · Resolved 2 min ago
Resolved
The severity test
Would ignoring it cause an incorrect payment?Critical · blocks the run
Would ignoring it surprise someone later?Warning · acknowledge to pass
Is it merely informational?Info banner · no interruption
Confirm gate · try it: type the total to unlock
Payroll summary · June 2025
32 employees · all alerts resolved
Salaried employees (26)$142,500.00
Hourly employees (3)$21,500.00
Contractors (3)$13,000.00
Social contributions$7,200.00
Total payroll cost$184,200.00
Payroll for June 2025 is on its way
$184,200.00 to 32 employees. This is a demo, so nothing was sent.

Resolve, review, consent, receipt

Only dispatching payroll and deleting an employee record cannot be undone. Both follow the same four steps, and nothing else in the product may use that shape.

Typing is the consent

The gate input has a dashed critical border so it never feels routine. The button stays disabled until the figure matches. The escape route is "Back to review", never "Cancel", so nothing entered is lost.

Motion confirms, never decorates

Five durations from 80 to 320ms. The slowest is reserved for the payroll success state, the one place a pause is wanted. Under reduced motion every duration collapses to zero.

06Permissions

Same record. Four outcomes.

The defining pattern of PeopleDesk. Permissions apply per field, not per page, so the same employee record renders differently for each role. Which outcome a field gets is a design decision, documented so it is never left to whoever writes the query.

Viewing as
AC
Andrea C.Manager · Salaried
Viewing as: HR Admin
Leave balance Read-only
12 days available · 3 pending approval
Compensation Read-only
$8,500.00 monthly · Salaried
Performance reviews
Q1 2025 · Owned the design system migration end to end. Ready for more scope next quarter.
Visible

Rendered normally. The role owns or needs the field.

Read-only

Rendered with controls removed and a read-only label.

Withheld

Replaced by a lock note naming who can see it.

Omitted

Not rendered at all. The role should not know it exists.

Silence reads as broken

An empty panel tells a finance user the record is incomplete. A lock note tells them the data exists, who can see it, and that nothing is wrong.

Withheld or omitted is a design call

Withhold when the role may know the field exists. Omit when it may not. The consultant never learns that compensation or reviews exist on this record.

The lens is always on screen

Every record header says which role it is being viewed as. A user with more than one role should know which lens they are looking through before they act on what they see.

07Components

Seventeen components. Each one carries a rule.

Every component is documented with its anatomy, states, tier-3 tokens, accessibility notes and at least one do and don't. Variants are named by role, never by appearance: --critical, not --red.

Controls

5 components

  • Button 5 variants, loading
  • Input & form field help, error
  • Segmented control 2 to 4 options
  • Badge type vs status
  • Avatar 5 sizes

Structure & data

7 components

  • Nav item & sidebar hidden vs disabled
  • Page header
  • Stat card
  • Data table reflows to cards
  • Kanban & candidate card
  • Request row approve, reject
  • Charts 5 viz tokens

Feedback

5 components

  • Alert row 3 severities
  • Progress
  • Banner & lock note
  • Modal & confirm gate used once
  • Empty, loading & error

08In the product

Where the system shows up.

The same tokens and components, assembled. The payroll dashboard leans on tabular numerals, status badges and the resolver. The employee record is where the permission outcomes and the lens live.

PeopleDesk payroll dashboard built with the system
Payroll dashboard
PeopleDesk employee record built with the system
Employee record

09Voice

A competent colleague. Never cheerful about money.

Microcopy is part of the system, with the same do and don't treatment as a component. Name the person and the problem in the same line. Say what succeeded before what failed. No exclamation marks anywhere in the payroll domain.

ContextWriteNot
Status badgeMissing bankError
Fix actionReview timesheetClick here
SuccessPayroll for June 2025 is on its waySuccess!
PermissionVisible to HR & Owner onlyAccess denied
Partial failureThe other 31 payments went throughSome payments failed

10Principles

The rules behind the system.

Four rules settle most arguments in this product. When a component decision is contested, the earlier principle wins.

01

Severity is structural, not decorative

Every status pairs a hue with an icon and a label, and each severity maps to a different consequence. No fourth severity without a behaviour of its own.

02

Friction is spent, not spread

The product is fast everywhere except where an action cannot be undone. Adding confirmation to a reversible action devalues the gate that matters.

03

Permission is visible, not silent

When a role cannot see a field, the product says so. A user should understand that data is withheld, not wonder whether the record is incomplete.

04

Density serves the operator

Row height, type size and spacing are tuned for scanning, not comfort. Whitespace separates groups instead of padding individual items.

Deliberately left out. No light theme: the tokens are namespaced so one can be added, but a second mode would have doubled what needs maintaining. No custom icon set: Lucide outline, with reserved meanings, so the lock always means withheld by permission and never "secure".

What this page does not claim. PeopleDesk was built to be resold, so there is no adoption or reuse data behind this system yet. With a reseller shipping on it, I would track hard-coded values introduced instead of tokens, and how long a rebrand takes against the ten values it should touch.