Design Book

v1.9 — Tarbert

This document defines the shared design language for GTV, the JACB Services helpdesk app, and any future projects. It follows GOV.UK Design System structure and principles, with tokens adapted to our brand and themes.

The system uses two themes — light (GTV default) and dark (helpdesk and invoice app) — driven by CSS custom properties. Use the Light / Dark buttons in the top bar to switch.

Colour

All colours are defined as CSS custom properties. The dark theme overrides the same properties — no additional class names needed on components.

Brand

brand#4b286d
brand-dark#361f50
brand-mid#7c52a5
brand-light#f3eef8

Status

success#00703c
error#d4351c
warning#f47738
info#1d70b8

Typography

IBM Plex Sans for UI text, IBM Plex Mono for code, metadata, and monospace contexts.

--text-3xl / 40px
Page heading
--text-2xl / 32px
Section heading
--text-xl / 24px
Sub-section heading
--text-lg / 20px
Component heading
--text-md / 18px
Lead paragraph
--text-base / 16px
Body text
--text-sm / 14px
Secondary text, labels
--text-xs / 12px
Mono — tags, metadata

Spacing

4px base unit. Use the named scale rather than arbitrary values.

--space-1 · 4px
--space-2 · 8px
--space-3 · 12px
--space-4 · 16px
--space-6 · 24px
--space-8 · 32px
--space-12 · 48px
--space-16 · 64px

Button

One primary action per page. Destructive actions use the warning variant. Ghost buttons are for low-emphasis inline actions.

Primary

Example
<button class="btn btn--primary">Save and continue</button>

Secondary

Example
<button class="btn btn--secondary">Cancel</button>

Warning (destructive)

Example
<button class="btn btn--warning">Delete record</button>

Ghost

Example
<button class="btn btn--ghost">View all records</button>

All variants

Example

Notification banner

Used for system feedback. Always placed at the top of the main content area, above the page heading.

Success

Example
<div class="banner banner--success" role="alert"> <div class="banner__icon">✓</div> <div> <p class="banner__title">Record saved</p> <p class="banner__body">The testimony has been updated.</p> </div> </div>

Error

Example

Warning

Example

Info

Example

Card

Cards are used for content listings — news items, testimonials, tickets, records. The branded variant with a top border is the primary pattern.

Standard card

Example
Testimony

Ruth Adler — Glasgow, 1938

Added 14 January 2025

Ruth fled Vienna with her family after Kristallnacht. She settled in Glasgow and later became a teacher.

View testimony →
<div class="card card--branded"> <span class="card__tag">Testimony</span> <h3 class="card__title"><a href="#">Title</a></h3> <p class="card__meta">Added 14 January 2025</p> <p class="card__body">Summary text.</p> <a href="#" class="card__action">View →</a> </div>

Card grid (3-up)

Example
News

New testimonies added

12 March 2025

Three new oral histories from the Dundee collection have been digitised.

Event

Exhibition opens in Edinburgh

4 March 2025

The interactive exhibition visits the Scottish Parliament next month.

Update

Partnership with NLS confirmed

18 February 2025

The National Library of Scotland will host the archive from 2026.

Table

Use for structured data with clear column relationships. Numeric columns align right with mono font.

Standard table

Example
NameStatusCountry of originYear arrived
Ruth AdlerPublishedAustria1938
Max FreedmanDraftGermany1936
Hana KovačPublishedCzechoslovakia1939

Striped variant

Example
TicketAssigned toPriorityCreated
#1042JeremyHigh21 Mar
#1041UnassignedLow20 Mar
#1040JeremyMedium19 Mar
#1039UnassignedHigh19 Mar

Vertical nav

Used for in-page or section navigation in a left sidebar. Groups of links are separated by small-caps headings. The active item has a solid brand-coloured left border.

Standard vertical nav

Example
<nav class="vnav" aria-label="Section navigation"> <div class="vnav__section"> <p class="vnav__heading">Foundations</p> <ul class="vnav__list"> <li><a href="#colour">Colour</a></li> <li><a href="#spacing" class="active">Spacing</a></li> </ul> </div> </nav>

Accordion

Use to let users show and hide sections of content. Good for FAQs and supporting detail. Do not use to hide information that most users will need.

Standard accordion

Example

Gathering the Voices is a Scottish charity that records and preserves oral testimonies from Holocaust survivors and refugees who settled in Scotland.

All testimonies are available on the GTV website. Some include audio recordings, transcripts, and photographs.

Yes. If you or a family member has a testimony to share, get in touch through the contact page.

