Files
ArchiTools/docs/guides/UI-DESIGN-SYSTEM.md
Marius Tarau 4c46e8bcdd Initial commit: ArchiTools modular dashboard platform
Complete Next.js 16 application with 13 fully implemented modules:
Email Signature, Word XML Generator, Registratura, Dashboard,
Tag Manager, IT Inventory, Address Book, Password Vault,
Mini Utilities, Prompt Generator, Digital Signatures,
Word Templates, and AI Chat.

Includes core platform systems (module registry, feature flags,
storage abstraction, i18n, theming, auth stub, tagging),
16 technical documentation files, Docker deployment config,
and legacy HTML tool reference.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 12:50:25 +02:00

21 KiB

UI Design System

ArchiTools internal design system reference. All UI decisions flow from this document.


Design Philosophy

ArchiTools serves architecture and engineering professionals at Beletage SRL, Urban Switch SRL, and Studii de Teren SRL. The interface must reflect the discipline of the work itself: precise, structured, technically grounded.

Guiding principles:

  • Professional over playful. No rounded bubbly elements, no bright consumer gradients, no emoji-heavy interfaces. The aesthetic is closer to a CAD toolbar than a social media dashboard.
  • Information-dense but not cluttered. Architecture professionals need data visible at a glance. Favor card-based layouts with clear hierarchy over sparse minimalist voids.
  • Technical confidence. Use monospaced fonts for data fields, structured grids for layout, and precise spacing. The UI should feel like a well-organized technical drawing.
  • Consistent across tools. Every module (email signatures, XML generators, future tools) must feel like part of the same platform, not a collection of standalone pages.
  • Dark and light with equal quality. Both themes are first-class. The dark theme is the default (matching existing tool aesthetics). The light theme must be equally polished.

Color System

Brand Colors

Token Hex Usage
brand-teal #22B5AB Primary accent. Beletage brand teal. Used for active states, primary buttons, links, focus rings.
brand-teal-light #2DD4BF Hover state for teal elements.
brand-teal-dark #14978F Pressed/active state.

Each company in the group may define an override accent color. The teal serves as the platform default and Beletage-specific accent.

Company Accent Usage Context
Beletage SRL #22B5AB (teal) Architecture projects
Urban Switch SRL TBD Urban planning projects
Studii de Teren SRL TBD Land survey projects

The company selector in the header drives the active accent color via a CSS custom property (--accent).

Slate Backgrounds

Derived from Tailwind's slate scale. These form the structural palette for both themes.

Dark theme (default):

Token Tailwind Class Hex Usage
bg-app bg-slate-950 #020617 Application background
bg-card bg-slate-900 #0f172a Card surfaces
bg-card-elevated bg-slate-800 #1e293b Elevated cards, dropdowns, popovers
bg-input bg-slate-950 #020617 Input field backgrounds
border-default border-slate-700 #334155 Card borders, dividers
border-subtle border-slate-800 #1e293b Subtle separators
text-primary text-slate-100 #f1f5f9 Primary text
text-secondary text-slate-400 #94a3b8 Secondary text, labels
text-muted text-slate-500 #64748b Disabled text, placeholders

Light theme:

Token Tailwind Class Hex Usage
bg-app bg-slate-50 #f8fafc Application background
bg-card bg-white #ffffff Card surfaces
bg-card-elevated bg-slate-50 #f8fafc Elevated cards
bg-input bg-white #ffffff Input field backgrounds
border-default border-slate-200 #e2e8f0 Card borders, dividers
border-subtle border-slate-100 #f1f5f9 Subtle separators
text-primary text-slate-900 #0f172a Primary text
text-secondary text-slate-600 #475569 Secondary text, labels
text-muted text-slate-400 #94a3b8 Disabled text, placeholders

Semantic Colors

Semantic Light Dark Usage
success #16a34a (green-600) #22c55e (green-500) Confirmations, valid states
warning #d97706 (amber-600) #f59e0b (amber-500) Caution states, non-blocking issues
error #dc2626 (red-600) #ef4444 (red-500) Errors, destructive actions
info #2563eb (blue-600) #3b82f6 (blue-500) Informational highlights

