feat(web): Widget-Titel je Widget ausblenden, Seitenleiste gegliedert
Neuer Schalter im Bearbeitungsmodus (neben dem Griff) setzt hideTitle in der Widget-Konfiguration (setWidgetConfig im Dashboard-Store, optimistisch mit Ruecksetzen); in der Ansicht entfaellt die Titelzeile per data-hide-title, Aktionen der Titelzeile bleiben oben rechts. Kategorien der Seitenleiste 14 px, Moduleintraege 13 px / 32 px hoch. Version 1.5.2. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import type { CSSProperties } from 'react';
|
||||
import { useDashboardStore } from '@/lib/stores/dashboard-store';
|
||||
import { WIDGET_REGISTRY, type WidgetType } from '../widget-registry';
|
||||
import { WidgetIcon } from './widget-icon';
|
||||
|
||||
@@ -14,6 +15,14 @@ import { WidgetIcon } from './widget-icon';
|
||||
*/
|
||||
const FRAME_HEADER_TYPES = new Set(['calendar', 'clock', 'calculator', 'stopwatch']);
|
||||
|
||||
/**
|
||||
* Kacheltypen mit Titelzeile — nur diese bekommen im Bearbeitungsmodus den
|
||||
* Schalter „Titel ausblenden“ (quick-260928-wtt). Die Wahl steht als
|
||||
* `hideTitle: true` in der Widget-Konfiguration und gilt nur in der Ansicht;
|
||||
* im Bearbeitungsmodus bleibt der Titel sichtbar (und editierbar).
|
||||
*/
|
||||
const TITLE_TYPES = new Set([...FRAME_HEADER_TYPES, 'note', 'favorites', 'proxmox', 'xframe']);
|
||||
|
||||
interface WidgetWrapperProps {
|
||||
widget: {
|
||||
id: string;
|
||||
@@ -42,6 +51,9 @@ export function WidgetWrapper({ widget, isEditMode, onRemove, enterIndex = 0 }:
|
||||
const t = useTranslations('widgets');
|
||||
const definition = WIDGET_REGISTRY[widget.widgetType as WidgetType];
|
||||
const WidgetComponent = definition?.component;
|
||||
const setWidgetConfig = useDashboardStore((state) => state.setWidgetConfig);
|
||||
const hasTitle = TITLE_TYPES.has(widget.widgetType);
|
||||
const titleHidden = widget.config?.hideTitle === true;
|
||||
|
||||
// Design „Mosaik“: in der Ansicht eine ruhige Fluent-Karte (hell Schatten,
|
||||
// dunkel Haarlinie), die Akzent-Umrandung nur im Bearbeitungsmodus.
|
||||
@@ -54,6 +66,7 @@ export function WidgetWrapper({ widget, isEditMode, onRemove, enterIndex = 0 }:
|
||||
className={cardClassName}
|
||||
style={{ '--enter-delay': `${Math.min(enterIndex, 8) * 80}ms` } as CSSProperties}
|
||||
data-widget-id={widget.id}
|
||||
data-hide-title={!isEditMode && hasTitle && titleHidden ? '' : undefined}
|
||||
aria-label={definition ? t(definition.nameKey) : widget.widgetType}
|
||||
>
|
||||
{/* Edit mode: Overlay-Kopfleiste (Griff-Hinweis) mit Loesch-Knopf rechts.
|
||||
@@ -81,6 +94,39 @@ export function WidgetWrapper({ widget, isEditMode, onRemove, enterIndex = 0 }:
|
||||
<circle cx="12" cy="15" r="1.5" />
|
||||
<circle cx="19" cy="15" r="1.5" />
|
||||
</svg>
|
||||
{hasTitle && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
void setWidgetConfig(widget.id, { hideTitle: !titleHidden });
|
||||
}}
|
||||
className={`ml-1.5 flex h-5 w-5 items-center justify-center rounded-full bg-card transition-colors hover:bg-muted hover:text-foreground ${titleHidden ? 'text-muted-foreground/60' : 'text-muted-foreground'}`}
|
||||
aria-label={titleHidden ? t('showTitle') : t('hideTitle')}
|
||||
title={titleHidden ? t('showTitle') : t('hideTitle')}
|
||||
aria-pressed={titleHidden}
|
||||
data-no-drag=""
|
||||
>
|
||||
{/* „T“ mit Querstrich, solange der Titel ausgeblendet ist */}
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="12"
|
||||
height="12"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<polyline points="4 7 4 4 20 4 20 7" />
|
||||
<line x1="9" y1="20" x2="15" y2="20" />
|
||||
<line x1="12" y1="4" x2="12" y2="20" />
|
||||
{titleHidden && <line x1="3" y1="3" x2="21" y2="21" />}
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
|
||||
Reference in New Issue
Block a user