PlanTempusApp/PlanTempus.Application/wwwroot/css/COMPONENT-CATALOG.md
Janus C. H. Knudsen 5fab58ff6f Adds double-click to edit support for rates
Enables quick editing of salary rates by double-clicking card inputs

Introduces functionality to:
- Open rates drawer on double-click
- Automatically focus and select corresponding input
- Add temporary highlight to edited row
2026-01-14 18:34:05 +01:00

547 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# SWP Design System - Component Catalog
Reference for alle genbrugelige komponenter. **LAV ALDRIG EN NY KOMPONENT HVIS DEN ALLEREDE EKSISTERER HER.**
---
## Base Patterns (components.css)
**VIGTIGT:** Disse base patterns skal ALTID bruges som foundation for nye features.
### Data Table Pattern (ANBEFALET)
Alle nye tabeller skal bruge `swp-data-table` fra components.css:
```html
<swp-card class="feature-context">
<swp-data-table>
<swp-data-table-header>
<swp-data-table-cell>Kolonne 1</swp-data-table-cell>
<swp-data-table-cell>Kolonne 2</swp-data-table-cell>
</swp-data-table-header>
<swp-data-table-row>
<swp-data-table-cell>Data 1</swp-data-table-cell>
<swp-data-table-cell>Data 2</swp-data-table-cell>
</swp-data-table-row>
</swp-data-table>
</swp-card>
```
**CSS Pattern:**
```css
/* I feature CSS - definer kun kolonner via context class */
swp-card.feature-context swp-data-table {
grid-template-columns: 1fr 120px 80px;
}
/* Kolonne-specifik styling med nth-child */
swp-card.feature-context swp-data-table-cell:nth-child(2) {
font-family: var(--font-mono);
}
```
**VIGTIGT:** Context class skal være på `swp-card`, IKKE en wrapper div!
### List Item Pattern
Alle lister (notifikationer, bookinger, attentions) bruger:
```html
<swp-feature-list> <!-- display: contents -->
<swp-feature-item> <!-- extends swp-list-item-base -->
<!-- content -->
</swp-feature-item>
</swp-feature-list>
```
### Icon Container Pattern
Standard icon wrapper (40×40px cirkel):
```html
<swp-icon-container>
<i class="ph ph-icon"></i>
</swp-icon-container>
```
---
## Page Structure (page.css)
| Element | Beskrivelse | Eksempel |
|---------|-------------|----------|
| `swp-page-container` | Hovedcontainer for side | `<swp-page-container>...</swp-page-container>` |
| `swp-page-header` | Side header med titel og actions | Flex, space-between |
| `swp-page-title` | Titel-wrapper med h1 og p | h1 + subtitle |
| `swp-page-actions` | Action buttons i header | Flex gap |
| `swp-card` | Standard card wrapper | Border, padding, rounded |
| `swp-section-label` | Card section label | Uppercase, 11px, border-bottom |
| `swp-section-header` | Wrapper for label + action | Flex, space-between |
| `swp-section-action` | Action link i section header | Teal, clickable |
| `swp-card-content` | Card indhold | Block |
### Card Header Eksempler
**Simpel label (uden action):**
```html
<swp-card>
<swp-section-label>Kontakter</swp-section-label>
<swp-card-content>...</swp-card-content>
</swp-card>
```
**Label med action:**
```html
<swp-card>
<swp-section-header>
<swp-section-label>Dagens bookinger</swp-section-label>
<swp-section-action>Se alle</swp-section-action>
</swp-section-header>
<swp-card-content>...</swp-card-content>
</swp-card>
```
---
## Stats Components (stats.css)
### Containers
| Element | Kolonner | Brug |
|---------|----------|------|
| `swp-stats-bar` | 4 kolonner | Dashboard stats |
| `swp-stats-grid` | 4 kolonner | Grid layout |
| `swp-stats-row` | 3 kolonner | Feature pages (Employees, etc.) |
### Stat Card
```html
<swp-stat-card class="[variant]">
<swp-stat-value>42</swp-stat-value>
<swp-stat-label>Aktive brugere</swp-stat-label>
</swp-stat-card>
```
**Varianter (class):**
- `highlight` / `teal` - Teal farve
- `success` - Grøn
- `warning` / `amber` - Amber/orange
- `danger` / `negative` / `red` - Rød
- `purple` - Lilla
- `highlight filled` - Filled teal baggrund
**VIGTIGT:** `swp-stat-value` bruger `font-family: var(--font-mono)` automatisk!
---
## Tabs (tabs.css)
```html
<swp-tab-bar>
<swp-tab class="active" data-tab="users">
<i class="ph ph-users"></i>
<span>Brugere</span>
</swp-tab>
<swp-tab data-tab="roles">
<i class="ph ph-shield-check"></i>
<span>Roller</span>
</swp-tab>
</swp-tab-bar>
<swp-tab-content data-tab="users" class="active">
<!-- Content -->
</swp-tab-content>
<swp-tab-content data-tab="roles">
<!-- Content -->
</swp-tab-content>
```
**VIGTIGT:**
- Aktiv tab: `class="active"` (IKKE data-active="true")
- Tab content: `class="active"` for at vise
---
## Buttons (cash.css)
```html
<swp-btn class="primary">
<i class="ph ph-plus"></i>
Tilføj
</swp-btn>
```
**Varianter:**
- `primary` - Teal baggrund, hvid tekst
- `secondary` - Hvid baggrund, border
- `ghost` - Transparent
---
## Badges (cash.css)
**ALLE badges bruger `swp-status-badge`** - kun farve og indhold ændres.
```html
<swp-status-badge class="[variant]">Tekst</swp-status-badge>
```
**Varianter:**
| Class | Farve | Brug |
|-------|-------|------|
| `approved` | Grøn | Godkendt status |
| `active` | Grøn | Aktiv status |
| `paid` | Grøn | Betalt status |
| `draft` | Amber | Kladde status |
| `invited` | Amber | Invitation sendt |
| `pending` | Amber | Afventer status |
| `owner` | Teal | Ejer rolle |
| `admin` | Purple | Admin rolle |
| `leader` | Blue | Leder rolle |
| `employee` | Grå | Medarbejder rolle |
Automatisk dot via `::before` pseudo-element.
---
## Tables - swp-data-table Pattern
**BRUG ALTID `swp-data-table`** for nye tabeller. Den generiske komponent er defineret i components.css.
### Struktur
```html
<swp-card class="context-class">
<swp-data-table>
<swp-data-table-header>
<swp-data-table-cell>Kolonne 1</swp-data-table-cell>
<swp-data-table-cell>Kolonne 2</swp-data-table-cell>
</swp-data-table-header>
<swp-data-table-row>
<swp-data-table-cell>Data 1</swp-data-table-cell>
<swp-data-table-cell>Data 2</swp-data-table-cell>
</swp-data-table-row>
</swp-data-table>
</swp-card>
```
### CSS Pattern
```css
/* Definer kolonner via context class på swp-card */
swp-card.context-class swp-data-table {
grid-template-columns: 1fr 120px 80px;
}
/* Kolonne-specifik styling med nth-child */
swp-card.context-class swp-data-table-cell:nth-child(2) {
font-family: var(--font-mono);
}
```
### Eksisterende tabeller
| Feature | Card Class | CSS fil |
|---------|------------|---------|
| Employees list | `swp-card.employees-list` | employees.css |
| Salary history | `swp-card.salary-history` | employees.css |
| Invoice history | `swp-card.invoice-history` | account.css |
| Stats bookings | `swp-card.stats-bookings` | employees.css |
| Cash | `swp-cash-table` (kompleks) | cash.css |
**Lister (ikke tabeller):**
| Feature | Container | Item | CSS fil |
|---------|-----------|------|---------|
| Bookings | `swp-booking-list` | `swp-booking-item` | bookings.css |
| Notifications | `swp-notification-list` | `swp-notification-item` | notifications.css |
| Attentions | `swp-attention-list` | `swp-attention-item` | attentions.css |
---
## Table Cells - Standard Styling
Base styling er i components.css. Tilpas kun via context class:
```css
/* Header cells (automatisk fra components.css) */
swp-data-table-header swp-data-table-cell {
font-size: var(--font-size-xs);
font-weight: var(--font-weight-semibold);
text-transform: uppercase;
color: var(--color-text-secondary);
}
/* Body cells (automatisk fra components.css) */
swp-data-table-cell {
padding: var(--spacing-4);
font-size: var(--font-size-base);
color: var(--color-text);
}
/* Feature-specifik tilpasning via context */
swp-card.my-feature swp-data-table-cell:nth-child(3) {
text-align: right;
}
```
---
## Icon Buttons (employees.css)
```html
<swp-table-actions>
<swp-icon-btn title="Rediger">
<i class="ph ph-pencil"></i>
</swp-icon-btn>
<swp-icon-btn class="danger" title="Slet">
<i class="ph ph-trash"></i>
</swp-icon-btn>
</swp-table-actions>
```
---
## Edit Forms (employees.css)
Key-value display med valgfri redigering. Bruger Grid + Subgrid for alignment.
### Basis struktur
```html
<swp-edit-section>
<swp-edit-row>
<swp-edit-label>Label tekst</swp-edit-label>
<swp-edit-value>Værdi</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Med redigering</swp-edit-label>
<swp-edit-value contenteditable="true">Redigerbar værdi</swp-edit-value>
</swp-edit-row>
</swp-edit-section>
```
### Med select dropdown
```html
<swp-edit-section>
<swp-edit-row>
<swp-edit-label>Vælg type</swp-edit-label>
<swp-edit-select>
<select>
<option>Option 1</option>
<option>Option 2</option>
</select>
</swp-edit-select>
</swp-edit-row>
</swp-edit-section>
```
### Mono-font for tal
```html
<swp-edit-value class="mono">131,49 kr</swp-edit-value>
```
---
## User Info Pattern (employees.css)
```html
<swp-user-info>
<swp-user-avatar class="[color]">MJ</swp-user-avatar>
<swp-user-details>
<swp-user-name>Maria Jensen</swp-user-name>
<swp-user-email>maria@example.com</swp-user-email>
</swp-user-details>
</swp-user-info>
```
**Avatar farver:** (ingen class = teal), `purple`, `blue`, `amber`
---
## Document List (employees.css)
Genbruges til dokumenter, certificeringer, kurser og lignende lister.
```html
<swp-document-list>
<swp-document-item>
<i class="ph ph-file-pdf"></i>
<swp-document-info>
<swp-document-name>Ansættelseskontrakt.pdf</swp-document-name>
<swp-document-meta>Uploadet 1. aug 2019</swp-document-meta>
</swp-document-info>
<swp-document-actions>
<swp-btn class="secondary sm">Vis</swp-btn>
</swp-document-actions>
</swp-document-item>
</swp-document-list>
```
**Med badge i stedet for knap:**
```html
<swp-document-item>
<i class="ph ph-certificate"></i>
<swp-document-info>
<swp-document-name>Balayage Specialist</swp-document-name>
<swp-document-meta>Udløber: 15. juni 2026</swp-document-meta>
</swp-document-info>
<swp-document-actions>
<swp-status-badge class="valid">Gyldig</swp-status-badge>
</swp-document-actions>
</swp-document-item>
```
---
## Subsection (employees.css)
Til gruppering af lister (f.eks. "Gennemførte kurser" / "Planlagte kurser").
```html
<swp-subsection>
<swp-subsection-title>Gennemførte kurser</swp-subsection-title>
<swp-document-list>
<!-- items -->
</swp-document-list>
</swp-subsection>
```
---
## Simple List (employees.css)
Simpel liste med tekst + badge (f.eks. planlagt fravær).
```html
<swp-simple-list>
<swp-simple-item>
<swp-simple-item-text>23. dec 2. jan 2026</swp-simple-item-text>
<swp-status-badge class="ferie">Ferie</swp-status-badge>
</swp-simple-item>
</swp-simple-list>
```
---
## Salary History Table (employees.css)
Bruger `swp-data-table` med `.salary-history` context class.
```html
<swp-card class="salary-history">
<swp-section-label>Lønhistorik</swp-section-label>
<swp-data-table>
<swp-data-table-header>
<swp-data-table-cell>Periode</swp-data-table-cell>
<swp-data-table-cell>Bruttoløn</swp-data-table-cell>
<swp-data-table-cell></swp-data-table-cell>
</swp-data-table-header>
<swp-data-table-row>
<swp-data-table-cell>Januar 2026</swp-data-table-cell>
<swp-data-table-cell class="mono">34.063,50 kr</swp-data-table-cell>
<swp-data-table-cell><i class="ph ph-caret-right"></i></swp-data-table-cell>
</swp-data-table-row>
</swp-data-table>
</swp-card>
```
Rækker har hover-effekt og chevron bliver teal ved hover.
---
## Add Button (components.css)
Dashed border knap til tilføjelse af elementer.
```html
<swp-add-button>+ Upload dokument</swp-add-button>
<swp-add-button>+ Tilføj certificering</swp-add-button>
```
**Styling:** Dashed border, centreret, hover → teal border og tekst.
---
## Design Tokens (design-tokens.css)
### Farver
| Token | Brug |
|-------|------|
| `--color-teal` | Primary brand, success |
| `--color-green` | Success, positive |
| `--color-amber` | Warning, pending |
| `--color-red` | Error, danger |
| `--color-purple` | Special, AI |
| `--color-blue` | Info |
### Spacing
```css
--spacing-1: 2px;
--spacing-2: 4px;
--spacing-3: 6px;
--spacing-4: 8px;
--spacing-5: 10px;
--spacing-6: 12px;
--spacing-7: 14px;
--spacing-8: 16px;
--spacing-10: 20px;
--spacing-12: 24px;
```
### Font Sizes
```css
--font-size-xs: 11px;
--font-size-sm: 12px;
--font-size-md: 13px;
--font-size-base: 14px; /* Standard body text */
--font-size-lg: 16px;
--font-size-xl: 18px;
--font-size-2xl: 20px;
--font-size-3xl: 22px;
```
### Font Families
```css
--font-family: 'Poppins', sans-serif;
--font-mono: 'JetBrains Mono', monospace; /* Til tal/værdier */
```
---
## Checklist for Ny Side
1. [ ] Læs denne fil
2. [ ] List UI elementer der skal bruges
3. [ ] Match hver element med eksisterende komponent
4. [ ] Dokumenter kun NYE elementer der skal oprettes
5. [ ] Opret feature CSS med header der angiver genbrugte komponenter
6. [ ] Brug `var(--font-size-base)` for body text
7. [ ] Brug `var(--font-mono)` kun for tal/værdier
---
## Fil Reference
| Fil | Indhold |
|-----|---------|
| `design-tokens.css` | Farver, spacing, fonts, shadows |
| `design-system.css` | Base resets, typography |
| `page.css` | Page structure, sticky-header |
| `components.css` | Buttons, badges, cards, section-label, add-button, avatars, icon-btn, **swp-data-table** |
| `stats.css` | Stat cards, stat rows |
| `tabs.css` | Tab bar, tab content |
| `employees.css` | User info, edit forms, document lists, context styles (.employees-list, .salary-history, .stats-bookings) |
| `account.css` | Account/billing styles, context styles (.invoice-history) |
| `bookings.css` | Booking list items |
| `notifications.css` | Notification items |
| `attentions.css` | Attention items |
| `cash.css` | Cash register (swp-cash-table - kompleks, ikke migreret) |