Each semantic color has a background variant at 10% opacity for alert/badge backgrounds:

  • bg-success: success / 10% over card background
  • Same pattern for warning, error, info

Theme Implementation

Theme is managed by next-themes with the attribute="class" strategy. Tailwind's darkMode: "class" is enabled. All theme-dependent styles use the dark: prefix.

// layout.tsx
import { ThemeProvider } from 'next-themes';

<ThemeProvider attribute="class" defaultTheme="dark" enableSystem>
  {children}
</ThemeProvider>

CSS custom properties for the accent color are set on <html> based on the active company selection:

:root {
  --accent: 34 181 171;          /* #22B5AB in RGB */
  --accent-foreground: 255 255 255;
}

Components reference accent via bg-[rgb(var(--accent))] or through shadcn/ui's HSL-based theming variables in globals.css.


Typography

Font Stack

Primary: Inter (loaded via next/font/google), falling back to system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif.

Monospace (for code, XML output, data fields): "JetBrains Mono", "Fira Code", ui-monospace, monospace.

Size Scale

All sizes reference Tailwind's default scale. Do not use arbitrary pixel values.

Token Tailwind Size Usage
text-xs text-xs 0.75rem / 12px Badges, fine print, metadata
text-sm text-sm 0.875rem / 14px Labels, secondary text, table cells
text-base text-base 1rem / 16px Body text, input values
text-lg text-lg 1.125rem / 18px Card titles, section headers
text-xl text-xl 1.25rem / 20px Page section titles
text-2xl text-2xl 1.5rem / 24px Page titles
text-3xl text-3xl 1.875rem / 30px Dashboard hero stats only

Font Weight

Weight Tailwind Usage
400 font-normal Body text
500 font-medium Labels, table headers, navigation items
600 font-semibold Card titles, section headers
700 font-bold Page titles, stat values

Line Height

Use Tailwind defaults. Override only for tight stat displays (leading-tight / leading-none on large numeric values).


Component Library

Base: shadcn/ui

All interactive components are built on shadcn/ui. Components are installed into src/shared/components/ui/ via the shadcn CLI and customized in place.

Customization approach:

  1. Install the shadcn/ui component (npx shadcn@latest add button).
  2. The component lands in src/shared/components/ui/button.tsx.
  3. Modify theme tokens in globals.css to match our color system.
  4. Extend component variants if needed (e.g., adding a brand variant to Button).
  5. Never wrap shadcn components in another abstraction layer unless adding substantial logic. Use them directly.

Key shadcn/ui components in use:

  • Button -- primary actions, secondary actions, destructive actions, ghost navigation
  • Input, Textarea, Select -- form controls
  • Card, CardHeader, CardContent, CardFooter -- content containers
  • Dialog, AlertDialog -- modal interactions (replaces alert()/confirm())
  • DropdownMenu -- context menus, overflow actions
  • Tabs -- in-page mode switching (e.g., simple/advanced toggle)
  • Table -- data display
  • Badge -- status indicators, category labels
  • Tooltip -- icon-only button labels
  • Separator -- visual dividers
  • Switch, Checkbox -- boolean toggles
  • Breadcrumb -- navigation breadcrumbs in header
  • Sidebar -- app shell navigation (shadcn sidebar component)
  • Sheet -- mobile navigation drawer

Layout System

App Shell

The application uses a fixed sidebar + header + scrollable content area layout.

+--------------------------------------------------+
| [Sidebar]  |  [Header: breadcrumbs | theme | co] |
|            |--------------------------------------|
|  Nav       |                                      |
|  items     |  [Content area]                      |
|            |                                      |
|  grouped   |  max-w-6xl mx-auto px-6 py-6         |
|  by        |                                      |
|  category  |                                      |
|            |                                      |
+--------------------------------------------------+

