Surfe
RGonline

Design system · Foundation v0.1

Precise enough for data. Human enough for decisions.

Current evolves Wave into a quieter, denser system for Surfe’s GTM intelligence platform—built for context, confidence, and momentum.

01

Intent stays visible

Prompts resolve into inspectable filters, fields, and actions.

02

Density without noise

Compact GTM data is structured through rhythm, not decoration.

03

Confidence by design

Source, freshness, cost, and progress sit beside the decision.

Foundations / Color

Brand energy, used with restraint

Wave’s petrol, blue, orange, and purple remain recognizably Surfe. Semantic roles keep saturated colors meaningful in a data-dense product.

Blue

Brand, actions, focus and data

50

#EFFBFE

100

#EBFAFE

200

#D1F2FD

400

#88D7F0

500

#73C7E1

600

#1798C1

650

#0F82A7

700

#387082

800

#073742

900

#08272E

Grey

Canvas, hierarchy and borders

50

#FAFAFA

100

#F4F5F6

150

#EBEFF0

200

#E0E5E6

300

#C1CACD

400

#889BA0

450

#5C818A

500

#5A6C71

600

#49575B

700

#3A4446

800

#22282A

900

#15191A

Semantic

Feedback, AI and brand warmth

Green 100

#ECFBF3

Green 500

#00BD9D

Green 600

#068570

Orange 100

#FEEFE6

Orange 500

#FFB554

Orange 600

#E5661E

Orange 700 · warning

#B4470F

Purple 100

#EFE7FF

Purple 500

#AF8AF5

Purple 600

#7A5AB8

Pink 100

#FFF1FC

Pink 500

#FC84E1

Pink 600

#D160B7

Red 100

#FFEBEE

Red 500

#F26379

Red 600

#D64D62

Yellow 100 · accent only

#F8FABB

Yellow 500 · accent only

#EBD619

Yellow 700 · accent only

#7D720E

Foundations / Typography

One family, deliberate hierarchy

Inter keeps parity with Wave while a compact product scale, tabular numerals, and tighter headings improve analytical scanning.

Display36 / 40The clearest path to your next customer
Title24 / 32Companies showing buying intent
Heading16 / 24Enrichment coverage
Body14 / 20Review the fields Surfe will enrich before using credits.
Label12 / 16WORK EMAIL · VERIFIED
Micro11 / 16UPDATED 4 MIN AGO

Foundations / Scale

A complete, predictable spatial system

A 4px base supports compact controls and spacious compositions. Named control and panel sizes prevent one-off dimensions.

Spacing · 4px base

14px
28px
312px
416px
624px
832px
1248px
1664px

Radius & elevation

6px
10px
16px
Hairline surface
Tray · secondary affordances

Radius scales with the box: small radii express precision, large radii belong to panels and major compositions. Depth is a hairline plus a background step — a tray tucks behind its surface instead of earning a border, and the single shadow tier is reserved for layers that float above the page.

Hierarchy & rhythm

Category title

Sits on the canvas, never inside the card.

Row label

Supporting line

Row label

Supporting line

  • The card is the category. One card holds one category, and its edge is the only grouping device. A row inside it never repeats the category’s weight.
  • Three tiers. Page title 24px semibold, category title 16px semibold on the canvas, row label 14px medium in the card. Each tier is a size step and a weight step from the next, so no rule or indent is needed to read the structure.
  • Space carries the grouping. 48px between categories, 12px from a title to its card, and rows at 64px. A title is always closer to its own card than to the category above it.
  • Warning is orange. Yellow is a brand accent and never a state: warnings, scheduled changes and amber meters all read from `--warning`.

Foundations / Motion

Weight, not decoration

Arrivals ease out, departures ease in fast, things the user throws get a touch of spring. Frequent actions do not animate. Reduced motion keeps the information and drops the travel.

Durations

  • --motion-instant0msKeyboard-driven changes, command palette
  • --motion-fast100msHover tints, pressed states, tooltips, checks
  • --motion-base160msPopovers, menus, tab indicator, toasts
  • --motion-slow240msDialogs, drawers, row reorder
  • --motion-deliberate400msValue arrival glow, number count-up
  • --motion-celebrate600msMilestones only

Easings

Click a row to run it at the deliberate duration.

