Skip to content

Reast Design Manual

Standalone developer reference for the Reast visual identity. Authoritative source for design tokens, component patterns and enforcement rules. For the embedded web-app version see Design System.


Design Principles

  1. Literary warmth — Warm neutrals, serif headlines, generous whitespace evoke book culture.
  2. Content-first — Stories are the star; UI recedes behind content.
  3. Consistent rhythm — 4px base grid, modular scale, predictable spacing.
  4. Accessible contrast — WCAG AA minimum, clear text hierarchy, high-contrast themes available.
  5. Subtle interactions — Gentle hover lifts, smooth transitions, no jarring movements.
  6. Offline-ready — Every reader feature works without a network connection.
  7. No external UI libraries — Angular CDK for behaviour; all visuals are custom.

Color Tokens

All colors are CSS custom properties defined in apps/web/src/styles.scss. Five themes are supported: default (light), dark, high-contrast, dark high-contrast, and light high-contrast.

Default (Light) — :root

TokenValueUsage
--color-bg#faf9f6Page background (warm white)
--color-bg-alt#f3f1ecSection backgrounds (warm gray)
--color-bg-card#ffffffCard surfaces
--color-bg-card-hover#fdfcfaCard hover state
--color-surface#edeae4Inputs, wells
--color-border#ddd9d1Primary borders
--color-border-light#e8e5deSubtle borders
--color-text#1f1f2ePrimary text (near-black, warm)
--color-text-muted#5c5c6eSecondary text
--color-text-dim#67677aTertiary / meta text
--color-accent#5b4fc7Interactive elements (indigo)
--color-accent-hover#4a3fb0Hover state
--color-accent-strong#5b4fc7CTA backgrounds (white text, WCAG AA)
--color-accent-strong-hover#4a3fb0CTA hover
--color-accent-glowrgba(91, 79, 199, 0.12)Focus rings, glows
--color-accent-softrgba(91, 79, 199, 0.08)Subtle accent backgrounds
--color-gold#d97706Ratings, highlights
--color-success#059669Success states
--color-danger#dc2626Error states

Dark — [data-theme='dark']

TokenValue
--color-bg#121218
--color-bg-alt#1a1a24
--color-bg-card#1e1e2a
--color-bg-card-hover#252535
--color-surface#2a2a3a
--color-border#3a3a4e
--color-border-light#2e2e42
--color-text#e8e6f0
--color-text-muted#a0a0b8
--color-text-dim#9494b0
--color-accent#7b6ff0
--color-accent-hover#9488f5
--color-accent-strong#5b4fc7
--color-accent-strong-hover#4a3fb0
--color-accent-glowrgba(123, 111, 240, 0.15)
--color-accent-softrgba(123, 111, 240, 0.1)
--color-gold#f59e0b
--color-success#10b981
--color-danger#ef4444

High Contrast — [data-theme='high-contrast'] / [data-theme='dark-hc']

TokenValue
--color-bg#000000
--color-bg-alt#0a0a0a
--color-bg-card#111111
--color-text#ffffff
--color-border#ffffff
--color-accent#ffcc00
--color-accent-hover#ffe066
--color-gold#fbbf24
--color-success#34d399
--color-danger#f87171

Light High Contrast — [data-theme='light-hc']

TokenValue
--color-bg#ffffff
--color-bg-alt#f5f5f5
--color-bg-card#ffffff
--color-text#000000
--color-border#000000
--color-accent#0000ee
--color-accent-hover#0000bb
--color-gold#b45309
--color-success#047857
--color-danger#b91c1c

Typography

RoleFontSizeWeightLine-height
Display headlineLiterata (serif)clamp(1.75rem, 3.5vw, 2.5rem)7001.15
Section titleLiterata1.5rem7001.25
Card titleLiterata1.15rem7001.3
Body / ReadingLiterataclamp(1.0625rem, 0.95rem + 0.5vw, 1.25rem)4001.7
UI textInter (sans)1rem4001.6
Small / metaInter0.8rem – 0.85rem400–5001.5
Label / badgeInter0.7rem6001

Font stacks

css
--font-sans: "Inter", system-ui, -apple-system, sans-serif;
--font-serif: "Literata", Georgia, serif;

Accessibility font

OpenDyslexic is bundled (/fonts/OpenDyslexic-Regular.woff2, /fonts/OpenDyslexic-Bold.woff2) as an opt-in accessibility font for users with dyslexia. It is activated via user preferences in the reading settings.

Rules

  • Headlines always use the serif font (--font-serif).
  • UI chrome (buttons, labels, navigation) always uses the sans font (--font-sans).
  • Story body text uses the serif font at reading size with generous line-height (1.7).
  • Use clamp() for fluid sizing — never fixed px for text.
  • font-display: swap on all custom fonts.
  • Google Fonts subsets: latin, latin-ext.

