hugin/static/css-framework/.opencode/skills/references/components.md
2026-10-27 08:33:21 +01:00

565 lines
No EOL
14 KiB
Markdown
Raw Permalink 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.

# Komponenten-Referenz
Vollständige Dokumentation aller opt-in Klassen aus `components.css`.
---
## Navigation
### Top Navigation (`.topnav`)
Sticky Navigationsleiste mit Branding, Links und optionalem User-Dropdown.
```html
<nav class="topnav">
<div class="topnav-inner">
<a class="topnav-brand" href="/">Brand</a>
<ul class="topnav-links">
<li><a href="/" class="active">Dashboard</a></li>
<li>
<button data-action="nav-dropdown">
Mehr <svg class="nav-chevron"><!-- Chevron SVG --></svg>
</button>
<div class="topnav-dropdown">
<a href="/settings">Einstellungen</a>
<a href="/profile">Profil</a>
</div>
</li>
</ul>
<div class="topnav-end">
<!-- Buttons, User-Dropdown, Theme-Toggle -->
</div>
<button class="topnav-burger" aria-label="Menü öffnen">☰</button>
</div>
<div class="topnav-mobile">
<!-- Mobile Links -->
</div>
</nav>
```
**Modifier:** `.topnav-static` — nicht sticky
### Sidebar (`.sidebar`)
Feste Seitenleiste für App-Layouts. Wird mit `.with-sidebar` kombiniert.
```html
<!-- Vor dem with-sidebar-Container -->
<div class="mobile-topbar">
<button id="sidebar-toggle" aria-label="Menü öffnen">☰</button>
<span>App Name</span>
</div>
<div id="sidebar-backdrop" class="sidebar-backdrop"></div>
<div class="with-sidebar">
<aside class="sidebar">
<div class="sidebar-header">
<a href="/" class="sidebar-brand">Brand</a>
</div>
<nav class="sidebar-nav">
<div class="sidebar-section">Hauptmenü</div>
<a href="/" class="active">
<svg><!-- Icon --></svg>
Dashboard
<span class="nav-count">4</span>
</a>
<details class="sidebar-group">
<summary><svg><!-- Icon --></svg> Gruppe</summary>
<div class="sidebar-group-items">
<a href="/unterseite">Unterseite</a>
</div>
</details>
</nav>
<div class="sidebar-footer">
<a href="/profil" class="sidebar-user">
<div class="avatar avatar-sm">AM</div>
<div class="sidebar-user-info">
<div class="sidebar-user-name">Anna Müller</div>
<div class="sidebar-user-role">Admin</div>
</div>
</a>
</div>
</aside>
<main class="stack stack-lg">
<!-- Seiteninhalt -->
</main>
</div>
```
### Footer (`.footer`)
```html
<!-- Einfach -->
<footer class="footer">
<div class="footer-inner">
<a class="footer-brand" href="/">Brand</a>
<ul class="footer-links">
<li><a href="/impressum">Impressum</a></li>
<li><a href="/datenschutz">Datenschutz</a></li>
</ul>
<p class="footer-copy">© 2025 Acme GmbH</p>
</div>
</footer>
<!-- Mehrspaltig -->
<footer class="footer footer-full">
<div class="footer-inner">
<div class="footer-col">
<p class="footer-col-title">Produkt</p>
<a href="/features">Features</a>
<a href="/pricing">Preise</a>
</div>
<div class="footer-col">
<p class="footer-col-title">Rechtliches</p>
<a href="/impressum">Impressum</a>
</div>
</div>
<div class="footer-bottom">
<span>© 2025 Acme GmbH</span>
<ul class="footer-social">
<li><a href="https://github.com/..."><svg><!-- GitHub Icon --></svg></a></li>
</ul>
</div>
</footer>
```
---
## Breadcrumbs (`.breadcrumbs`)
```html
<nav class="breadcrumbs" aria-label="Breadcrumb">
<ol>
<li><a href="/dashboard">Dashboard</a></li>
<li><a href="/projekte">Projekte</a></li>
<li><span aria-current="page">Einstellungen</span></li>
</ol>
</nav>
```
Horizontaler Navigationspfad. Auf schmalen Viewports horizontal scrollbar.
---
## Buttons (`.btn`)
Alle Buttons benötigen `.btn` als Basisklasse plus eine Variante.
```html
<!-- Varianten -->
<button class="btn btn-primary">Primary</button>
<button class="btn btn-secondary">Secondary</button>
<button class="btn btn-ghost">Ghost</button>
<button class="btn btn-danger">Danger</button>
<button class="btn btn-success">Success</button>
<!-- Größen (Standardgröße ist keine Größenklasse = medium) -->
<button class="btn btn-primary btn-xs">XSmall</button>
<button class="btn btn-primary btn-sm">Small</button>
<button class="btn btn-primary btn-lg">Large</button>
<button class="btn btn-primary btn-xl">XLarge</button>
<!-- Modifiers -->
<button class="btn btn-primary btn-full">Volle Breite</button>
<button class="btn btn-ghost btn-icon"><svg><!-- Icon --></svg></button>
<!-- Als Link -->
<a href="/ziel" class="btn btn-primary">Link-Button</a>
<!-- Disabled -->
<button class="btn btn-primary" disabled>Gesperrt</button>
<!-- Button Group -->
<div class="button-group" role="group">
<button class="btn btn-secondary">Liste</button>
<button class="btn btn-secondary">Board</button>
<button class="btn btn-secondary">Kalender</button>
</div>
<!-- Segmented Control (Radio-Basis, kein JS) -->
<div class="segmented" role="radiogroup">
<label class="segmented-option" for="r-tag">
<input class="segmented-input" type="radio" name="range" id="r-tag">
<span class="segmented-button">Tag</span>
</label>
<label class="segmented-option" for="r-woche">
<input class="segmented-input" type="radio" name="range" id="r-woche" checked>
<span class="segmented-button">Woche</span>
</label>
<label class="segmented-option" for="r-monat">
<input class="segmented-input" type="radio" name="range" id="r-monat">
<span class="segmented-button">Monat</span>
</label>
</div>
```
---
## Badges (`.badge`)
```html
<span class="badge badge-default">Standard</span>
<span class="badge badge-primary">Primär</span>
<span class="badge badge-success">Erfolg</span>
<span class="badge badge-warning">Warnung</span>
<span class="badge badge-danger">Fehler</span>
<span class="badge badge-info">Info</span>
<span class="badge badge-outline">Outline</span>
<!-- Mit Dot-Indikator -->
<span class="badge badge-success badge-dot">Live</span>
```
---
## Cards (`.card`)
```html
<div class="card">
<div class="card-header">
<h3>Titel</h3>
<span class="badge badge-success">Aktiv</span>
</div>
<div class="card-body">
Inhalt der Karte
</div>
<div class="card-footer">
<button class="btn btn-ghost btn-sm">Abbrechen</button>
<button class="btn btn-primary btn-sm">Aktion</button>
</div>
</div>
```
**Varianten:** `.card-flat`, `.card-raised`, `.card-ghost`
**Hover-Effekt:** `.card.card-hover`
**Image Card:**
```html
<div class="card">
<div class="card-media">
<img src="..." alt="...">
</div>
<div class="card-body">
<h3>Titel</h3>
<p>Beschreibung</p>
</div>
</div>
```
---
## Formulare
Basis-Eingabeelemente (`input`, `select`, `textarea`) werden classless gestylt.
Opt-in Klassen für Gruppierung und Zustände:
```html
<div class="form-group">
<label for="email">E-Mail</label>
<input type="email" id="email" name="email">
<span class="form-hint">Wird für Login genutzt.</span>
</div>
<!-- Fehler-State -->
<div class="form-group">
<label for="pwd">Passwort</label>
<input type="password" id="pwd" class="error">
<span class="form-error">Mindestens 8 Zeichen.</span>
</div>
<!-- Mehrere Felder nebeneinander -->
<div class="form-row">
<div class="form-group">
<label for="vorname">Vorname</label>
<input type="text" id="vorname">
</div>
<div class="form-group">
<label for="nachname">Nachname</label>
<input type="text" id="nachname">
</div>
</div>
<!-- Input mit Prefix/Suffix -->
<div class="input-group">
<span class="input-group-prefix">https://</span>
<input type="text" placeholder="beispiel.de">
</div>
<div class="input-group">
<input type="text" placeholder="Betrag">
<span class="input-group-suffix">EUR</span>
</div>
```
---
## Tabellen
Classless gestylt — kein Wrapper nötig für einfache Tabellen:
```html
<table>
<thead>
<tr><th>Name</th><th>Status</th><th>Datum</th></tr>
</thead>
<tbody>
<tr><td>Anna Müller</td><td><span class="badge badge-success">Aktiv</span></td><td>2025-01-15</td></tr>
</tbody>
</table>
<!-- Mit Rahmen und horizontalem Scroll (z.B. auf Mobile) -->
<div class="table-wrap">
<table>...</table>
</div>
<!-- Modifier -->
<table class="table-striped">...</table>
<table class="table-compact">...</table>
```
---
## Alerts
```html
<div class="alert alert-info">
<svg class="alert-icon"><!-- Icon --></svg>
<div class="alert-content">
<p class="alert-title">Hinweis</p>
<p>Deine Änderungen werden gespeichert.</p>
</div>
</div>
```
**Varianten:** `alert-info`, `alert-success`, `alert-warning`, `alert-danger`
---
## Modals
```html
<!-- Struktur -->
<div class="modal-backdrop" id="mein-modal"
data-action="modal-backdrop">
<div class="modal">
<div class="modal-header">
<h3>Titel</h3>
<button class="btn btn-ghost btn-icon btn-sm"
data-action="modal-close" data-target="mein-modal">✕</button>
</div>
<div class="modal-body">Inhalt</div>
<div class="modal-footer">
<button class="btn btn-ghost" data-action="modal-close" data-target="mein-modal">Abbrechen</button>
<button class="btn btn-primary">Bestätigen</button>
</div>
</div>
</div>
<button data-action="modal-open" data-target="mein-modal">Modal öffnen</button>
```
**Größen:** `.modal-sm`, `.modal-lg`, `.modal-xl`
---
## Tabs
```html
<div class="tabs">
<ul class="tab-list" role="tablist">
<li>
<button class="active" role="tab"
data-action="tab" data-target="panel-1">Tab 1</button>
</li>
<li>
<button role="tab"
data-action="tab" data-target="panel-2">Tab 2</button>
</li>
</ul>
<div id="panel-1" class="tab-panel active">Inhalt Tab 1</div>
<div id="panel-2" class="tab-panel">Inhalt Tab 2</div>
</div>
```
---
## Dropdowns
```html
<div class="dropdown" id="dd-aktionen">
<button class="btn btn-secondary" data-action="dropdown" data-target="dd-aktionen">
Aktionen
</button>
<div class="dropdown-menu">
<div class="dropdown-label">Aktionen</div>
<button class="dropdown-item">Bearbeiten</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item danger">Löschen</button>
</div>
</div>
```
**Positionierung:** `.dropdown-menu-left`, `.dropdown-menu-top`
**Breite:** `.dropdown-wide`
**Spezielle Item-Typen:**
```html
<!-- Mit Beschreibung -->
<button class="dropdown-item dropdown-item-rich">
<div class="dropdown-item-title">Projekt</div>
<div class="dropdown-item-desc">Neue Projektmappe erstellen</div>
</button>
<!-- Checkbox/Filter -->
<button class="dropdown-item dropdown-item-check checked"
data-action="toggle-class" data-class="checked">
Aktiv
</button>
<!-- User-Header -->
<div class="dropdown-header">
<div class="avatar">AM</div>
<div>
<div class="dropdown-header-name">Anna Müller</div>
<div class="dropdown-header-sub">anna@beispiel.de</div>
</div>
</div>
```
---
## Pagination
```html
<ul class="pagination">
<li class="disabled"><a>←</a></li>
<li><a class="active" href="?page=1">1</a></li>
<li><a href="?page=2">2</a></li>
<li><a href="?page=3">3</a></li>
<li><a href="?page=2">→</a></li>
</ul>
```
---
## Feedback & Status-Komponenten
### Spinner
```html
<div class="spinner spinner-sm"></div>
<div class="spinner"></div> <!-- default -->
<div class="spinner spinner-lg"></div>
```
### Fortschrittsbalken
```html
<div class="progress">
<div class="progress-bar" data-progress="75"></div>
</div>
<div class="progress">
<div class="progress-bar success" data-progress="100"></div>
</div>
```
### Skeleton (Lade-Platzhalter)
```html
<div class="skeleton skeleton-line is-short"></div>
<div class="skeleton skeleton-title"></div>
<div class="skeleton skeleton-block"></div>
```
### KPI / Stat
```html
<div class="stat">
<span class="stat-label">Umsatz</span>
<span class="stat-value">€ 48.291</span>
<span class="stat-change up">↑ +12.4%</span>
</div>
<!-- Trend-basierte Einfärbung des Hauptwerts -->
<div class="stat" data-trend="positive">
<span class="stat-label">Saldo</span>
<span class="stat-value">+ € 1.240</span>
</div>
<div class="stat" data-trend="negative">
<span class="stat-label">Saldo</span>
<span class="stat-value">− € 320</span>
</div>
```
### Avatar
```html
<div class="avatar">AM</div>
<div class="avatar avatar-sm">AM</div>
<div class="avatar avatar-lg"><img src="..." alt="Profilbild"></div>
<!-- Avatar Group -->
<div class="avatar-group">
<div class="avatar avatar-sm">AM</div>
<div class="avatar avatar-sm">BS</div>
<div class="avatar avatar-sm">CK</div>
</div>
```
### Empty State
```html
<div class="empty">
<svg class="empty-icon"><!-- Illustration/Icon --></svg>
<p class="empty-title">Keine Einträge</p>
<p class="empty-description">Erstelle deinen ersten Eintrag, um loszulegen.</p>
<button class="btn btn-primary btn-sm">Erstellen</button>
</div>
```
### Toasts
```html
<div class="toast-container" id="toast-container"></div>
<!-- Aus einem Button heraus -->
<button class="btn" data-action="toast" data-message="Gespeichert!" data-type="success">Speichern</button>
<!-- Nach einer HTMX-Antwort: Server setzt HX-Trigger, eigenes Skript (als Datei) reagiert -->
<!-- Response-Header: HX-Trigger: {"toast": {"message": "Gespeichert!", "type": "success"}} -->
<!-- static/js/app.js: document.body.addEventListener('toast', e => showToast(e.detail.message, e.detail.type)); -->
```
### Divider mit Label
```html
<div class="divider">oder</div>
```
### Filter-Leiste
```html
<!-- Flex-Row, auf Mobile gestapelt (< 40rem) -->
<div class="filter-bar">
<div class="form-group">
<label>Monat</label>
<input type="month">
</div>
<div class="form-group">
<label>Typ</label>
<select>
<option>Alle</option>
<option>Einnahme</option>
</select>
</div>
<button class="btn btn-secondary btn-sm">Filtern</button>
</div>
```
---