feat(web): Design Mosaik Runde 3 - Reiter in der Seitenleiste, lebendigere Kacheln
- Dashboard-Reiter stehen in der aufgeklappten Seitenleiste als Liste unter "Dashboard" (Ziehen sortiert senkrecht, Umbenennen/Loeschen/Neu im Bearbeitungsmodus); eingeklappt und auf dem Handy wie bisher in der Kopfzeile. Die Kopfzeile zeigt sonst den Namen des Dashboards. - Begruessung einzeilig auf Hoehe der Befehlsleiste. - Kachel-Groesse: kollidiert die gezogene Groesse mit einem Nachbarn, wird nur die freie Achse uebernommen - vorher verwarf react-grid-layout mit preventCollision die ganze Aenderung, sobald die Maus eine Zeile nach unten wackelte (Favoriten liessen sich deshalb oft nicht schmaler ziehen). - Ansicht: belegte Spalten mittig, Begruessung/Befehlsleiste ruecken mit. - Kalender: einzeilige Terminliste mit "Heute"/"Morgen" in Akzentfarbe, Ort im Tooltip, Standardhoehe 16 statt 12. - Hintergrund "Bluete" im Dunkelmodus weggelassen (Farbstufen), Ersatz Nebel. - Kacheln: Symbol-Chip in der Akzentfarbe, leichtes Anheben beim Zeigen, gestaffeltes Einblenden beim Laden (ohne bei reduzierter Bewegung). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import { AppVersionBadge } from '@/components/layout/app-version-badge';
|
||||
import { ModuleTile } from '@/components/modules/module-tile';
|
||||
import { useCategoryLabel } from '@/lib/use-category-label';
|
||||
import { useNavStore } from '@/lib/stores/nav-store';
|
||||
import { SIDEBAR_DASHBOARD_SLOT_ID } from '@/components/layout/header-slot';
|
||||
|
||||
/** Fluent-Auswahlmarke: 3 x 16 px Pille am linken Rand des gewaehlten Eintrags. */
|
||||
function SelectionPill() {
|
||||
@@ -128,7 +129,10 @@ export function Sidebar() {
|
||||
</svg>
|
||||
);
|
||||
|
||||
const sidebarContent = (
|
||||
// `inDrawer`: die mobile Schublade rendert denselben Inhalt ein zweites
|
||||
// Mal — der Einhaengepunkt der Dashboard-Reiter darf nur einmal im DOM
|
||||
// stehen und gehoert zur Desktop-Leiste.
|
||||
const renderContent = (inDrawer: boolean) => (
|
||||
<div className="flex h-full flex-col bg-sidebar">
|
||||
<nav className={`flex-1 overflow-y-auto py-3 ${isCollapsed ? 'px-2' : 'px-3'}`}>
|
||||
<ul className="flex flex-col gap-0.5">
|
||||
@@ -145,6 +149,9 @@ export function Sidebar() {
|
||||
)}
|
||||
{!isCollapsed && <span className="truncate">{t('dashboard')}</span>}
|
||||
</Link>
|
||||
{/* Dashboard-Reiter (Runde 3): `DashboardTabs` zeichnet per Portal
|
||||
hierher, der Punkt bleibt im React-Baum der Leiste leer. */}
|
||||
{!inDrawer && !isCollapsed && <div id={SIDEBAR_DASHBOARD_SLOT_ID} />}
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/marketplace" className={linkClass('/marketplace')} aria-label={t('marketplace')} title={isCollapsed ? t('marketplace') : undefined}>
|
||||
@@ -275,7 +282,7 @@ export function Sidebar() {
|
||||
: 'var(--sidebar-width)',
|
||||
}}
|
||||
>
|
||||
{sidebarContent}
|
||||
{renderContent(false)}
|
||||
</aside>
|
||||
|
||||
{isMobileOpen && (
|
||||
@@ -307,7 +314,7 @@ export function Sidebar() {
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div className="min-h-0 flex-1">{sidebarContent}</div>
|
||||
<div className="min-h-0 flex-1">{renderContent(true)}</div>
|
||||
</aside>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user