Sidebar

  • Width: 16rem (256px) expanded, 3rem (48px) collapsed (icon-only mode).
  • Collapsible via a toggle button at the bottom of the sidebar.
  • Collapse state persisted to localStorage via a cookie (for SSR compatibility with next-themes).
  • Background: bg-slate-900 (dark) / bg-white (light) with a right border.
  • Navigation items are grouped by category. Groups are driven by the module registry (src/config/modules.ts).

Navigation structure:

INSTRUMENTE (Tools)
  - Semnatura Email
  - Generator XML Word

ADMINISTRARE (Admin)
  - Etichete Proiecte (Project Tags)
  - Configurare (Settings)

(future groups added via module registry)

Each nav item displays:

  • A Lucide icon (24x24)
  • The module label (from labels.ts)
  • An optional badge (e.g., count of saved configs)

Active state: teal left border + teal-tinted background (bg-teal-500/10).

Header

Fixed at the top of the content area. Contains:

  1. Breadcrumbs (left): Module group > Module name > Sub-page. Uses shadcn Breadcrumb.
  2. Company selector (center-right): Dropdown to switch active company context. Drives branding colors and available configurations.
  3. Theme toggle (right): Sun/Moon icon button. Toggles between dark/light via next-themes.
  4. User area (far right, future): Avatar + dropdown for auth when implemented.

Height: h-14 (56px). Bottom border separator.

Content Area

  • Container: max-w-6xl mx-auto px-4 sm:px-6 py-6
  • For full-width tools (e.g., XML generator with preview): use max-w-7xl or remove max-width constraint.
  • Content scrolls independently of sidebar and header.

Card Patterns

Primary Content Card

The standard content container. Used for forms, configuration panels, output displays.

<Card>
  <CardHeader>
    <CardTitle>Configurare Semnatura</CardTitle>
    <CardDescription>Completati datele pentru generarea semnaturii.</CardDescription>
  </CardHeader>
  <CardContent>
    {/* form fields, content */}
  </CardContent>
  <CardFooter>
    {/* action buttons */}
  </CardFooter>
</Card>

Styling: rounded-xl border with theme-appropriate background. No drop shadows in light mode (border is sufficient). Subtle shadow in dark mode (shadow-lg shadow-black/20).

Stat Card

For dashboard counters and KPIs.

<Card className="p-6">
  <div className="flex items-center justify-between">
    <div>
      <p className="text-sm text-muted-foreground">{label}</p>
      <p className="text-3xl font-bold leading-none mt-1">{value}</p>
    </div>
    <div className="rounded-lg bg-teal-500/10 p-3">
      <Icon className="h-6 w-6 text-teal-500" />
    </div>
  </div>
</Card>

Widget Card

For dashboard widgets (quick actions, recent items, external links).

Same structure as primary content card but with a fixed height and internal scroll if content overflows. Header includes an optional "View all" link.


Form Patterns

Input Groups

Each form field follows this structure:

<div className="space-y-2">
  <Label htmlFor="field-id">{labels.fieldName}</Label>
  <Input id="field-id" {...props} />
  <p className="text-xs text-muted-foreground">{labels.fieldHint}</p>
</div>
  • Labels come from the label constants file (never hardcoded Romanian strings in JSX).
  • Hints are optional text-xs text-muted-foreground paragraphs below the input.
  • Required fields: no asterisk; instead, validation messages appear on submit.

Form Layout

  • Single column for simple forms.
  • Two-column grid (grid grid-cols-1 md:grid-cols-2 gap-4) for forms with many short fields.
  • Full-width fields (textareas, complex inputs) span both columns via md:col-span-2.

Validation Display

Validation errors appear below the field as text-xs text-destructive:

{error && <p className="text-xs text-destructive">{error}</p>}

Input border turns red on error: border-destructive.

Romanian Labels

All user-facing text is sourced from src/core/i18n/labels.ts. Components reference label keys:

import { labels } from '@/core/i18n/labels';

<Label>{labels.signature.fieldName}</Label>

Never write Romanian text directly in JSX. This ensures consistency, makes future i18n possible, and centralizes all copy for review.