<div class="accordion"> <div class="accordion__item"> <button class="accordion__btn" aria-expanded="false"> Title <span class="accordion__icon" aria-hidden="true"></span> </button> <div class="accordion__body"> <div class="accordion__content"><p>Content.</p></div> </div> </div> </div>

Pattern: Article page

A long-form editorial article layout inspired by The Bell. Single centred column, no sidebar — content only. Combines existing design book components with two new article-specific patterns: pull quote and inline CTA.

Live example

The full working page is in article.html. It uses GTV content as a demo but the pattern applies to any project.

Open article.html ↗

Page structure

Header (hd) └── Breadcrumb └── Article header ├── Category tag (article-tag) ├── Headline (article-headline) ├── Standfirst (article-standfirst) └── Byline strip (article-header__byline) └── Hero image + caption (article-hero) └── Article body (article-body) ├── Body paragraphs ├── Section headings (h2 with border-top rule) ├── Pull quote (pull-quote) ← new pattern └── Inline CTA (article-cta) ← adapts banner └── Article footer — tags + share └── Related articles (card-grid) Footer (footer)

Components used from design book

  • Headerhd, hd__nav — same as all pages, GTV logo variant
  • Breadcrumbbreadcrumb — Home › News › Article title
  • Card / card-gridcard card--branded — related articles at the foot
  • Buttonbtn btn--primary, btn--secondary — CTA and share button
  • Tagcard__tag — category and footer tags
  • Footerfooter — standard footer
  • Tokens — all colours, typography, spacing from :root

New patterns introduced

  • Pull quote (pull-quote) — brand left border, italic body, mono attribution. Candidate for promotion to a full component.
  • Article CTA (article-cta) — adapts the banner component into an inline engagement prompt with a heading, body text, and button.
  • Reading progress bar — thin brand-purple bar at the top of the viewport driven by scroll position. Pure JS, no dependencies.
  • Article layout (article-page) — single centred column, 720px max, no sidebar. The key layout difference from design book inner pages.

Key design decisions

The article column is deliberately narrow — 720px — to keep line length comfortable for long reads (around 70 characters). The body text is slightly larger than base (1.0625rem) and line height is 1.75, both looser than UI components. Section headings get a border-top rule and top padding rather than just margin, giving clear visual breaks without feeling heavy. The standfirst uses the brand left border treatment from the banner component, repurposed editorially.

Pattern: WordPress Admin Dashboard

A full-page admin dashboard for WordPress plugins, rendered inside the WP admin panel. Uses the dark theme palette with JACB purple chrome. Tabs provide Overview, All Events, and Settings panels. First built for the GTV Timeline plugin (v1.28).

Anatomy

