diff --git a/UI_GUIDELINES.md b/UI_GUIDELINES.md index a197b0b..20f2558 100644 --- a/UI_GUIDELINES.md +++ b/UI_GUIDELINES.md @@ -58,12 +58,24 @@ Alle Farben sind als CSS-Custom-Properties auf `html` definiert und **müssen** ### Schatten +Alle globalen Schatten-Variablen sind auf `none` gesetzt – das Design ist bewusst schattenlos. + | Variable | Wert | Verwendung | |---|---|---| -| `--app-shadow-sm` | `0 12px 28px rgba(15,23,42,0.08)` | Kleine Karten | -| `--app-shadow-md` | `0 20px 44px rgba(15,23,42,0.10)` | Mittlere Panels | -| `--app-shadow-lg` | `0 28px 72px rgba(15,23,42,0.12)` | Surface-Panels | -| `--app-shadow-xl` | `0 36px 88px rgba(8,18,36,0.24)` | Hero-Bereiche, Dialoge | +| `--app-shadow-sm` | `none` | – | +| `--app-shadow-md` | `none` | – | +| `--app-shadow-lg` | `none` | – | +| `--app-shadow-xl` | `none` | – | + +Auch die Lumo-Schatten-Overrides sind `none`: +```css +--lumo-box-shadow-xs: none; +--lumo-box-shadow-s: var(--app-shadow-sm); /* → none */ +--lumo-box-shadow-m: var(--app-shadow-md); /* → none */ +--lumo-box-shadow-l: var(--app-shadow-lg); /* → none */ +``` + +**Ausnahme**: Buttons behalten eigene Schatten (siehe Abschnitt 24). --- @@ -117,6 +129,7 @@ Der Container, in dem alle gerouteten Views dargestellt werden: .view-container { display: flex; flex-direction: column; + background: transparent; margin: 20px; /* Abstand zum Browserrand */ width: calc(100% - 40px); height: calc(100dvh - 40px); @@ -145,8 +158,9 @@ Jede View muss **genau eine** der folgenden Root-Klassen tragen: | `message-hub-view` | Nachrichten-Übersicht | `Main` | | `statistics-chat-view` | Statistik/Chat | `VerticalLayout` | | `dashboard-view` | Dashboard-Seiten | `VerticalLayout` | -| `landing-view` | Startseite (unauthentifiziert) | `Main` | -| `login-view` | Login-Seite | `Main` | +| `dashboard-home-view` | Haupt-Dashboard (transparenter Hintergrund) | `VerticalLayout` | +| `landing-view` | Startseite (unauthentifiziert, weißer Hintergrund) | `Main` | +| `login-view` | Login-Seite (weißer Hintergrund, fullscreen) | `Main` | ### Kritische Java-Regeln @@ -335,7 +349,48 @@ filterBar.setWidthFull(); --- -## 11. Sidebar / Navigation +## 11. Dashboard Home View + +Die `dashboard-home-view` hat einen transparenten Hintergrund, der den Shell-Gradient durchscheinen lässt. + +```css +.dashboard-home-view { + background: transparent !important; +} +.view-container:has(.dashboard-home-view) { + border-radius: 12px; + background: transparent; + overflow: auto; +} +body:has(.dashboard-home-view) { + background: var(--app-shell-background); +} +/* Surface-Panels und Hero-Panels im Dashboard: kein Border, kein Schatten */ +.dashboard-home-view .surface-panel { + border: 0; + background: transparent; + backdrop-filter: none; + box-shadow: none; +} +.dashboard-home-view .hero-panel { + box-shadow: none; +} +``` + +--- + +## 12. Sidebar / Navigation + +### Drawer Header (klickbar) + +Der Drawer-Header (Logo + App-Name) ist klickbar und navigiert zum Dashboard: + +```java +header.getStyle().set("cursor", "pointer"); +header.getElement().setProperty("title", "Zum Dashboard"); +header.addClickListener(event -> UI.getCurrent().navigate("dashboard")); +// AdminLayout navigiert zu "admin-dashboard" +``` ### Nav-Rows @@ -368,7 +423,7 @@ filterBar.setWidthFull(); --- -## 12. Karten-Hierarchie +## 13. Karten-Hierarchie | Klasse | Radius | Hintergrund | Einsatz | |---|---|---|---| @@ -385,7 +440,7 @@ filterBar.setWidthFull(); --- -## 13. Station Tiles & Kacheln +## 14. Station Tiles & Kacheln ### Station Tile @@ -430,7 +485,7 @@ filterBar.setWidthFull(); --- -## 14. Job Task Cards +## 15. Job Task Cards ```css .job-task-card { @@ -471,7 +526,7 @@ filterBar.setWidthFull(); --- -## 15. Dashboard Stat Cards +## 16. Dashboard Stat Cards ```css .dashboard-stat-card { @@ -504,7 +559,7 @@ filterBar.setWidthFull(); --- -## 16. Message & Chat Components +## 17. Message & Chat Components ### Message Card @@ -561,7 +616,7 @@ filterBar.setWidthFull(); --- -## 17. Dialoge +## 18. Dialoge ```css vaadin-dialog-overlay::part(content) { @@ -593,7 +648,7 @@ vaadin-dialog-overlay::part(content) { --- -## 18. Detail Cards +## 19. Detail Cards ```css .detail-card { @@ -615,7 +670,7 @@ vaadin-dialog-overlay::part(content) { --- -## 19. Route & Summary Cards +## 20. Route & Summary Cards ```css .route-card, @@ -638,37 +693,47 @@ vaadin-dialog-overlay::part(content) { --- -## 20. Login Seite +## 21. Login Seite + +Die Login-Seite verwendet ein **einspaltiges**, zentriertes Layout ohne Highlight-Panel. ```css -.login-shell { - width: min(1120px, 100%); - display: grid; - grid-template-columns: minmax(0, 1.15fr) minmax(360px, 440px); - gap: 1.5rem; +.login-view { + padding-inline: 0; + background: var(--app-shell-background) !important; + min-height: 100vh; + min-height: 100dvh; } -.login-highlight { - position: relative; - overflow: hidden; - min-height: 560px; - padding: clamp(1.8rem, 4vw, 3rem); - border-radius: 32px; - border: 1px solid rgba(255,255,255,0.14); - background: linear-gradient(140deg, #081224 0%, #173d8d 52%, #0f766e 100%); - box-shadow: var(--app-shadow-xl); +.login-shell { + width: min(750px, 100%); + display: grid; + grid-template-columns: 1fr; + gap: 1.5rem; } .login-card { width: 100%; padding: clamp(1.35rem, 3vw, 2rem); border-radius: 32px; border: 1px solid var(--app-border-strong); - background: rgba(255,255,255,0.88); - backdrop-filter: blur(20px); + background: #ffffff; box-shadow: var(--app-shadow-lg); } +.login-card vaadin-login-form-wrapper { + background: #ffffff !important; +} ``` -### Eyebrow Chip +### Java-Aufbau (LoginView) + +```java +// Login-Card enthält direkt: flashBox, loginForm, 2FA-Felder, registerButton, versionSpan +// KEIN login-highlight Panel, KEIN H1-Titel (login-card-title entfernt) +loginLayout.add(flashBox, loginForm, twoFaField, verify2faButton, registerButton, versionSpan); +Div loginShell = new Div(loginLayout); +loginShell.addClassName("login-shell"); +``` + +### Eyebrow Chip (Landing Page) ```css .eyebrow-chip { @@ -687,7 +752,20 @@ vaadin-dialog-overlay::part(content) { --- -## 21. Landing Page +## 22. Landing Page + +```css +.landing-view { + padding: 20px; + gap: 20px; + background: #ffffff !important; + min-height: 100vh; + min-height: 100dvh; +} +body:has(.landing-view) { + background: #ffffff; +} +``` ```css .landing-header { @@ -736,7 +814,7 @@ vaadin-dialog-overlay::part(content) { --- -## 22. Timeline Components +## 23. Timeline Components ```css .timeline-entry-card { @@ -760,7 +838,7 @@ vaadin-dialog-overlay::part(content) { --- -## 23. Invoice Components +## 24. Invoice Components ### Invoice Generator @@ -821,7 +899,7 @@ vaadin-dialog-overlay::part(content) { --- -## 24. Buttons +## 25. Buttons ```css vaadin-button { @@ -832,26 +910,64 @@ vaadin-button { vaadin-button:not([disabled]):hover { transform: translateY(-1px); } + +/* Primary Buttons – eigene Schatten (Ausnahme vom globalen none) */ vaadin-button[theme~="primary"] { box-shadow: 0 8px 20px rgba(37,99,235,0.22); } +vaadin-button[theme~="primary"]:not([disabled]):hover { + box-shadow: 0 12px 28px rgba(37,99,235,0.32); +} + +/* Success Primary */ vaadin-button[theme~="primary"][theme~="success"] { box-shadow: 0 8px 20px rgba(5,150,105,0.24); } +vaadin-button[theme~="primary"][theme~="success"]:not([disabled]):hover { + box-shadow: 0 12px 28px rgba(5,150,105,0.34); +} + +/* Error Primary */ vaadin-button[theme~="primary"][theme~="error"] { box-shadow: 0 8px 20px rgba(220,38,38,0.24); } + +/* Tertiary Error Hover */ +vaadin-button[theme~="tertiary"][theme~="error"]:not([disabled]):hover { + background: rgba(220,38,38,0.08); + transform: translateY(-1px); +} + +/* Disabled */ vaadin-button[disabled] { opacity: 0.46; transform: none !important; } ``` +### Button-Varianten-Konvention (Java) + +| Rolle | Theme-Variante | Beispiel | +|---|---|---| +| Hauptaktion (Erstellen, Speichern, Anwenden) | `LUMO_PRIMARY` | `addButton`, `applyFilter` | +| Sekundäraktion (Abbrechen, Zurück, Export, Paginierung) | `LUMO_TERTIARY` | `cancelButton`, `backButton`, `exportButton` | +| Gefährliche Aktion (Löschen) | `LUMO_ERROR` | `deleteButton` | + +```java +// ✅ Sekundäre Buttons immer mit LUMO_TERTIARY: +cancelButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY); +backButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY); +exportButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY); + +// ✅ Primäre Buttons mit LUMO_PRIMARY: +addButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); +``` + **Pill-Buttons** (Nav, Landing): `border-radius: 999px` --- -## 25. Overflow & Box-Model Regeln +## 26. Overflow & Box-Model Regeln ### Pflicht bei allen Container-Elementen @@ -878,7 +994,7 @@ In Flex-Containern verhindert die Default-Eigenschaft `min-width: auto`, dass Fl --- -## 26. Lumo-Override-Strategie +## 27. Lumo-Override-Strategie ### Padding-Override @@ -903,16 +1019,17 @@ vaadin-vertical-layout.data-view { --- -## 27. Responsive Verhalten +## 28. Responsive Verhalten ### Breakpoints | Breakpoint | Änderungen | |---|---| -| `max-width: 980px` | Login-Shell wird einspaltig | | `max-width: 720px` | `view-container` Margin reduziert auf 10px, border-radius auf 8px | | `max-height: 820px` | Drawer-Header und Nav-Rows bekommen kompakteres Padding | +> **Hinweis**: Login-Shell ist jetzt immer einspaltig – der alte 980px-Breakpoint entfällt. + ### Mobile View-Container ```css @@ -936,7 +1053,7 @@ layout.getStyle().set("flex-wrap", "wrap"); --- -## 28. Photo Gallery +## 29. Photo Gallery ```css .job-photo-gallery { @@ -973,7 +1090,7 @@ layout.getStyle().set("flex-wrap", "wrap"); --- -## 29. Empty State +## 30. Empty State ```css .empty-state-card { @@ -988,7 +1105,7 @@ layout.getStyle().set("flex-wrap", "wrap"); --- -## 30. Inline Flash (Fehlermeldungen) +## 31. Inline Flash (Fehlermeldungen) ```css .inline-flash { @@ -1004,7 +1121,7 @@ layout.getStyle().set("flex-wrap", "wrap"); --- -## 31. Checkliste für neue Views +## 32. Checkliste für neue Views Beim Erstellen einer neuen View folgende Punkte prüfen: @@ -1018,3 +1135,4 @@ Beim Erstellen einer neuen View folgende Punkte prüfen: - [ ] Grid-Panel verwendet `surface-panel data-grid-panel` mit `setWidthFull()` - [ ] Schmale Formular-Container haben `setWidth("Xpx")` **und** `setMaxWidth("100%")` - [ ] Inline-Styles nur für dynamische Werte verwenden, alles andere per CSS-Klassen +- [ ] Sekundäre Buttons (`Abbrechen`, `Zurück`, `Export`) haben `LUMO_TERTIARY`, Hauptaktionen haben `LUMO_PRIMARY`