CRM Design Systemv1.0 · Sep 2026
Theme
Design system for CRM work surfaces

Rebrand the whole CRM by editing ten values.

Every colour, surface and state below is computed from ten brand inputs. Change the hue, the fonts and the corner radius, and the whole CRM changes with it, including contrast, hover states and dark mode.

Paste your colour as L · C · H

Convert the brand hex at oklch.com and set --brand-l / -c / -h. Ramps, neutrals, focus and dark mode follow.

Swap three font stacks

Display for titles, UI for everything you read in a table, mono for IDs, phone numbers and CIN.

Pick radius and density

One --radius-base drives every corner. --density scales controls and rows together.

How it is layered

Layer 1Brand inputs10 values. The only place a brand lives. Edit these.
Layer 2Derived scalesBrand and neutral ramps at fixed lightness steps, type, space, radius, motion. Never edit by hand.
Layer 3Semantic roles--text-2, --action, --danger-bg… Light and dark map here.
Layer 4ComponentsRead Layer 3 only, which is why a rebrand cannot break a hover state.

Try a brand

Your brand inputs
Callback requestedInterestedNo answerDNC · existing client
/
CityBengaluru

Sample values. Counts are illustrative.

Principles

Eight rules that decide arguments. Each is tied to the Law of UX it serves, so a design review can point at the law instead of at taste.

A list is a queue, not a database

Sort by what is due. Show what happened last and what happens next before any company fact.

Law · Goal-Gradient, Zeigarnik

One filled button per view

The filled button is the job. Everything else is outlined, ghost or tucked in More.

Law · Von Restorff, Hick

Scope before filter

Pick the project first, and keep it visible. Per-project fields never appear without their project.

Law · Mental model, Tesler

One word per idea

Disposition is per call, status is per record, DNC is a block. Never two words for one idea.

Law · Jakob, Similarity

Dot for state, badge for a block

States show as quiet dots. Only things that stop work (DNC, overdue) get a filled badge. Colour is never the only signal.

Law · Von Restorff, Selective attention

Data starts within 160px

Top bar, one toolbar, table header. Filters open on demand; they do not stack as permanent bands.

Law · Cognitive load, Prägnanz

Every empty state names a next step

Say which filter is hiding rows, and offer the one action that fixes it.

Law · Peak-End, Postel

Readable, reachable, quick

Text ≥12px at AA contrast, targets ≥28px, feedback within 400ms, motion 120–260ms.

Law · Fitts, Doherty

Color

Ramps sit at fixed lightness steps, so any hue you paste keeps the same contrast. Status hues are fixed on purpose: red must mean danger in every brand.

Brand ramp

Neutral ramp (tinted with the brand hue)

Semantic roles

TokenUse it forContrast on surface

Status

InterestedVerifiedsuccess · hue 155
No answerDue todaywarning · hue 70
Not interestedDNCdanger · hue 28
Callback requestedNewinfo · follows brand

Data visualisation

ConnectedCallbackNo answerMeeting setNot interestedWrong number
Six categorical hues at equal lightness, so no series looks more important than another. Bar heights are illustrative.

Typography

Display face for titles only. A UI face built for tables and numbers for everything you read. Mono for identifiers people copy. Nothing below 12px except uppercase overlines.

Space, shape, motion

A 4px grid, one radius dial, three shadows that mean three heights, and motion that confirms rather than decorates.

Space

Radius

sm
md
lg
xl
pill

Motion (hover each)

Elevation

shadow-1Resting surfaces, the pressed segment. Barely there.
shadow-2Menus, popovers, the preview panel, toasts.
shadow-3Dialogs only. If two things float at once, one is wrong.

Chrome budget

Hybrid mockup, all lines open
Top bar 64Toolbar 38Views 34Filters 34Selection 34Header 40
244px
This system
Top bar 56Toolbar 48Header 40
144px

Active filters live as chips inside the toolbar. The selection bar replaces the toolbar while rows are selected, so it never adds height.

Icons

One family, 24px grid, 1.75 stroke, drawn at 16px beside text. Icons label actions; they never replace a word the user needs to read. No emoji, no Unicode glyphs.

Components

Every state is shown side by side. Hover moves the background, never dims the text. Focus is always visible.

Buttons

RestHoverFocusDisabled Primary Secondary Soft Ghost Danger
Columns C
Primary = the one job of the view. Soft = a frequent secondary action on a record. Danger is outlined until the confirm dialog.

Inputs

As registered. Domain is matched separately.
/
Accepts any of the three.
Per project · HungerBox
Add the domain, e.g. licious.in
Only admins can edit CIN.

Navigation

Tabs switch content inside one record.
Segmented control switches how the same rows are shown.

Chips, status, badges, people

CityBengaluru, PuneOwnerMe
Callback requestedInterestedNo answerNot interestedNot called yet
DNC · existing clientOverdue 2dAccurateUnverifiedWrong
PRHBLIZOPeople are round, companies are square — you can tell a person from a company before reading.

Overlays and feedback

Menu · destructive items last, after a divider.
Call logged · Callback on Fri
Open record ↵ Toast confirms and offers undo. Tooltips carry the shortcut.
Skeleton keeps the layout still while data loads.
Mark Razorpay as do-not-call?

Nobody on HungerBox can call its 6 contacts until you lift it. Other projects are not affected.

No companies match

Two things are hiding them: City · Pune and Owner · Me.

CRM patterns

Components assembled into the pieces every list and record reuses. This is the grammar the Companies module will be built from.

List toolbar: one line, five zones

/
ScopeProject. Always visible, always first.
FindOne search, three kinds of key.
ViewsThree at most. Counts beside them.
ShapeFilters, columns, more — quiet.
ActThe one filled button.

Work-first table

CompanyLast outcomeNext stepReachableOwner

Sample data for the specimen only. Company facts (industry · city · size) collapse into one line under the name. Blocked rows stay visible but cannot be called.

Contact channel with verification

+91 98••• ••210Accurate
pri•••@licious.inUnverified
Numbers in mono so digits line up. Masked by default, revealed on purpose. One verification mark follows the channel everywhere it appears.

Do and don't

Most of the "looks old" feeling came from these. Hold every screen to them.

  • Read colour only from Layer 3 roles in components.
  • Show status as a dot plus a word; the word carries the meaning.
  • Put the next step in the row; hide rarely used actions in More.
  • Right-align and tabular-align every number column.
  • Show the project scope on every screen with per-project data.
  • No raw hex in components, no second accent colour.
  • No filled pills for every status; five colours in one row is noise.
  • No actions that only appear on hover for the primary job.
  • No text under 12px, no grey that fails 4.5:1, no emoji as icons.
  • No permanent filter bands stacked above the table.

Copy the file

One stylesheet: tokens and components. Paste it into any project, wrap the app in class="ds", then edit Layer 1. Set data-theme="dark" on any ancestor for dark mode.

crm-design-system.css Download
Copied