Signature interaction · value arrival

Work email

Shimmer while pending, then a crossfade with an accent glow that decays over 1.2s. The button keeps its width and label while loading.

Controls · spring on the things you throw

Check pops with the snappy spring, the switch thumb travels with the soft spring. The button press lands instantly, half a pixel down with a tint, and only the release lifts over 100ms. No spring: frequent actions get feedback, not motion.

Foundations / Appearance

Things come from somewhere

Nothing appears at full size from nowhere. Popovers scale from their trigger, drawers slide from their edge, lists reveal once at 20ms per item and never again. Everything here is a token — no animation library runs on the hot path.

Arrival animations

fade-in

base · 160ms

Page and region crossfades. No travel, no scale.

scale-in

base · 160ms

Popovers and menus, growing from the trigger’s side at 0.96.

rise-in

slow · 240ms

Cards and rows on first paint. 6px of travel, never more.

pop-in

base · snappy

A badge or count that changes, with the snappy spring.

slide-in-right

slow · 240ms

Drawers and rails, travelling from their own edge.

slide-in-bottom

slow · 240ms

Sheets on narrow viewports, and the proposal card.

Every arrival eases out; every departure eases in one duration token faster. Scale never starts below 0.96 for overlays or 0.9 for a badge, and slides travel 4–8px — except drawers, which travel their own width.

Stagger · first paint only

Amelia Morgan
Amelia MorganEmail known
Jonas Lee
Jonas LeeEmail known
Sarah Okafor
Sarah OkaforEmail known
Nils Carlsen
Nils CarlsenEmail known

20ms per item, capped at six, and only the first time a list paints. Never on reorder, never on filter — a list that re-staggers on every keystroke reads as slow, not as alive.

Ongoing animations

shimmer · skeletons

breathe · the assistant is thinking

glow-decay · an enriched value lands

amelia@northwind.io

Shimmer says a placeholder is waiting. Breathe says one thing is thinking — one dot, at the deliberate cadence, never a row of bouncing dots. The glow decays over 1.2s so the eye finds what changed in a 10,000-row grid.

Celebration · rare by design

A ripple in the accent colour, once per milestone, then a static check and one line of warm copy. Four moments qualify: first list saved, the first enrichment that finds a missing email, a bulk run over 100 rows finishing clean, and credits topped up. No confetti, no sound, no modal.

Foundations / Loading

A skeleton per kind of thing

A skeleton is not a grey box. It is a stand-in for one specific element at that element's exact size, so content lands without a shift and the shape tells the reader what is coming. Flip the switch: nothing below should move between the two states.

The eight variants

  • text

    A line of body copy

  • heading

    A title line

  • circle

    Person avatar, icon button, status dot

  • rect

    Company logo, thumbnail, media box

  • block

    A card body, a chart, a map

  • chip

    Badge or filter chip

  • control

    Button or input, keeping the toolbar height

  • cell

    Inside a data cell

Each one carries the geometry of what it replaces: text is a cap-height line, circle is a person, rect is a logo, control keeps a button's 32px so a toolbar never reflows. Nothing here is a rectangle by accident.

List rows

Loading people

SkeletonListRow reads the same --density-row as ListRow, so a list of placeholders is exactly as tall as the list that replaces it. Media, description and meta are opt-in per surface.

Key–value pairs

Loading record

The term line is short and lighter, the value line is long. A panel of these reads as a record before a single value has arrived.

Table rows

PersonCompanyStaff

DataTableSkeleton takes one width per column, so the header never jumps sideways when the body fills. The header, toolbar and footer stay live the whole time — a full-page skeleton for a shell the user already saw is a failure.

Toolbars

Loading filters

Controls hold their height so the surface below never slides up. The search field, the filter chips and the trailing action each keep their own footprint.

Cards and panels

Loading profile

A card skeleton mirrors its own anatomy: identity header, body copy, footer actions. It is built from the same slots as the card it replaces, which is why the two line up.

Charts and long copy

Loading usage

Bar heights are fixed, never random, so the placeholder never implies a shape the data does not have — and so the server and the client render the same thing. Paragraph skeletons end on a short line, the way real text does.

