| name | frontend-design-guide |
| description | Defines the visual design system for the travel expense application, including colors, typography, and styles for navigation, tables, forms, and modals. All frontend components must follow these guidelines to ensure a consistent user experience. |
Frontend Design Guide
This skill defines the visual design system for the travel expense application. All frontend components must follow these guidelines.
Color Palette
Use CSS custom properties (variables) defined in the global stylesheet:
:root {
--color-nav-bg: #1a2f4e;
--color-nav-text: #ffffff;
--color-nav-hover: #243d60;
--color-header-bg: #4472c4;
--color-header-text: #ffffff;
--color-primary: #0078d4;
--color-primary-hover: #006cbe;
--color-primary-text: #ffffff;
--color-bg-app: #f0f0f0;
--color-bg-surface: #ffffff;
--color-bg-row-alt: #f5f8ff;
--color-bg-row-hover: #dce8f8;
--color-bg-selected: #cce0f5;
--color-field-required-bg: #fffde7;
--color-field-required-border: #e0a800;
--color-field-error-bg: #fff0f0;
--color-field-error-border: #d32f2f;
--color-error: #d32f2f;
--color-error-light: #fde8e8;
--color-warning: #e6a000;
--color-success: #2e7d32;
--color-text-primary: #1a1a1a;
--color-text-secondary:#555555;
--color-text-muted: #888888;
--color-text-disabled: #aaaaaa;
--color-border: #cccccc;
--color-border-light: #e0e0e0;
--shadow-panel: 0 4px 16px rgba(0, 0, 0, 0.18);
--shadow-card: 0 1px 4px rgba(0, 0, 0, 0.10);
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 24px;
--space-6: 32px;
--space-7: 48px;
--radius-sm: 2px;
--radius-md: 4px;
--radius-lg: 8px;
--font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
--font-size-xs: 11px;
--font-size-sm: 12px;
--font-size-base: 13px;
--font-size-md: 14px;
--font-size-lg: 16px;
--font-size-xl: 20px;
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-bold: 600;
--line-height: 1.4;
}
Typography
- Font family:
'Segoe UI', system-ui, -apple-system, sans-serif
- Body text: 13 px,
var(--font-weight-normal)
- Labels / secondary text: 12–13 px,
var(--color-text-secondary)
- Navigation items: 13 px, uppercase, letter-spacing 0.04 em
- Section headings (inside panels): 15–16 px,
var(--font-weight-bold), uppercase
- Column headers: 12–13 px,
var(--font-weight-medium)
Top Navigation Bar
.nav-bar {
background: var(--color-nav-bg);
color: var(--color-nav-text);
height: 42px;
display: flex;
align-items: center;
padding: 0 var(--space-4);
gap: var(--space-5);
font-size: var(--font-size-base);
letter-spacing: 0.04em;
text-transform: uppercase;
}
.nav-item {
cursor: pointer;
padding: var(--space-2) var(--space-3);
border-radius: var(--radius-sm);
}
.nav-item:hover {
background: var(--color-nav-hover);
}
- Right side: user name, notification bell, keyboard icon – all in white
- Environment badge ("DEV") uses a red pill badge
Data Grid / Table
.data-grid {
width: 100%;
border-collapse: collapse;
font-size: var(--font-size-base);
}
.data-grid thead th {
background: var(--color-header-bg);
color: var(--color-header-text);
padding: var(--space-2) var(--space-3);
text-align: left;
font-weight: var(--font-weight-medium);
font-size: var(--font-size-sm);
user-select: none;
border-right: 1px solid rgba(255,255,255,0.2);
}
.data-grid tbody tr {
border-bottom: 1px solid var(--color-border-light);
background: var(--color-bg-surface);
}
.data-grid tbody tr:nth-child(even) {
background: var(--color-bg-row-alt);
}
.data-grid tbody tr:hover {
background: (--color-bg-row-hover);
: pointer;
}
{
: (--color-bg-selected);
}
{
: (--space-) (--space-);
: middle;
}
- Column headers have a drag-handle / reorder area and a 3-dot context menu (⋮) icon
- A checkbox column on the far left enables multi-select
- A toolbar above the grid contains: + Hinzufügen, Bearbeiten, Kopieren, Löschen, Aktualisieren (icon + label, flat buttons)
- A grouping hint row appears below the toolbar: "Drag a column header and drop it here to group by that column"
- Row count and a search icon appear on the right side of the toolbar area
Action / Toolbar Buttons
.btn {
display: inline-flex;
align-items: center;
gap: var(--space-1);
padding: var(--space-1) var(--space-3);
border-radius: var(--radius-sm);
font-size: var(--font-size-base);
font-family: var(--font-family);
cursor: pointer;
border: 1px solid transparent;
white-space: nowrap;
}
.btn-primary {
background: var(--color-primary);
color: var(--color-primary-text);
border-color: var(--color-primary);
}
.btn-primary:hover {
background: var(--color-primary-hover);
border-color: var(--color-primary-hover);
}
.btn-secondary {
background: var(--color-bg-surface);
color: var(--color-text-primary);
border-color: var(--color-border);
}
.btn-secondary:hover {
background: var(--color-bg-row-alt);
}
{
: transparent;
: (--color-text-primary);
: none;
: (--space-) (--space-);
}
{
: (--color-bg-row-alt);
}
- Modal footer button order: Primary action (e.g. "Speichern & schließen") → Secondary ("Speichern") → Cancel ("Abbrechen")
Modal / Side Panel
The detail form opens as an overlay panel anchored to the right side of the viewport.
.panel {
background: var(--color-bg-surface);
box-shadow: var(--shadow-panel);
border-radius: var(--radius-md) 0 0 var(--radius-md);
display: flex;
flex-direction: column;
min-width: 480px;
max-width: 680px;
}
.panel-header {
padding: var(--space-3) var(--space-4);
border-bottom: 1px solid var(--color-border-light);
display: flex;
align-items: center;
gap: var(--space-2);
}
.panel-tabs {
display: flex;
gap: 0;
padding: 0 var(--space-4);
border-bottom: 2px solid var(--color-border-light);
}
.panel-tab {
padding: var(--space-2) var(--space-4);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
: uppercase;
: ;
: (--color-text-secondary);
: pointer;
: solid transparent;
: -;
}
{
: (--color-primary);
: (--color-primary);
}
{
: (--font-size-base);
: (--font-weight-bold);
: uppercase;
: ;
}
{
: (--space-);
: ;
: auto;
}
{
: (--space-) (--space-);
: solid (--color-border-light);
: flex;
: center;
: (--space-);
}
- Top-right corner of the panel: ▶ (navigate to detail view) and ✕ (close) icons
- The panel title repeats the entity name in uppercase
Form Layout
Forms inside panels use a two-column grid: label on the left (~180 px fixed), input filling the right.
.form-grid {
display: grid;
grid-template-columns: 180px 1fr;
gap: var(--space-3) var(--space-4);
align-items: center;
}
.form-label {
font-size: var(--font-size-base);
color: var(--color-text-primary);
text-align: right;
padding-right: var(--space-3);
}
.form-input {
width: 100%;
height: 28px;
padding: 0 var(--space-2);
border: 1px solid var(--color-border);
border-radius: var(--radius-sm);
font-size: var(--font-size-base);
font-family: var(--font-family);
color: var(--color-text-primary);
background: var(--color-bg-surface);
box-sizing: border-box;
}
.form-input:focus {
outline: none;
border-color: var(--color-primary);
box-shadow: 0 (, , , );
}
() {
: (--color-field-required-bg);
: (--color-field-required-border);
}
{
: (--color-field-error-bg);
: (--color-field-error-border);
}
Validation & Errors
- Required fields get a pale yellow background and amber border before the user interacts
- After a failed submit attempt, required-but-empty fields switch to red border
- An error summary appears at the bottom of the panel footer:
- Red triangle icon +
"Feldname ist ein Pflichtfeld!" inline message in red
- A pill badge:
"N Fehler – alle anzeigen ▼" (dark red background, white text) that expands
.validation-message {
color: var(--color-error);
font-size: var(--font-size-sm);
display: flex;
align-items: center;
gap: var(--space-1);
}
.error-summary-badge {
background: var(--color-error);
color: #fff;
border-radius: 20px;
padding: var(--space-1) var(--space-3);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
cursor: pointer;
display: inline-flex;
align-items: center;
gap: var(--space-1);
}
Page / Section Header
.page-header {
height: 40px;
background: var(--color-bg-app);
padding: 0 var(--space-4);
display: flex;
align-items: center;
gap: var(--space-3);
border-bottom: 1px solid var(--color-border-light);
}
.page-title {
font-size: var(--font-size-base);
font-weight: var(--font-weight-bold);
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--color-text-primary);
}
- A Filter toggle link (with chevron icon) appears next to the page title
- "Filter anwenden" button in the top-right, styled as
btn-primary
- Element count ("30 Elemente") and a search icon on the far right
Icons
Use lightweight SVG icons or a well-known icon library (e.g. Lucide, Tabler Icons, or Heroicons outlined). Keep icon sizes consistent:
- Navigation & toolbar: 16 × 16 px
- Inline / form: 14 × 14 px
- Status badges: 12 × 12 px
Responsive Behavior
The layout is a desktop-first business application:
- Minimum supported viewport: 1024 px wide
- The side panel overlays the grid; the grid is not resized
- No mobile-specific breakpoints are required
General Rules
- Use CSS custom properties for all colors, spacing, and font sizes – never hardcode values.
- Prefer flat, minimal design: subtle borders, little rounding, no gradients on interactive controls.
- All interactive elements must have a visible
:focus-visible outline using var(--color-primary).
- Text must meet WCAG AA contrast against its background.
- German UI strings use the formal "Sie" form.
- Date/number formatting follows Austrian/German locale (
de-AT): dd.MM.yyyy, decimal comma.