Documentation

Build on the Patterson brand.

Link one stylesheet, read components off one global. No build step, no package manager, no framework requirement.

Getting started

The system ships as plain CSS custom properties plus a compiled React bundle. Everything below runs in a browser as-is — open an HTML file and it works.

If you only need the brand — colours, type, spacing, the icon font — link styles.css and stop there. If you want the React components too, add the bundle.

Read DESIGN.md before you build. It is the verified spec: every rule tagged V production-verified, S system convention, or C corrected. Several intuitive-seeming rules are false — see Gotchas.

Install

Two tags. Paths are relative to your page.

<!-- tokens + fonts + the official icon font -->
<link rel="stylesheet" href="styles.css">

<!-- React components (optional) -->
<script src="_ds_bundle.js"></script>

Components come off one global:

const { Button, Card, Stat, Icon, Input, Alert, Tabs } =
  window.PattersonCompaniesDesignSystem_3534f9;

The bundle expects React 18 already on the page. For a prototype, load React, ReactDOM and Babel first, then the bundle, then your script.

Inside a template folder, ds-base.js does all of this for you — it resolves the stylesheet and bundle from one base constant. Copying a template out means editing that one line.

What's in the box

PathWhat it is
styles.cssThe single entry point. Imports every token file — link this, nothing else.
tokens/fonts · icons · colors · typography · spacing · effects · base
components/13 React components in core / forms / feedback
templates/11 starting points — surfaces, decks, app shells
guidelines/Specimen cards for every foundation
integrations/Tailwind (v3 + v4), UnoCSS, shadcn/ui, Theme UI
theme.jsonMachine-readable theme; the adapters are generated from it
assets/Lockups, favicons, photography, fonts, the icon font

Tokens

211 custom properties. Every one is available the moment styles.css is linked — there is no theme provider and no JavaScript involved.

Two scales live side by side

Type and spacing each carry production-verified values alongside this system's own conventions, because the two genuinely differ. Production values describe the live Patterson sites; system values are deliberate additions that make the system more consistent and more accessible.

  • Production — the --pt-* type scale, --radius-btn (5px), --radius-field (2px), --download-shadow, --transition-prod.
  • System — the fluid --fs-* scale, --radius-pill, navy-tinted --shadow-*, --ring-focus, the tracking tokens, the 44px control floor.

Add class="pat-production" to any subtree to render the exact live scale instead of the system one.

Production name aliases

The live theme's own property names are aliased in, so markup lifted straight from production works unchanged:

--color-primary-dark-blue   → --pat-navy
--color-primary-light-blue  → --pat-sky
--color-primary-cool-grey   → --pat-gray
--primary-hover             → #315D83

Colour

#003767
#00A8E1
#147EC2
#6DCFF6
#58585B
#ECECEC

Navy #003767 carries headings, chrome and emphasis surfaces. Sky #00A8E1 is the accent — focus rings, statistics, active underlines, card stripes. White does most of the work; navy bands punctuate.

Rules that matter

  • Every heading level is navy. Production sets color: var(--color-primary-dark-blue) on h1 through h4, the eyebrow and the caption alike. Headings are never grey or near-black.
  • The tertiary set is for data only. Green #7BC24D, teal #00817D and purple #522E91 belong in charts and infographics — never as page chrome.
  • Sky is accent-scale, navy is surface-scale. Don't fill a large band with sky.
  • #AFA593 is a warm taupe and it is deliberate — the brand's one non-cool grey, used for input borders. Don't "correct" it.

Type

One family does everything: Proxima Nova, with Figtree as the loaded open fallback and Arial as the PowerPoint-safe substitute. There is no display/body split — hierarchy comes from size and weight.

Only 400 and 700 are real. The licensed Typekit kit serves exactly four faces — 400, 400 italic, 700, 700 italic. The production theme still asks for 800 on h1/h2, 600 on buttons and 500 on eyebrows, so the live sites render browser-synthesized faux bold at those weights. Treat 700 as the real bold ceiling.