Rules that make them work

  • Show nothing below 200ms — a flash of skeleton reads slower than a blank.
  • Once shown, hold for at least 300ms so it cannot flicker.
  • Match the final layout exactly, then crossfade. Nothing jumps.
  • Never skeleton a shell the user has already seen — refetch behind a hairline progress bar instead.
  • One SkeletonRegion announces the wait once; the boxes themselves are aria-hidden.
  • Fixed dimensions only, never randomised widths: the server and client must agree.
  • Shimmer, not pulse — and under reduced motion the wave stops while the shape stays.
  • A busy control gets a Spinner. A loading region gets a skeleton. Never the reverse.

Break any one of these and the skeleton reads slower than a blank space.

Avatars

People stay round, companies stay square, at all four sizes — so even the placeholder says which kind of record is arriving.

Primitives / Actions

Every state a control can be in

Six variants and four sizes, then the states that decide whether a control is trustworthy: loading keeps its width, disabled keeps its shape, and pressed lands in the same frame as the click.

Variants

Petrol is the one primary. Brand blue carries progressive actions, soft and ghost carry utilities. Two primaries in one region is a review failure.

Sizes

24 / 28 / 32 / 40px, from inside a cell to a hero action. Icons scale with the control: 14 / 16 / 16 / 20px.

States

Rest / hover
Hover is a tint. Never a lift, never a shadow change.
Loading
Disabled
Pair with a reason in a tooltip; a dead button explains nothing.
Pressed

Loading swaps the leading icon for a spinner, keeps the label and the width, sets aria-busy and blocks re-entry. It never shrinks to a bare spinner.

Icon-only and groups

An IconButton always carries a label: it becomes the aria-label and the tooltip. ButtonGroup attaches related actions; the split button is a group whose second child opens a menu.

Links

Amelia was added from UK RevOps leaders four days ago.

Standalone links look like actions, inline links stay underlined inside a sentence, and external links carry the arrow plus rel=noreferrer.

Keyboard hints

Command paletteCtrlKUndoCtrlZShortcuts?

Shortcuts are visible where the action is: in menus, in icon-button tooltips, and in the ? dialog. The modifier glyph resolves per platform at render, never hard-coded.

Primitives / Forms

Fields that prevent the error

A Field owns the label, the description, the error and the control's ids, so a control is never labelled by placeholder text. Invalid state travels up from the input through has-* — nothing passes an isInvalid boolean around.

Input · sizes and states

sm / md / lg
Slots
Loading
Invalid
Read-only
Ghost / inline

Placeholder text never replaces a label. Read-only is muted but selectable; disabled is not. The loading spinner sits in the trailing slot so the field keeps its width.

Search and numbers

/

Reported value:

staff

Employee range · 50500

Search echoes the keystroke immediately and reports the value 150ms later; Esc clears. Number fields format on blur, and arrows step — Shift steps by ten.

Field anatomy

Shown in the sidebar and in the assistant’s context.

Label, description, control, error. The error replaces nothing — it is added below, so the layout does not jump when validation runs.

Selection

Start the list from

Select-all is a parent checkbox with a real indeterminate bar, not a dimmed check. Radio cards carry a description, so a choice is made once.

Long-form and actions

The textarea grows with its content through field-sizing, capped before it swallows the dialog. FormActions fixes placement: destructive far left, confirm always last on the right.

Primitives / Display

Everything that shows a value

Text and Heading keep the ramp finite. Badge, Chip and StatusDot share one tone set, and every one of them pairs colour with a word or a glyph, so status survives a colour-blind reader and a greyscale print.

Text and Heading

Companies showing buying intent

Enrichment coverage

Work email

Body · the reading size in panels and forms.

Muted · secondary lines and metadata.

Subtle · the quietest tier, for timestamps.

Updated 4 min ago

12,340 rows · 1,284 credits

Truncation · Northwind Analytics International Holdings and Subsidiaries Limited

Clamp · Amelia owns the RevOps tooling budget for EMEA and has been evaluating replacements for their current enrichment vendor since the start of the quarter.

Visual level is decoupled from the semantic tag: a card title can be an h3 that looks 14px. Numbers get tabular figures so columns of them align.

Badge · variant × tone

soft
neutralinfoaccentsuccesswarningdangerai
solid
neutralinfoaccentsuccesswarningdangerai
outline
neutralinfoaccentsuccesswarningdangerai
With glyph
Verified SuggestedCatch-all1 credit99+

