Files
familienarchiv/docs/STYLEGUIDE.md
2026-03-17 18:06:50 +00:00

13 KiB

Familienarchiv — Design Styleguide

This document defines the visual language for the Familienarchiv frontend. All UI work should follow these conventions to stay consistent with the De Gruyter Brill corporate identity.


Brand Identity

The design is based on the De Gruyter Brill brand identity (unveiled at Frankfurt Book Fair 2024). Key characteristics:

  • Clean white backgrounds, high contrast
  • Strong typographic hierarchy (uppercase labels, serif body text)
  • Academic publisher aesthetic: authoritative, clear, uncluttered
  • The Melrose purple (#B4B9FF) quotation-mark logo is the primary brand signature

Colors

Defined in src/routes/layout.css as @theme variables. All generate Tailwind utilities automatically (bg-*, text-*, border-*).

Token Hex Usage
brand-navy #012851 Primary text, headings, buttons, active states — Prussian Blue
brand-mint #A1DCD8 Accent color, icon tints, hover underlines — Aqua Island
brand-purple #B4B9FF Logo, nav active state highlight, top accent strip — Melrose
brand-sand #F0EFE9 Subtle card backgrounds, borders, hover backgrounds — paper tone
brand-white #FFFFFF Page background, card surfaces
brand-dark #0D0D0D Near-black text when maximum contrast is needed

Color usage rules

  • Never use raw hex values in components — always use token utilities.
  • Page and card backgrounds are white. Use bg-brand-sand only for subtle inset areas (e.g. bg-brand-sand/30).
  • brand-navy is the workhorse: headings, body text, borders, primary buttons.
  • brand-mint is an accent only — never use it as primary text color on white (contrast too low).
  • brand-purple is reserved for the logo and the single top accent strip in the header.

Typography

Fonts

Role Font Tailwind Notes
Body / Serif Tinos (Times substitute) font-serif Loaded from Google Fonts. Used for document titles, names, body copy, dates. Matches DGB's use of Times.
UI / Sans Montserrat (Gotham substitute) font-sans Loaded from Google Fonts. Used for labels, navigation, buttons, metadata, form elements. Matches DGB's use of Gotham.

Type scale and usage

Element Classes Example
Page title font-serif text-3xl text-brand-navy <h1>
Card section heading font-sans text-xs font-bold uppercase tracking-widest text-gray-400 Section labels
Document / item title font-serif text-xl font-medium text-brand-navy List items
Metadata / label font-sans text-xs font-bold uppercase tracking-widest text-gray-500 Field labels
Body text font-serif text-sm text-brand-navy Descriptions, summaries
Navigation font-sans text-xs font-bold uppercase tracking-widest Nav links

Rules

  • Labels are always uppercase + tracked: text-xs font-bold uppercase tracking-widest
  • Headings use font-sans (Montserrat), set in CSS globally.
  • Content (document titles, person names, summaries) uses font-serif (Tinos).
  • Never use font-serif for UI chrome (buttons, labels, nav).

Icons

Library

686 SVG icons in frontend/static/degruyter-icons/. Two families:

  • Simple — single-color, action-oriented. Use for all UI icons. Available in 4 sizes.
  • Complex — multi-color illustrative icons. Use sparingly for empty states or section headers.

Simple icon sizes

Size Pixels Path segment Use
XS 12px X-Small-12px Inline text hints, badges
SM 16px Small-16px Compact UI, table cells
MD 24px Medium-24px Standard UI icon — default choice
LG 32px Large-32px Feature headers, empty states

URL pattern

/degruyter-icons/Simple/{Size}/SVG/{Category}/{Name}-{Size-Code}.svg

Size codes: XS, SM, MD, LG

SVG fills are hardcoded to #000000. Use CSS to tint/size them:

<!-- Standard icon -->
<img src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Edit-Content-MD.svg"
     alt="" aria-hidden="true" class="w-6 h-6" />

<!-- Muted/secondary icon -->
<img src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Edit-Content-MD.svg"
     alt="" aria-hidden="true" class="w-6 h-6 opacity-40" />

<!-- Colored via CSS filter (navy tint) -->
<img src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Edit-Content-MD.svg"
     alt="" aria-hidden="true"
     class="w-6 h-6"
     style="filter: invert(11%) sepia(58%) saturate(1200%) hue-rotate(192deg) brightness(95%) contrast(101%)" />

Note: Always include alt="" and aria-hidden="true" for decorative icons. For meaningful icons (no visible label next to them), use a descriptive alt text instead.

Key icons for this app

Use case Icon path
Edit / Bearbeiten Action/Edit-Content-MD.svg
Search / Suche Action/Mag-Glass-MD.svg
New document Action/Add/Add-General-MD.svg
Download Action/Download-MD.svg
Upload Action/Upload-MD.svg
Filter Action/Filter/Filter-Outline-MD.svg
Calendar / date Action/Calendar/Calendar-Add-MD.svg
Location Action/Location-MD.svg
Person / account Action/Account-MD.svg
Chat / conversation Action/Chat-MD.svg
Tag / bookmark Action/Bookmark/Bookmark-Outline-MD.svg
Close / dismiss Action/Close-MD.svg
Back / left arrow Action/Arrow/Arrow-Left-MD.svg
Settings / admin Action/Settings-MD.svg
Document / PDF Action/PDF-Document-MD.svg
Mail Action/Mail-MD.svg
Delete Action/Remove/Remove-General-MD.svg
Info Action/Info/Block/Info-Block-Border-MD.svg

Spacing

Based on Tailwind's 4pt grid. Prefer multiples of 4 for all spacing.

Scale Value Use
p-1 / gap-1 4px Tight inline spacing
p-2 8px Small padding (badges, chips)
p-3 12px Compact buttons
p-4 16px Default section padding
p-6 24px Card inner padding (default)
p-8 32px Large card padding
p-10 40px Page vertical padding
gap-6 24px Grid/list gaps
mb-6 24px Standard spacing between sections
mb-10 40px Large spacing between card sections

Layout

Page wrapper

All content pages use:

<div class="max-w-7xl mx-auto py-8 px-4 sm:px-6 lg:px-8">

Narrower pages (forms, detail views):

<div class="max-w-4xl mx-auto py-10 px-4">

Header

The global sticky header in +layout.svelte:

  • Height: 68px (4px purple accent strip + 64px nav bar)
  • Background: bg-white
  • Bottom border: border-b border-gray-100
  • Z-index: z-50

Full-screen views

Document detail (/documents/[id]) uses a full-viewport split layout:

<div class="h-screen flex flex-col bg-white">
  <!-- top bar -->
  <!-- content: sidebar + preview -->
</div>

Components

Card

Standard content card:

<div class="bg-white shadow-sm border border-brand-sand rounded-sm p-6">
  <h2 class="text-xs font-bold uppercase tracking-widest text-gray-400 mb-5">
    Section Title
  </h2>
  <!-- content -->
</div>

Card with colored accent bar (person/document detail):

<div class="bg-white shadow-sm border border-brand-sand rounded-sm overflow-hidden">
  <div class="h-2 bg-brand-navy w-full"></div>
  <div class="p-8 md:p-10">
    <!-- content -->
  </div>
</div>

Buttons

Primary button:

<button class="bg-brand-navy text-white px-5 py-2 text-xs font-bold uppercase tracking-widest font-sans hover:bg-brand-navy/90 transition-colors">
  Speichern
</button>

Secondary / outline button:

<button class="border border-gray-300 text-gray-600 px-5 py-2 text-xs font-bold uppercase tracking-widest font-sans hover:bg-gray-50 transition-colors rounded-sm">
  Abbrechen
</button>

Ghost / text button (inline actions):

<button class="text-brand-navy/60 hover:text-brand-navy text-sm font-medium font-sans transition-colors">
  Aktion
</button>

Destructive button:

<button class="border border-red-300 text-red-600 px-4 py-2 text-xs font-bold uppercase tracking-widest font-sans hover:bg-red-50 transition-colors rounded-sm">
  Löschen
</button>

Button with DGB icon:

<button class="inline-flex items-center gap-2 bg-brand-navy text-white px-4 py-2 text-xs font-bold uppercase tracking-widest font-sans hover:bg-brand-navy/90 transition-colors">
  <img src="/degruyter-icons/Simple/Small-16px/SVG/Action/Edit-Content-SM.svg"
       alt="" aria-hidden="true" class="w-4 h-4 invert" />
  Bearbeiten
</button>

Use class="invert" on icons inside dark (navy) buttons to make the black SVG white.

Form inputs

Label + input pair:

<div>
  <label for="field" class="block text-xs font-bold uppercase tracking-widest text-gray-500 mb-1.5 font-sans">
    Feldname *
  </label>
  <input
    id="field" name="field" type="text"
    class="block w-full border border-gray-300 py-2.5 px-3 text-sm font-serif text-brand-navy placeholder-gray-400 focus:border-brand-navy focus:ring-1 focus:ring-brand-navy focus:outline-none"
  />
</div>

Search input:

<div class="relative">
  <input type="text" placeholder="Suchen..."
    class="block w-full border border-gray-300 py-2.5 pr-10 pl-3 font-sans text-sm text-brand-navy placeholder-gray-400 focus:border-brand-navy focus:ring-1 focus:ring-brand-navy focus:outline-none" />
  <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
    <img src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Mag-Glass-MD.svg"
         alt="" aria-hidden="true" class="w-4 h-4 opacity-40" />
  </div>
</div>

Status badges

<!-- Mint (uploaded/active) -->
<span class="inline-flex items-center rounded-full border border-brand-mint/50 bg-brand-mint/20 text-brand-navy px-2.5 py-0.5 text-[10px] font-bold tracking-wide uppercase font-sans">
  UPLOADED
</span>

<!-- Yellow (placeholder/pending) -->
<span class="inline-flex items-center rounded-full border border-yellow-200 bg-yellow-50 text-yellow-700 px-2.5 py-0.5 text-[10px] font-bold tracking-wide uppercase font-sans">
  PLACEHOLDER
</span>

Tag chips

<button class="inline-flex items-center rounded bg-brand-sand/30 px-2 py-1 text-[10px] font-bold tracking-widest text-brand-navy uppercase font-sans transition-colors hover:bg-brand-navy hover:text-white">
  Schlagwort
</button>
<a href="/persons" class="inline-flex items-center text-xs font-bold uppercase tracking-widest text-gray-500 hover:text-brand-navy transition-colors group mb-4 font-sans">
  <img src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Arrow/Arrow-Left-MD.svg"
       alt="" aria-hidden="true"
       class="w-4 h-4 mr-2 opacity-40 group-hover:opacity-100 transition-opacity" />
  Zurück zur Übersicht
</a>
<a href="/documents/new" class="inline-flex items-center gap-1 text-sm font-medium text-brand-navy/60 hover:text-brand-navy transition-colors font-sans">
  <img src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Add/Add-General-MD.svg"
       alt="" aria-hidden="true" class="w-4 h-4 opacity-60" />
  Neues Dokument
</a>

Empty state

<div class="p-16 text-center">
  <div class="mx-auto mb-4 w-16 h-16 flex items-center justify-center">
    <img src="/degruyter-icons/Simple/Large-32px/SVG/Action/Mag-Glass-LG.svg"
         alt="" aria-hidden="true" class="w-10 h-10 opacity-20" />
  </div>
  <h3 class="font-serif text-lg font-medium text-brand-navy">Keine Dokumente gefunden</h3>
  <p class="mt-1 font-sans text-sm text-gray-500">Versuchen Sie, die Filter anzupassen.</p>
</div>

Nav active state

Current page nav link:

class="text-brand-navy bg-brand-purple/15 rounded"

Inactive nav link:

class="text-gray-500 hover:text-brand-navy hover:bg-brand-sand/60 rounded"

Both share the base: inline-flex items-center px-3 py-1.5 text-xs font-bold uppercase tracking-widest font-sans transition-colors

Save bar (long forms)

Sticky full-bleed (document edit):

<div class="sticky bottom-0 z-10 -mx-4 px-6 py-4 bg-white border-t border-brand-sand shadow-[0_-2px_8px_rgba(0,0,0,0.06)] flex items-center justify-between">
  <a href="..." class="text-xs font-bold uppercase tracking-widest text-gray-500 hover:text-brand-navy font-sans transition-colors">
    Abbrechen
  </a>
  <button type="submit" class="bg-brand-navy text-white px-6 py-2.5 text-xs font-bold uppercase tracking-widest font-sans hover:bg-brand-navy/90 transition-colors">
    Speichern
  </button>
</div>

Card-style (short forms):

<div class="mt-4 flex items-center justify-between rounded-sm border border-brand-sand bg-white px-6 py-4 shadow-sm">

Do / Don't

Do Don't
Use font-sans for all UI labels, buttons, nav Use font-serif for buttons or labels
Use uppercase tracking-widest for labels Use sentence case for field labels
Use brand-navy for primary actions Use brand-mint as primary action color
Use opacity-* to create icon tints Change icon fill color inline
Use invert class on icons inside bg-brand-navy buttons Use colored icon files for button icons
Use rounded-sm for cards and buttons (subtle) Use rounded-full for non-pill elements
Use shadow-sm for card elevation Use large shadows
Keep borders border-gray-100 or border-brand-sand Use dark borders