Atoms thatsadam Design System

thats adam
Basic Building Blocks

The smallest functional units of the interface — indivisible elements that cannot be broken down further without losing their meaning. Buttons, type styles, labels, dividers. Everything else is built from these.

Buttons

Five variants mapped from Figma. All share the .btn base class. Hover transitions via the secondary-hover token. Active/pressed states use the blue glow token.

.btn-primary

Filled yellow. Single most important CTA per viewport. Limit to one visible at a time.

Default
Hover
Active
Disabled
.btn-secondary

Transparent with yellow border. Paired with primary where two CTAs are needed.

Default
Hover
Active
Disabled
.btn-ghost

Black weight, no border. Nav-adjacent or inline link contexts.

Default
Hover
Active
.btn-text

Regular weight. Nav links. Add .btn-text--active for current page state.

Default
Hover
Active page
.btn-large-text

Extralight 200. Exclusively for the hero audience selector — dramatic weight contrast is the point.

Default
Hover
Active
<button class="btn btn-primary">Get in touch</button>
<button class="btn btn-secondary">View work</button>
<a href="#" class="btn btn-ghost">Read more</a>
<a href="#" class="btn btn-text">Work</a>
<a href="#" class="btn btn-text btn-text--active">About</a>
<button class="btn btn-large-text btn-large-text--active">Designer</button>
Button hover/active text
var(--text-on-dark-btn)Primary button hover & active text — black (#000000), paired with --surface-branding-secondary-hover and --color-active-glow yellow/blue backgrounds
Do

Use exactly one .btn-primary per viewport. Pair with .btn-secondary for a secondary action.

Don't

Never place two .btn-primary buttons side by side — it dilutes hierarchy and confuses intent.

Typography Utilities

Utility classes that express the type system. Semantic level (h1–h6) and visual level are decoupled — you can use .heading-xxxl on a <p> tag.

label-s · 12px semibold uppercase +2px tracking

label-m · 16px semibold uppercase +4px tracking

label-xl · 24px semibold uppercase +6px tracking

body-m — Regular 16px · line-height 24px · tertiary colour. Used for descriptions and supporting copy throughout the site.

body-l — Regular 20px · line-height 32px. Intro paragraphs and pull-out descriptions.

heading-m · Black 32px

heading-xl · Black 48px

heading-xxl · Black 56px

Utility class reference
.label-s12px · fw-semibold · uppercase · ls-label-s · secondary colour
.label-m16px · fw-semibold · uppercase · ls-label-m · secondary colour
.label-xl24px · fw-semibold · uppercase · ls-label-xl · secondary colour
.body-m16px · fw-regular · lh-xs · tertiary colour
.body-l20px · fw-regular · lh-s · tertiary colour
.heading-m32px · fw-black · lh-m · primary colour
.heading-xl48px · fw-black · lh-xl · primary colour
.heading-xxl56px · fw-black · lh-xxl · primary colour (responsive)
.heading-xxxl96px · fw-black · lh-xxxl · primary colour (responsive)
<p class="label-m">Case study</p>
<h2 class="heading-xl">Designing for complexity</h2>
<p class="body-l">Intro paragraph in large body copy.</p>
<p class="body-m">Supporting copy in regular body size.</p>

<!-- Visual level is independent of the tag -->
<p class="heading-xxxl">Hero</p>

Labels & Chips

Rounded tags used for insight chips and metadata. border-radius: 12px (a rounded square, so wrapped multi-line text still reads well) with a primary-30 border.

  • Research insight
  • Navigation patterns
  • Mobile-first
<ul class="ui-entry__chips" aria-label="Key insights">
  <li class="ui-entry__chip">Research insight</li>
  <li class="ui-entry__chip">Navigation patterns</li>
  <li class="ui-entry__chip">Mobile-first</li>
</ul>

Dividers

1px horizontal rules using --surface-branding-primary-30. Used between list entries, section blocks, and accordion items.

.divider

<div class="divider"></div>

Filter Tabs

Single tab within a Filter Bar. Three states — idle (grey), hover (white), active (white + blue ::after underline via scaleX(0→1)). Class: .work-filter-tab / .work-filter-tab--active.

Idle
Hover
Active
Spec
class.work-filter-tab · .work-filter-tab--active
paddingvar(--space-xs) var(--space-m) — 8px 16px
fontInter · var(--fw-regular) · var(--text-m) 16px
idle colourvar(--text-on-dark-tertiary) — grey
hover colourvar(--text-on-dark-primary) — white
active colourvar(--text-on-dark-primary) + blue ::after underline (height:2px, scaleX 0→1 from left)
::after underlineposition:absolute · bottom:-2px · left/right: var(--space-m) · height:2px · background:var(--color-active-glow)
<button class="work-filter-tab work-filter-tab--active" data-filter="all" role="tab" aria-selected="true">All projects</button>
<button class="work-filter-tab" data-filter="ux-design" role="tab" aria-selected="false">UX Design</button>

Number Circle

106×106px circular badge used as a fallback when no step image is uploaded in the Flow block. 1px yellow border, no fill. Number is zero-padded in PHP.

01
02
03
<div class="acf-flow__img-wrap acf-flow__img-wrap--number" aria-hidden="true">
  <span class="acf-flow__number">01</span>
</div>

Section Header

Pink uppercase label stacked above a black-weight heading. Used at the top of every ACF block that has a titled section. Two size combinations.

Small — Subheading S + Heading M

Research findings

User needs drive every decision

Large — Subheading M + Heading XL

Case study

Designing for complexity

Spec
Labelvar(--text-xs/m) · var(--fw-semibold) · uppercase · var(--text-on-dark-secondary) · tracking var(--ls-label-m)
Headingvar(--text-2xl/3xl) · var(--fw-black) · var(--text-on-dark-primary)
Gap (small)var(--space-m) — 16px
Gap (large)var(--space-1xl) — 40px
<!-- Content blocks (small) -->
<div class="acf-text-block__header">
  <p class="acf-block__label">Research findings</p>
  <h2 class="acf-block__heading">User needs drive every decision</h2>
</div>

<!-- Page sections (large) -->
<p class="label-m">Case study</p>
<h2 class="heading-xl">Designing for complexity</h2>

Icons

Three inline SVG icons used across the system. Always rendered as inline SVG — never <img> — to prevent distortion. Thumb-down is thumb-up with transform: scaleY(-1).

thumb_up
thumb_down
Bio icon bio
Spec
thumb_up / thumb_down44×44px · fill: currentColor (red via parent) · thumb_down uses transform:scaleY(-1)
bio44×55px · inline SVG (source file: assets/icon-bio.svg) · fill: currentColor
colourvar(--surface-branding-primary) on parent
<!-- thumb_up (inline SVG, inherits colour) -->
<svg class="prs-li__thumb" viewBox="0 0 40.9603 35.5369" width="44" height="44" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
  <path d="M22.22 0.813556L12.0633 10.9702C11.385 11.6486 11 12.5836 11 13.5552V31.8702C11 33.8869 12.65 35.5369 14.6667 35.5369H31.1667C32.6333 35.5369 33.9533 34.6569 34.54 33.3186L40.5167 19.3669C42.0567 15.7369 39.3983 11.7036 35.4567 11.7036H25.0983L26.84 3.30689C27.0233 2.39022 26.7483 1.45522 26.0883 0.795223C25.0067 -0.26811 23.2833 -0.26811 22.22 0.813556ZM3.66667 35.5369C5.68333 35.5369 7.33333 33.8869 7.33333 31.8702V17.2036C7.33333 15.1869 5.68333 13.5369 3.66667 13.5369C1.65 13.5369 0 15.1869 0 17.2036V31.8702C0 33.8869 1.65 35.5369 3.66667 35.5369Z" fill="currentColor"/>
</svg>

<!-- thumb_down: same SVG plus a modifier class -->
<svg class="prs-li__thumb prs-li__thumb--down" …>…</svg>

<!-- bio (inline SVG, inherits colour) -->
<svg class="prs-li__img--bio" viewBox="0 0 44 55" width="44" height="55" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
  <path d="M40.333 0C42.3581 0 44 1.64195 44 3.66699V51.333 …" fill="currentColor"/>
</svg>

List Item

Icon + text pair used in persona bios. 44px icon column, 24px gap, text column with bold label prefix + regular body.

Interests: Startups, SaaS, scale-up culture, impact metrics

Frustrations: Designers who can't communicate trade-offs

Spec
layoutflex row · align-items:center · gap: 24px (var(--space-l))
icon col44px wide · flex-shrink:0 · red via currentColor
text16px · var(--fw-regular) · var(--text-on-dark-tertiary) · bold prefix in var(--fw-black)
<div class="prs-li">
  <div class="prs-li__icon" aria-hidden="true">
    <svg class="prs-li__thumb" viewBox="0 0 40.9603 35.5369" width="44" height="44" fill="none">…</svg>
  </div>
  <p class="prs-li__text"><strong>Interests:</strong> Startups, SaaS, scale-up culture, impact metrics</p>
</div>

<!-- Frustrations use the flipped thumb -->
<div class="prs-li">
  <div class="prs-li__icon" aria-hidden="true">
    <svg class="prs-li__thumb prs-li__thumb--down" …>…</svg>
  </div>
  <p class="prs-li__text"><strong>Frustrations:</strong> Designers who can't communicate trade-offs</p>
</div>

Input (base)

Bare input atom. Bottom border only — no surrounding box. Four states. Used inside the Input Field molecule which adds a label and helper text.

Idle
Focus (blue)
Success
Error
Spec
height69px
fontRoboto · var(--fw-regular) · var(--text-l) 20px
borderbottom only · idle: var(--surface-branding-primary-30) · focus: var(--color-active-glow) 2px · success: #63eb47 (dark) / #1a7a0f (light) · error: #ff3344
radius0 — no rounding
<input class="contact-form__input" type="email" id="contact_email" name="contact_email"
       required autocomplete="email" placeholder="your@email.com">

Preview Image

Thumbnail used in project cards. Two aspect ratios. Hover shows a black shadow and a "View project" button overlay. Focus shows a 4px blue border.

Idle — 1:1
Image
Hover
ImageView project
Focus
Image
1:2 crop
1:2
Spec
border-radiusvar(--radius-xs) — 8px
hoverfilter: drop-shadow(0 0 30px var(--shadow-glow)) + "View project" btn overlay
focus4px solid var(--surface-branding-primary) border
aspect ratios1:1 (square) or 1:2 (portrait)
<a href="/work/spotted/" class="project-card__image-link" tabindex="-1" aria-hidden="true">
  <div class="project-card__image">
    <img src="spotted.jpg" alt="Spotted app screens" loading="lazy" class="project-card__img">
  </div>
</a>

Mock Up Screen

Phone-frame mockup at 208×438.63px. Black shadow via drop-shadow filter. Used in the Screen Mockups block — images must be PNG with transparent background for the shadow to work.

Screen
Screen
Spec
size208 × 438.63px (production) — scaled 75% here for display
border-radiusvar(--radius-m) — 16px
glowfilter: drop-shadow(0 0 30px var(--shadow-glow))
image requirementPNG with transparent background — glow bleeds correctly
<div class="acf-screen-mockups__item" style="width:198px;">
  <div class="acf-screen-mockups__mockup">
    <img src="screen-dashboard.png" alt="Dashboard view" style="aspect-ratio:432/911;" loading="lazy">
  </div>
  <p class="acf-screen-mockups__caption">Dashboard view</p>
</div>

Client Grid

"Selected Clients" showcase row. Client names at 50% opacity — present but not prominent. Large black-weight type makes the brand names readable at a glance.

Selected Clients

Accenture Novo Nordisk Maersk LEGO
Spec
label.label-m — "Selected Clients"
namesvar(--text-2xl) 32px · var(--fw-black) · var(--text-on-dark-primary) · opacity: 0.5
layoutflex row · gap: var(--space-2xl) 64px · flex-wrap
paddingpadding-block: var(--space-4xl) 96px
<section class="about-clients container">
  <p class="label-m about-clients__label">Selected Clients</p>
  <div class="about-clients__list">
    <span class="about-clients__name">Accenture</span>
    <span class="about-clients__name">Novo Nordisk</span>
    <span class="about-clients__name">Maersk</span>
    <span class="about-clients__name">LEGO</span>
  </div>
</section>