Soft is the default in dense surfaces, solid is for a single emphatic state, outline is for a badge sitting on a tinted background. Counts cap at 99+ so a badge never resizes its parent.

Chip

Filter chips read field · operator · value and open their editor on click. Backspace removes from the keyboard; the × removes from the pointer. Long values truncate rather than wrap the bar to a third line.

Identity

Amelia Morgan
Jonas Lee
Sarah Okaforonline
Nils Carlsenoffline
Northwind
Broken Logo Co
Amelia Morgan
Jonas Lee
Sarah Okafor
Nils Carlsen
+2
Loading

People are round, companies are square — the shape is the type. The tint is derived from the record id, so the same person keeps the same colour on every surface. A failed logo falls back to a monogram without shifting the row.

Status, progress and credit pools

Verified VerifiedCatch-all Catch-allEnriching EnrichingFailed Failed
Email credits820 of 1,000
x
Phone credits34 of 250
x
Export credits0 of 500
x

All pools

854 of 1750: Email 820, Phone 34, Export 0
Enriching 240 rows
x

A meter changes tone at 20% and again at empty, so a low balance is seen before it is read. Progress only ever moves forward.

Loading and iconography

Finding matches…

Skeletons match the final layout exactly and shimmer rather than pulse. Spinners belong on controls, never in place of a region skeleton. Icons come through Icon at 14/16/20/24 with stroke 1.75.

Description list · the honesty ladder

Work email
amelia@northwind.io
Mobile phone
LinkedIn
EnrichingEnriching
Direct dial
CRM status
Couldn’t fetch

Every value states which of the five statuses it is in. Missing offers the enrich affordance with its cost, unavailable explains why in a popover, failed offers retry. A blank cell is never acceptable.

Primitives / Feedback

Say what happened, what it means, and what to do

Empty states name what will be here and offer the first step. Errors never blame the user and never lead with a status code. One alert per region — a stack of banners is a design failure, not an information architecture.

Empty · page

No lists yet

Start from a search, a prompt, or a blank list. Whatever you build stays yours.

The wave motif appears only here and at milestones: brand gradient at low opacity, never a character.

Empty · panel and cell

No people match these filters

Seniority VP+ in the United Kingdom returns nothing at this company size.

Nothing here yet

The no-results variant offers the action that would widen the search, not a shrug. In a cell there is no illustration and no button.

Error · retryable and terminal

Three sentences maximum. The correlation id is there for a support conversation, small and out of the way.

Inline alert

118 email credits left

This enrichment needs 240. Enrich only the missing 118, or top up first.
See usage
Found 21 emails. 3 couldn’t be verified.
We assumed EMEA means the EU plus the UK, Switzerland and Norway.

Viewer access

You can read this list and export it. Enrichment needs an editor seat.

Only the danger tone announces itself to assistive tech. Dismissal is the user’s call — an alert never times out on its own.

Primitives / Overlays

Modals, menus and everything that floats

Things come from somewhere: a popover scales from its trigger, a sheet slides from its edge, a dialog fades and scales from 0.98. Menus opened by keyboard do not animate at all — the frequency law is a speed rule as much as a taste rule.

Dialog · a decision

Backdrop dims to 40% and blurs slightly; the page behind is inert and cannot scroll. Focus starts on the first field and returns to the trigger on close. A dialog never opens another dialog.

Alert dialog · the irreversible

Reversible actions run immediately and offer undo for five seconds. Confirm is only for bulk delete, credit spend above a threshold, and leaving unsaved work.

Confirmation is reserved for what undo cannot fix. Initial focus is on Cancel, and above 50 rows the confirm needs the list name typed. Everything reversible skips this and gets an undo toast instead.

Sheet · work, not a decision

A sheet that holds work is non-modal and does not dim the page; one that holds a decision is modal. Both slide from their own edge over 240ms and leave over 160ms.

Menus

Right-click this row

Destructive items sit last, after a separator, and take the danger tone only on hover and focus. Shortcuts are visible in the menu, not learned elsewhere.

Tooltip, popover, preview card