The production scale

TokenMobileDesktopWeight
h12.75rem / 3rem4rem / 4.25rem800
h22.25rem / 2.5rem2.75rem / 3rem800
h31.5rem / 1.75rem2.25rem / 2.5rem400
h41.5rem / 1.75rem—400
body1.125rem / 1.5rem—400
eyebrow0.875rem / 1.375rem—500
button0.9375rem / 1.25rem—600

Note the hard drop: 800 at h1 and h2, then 400 from h3 down. Hierarchy is a size step plus a weight step, not a continuous bold ramp.

Two things people add that don't belong

  • Letter-spacing. Production declares none anywhere — not negative on display sizes, not positive on uppercase labels.
  • Uppercase sky eyebrows. The production eyebrow is navy, 14px, weight 500, sentence case. "Trusted expertise" and "Unrivaled support" appear verbatim as section eyebrows on the live sites. .pat-eyebrow--accent keeps the uppercase-sky treatment as a system option.

Shape & depth

Production is restrained. Radii are small, shadows are soft and low-alpha, and there are no gradients anywhere in the stylesheet.

TokenValueUse
--radius-field2pxInput, select, textarea
--radius-btn5pxButtons
--radius-btn-elevated6pxDownload / external buttons
--radius-lg10pxCards — the signature container radius
--radius-pill999pxSystem convention only — no pill exists in production

Elevation runs five navy-tinted steps, --shadow-xs through --shadow-xl. Cards rest at --shadow-sm and lift 3px to --shadow-lg when interactive. Focus is a 3px sky ring, --ring-focus, and it is never removed.

Motion is 120–320ms on colour, border-colour, transform and height. No bounces, no springs, no parallax, no infinite loops.


Icons

The official Patterson icon font ships with the system — 93 glyphs lifted from the production storefront pattern library, at private-use codepoints from U+E900. It replaces Lucide and every other third-party set.

<!-- plain HTML -->
<i class="pat-i pat-i-cart" aria-hidden="true"></i>

// React
<Icon name="chevron-right" size="sm" />

Because it is a font, glyphs inherit color and scale with font-size — there is no stroke to set. Production renders inline glyphs at 14px (--icon-size-sm).

The set covers navigation, commerce, documents, account and social, plus specifics no generic library has: pedigree, prescription, formulary-list, hazmat, shiponice, previouslypurchased.

Always pair a glyph with a text label or an aria-label — private-use codepoints read as nothing to a screen reader. Browse all 93 →

Spot illustrations are a separate tier

The navy-and-sky two-tone line illustrations used to head a capability card are not in the font. They live in assets/brand at 64–120px with heavy rounded strokes.


Components

Thirteen React components on one namespace. Each ships typed props, a specimen card and usage notes for agents.

GroupComponents
coreButton · IconButton · Icon · Badge · Stat · Card
formsInput · Select · Checkbox · Radio · Switch
feedbackAlert · Tabs

The interaction contract

  • Buttons are 5px with 15px/30px padding. primary is navy hovering to a lighter navy #315D83. secondary is a filled light blue #6DCFF6 with a navy label. Both are production-verified; sky, outline, ghost and onDark are system additions.
  • Fields are 2px radius with the warm taupe border, and gain the sky ring on focus.
  • Cards rest at 10px with a hairline and soft shadow; interactive cards lift 3px.
  • Stat is the signature device — an oversized sky numeral over a grey caption. Numbers are how this brand proves things.

See every component in every state →


Templates

Ten starting points in templates/. Each folder is self-contained — open its entry file, replace the content, ship.

KindTemplates
Product surfacescorporate-website · storefront · docs-site
Decksdeck · executive-deck · purpose-vision-values
Shells & pagescanvas · patterson-docs · file-manager · corporate-page

Templates are not compiled into the bundle and their JSX is loaded directly by the page, so anything in a template can call ReactDOM.createRoot at module scope safely.

To copy one into another project, change a single line:

