feat(web): Dashboard-Aktionen in die App-Leiste, Bearbeiten als Stift
Tessera CI/CD / Build & Publish Images (push) Successful in 2m53s
Tessera CI/CD / Lint & Type Check (push) Successful in 1m3s
Tessera CI/CD / Tests (push) Successful in 1m35s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 5m9s

Der Knopf Bearbeiten belegte eine eigene Zeile ueber den Widgets. Die
Aktionen rendern jetzt per Portal in einen Einhaengepunkt rechts in der
Kopfzeile (HEADER_ACTIONS_SLOT_ID); in der Ansicht nur der Stift, im
Bearbeitungsmodus Hintergrund, Widget hinzufuegen und Fertig. Version 1.5.1.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-28 23:12:38 +02:00
parent 03026d616f
commit bdaa3c8db5
7 changed files with 87 additions and 54 deletions
@@ -227,7 +227,9 @@ export function BackgroundPicker({ value, onChange }: BackgroundPickerProps) {
onClick={() => setOpen((v) => !v)}
aria-expanded={open}
aria-haspopup="dialog"
className="btn btn-subtle"
aria-label={t('button')}
title={t('button')}
className="btn btn-appbar"
>
<svg
aria-hidden="true"
@@ -245,7 +247,8 @@ export function BackgroundPicker({ value, onChange }: BackgroundPickerProps) {
<circle cx="9" cy="9" r="2" />
<path d="m21 15-3.1-3.1a2 2 0 0 0-2.8 0L6 21" />
</svg>
{t('button')}
{/* In der App-Leiste ist der Platz knapp: Beschriftung erst ab lg. */}
<span className="hidden lg:inline">{t('button')}</span>
</button>
{open && (
@@ -10,9 +10,9 @@ interface EditModeToggleProps {
/**
* Pencil / Checkmark icon button to toggle dashboard edit mode (D-01).
* Active state (edit mode) uses primary background.
* Schwebt in der festen Aktionsleiste unten rechts (quick-260916-dyv):
* inaktiv mit Karten-Hintergrund, Rahmen und Schatten, damit der Stift
* ueber Widgets sichtbar bleibt.
* Sitzt seit quick-260928-vxe rechts in der dunklen App-Leiste: in der
* Ansicht nur der Stift (Name per aria-label/Tooltip), im Bearbeitungsmodus
* der gelbe Knopf „Fertig“.
*/
export function EditModeToggle({ isEditMode, onToggle }: EditModeToggleProps) {
const t = useTranslations('widgets');
@@ -21,8 +21,9 @@ export function EditModeToggle({ isEditMode, onToggle }: EditModeToggleProps) {
<button
type="button"
onClick={onToggle}
className={`btn ${isEditMode ? 'btn-primary' : 'btn-subtle'}`}
className={`btn ${isEditMode ? 'btn-primary' : 'btn-appbar btn-icon'}`}
aria-pressed={isEditMode}
aria-label={isEditMode ? undefined : t('editShort')}
title={isEditMode ? t('saveChanges') : t('editMode')}
>
{isEditMode ? (
@@ -60,7 +61,7 @@ export function EditModeToggle({ isEditMode, onToggle }: EditModeToggleProps) {
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
</svg>
)}
{isEditMode ? t('done') : t('editShort')}
{isEditMode ? t('done') : null}
</button>
);
}
@@ -4,3 +4,11 @@
* zeichnen per `createPortal` hinein (heute: die Dashboard-Reiter).
*/
export const HEADER_CENTER_SLOT_ID = 'header-center-slot';
/**
* Einhaengepunkt rechts in der Kopfzeile, vor „Fehler melden“ (quick-260928-vxe).
* Das Dashboard zeichnet dort seine Aktionen hinein (Bearbeiten, im
* Bearbeitungsmodus Hintergrund, Widget hinzufuegen, Fertig) — so belegen sie
* keine eigene Zeile ueber den Widgets.
*/
export const HEADER_ACTIONS_SLOT_ID = 'header-actions-slot';
+5 -1
View File
@@ -10,7 +10,7 @@ import { fetchSessionState, logout } from '@/lib/auth-actions';
import { buildNextParam } from '@/lib/safe-next';
import { ThemeToggle } from '@/components/theme-toggle';
import { BugReportButton } from '@/components/bug-report/bug-report-button';
import { HEADER_CENTER_SLOT_ID } from '@/components/layout/header-slot';
import { HEADER_ACTIONS_SLOT_ID, HEADER_CENTER_SLOT_ID } from '@/components/layout/header-slot';
import { usePathname } from 'next/navigation';
import { resolvePageTitle, useNavStore } from '@/lib/stores/nav-store';
@@ -169,6 +169,10 @@ export function Header() {
{/* Right: Actions */}
<div className="flex shrink-0 items-center gap-1">
{/* Einhaengepunkt fuer die Dashboard-Aktionen (quick-260928-vxe);
bleibt im React-Baum der Kopfzeile leer, `empty:hidden` nimmt ihm
auf anderen Seiten den Abstand. */}
<div id={HEADER_ACTIONS_SLOT_ID} className="flex items-center gap-1 empty:hidden" />
<BugReportButton />
<ThemeToggle />