Label File Structure

// src/core/i18n/labels.ts

export const labels = {
  common: {
    save: 'Salveaza',
    cancel: 'Anuleaza',
    delete: 'Sterge',
    download: 'Descarca',
    copy: 'Copiaza',
    generate: 'Genereaza',
    reset: 'Reseteaza',
    loading: 'Se incarca...',
    noData: 'Nu exista date.',
    confirm: 'Confirmare',
    search: 'Cauta',
  },
  nav: {
    tools: 'Instrumente',
    admin: 'Administrare',
    emailSignature: 'Semnatura Email',
    xmlGenerator: 'Generator XML Word',
    tagManager: 'Etichete Proiecte',
    settings: 'Configurare',
  },
  signature: {
    title: 'Configurator Semnatura Email',
    fieldPrefix: 'Titulatura (prefix)',
    fieldName: 'Nume si Prenume',
    fieldRole: 'Functia',
    fieldPhone: 'Telefon (format 07xxxxxxxx)',
    sectionColors: 'Culori Text',
    sectionLayout: 'Stil & Aranjare',
    sectionOptions: 'Optiuni',
    optionReply: 'Varianta simpla (fara logo/adresa)',
    optionSuperReply: 'Super-simpla (doar nume/telefon)',
    optionSvg: 'Foloseste imagini SVG (calitate maxima)',
    exportHtml: 'Descarca HTML',
    preview: 'Previzualizare Live',
  },
  xml: {
    title: 'Generator XML pentru Word',
    fieldNamespace: 'Namespace URI',
    fieldRootElement: 'Element radacina',
    fieldList: 'Lista de campuri (unul pe linie)',
    modeSimple: 'Simplu',
    modeAdvanced: 'Avansat',
    categoryLabel: 'Categorii de date',
    addCategory: 'Adauga categorie',
    resetPreset: 'Reset categorie la preset',
    clearFields: 'Curata campurile',
    generateAll: 'Genereaza XML pentru toate categoriile',
    downloadCurrent: 'Descarca XML categorie curenta',
    downloadZip: 'Descarca ZIP cu toate XML-urile',
    previewXml: 'XML categorie curenta',
    previewXpath: 'XPaths categorie curenta',
  },
  // Additional module labels added here as modules are built.
} as const;

export type LabelKey = typeof labels;

Table Patterns

Data tables use shadcn/ui Table components with the following conventions:

  • Header: font-medium text-sm text-muted-foreground, no background color differentiation.
  • Rows: alternating subtle background on hover (hover:bg-muted/50).
  • Sortable columns: click header to toggle. Arrow indicator next to sorted column.
  • Filtering: text input above the table, filters by visible columns.
  • Pagination: below the table. "X of Y results" + page controls.
  • Empty state: centered message inside the table area using labels.common.noData.

For complex data tables, use @tanstack/react-table as the headless engine with shadcn/ui table components for rendering.


Dashboard Widgets

The dashboard home page (/) uses a responsive grid of widget cards.

Layout

<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4">
  {/* stat cards row */}
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 mt-4">
  {/* widget cards */}
</div>

Widget Types

  1. Stat counters: Number of saved signature configs, XML templates, etc. Uses Stat Card pattern.
  2. Recent items: Last 5 saved/exported items across tools. List format inside a widget card.
  3. Quick actions: Buttons to jump to common tasks ("New signature", "New XML template"). Grid of icon+label buttons.
  4. External tool links: If legacy HTML tools are still accessible, link out to them with an "external" icon.

Widgets are defined in a registry and rendered dynamically. Each widget is a self-contained component that fetches its own data.


Icon System

All icons use Lucide React (lucide-react package).

Usage:

import { Mail, FileCode, Settings, ChevronRight } from 'lucide-react';

<Mail className="h-5 w-5" />

Conventions:

  • Navigation icons: h-5 w-5
  • Inline icons (next to text): h-4 w-4
  • Stat card icons: h-6 w-6
  • Button icons: h-4 w-4 mr-2 (left of label) or h-4 w-4 ml-2 (right of label)
  • Icon-only buttons must have a Tooltip or aria-label.

