From 509a541b7029a8068664196890671ceba68762e3 Mon Sep 17 00:00:00 2001 From: Till JS Date: Thu, 2 Apr 2026 13:25:08 +0200 Subject: [PATCH] feat(manacore/web): add minimized tabs bar to todo pages Wire up the minimize/restore/maximize flow for todo pages: - Minimized pages appear as a floating tab bar at the bottom - Each tab shows color dot + title, with maximize and close buttons - Click tab title to restore, click arrows-out to maximize - Tab bar has paper-sheet aesthetic matching the pages - Plus button on tab bar opens page picker - Tabs slide up with animation when pages are minimized Co-Authored-By: Claude Opus 4.6 (1M context) --- .../web/src/routes/(app)/todo/+page.svelte | 195 +++++++++++++++++- 1 file changed, 194 insertions(+), 1 deletion(-) diff --git a/apps/manacore/apps/web/src/routes/(app)/todo/+page.svelte b/apps/manacore/apps/web/src/routes/(app)/todo/+page.svelte index d3965d1c4..d5c8bdf99 100644 --- a/apps/manacore/apps/web/src/routes/(app)/todo/+page.svelte +++ b/apps/manacore/apps/web/src/routes/(app)/todo/+page.svelte @@ -13,7 +13,7 @@ tasksStore, taskTable, } from '$lib/modules/todo'; - import { Plus, PencilSimple, X, Gear } from '@manacore/shared-icons'; + import { Plus, PencilSimple, X, Gear, ArrowsOut } from '@manacore/shared-icons'; import { ShareModal } from '@manacore/shared-uload'; // Components @@ -103,6 +103,45 @@ let expandedPages = $derived(openPages.filter((p) => !p.minimized)); let customPages = $derived(todoSettings.customPages); + // Minimized pages for tab bar + const PAGE_META: Record = { + todo: { title: 'To Do', color: '#6B7280' }, + completed: { title: 'Erledigt', color: '#22C55E' }, + today: { title: 'Heute', color: '#F59E0B' }, + overdue: { title: 'Überfällig', color: '#EF4444' }, + all: { title: 'Alle Aufgaben', color: '#3B82F6' }, + 'high-priority': { title: 'Hohe Priorität', color: '#EF4444' }, + 'this-week': { title: 'Diese Woche', color: '#8B5CF6' }, + 'no-date': { title: 'Ohne Datum', color: '#6B7280' }, + }; + + const ICON_COLORS: Record = { + warning: '#EF4444', + calendar: '#3B82F6', + 'calendar-dots': '#8B5CF6', + check: '#22C55E', + star: '#F59E0B', + lightning: '#F97316', + clock: '#6B7280', + fire: '#EF4444', + leaf: '#22C55E', + heart: '#EC4899', + }; + + let minimizedPages = $derived( + openPages + .filter((p) => p.minimized) + .map((p) => { + const config = getCustomPageConfig(p.id); + const preset = PAGE_META[p.id]; + const title = p.customTitle ?? config?.label ?? preset?.title ?? p.id; + const color = config?.icon + ? (ICON_COLORS[config.icon] ?? '#8B5CF6') + : (preset?.color ?? '#6B7280'); + return { id: p.id, title, color }; + }) + ); + function handleAddPage(pageId: string) { if (!openPages.some((p) => p.id === pageId)) { openPages = [...openPages, { id: pageId, minimized: false }]; @@ -120,6 +159,10 @@ openPages = openPages.map((p) => (p.id === pageId ? { ...p, minimized: true } : p)); } + function handleRestorePage(pageId: string) { + openPages = openPages.map((p) => (p.id === pageId ? { ...p, minimized: false } : p)); + } + function handleMaximizePage(pageId: string) { openPages = openPages.map((p) => p.id === pageId ? { ...p, maximized: !p.maximized, minimized: false } : p @@ -378,6 +421,33 @@ {/if} + + {#if minimizedPages.length > 0} +
+ {#each minimizedPages as page (page.id)} +
+ + + + +
+ {/each} + +
+ {/if} +