A tooltip waits 400ms, then siblings open instantly. A preview card waits 300ms and is never modal. A popover closes on outside click, on Esc, and when its trigger scrolls away.

Command palette

Command Palette

Search for a command to run...

The palette is always one chord away, and it never animates: it is the most frequent action in the product, so it shows and filters instantly.

Disclosure

Identity, contact data and provenance.

Work email, mobile, LinkedIn. Section-level “Enrich missing” sits in the header with its credit cost.

Tabs switch peer views: the indicator slides, the content swaps instantly. Accordion and collapsible heights interpolate to auto, so a section can grow without a measured pixel value.

Data / Tables and lists

The table under real pressure

Row height, cell padding and control gaps all read from --density-*, so one attribute moves the whole surface. Selection tints instantly, hover is a tint and never a lift, and every one of the four body states preserves the column widths so content lands without a shift.

1 selected
PersonCompanyWork emailFitActions
Nils Carlsen
Nils CarlsenChief Revenue Officer
Vandelay Industrial Manufacturing and Logistics International Group
Vandelay Industrial Manufacturing and Logistics International Group
Couldn’t fetch8,400Low
Jonas Lee
Jonas LeeDirector of Revenue
Halyard
Halyard
1,280High
Amelia Morgan
Amelia MorganVP Revenue Operations
Northwind Analytics
Northwind Analytics
amelia@northwind.io420High
Sarah Okafor
Sarah OkaforHead of Go-To-Market
Census
Census
EnrichingEnriching96Medium
1–4 of 12,340

Column stress

  • Person · auto width, truncate with tooltip
  • Company · auto width, truncate with tooltip
  • Work email · auto width, truncate with tooltip
  • Employees · fixed width, right-aligned, tabular
  • Fit · fixed width, badge from a colour map plus a word

A 200-character company name truncates rather than widening the column. Numbers are right-aligned with tabular figures so the digits line up down the column. Actions appear on hover and on focus — never hover alone, or a keyboard user cannot reach them. Current density: compact.

Stacked list

Pinned

Q4 targets
Q4 targetsPeople · 340 rows · 82% emails known2h ago
UK RevOps
UK RevOps leadersPeople · 128 rows · 61% emails knownYesterday

All lists

Series B fintech, EMEACompanies · 96 rows3d ago
Churn risk accountsCompanies · 41 rowsLast week

The same row shape as the picker, the feed and the sidebar's saved lists. Group headers stick while their group scrolls. Past 100 items this is the seam where virtualisation goes in.

Primitives / Action

Buttons

Geometry communicates purpose: standard for dense controls, pill for named actions, and circle for icon utilities. Petrol anchors priority while Surfe blue adds energy to progressive actions.

Action hierarchy

Utility controls

Size × shape

Primitives / Input

Inputs and filters

Quiet at rest, unmistakable in focus. Labels carry meaning; placeholder text never replaces instructions.

Used for enrichment previews only.

⌘K

Primitives / Status

Badges and identity

Status color is always paired with language. Avatars stay calm and readable inside dense surfaces.

Semantic badges

DraftEnriched Suggested Verified12 creditsUnavailable

Identity

AMonline
LK
SOoffline
JM
NC
+8

Primitives / Navigation

Tabs

Tabs switch peer views, not sequential steps. The active state remains legible without a heavy container.

Patterns / Enrichment

Context before action

Identity, available data, provenance, and credit impact live in one inspectable decision surface.

AMonline

Amelia Morgan

Match

VP Revenue Operations · Northstar Labs

Work email

amelia@northstarlabs.com

Company size

201–500 employees

Location

London, United Kingdom

CRM status

Not in HubSpot

Estimated · 3 credits

Surfe assistant

Working with this profile

AI
Amelia fits your UK RevOps leaders audience. Want me to add her and find similar profiles?

Patterns / Data

A list row under real pressure

Column rhythm, selection, provenance, enrichment, and actions are tested together at realistic density.

248 people
PersonCompanyWork emailFitActions
AM

Amelia Morgan

VP RevOps

Northstar Labsamelia@northstar.ioHigh
JL

Jonas Lee

Revenue Director

AmplitudeHigh
SO

Sarah Okafor

Head of GTM

Censussarah@census.comMedium

Surfe Current · working product design system

Tokens → Primitives → Patterns → Compositions