Do not use SVG icons inline. Do not use icon fonts. Do not mix icon libraries.


Spacing and Grid Conventions

All spacing uses Tailwind's default 4px-based scale.

Context Spacing Tailwind
Between form fields 8px space-y-2
Between card sections 16px space-y-4
Card internal padding 24px p-6
Grid gap (cards) 16px gap-4
Page padding (desktop) 24px px-6 py-6
Page padding (mobile) 16px px-4 py-4

Grid uses Tailwind's grid utility with responsive column counts:

  • grid-cols-1 (mobile)
  • md:grid-cols-2 (tablet)
  • lg:grid-cols-3 (desktop)
  • xl:grid-cols-4 (wide desktop, stat cards only)

Responsive Breakpoints

Using Tailwind's default breakpoints:

Breakpoint Min-width Typical device
sm 640px Large phone, small tablet
md 768px Tablet portrait
lg 1024px Tablet landscape, small desktop
xl 1280px Desktop
2xl 1536px Wide desktop

Behavior:

  • Below lg: sidebar collapses to a mobile drawer (shadcn Sheet).
  • Below md: single-column content layout.
  • At lg and above: sidebar visible, two-column form layouts.
  • At xl and above: four-column stat card grid.

Animation Guidelines

Animations are minimal and purposeful. This is a professional tool, not a marketing site.

Allowed animations:

  • Transitions on interactive elements: transition-colors duration-150 on buttons, links, nav items.
  • Sidebar collapse/expand: transition-[width] duration-200 ease-in-out.
  • Card hover elevation (optional): transition-shadow duration-150.
  • Dialog/sheet enter/exit: Use shadcn/ui defaults (Radix UI built-in animations).
  • Skeleton loading: animate-pulse on placeholder blocks during data loading.

Not allowed:

  • Page transition animations.
  • Bouncing, jiggling, or attention-seeking element animations.
  • Parallax or scroll-linked effects.
  • Auto-playing animations that loop indefinitely (except loading spinners).
  • Transform-based hover effects on buttons (hover:scale-105 and similar -- this was used in the legacy HTML tools but is too playful for the dashboard).

Accessibility Baseline

  • All interactive elements must be keyboard navigable.
  • Focus rings: focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2.
  • Color contrast: minimum 4.5:1 for text, 3:1 for large text and UI elements (WCAG AA).
  • Images and icons: alt text on informational images, aria-hidden="true" on decorative icons, aria-label on icon-only buttons.
  • Form fields: every <Input> has an associated <Label> via htmlFor/id.
  • Dialogs: use shadcn/ui Dialog which handles focus trapping and aria-* attributes.
  • No information conveyed by color alone (always pair with text or icon).
  • Reduced motion: respect prefers-reduced-motion by wrapping non-essential animations in motion-safe:.

Summary: Design Tokens Quick Reference

/* globals.css -- theme tokens (simplified) */

:root {
  --background: 0 0% 100%;
  --foreground: 222.2 84% 4.9%;
  --card: 0 0% 100%;
  --card-foreground: 222.2 84% 4.9%;
  --primary: 174 68% 41%;           /* #22B5AB */
  --primary-foreground: 0 0% 100%;
  --muted: 210 40% 96%;
  --muted-foreground: 215.4 16.3% 46.9%;
  --border: 214.3 31.8% 91.4%;
  --ring: 174 68% 41%;
  --radius: 0.75rem;
}

.dark {
  --background: 222.2 84% 2%;       /* #020617 */
  --foreground: 210 40% 93%;
  --card: 222.2 84% 5%;             /* #0f172a */
  --card-foreground: 210 40% 93%;
  --primary: 174 68% 41%;
  --primary-foreground: 0 0% 100%;
  --muted: 217.2 32.6% 17.5%;
  --muted-foreground: 215 20.2% 65.1%;
  --border: 217.2 32.6% 17.5%;
  --ring: 174 68% 41%;
}