// templates/<slug>/ds-base.js
const base = '../..';  // → point at the bound _ds/<folder>

Browse all ten with descriptions →


Framework adapters

The brand is framework-agnostic. Four adapters are generated from theme.json, so colours are the exact brand hexes rather than re-derived values.

FileStack
tailwind.cssTailwind v4 CSS-first @theme, plus .pat-btn-* component utilities
tailwind.config.jsTailwind v3 / JS preset
uno.config.jsUnoCSS theme + brand shortcuts
shadcn-theme.cssshadcn/ui semantic variables, light + navy-ground dark
theme-ui.jsTheme UI theme with variants
Editing tokens? Change tokens/*.css and theme.json together — the adapters are generated from the JSON, and drift between them is the one way this system goes wrong quietly.

Brand rules

Do

  • Anchor pages on white. White plus space is the brand; navy and sky are punctuation.
  • Set every heading navy, with no letter-spacing.
  • Keep primary-button hover inside navy — #003767 → #315D83.
  • Use small radii on controls: 5px buttons, 2px fields, 10px cards.
  • Show the 3px sky focus ring on everything focusable.
  • Render statistics at full size — proof, not decoration.
  • Use warm, authentic photography of practitioners, animals and operations.

Don't

  • Don't introduce a second typeface.
  • Don't use gradients, textures or pattern fills — the production stylesheet contains zero gradient declarations. The wave watermark is the only decorative mark.
  • Don't build glassmorphic panels or blurred backdrops beyond a sticky header.
  • Don't use emoji or unicode glyphs, ever.
  • Don't scrim photography with black — the scrim is navy at ~55%.
  • Don't add bounce, spring, parallax or decorative animation.
  • Don't crowd corporate or marketing surfaces. Density is permitted on storefront catalogues and app shells only.

Voice

"We" for Patterson, "you / your" for the customer, partnership-framed. Verb-first CTAs — "Explore solutions", "Create my account" — never "Click here". Numbers as proof. Title Case only for product and programme brands.

Questions are allowed as headings; the live sites lead with "Need technical service or equipment repair?" Keep them short and answer them immediately.


Gotchas

Twelve claims that look right and aren't. Each was checked against the production theme stylesheet.

AssumptionReality
Everything is a pillButtons 5px, fields 2px — no pill radius exists in production
Primary hovers to sky#315D83, a lighter navy
Secondary is a navy outlineA filled #6DCFF6 with a navy label
Headlines are 700 throughout800 at h1/h2, then 400 from h3 down
Body is 16px at 1.618px at 24px line-height (1.33)
Display is tracked tightNo letter-spacing in the stylesheet at all
Eyebrows are uppercase skyNavy, 14px, weight 500, sentence case
All greys are cool#AFA593 is a warm taupe, used on field borders
Shadows are navy-tintedProduction uses neutral black at 4–12% alpha
Buttons are 44px tall≈50px — 15px/30px padding on a 20px line-box
Icons are single-colour strokesSpot illustrations are navy+sky two-tone; UI glyphs come from a font
Weights 300–900 are availableOnly 400 and 700 are licensed faces

The system keeps a handful of deliberate divergences from production — the pill token, navy-tinted shadows, the sky focus ring, the 44px floor. They are labelled S throughout DESIGN.md, and the focus ring in particular is a real accessibility gain over production, which ships none.


Contributing

Adding a token

  • Add it to the right file in tokens/.
  • Mirror it in theme.json.
  • If the compiler can't infer its kind, annotate: --my-token: 4px; /* @kind spacing */

Adding a component

  • Write Name.jsx and Name.d.ts side by side in a group folder — the pair is what the compiler looks for.
  • Add it to that group's *.card.html specimen.
  • Inherit the contract: 5px radius, the sky focus ring, a 120–320ms transition, and a 44px minimum target.

Adding a template

Create templates/<slug>/ with a <!-- @template name="…" description="…" --> comment as the first line of the entry file, and a sibling ds-base.js.

Run the design-system check after any edit; fix what it reports and run it again until clean.