Spacing Scale (4px base grid)

TokenValuePixels
--space-xs0.25rem4px
--space-sm0.5rem8px
--space-md1rem16px
--space-lg1.5rem24px
--space-xl2rem32px
--space-2xl3rem48px
--space-3xl4rem64px

All spacing must align to the 4px grid. Use the tokens, not arbitrary values.


Border Radius

TokenValueUsage
--radius-sm0.1875rem (3px)Badges, small elements
--radius-md0.375rem (6px)Cards, buttons
--radius-lg0.5rem (8px)Featured cards, modals
--radius-xl0.75rem (12px)Large containers
999pxPill shapeGenre filters, tags

Shadows

NameLight valueDark valueUsage
--shadow-sm0 1px 3px rgba(0,0,0,0.04)0 1px 3px rgba(0,0,0,0.2)Resting cards
--shadow-md0 4px 12px rgba(0,0,0,0.06)0 4px 12px rgba(0,0,0,0.3)Elevated elements
--shadow-lg0 8px 24px rgba(0,0,0,0.08)0 8px 24px rgba(0,0,0,0.4)Hover states, modals

Transitions

TokenValueUsage
--transition-fast150ms easeHover effects, toggles
--transition-normal250ms easeCard lifts, expansions
--transition-slow400ms easePage transitions

Layout

PropertyValue
Max content width1200px
Page padding (desktop)var(--space-xl) (32px)
Page padding (mobile)var(--space-md) (16px)
Header height56px, sticky, bottom border
Section spacingvar(--space-3xl) (64px) between major sections
Card gridrepeat(auto-fill, minmax(260px, 1fr))

Responsive Breakpoints

NameWidthAdjustments
Mobile≤ 768pxSingle column, reduced padding, stacked hero
Tablet769px – 1024px2-column grid
Desktop> 1024pxFull layout, 3–4 column grid

CSS methodology

  • Grid for 2D layouts, Flexbox for 1D.
  • Container queries where component-level responsiveness is needed.
  • Fluid units: em / rem / % / vw / dvh, clamp() / min() / max() / minmax().
  • Intrinsic sizes: min-content / max-content / fit-content.
  • Mobile-first media queries.
  • Logical properties (inline-start, block-end, etc.) for RTL readiness.
  • Minimum breakpoints — prefer fluid sizing over many breakpoints.
  • Fixed px only when strictly necessary (e.g. icon sizes, borders).

Header Modes

The header is mode-aware. Its width, title content and visibility rules change depending on the active surface. The header hosts three menu surfaces: LMenu (logo-triggered left panel, CSS prefix .lmenu-*), HMenu (horizontal text links, CSS prefix .hmenu-*), and RMenu (user tile right panel, CSS prefix .rmenu-*).

ModeHeader widthTitleSearch
Browser, Settings1200px container"reast""Search stories or authors"
ReaderFull-width, flush edgesStory title + authorNone
Author1200px containerAuthor name"Search author's stories"
Group1200px containerGroup name"Search stories or authors"
Editor, BuilderFull-width, flush edgesStory name or "New Story"None

Reader mode hides the header after scrolling past the title (logo remains visible).


Component Patterns

Story Card

  • White card with subtle border, lift on hover (+shadow, -2px translateY)
  • Cover image (140px), body with genre label, serif title, excerpt (2-line clamp), footer meta

Genre Pill

  • Pill shape (999px radius), border, transparent background
  • Active: accent background, white text
  • Hover: accent border

CTA Button

  • --color-accent-strong background, white text, medium weight
  • Hover: --color-accent-strong-hover
  • Padding: var(--space-sm) var(--space-lg)
  • Border radius: --radius-md

Browse Pages (canonical layout)

All browse pages (/stories, /authors, /groups) share a single layout primitive from apps/web/src/app/shared/browse-page.shared.scss.

  • Outer canvas .browse-page — full screen width, clamp() padding.
  • Inner container .browse-innermax-width: 1200px; margin: 0 auto.
  • Title .browse-title — serif, fluid size, left-aligned (never centered).
  • Search .browse-search — slim input with leading magnifier icon, width min(420px, 100%).
  • Grid .browse-gridrepeat(auto-fill, minmax(min(100%, 22rem), 1fr)).

Identity Card (authors, groups)

  • Square image left (96px mobile, 120px ≥480px container)
  • Name + bio + meta right
  • Gradient placeholder with initial until image uploaded

Icons

All SVG icons are defined in apps/web/src/app/shared/icons.ts — the single source of truth.

Specifications

  • 24×24 viewBox
  • Stroke-only (no fill)
  • stroke-width: 1.5
  • stroke-linecap: round, stroke-linejoin: round
  • Modern thin outlined style