Dashboard wrapper (#gtv-dashboard / .gtv-db) ├── Header bar (.db-header) │ ├── Title + version badge (.db-header__badge) │ └── Action buttons (.db-header__btn, .db-header__btn--primary) ├── Tab bar (.db-tabs) │ └── Tab links (.db-tabs__link, .active) + count pill (.db-tabs__count) └── Body (.db-body) ├── Overview tab │ ├── Stat cards row (.db-stats > .db-stat, .db-stat--accent) │ └── Two-col layout (.db-cols) │ ├── Left: Bar chart panel (.db-panel > .db-bar) │ └── Right stack (.db-col-stack) │ ├── Media cards (.db-media > .db-media__card) │ └── Recent list (.db-recent) ├── All Events tab │ ├── Filter input (.db-filter) │ └── Events table (.db-table) └── Settings tab ├── Success notice (.db-notice) └── Settings block (.db-settings-block) ├── Toggle control (.db-toggle-row > .db-toggle) ├── Number input (.db-number) └── Save button (.db-save)

Header bar

Example

Timeline Dashboard v1.28

<div class="db-header"> <h1 class="db-header__title"> Dashboard title <span class="db-header__badge">v1.0</span> </h1> <div class="db-header__actions"> <button class="db-header__btn">Secondary</button> <button class="db-header__btn db-header__btn--primary">+ Add</button> </div> </div>

Tab bar

Example
<div class="db-tabs"> <a class="db-tabs__link active" href="#">Overview</a> <a class="db-tabs__link" href="#"> All Events <span class="db-tabs__count">42</span> </a> <a class="db-tabs__link" href="#">Settings</a> </div>

Stat cards

Example
84Total Events
1933Earliest Year
1945Latest Year
7Decades Covered
<div class="db-stats"> <div class="db-stat db-stat--accent"> <span class="db-stat__num">84</span> <span class="db-stat__label">Total Events</span> </div> <div class="db-stat"> <span class="db-stat__num">1933</span> <span class="db-stat__label">Earliest Year</span> </div> </div>

Use .db-stat--accent on the primary/headline stat. Numbers use IBM Plex Mono. Grid is auto-fit minmax(150px, 1fr).

Bar chart panel

Example

Events by Decade

1930s12
1940s20
1950s8
<div class="db-panel"> <p class="db-panel__title">Events by Decade</p> <div class="db-bar"> <div class="db-bar__meta"> <span>1940s</span> <span class="db-bar__count">20</span> </div> <div class="db-bar__track"> <div class="db-bar__fill" style="width:100%"></div> </div> </div> </div>

Width percentage is calculated as (count / max) * 100 in PHP and output as an inline style. The gradient fill runs from #4b286d to var(--db-accent).

Events table (All Events tab)

Example
DateTitleMediaActions
14 January 1938Kristallnacht Precursors🖼EditView
9 November 1938Kristallnacht📹EditView
1939Kindertransport Begins🖼EditView
<input class="db-filter" type="text" placeholder="Filter by title or year…"> <table class="db-table"> <thead> <tr> <th>Date</th><th>Title</th><th>Media</th><th>Actions</th> </tr> </thead> <tbody> <tr> <td class="db-table__date">9 November 1938</td> <td><a href="#">Kristallnacht</a></td> <td>📹</td> <td class="db-table__actions"> <a href="#">Edit</a><a href="#">View</a> </td> </tr> </tbody> </table>

Settings tab — toggle and number input

Example

Homepage Preview coming soon

Controls for the homepage timeline preview strip.

Enabled

How many events to show in the preview strip. Default: 5. Max: 20.

<!-- Toggle --> <div class="db-toggle-row"> <label class="db-toggle"> <input type="checkbox" name="option" value="1"> <span class="db-toggle__slider"></span> </label> <span class="db-toggle__label">Enabled</span> </div> <!-- Number input --> <input type="number" class="db-number" value="5" min="1" max="20"> <!-- Save --> <button class="db-save">Save Settings</button>

Colour tokens (dark overlay)

--db-bg: #1e1230 /* Dashboard body background */ --db-bg-panel: #2d1b45 /* Panel / card backgrounds */ --db-bg-deep: #120b1e /* Deepest background (media cards) */ --db-border: #3a1f56 /* Panel borders */ --db-accent: #c084fc /* Numbers, links, active states */ --db-accent-dim: rgba(192,132,252,0.2) /* Accent with opacity */ --db-text: #f0eaf5 /* Primary text */ --db-text-sec: rgba(255,255,255,0.45) /* Secondary / labels */ /* Fixed values (not CSS vars) */ Header bar: #4b286d /* --brand */ Tab bar: #3a1f56 /* --brand-dark variant */ Active tab line: #c084fc /* --db-accent */

Usage notes

  • Apply the wrapper class .gtv-db (or equivalent) to your dashboard container — do not set data-theme="dark" on <html> as this will affect WordPress chrome.
  • The tab bar drives navigation via URL parameters (?tab=overview) — no JS required for the tab switching itself.
  • Bar chart widths are calculated server-side in PHP as round((count / max) * 100) and output as inline style="width:X%". No charting library needed.
  • The filter input uses a single inline addEventListener('input') to show/hide table rows by textContent — no library required.
  • Load IBM Plex Sans and IBM Plex Mono via wp_enqueue_style from Google Fonts, scoped to the admin page hook.
  • This pattern was first implemented in the GTV Timeline plugin (v1.28, April 2026).

Open source

This design system is free to use, adapt, and build on.

Our position

We built this for our own projects but we're happy for anyone to use it. Take what's useful, adapt it freely, use it commercially. No attribution required, though it's appreciated.

What you're free to do

  • Use the HTML, CSS, and JS in your own projects
  • Adapt the tokens and components to your own brand
  • Use it commercially
  • Build on top of it without crediting us
  • Redistribute it as part of your own work

Built on the shoulders of others

Built on the principles of the GOV.UK Design System, which is itself open source. IBM Plex Sans and Mono are released under the SIL Open Font Licence.

FAQ

Common questions about using the design system.

How do I switch between light and dark theme?

Add data-theme="dark" to the <html> element. Remove it for the light theme. All component styles respond automatically.

Do I need to include all the CSS?

For now yes — copy the full :root token block and the component styles you need.

Why no border-radius?

GOV.UK uses sharp corners throughout — clear and utilitarian rather than decorative. Kept consistent across all projects.

What fonts are required?

IBM Plex Sans (400, 500, 700) and IBM Plex Mono (400, 500). Load from Google Fonts:

<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&family=IBM+Plex+Sans:ital,wght@0,400;0,500;0,700;1,400&display=swap" rel="stylesheet">

Can I add new components?

Yes — follow the same structure: db-sub block, rendered example, code snippet. Add an entry to the sidebar nav and update the changelog.

What's the brand colour?

Primary purple is #4b286d. Always use --brand rather than the hex directly.

Openhearth Unleashed

Brand colour palette for openhearth.jacb.co.uk — a doggy day care and home boarding business based in Eaglesham, East Renfrewshire. Colours are drawn from the existing site at openhearth.scot. Earthy, warm, natural — sage greens and cream.

Brand Colours

oh-sage#7d8570
oh-sage-light#a8b49a
oh-forest#2d4a3e
oh-cream#f0ece0

CSS Custom Properties

/* Openhearth Unleashed — brand tokens */ :root { --oh-sage: #7d8570; /* Header / hero background */ --oh-sage-light: #a8b49a; /* Divider strip, secondary bg */ --oh-forest: #2d4a3e; /* Content background, dark sections */ --oh-cream: #f0ece0; /* Logo, text on dark, off-white bg */ }

Usage

OPENHEARTH
——
DOGGY DAY CARE
& HOME BOARDING
——
UNLEASHED

Openhearth Unleashed

Welcome to Openhearth Unleashed. My name is Susan Margetts-McEwan, and the care and wellbeing of animals has been a large part of my life.

Sage (--oh-sage) is used for the hero/header area. Forest green (--oh-forest) is used for content sections. Cream (--oh-cream) is used for all text and logo elements on dark backgrounds. Light sage (--oh-sage-light) works as a divider or secondary background strip.

Typography

No custom typeface specified yet — inherits IBM Plex Sans from the JACB base. To be confirmed once the new theme is built out.

Changelog

Version names are towns and villages on the west coast of Scotland, changing weekly.

v1.9 — Tarbert · April 2026

  • Client Brands section added to sidebar
  • Openhearth Unleashed brand palette documented — --oh-sage, --oh-sage-light, --oh-forest, --oh-cream
  • Colours sourced from existing openhearth.scot site; earthy sage greens and cream on dark forest green

v1.8 — Tarbert · April 2026

  • WordPress Admin Dashboard pattern added — header bar, tab bar, stat cards, bar chart panel, events table, toggle, number input, save button, settings block
  • All new components documented with live examples and code snippets
  • Dark overlay token set documented (--db-*) for use in WP admin without affecting WordPress chrome
  • First implemented in GTV Timeline plugin v1.28 (April 2026)

v1.7 — Tarbert · 21 March 2026

  • Added Patterns section to sidebar navigation
  • Article page pattern documented — structure, component list, design decisions
  • Live link to article.html from the design book
  • Pull quote, article CTA, reading progress bar, and article layout noted as new patterns introduced in article.html

v1.6 — Tarbert · 21 March 2026

  • Full layout rebuild — clean flex row with sticky sidebar, no content overlap
  • Search icon and input equal height (32px header, 44px component)
  • Working in-page search with overlay, keyword highlighting, Escape to close
  • Search added as a component with code example and usage notes

v1.5 — Tarbert · 21 March 2026

  • Header nav hover colour corrected
  • Logo mark changed from GTV to JACB on both pages
  • Footer updated to JACB Services branding
  • Open source section added

v1.4 — Tarbert · 21 March 2026

  • index.html homepage added in GOV.UK Design System style
  • Design book updated to full-width header bar + vertical nav layout
  • Navigation header component colours corrected
  • Vertical nav component added

v1.3 — Tarbert · 21 March 2026

  • Accordion component added with CSS animation and ARIA support
  • Named version scheme introduced — west coast Scotland towns, changing weekly

v1.2 — Tarbert · 21 March 2026

  • Navigation header height increased to 72px
  • Nav link hover jitter fixed
  • FAQ and Changelog sections added

v1.1 — Tarbert · 21 March 2026

  • Initial release — Colour, Typography, Spacing, Button, Notification banner, Card, Table, Navigation, Breadcrumb
  • Two themes: light (GTV) and dark (Helpdesk)

Design Book v1.9 Tarbert — JACB Services. Built on GOV.UK Design System principles.

Open source — use it, adapt it, build on it freely. Read our open source note →