dbbd54f5a1
- page.tsx: feste Aktionsleiste `fixed bottom-6 right-6 z-20` mit "Widget
hinzufuegen" (nur Bearbeitungsmodus) links neben dem Stift/Haekchen; Block
oben rechts und mt-8-Wrapper entfernt, Grid direkt im Container p-2
(12 + 8 + 8 = 28 px statt 60 px); page.test.tsx NEU mit 3 Tests
- widget-wrapper.tsx: Karte ist im Bearbeitungsmodus der Griff (cursor-grab),
20-px-Overlay-Kopfleiste mit Griff-Symbol und Tooltip dragHint, Loesch-Knopf
in der Kopfleiste mit data-no-drag; Rumpf h-full unveraendert (Hoehenkette)
- dashboard-grid.tsx: WIDGET_DRAG_HANDLE_SELECTOR, WIDGET_DRAG_CANCEL_SELECTOR
(input, textarea, select, button, a, [contenteditable], [data-no-drag],
.widgetNoDrag), threshold 3; FREE_PLACEMENT_COMPACTOR = noCompactor +
preventCollision: true (freie Platzierung bleibt, Commit c8f3361)
- dashboard-grid.test.tsx: Mock per importOriginal (echter noCompactor),
Tests 6-8 (dragConfig-Pin, Compactor-Pin, cancel/handle-Semantik im DOM)
- edit-mode-toggle.tsx: schwebend (shadow-lg, inaktiv border + bg-card)
- de.json/en.json: widgets.dragHint
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
67 lines
2.0 KiB
TypeScript
67 lines
2.0 KiB
TypeScript
'use client';
|
|
|
|
import { useTranslations } from 'next-intl';
|
|
|
|
interface EditModeToggleProps {
|
|
isEditMode: boolean;
|
|
onToggle: () => void;
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
export function EditModeToggle({ isEditMode, onToggle }: EditModeToggleProps) {
|
|
const t = useTranslations('widgets');
|
|
|
|
return (
|
|
<button
|
|
onClick={onToggle}
|
|
className={`inline-flex items-center justify-center rounded-md p-2 shadow-lg transition-colors ${
|
|
isEditMode
|
|
? 'bg-primary text-primary-foreground hover:opacity-90'
|
|
: 'border border-border bg-card text-muted-foreground hover:bg-muted hover:text-foreground'
|
|
}`}
|
|
aria-pressed={isEditMode}
|
|
aria-label={isEditMode ? t('saveChanges') : t('editMode')}
|
|
title={isEditMode ? t('saveChanges') : t('editMode')}
|
|
>
|
|
{isEditMode ? (
|
|
// Checkmark icon
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="20"
|
|
height="20"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<polyline points="20 6 9 17 4 12" />
|
|
</svg>
|
|
) : (
|
|
// Pencil icon
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="20"
|
|
height="20"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
|
|
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
|
|
</svg>
|
|
)}
|
|
</button>
|
|
);
|
|
}
|