# 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.
```tsx
// layout.tsx
import { ThemeProvider } from 'next-themes';
{children}
```
CSS custom properties for the accent color are set on `` based on the active company selection:
```css
: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](https://ui.shadcn.com/). 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.
```tsx
Configurare SemnaturaCompletati datele pentru generarea semnaturii.
{/* form fields, content */}
{/* action buttons */}
```
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.
```tsx
{label}
{value}
```
### 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:
```tsx
{labels.fieldHint}
```
- 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`:
```tsx
{error &&
{error}
}
```
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:
```tsx
import { labels } from '@/core/i18n/labels';
```
Never write Romanian text directly in JSX. This ensures consistency, makes future i18n possible, and centralizes all copy for review.
### Label File Structure
```ts
// 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
```tsx
{/* stat cards row */}
{/* widget cards */}
```
### 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](https://lucide.dev/) (`lucide-react` package).
**Usage:**
```tsx
import { Mail, FileCode, Settings, ChevronRight } from 'lucide-react';
```
**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 `` has an associated `