Usage

  1. Inline SVG — paste the path from ICONS.<name> inside an <svg> wrapper
  2. Strip / computed — import ICONS and reference path strings directly
  3. RSelectOption — use svgIcon: ICONS.<name>

Rules

  • Never use emoji or Unicode characters as icons (☰, 🌍, ⌨)
  • Never use external icon libraries (Material Icons, FontAwesome)
  • Always use custom SVG paths from icons.ts
  • Keep stroke-width="1.5" everywhere
  • Same entity = same icon everywhere (e.g. Groups = two-person icon, not flag in one place and people in another)
  • New icons must follow the same visual weight and style

Accessibility

Angular CDK (behaviour only)

The project uses @angular/cdk for keyboard handling, focus traps, ARIA roles and overlay positioning. @angular/material is explicitly not used.

WidgetCDK moduleDirectives
Menus@angular/cdk/menucdkMenuTriggerFor, cdkMenu, cdkMenuItem
Dialogs@angular/cdk/dialogModal surfaces
Focus traps@angular/cdk/a11ycdkTrapFocus
Listboxes@angular/cdk/listboxSingle-select pickers
Overlays@angular/cdk/overlayPositioning helpers

Rules

  • Always import from specific CDK sub-entries (@angular/cdk/menu), never from root
  • CDK provides behaviour; all visuals are custom CSS
  • Do not hand-roll role="menu" / role="menuitem" on CDK widgets — CDK emits ARIA roles automatically
  • Each interactive widget must use a CDK primitive or document why it cannot

Theme support

  • 5 themes: default, dark, high-contrast (dark-hc), light-hc
  • Theme selector in user preferences
  • All tokens must work across all themes — test every new component in all 5
  • OpenDyslexic font available as opt-in for readers with dyslexia
  • WCAG AA contrast minimum on all text/background combinations

The footer hosts the FMenu (CSS prefix .fmenu-*) — a columnar navigation section with Explore, Support and Legal columns.

ModeFooter content
Browser, Settings, GroupClassic: Reast, slogan, explore/support/legal links
ReaderFixed, low, transparent. "rea.st" right-bottom. Offline/online status indicator
Editor, BuilderStatus bar: left = reast (home link), right = support/help/terms
AuthorFollows Browser pattern

Do's and Don'ts

Do

  • Use design tokens (var(--color-*), var(--space-*)) everywhere
  • Test every component in all 5 themes
  • Use clamp() for fluid typography and spacing
  • Use CSS Grid for page layouts, Flexbox for component internals
  • Keep story content as the visual priority — UI recedes
  • Use transition with design tokens for hover/focus effects
  • Provide keyboard navigation for all interactive elements (via CDK)
  • Keep text readable: 1.6+ line-height for UI, 1.7 for reading

Don't

  • Don't use hardcoded color values — always use tokens
  • Don't use px for font sizes — use rem with clamp()
  • Don't import @angular/material
  • Don't use emoji or Unicode as icons
  • Don't center-align browse page titles
  • Don't create new card shapes when .identity-card fits
  • Don't use external icon fonts
  • Don't add role="menu" manually when using CDK menus
  • Don't skip dark/HC theme testing
  • Don't use position: fixed for headers (use position: sticky)
  • Don't redesign the search field per page — always slim with leading icon

Developer Checklist

Before submitting a UI change, verify:

  • [ ] All colors use var(--color-*) tokens
  • [ ] Spacing uses var(--space-*) tokens on the 4px grid
  • [ ] Typography uses the correct font family (serif for headings/reading, sans for UI)
  • [ ] Font sizes use rem or clamp(), not px
  • [ ] Component renders correctly in all 5 themes (default, dark, high-contrast, dark-hc, light-hc)
  • [ ] WCAG AA contrast ratio met for all text/background combinations
  • [ ] Interactive elements use Angular CDK primitives for keyboard/ARIA
  • [ ] Icons come from icons.ts, follow 24×24 stroke-only spec
  • [ ] Hover/focus states use design transition tokens
  • [ ] Layout uses CSS Grid (2D) or Flexbox (1D), not floats or tables
  • [ ] Responsive: tested at mobile (≤768px), tablet (769–1024px), desktop (>1024px)
  • [ ] No hardcoded colors, no @angular/material, no external icons

File References

FileDescription
apps/web/src/styles.scssGlobal CSS custom properties and theme definitions
apps/web/src/styles/animations.scssShared animation keyframes
apps/web/src/styles/buttons.scssButton base styles
apps/web/src/styles/dropdown.scssDropdown/menu shared styles
apps/web/src/app/shared/browse-page.shared.scssBrowse page canonical layout
apps/web/src/app/shared/icons.tsSVG icon path registry
docs/design/system.mdEmbedded design system (web-app scoped)