diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d2953b..a32fee4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,15 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die V ### Added - Outliner: Neuer Slash-Befehl `/text` (sowie Aliase `/p`, `/paragraph`, `/bullet`, `/standard`), um beliebige Blöcke (Überschriften, Callouts, Aufgaben, Trennlinien) in Standard-Text umzuwandeln; Aufgaben-Optionen und Block-Aktionsblase bieten ebenfalls die Rückumwandlung an. +- Triage-Deck: Touch-freundliche Schnellaktions-Leiste unter der aktiven mobilen Karte (Wegwerfen, Liste, Notiz, Aufgabe) mit Daumenbedienung (≥ 44 px). ### Changed - Outliner: Schriftgrößen für H1 (`text-xl sm:text-2xl font-bold`), H2 (`text-lg sm:text-xl font-semibold`) und H3 (`text-base font-semibold`) deutlich angehoben bei synchroner Textarea und dezentem oberen Abstand. - Outliner: Aktions-Buttons (Zoom, Auslagern, Löschen, Text-Umwandlung) als schwebende, kontrastreiche Blase (`backdrop-blur-sm`) positioniert, wodurch der Fließtext beim Einblenden nicht mehr ruckartig umbricht. - Outliner: Aktiver Eintrag im Slash-Befehlsmenü dezent als `bg-accent-dim text-accent` hervorgehoben statt vollflächig deckend. +- Quick Dump (Instant Capture): Platzhaltertexte gekürzt, vertikales Scrolling im einzeiligen Zustand unterbunden und Absende-Pfeil nach unten ausgerichtet. +- Zähler-Badges (`CountBadge`): Akzent-Badge über `--accent-dim` mit Rand, Muted-Badge über `--bg-panel-elevated` und `--text-muted` für hohe Lesbarkeit in allen Themes. +- Workspace: Popover-Dialoge (`FormSheet` mit Anker) öffnen zentriert unter dem Mauszeiger mit Rand-Schutz (Viewport-Clamping). ### Fixed - Outliner: Slash-Befehle werden an der tatsächlichen Cursorposition im Text erkannt (`/link`, `/diktat`); `/divider`, `/image`, `/audio` und `/code` werden nur noch in leeren Blöcken angeboten; das Menü schließt bei Klick ins Leere und Blur. diff --git a/frontend/src/components/FormSheet.tsx b/frontend/src/components/FormSheet.tsx index b606b24..7e1f097 100644 --- a/frontend/src/components/FormSheet.tsx +++ b/frontend/src/components/FormSheet.tsx @@ -36,7 +36,12 @@ export const FormSheet: React.FC = ({ }, [onClose]); const desktopAnchor = anchor - ? ({ '--sheet-left': `${anchor.x}px`, '--sheet-top': `${anchor.y}px` } as React.CSSProperties) + ? ({ + '--sheet-left': `${anchor.x}px`, + '--sheet-top': `${anchor.y}px`, + '--sheet-x': `clamp(12px, calc(${anchor.x}px - 8.25rem), calc(100vw - 16.5rem - 12px))`, + '--sheet-y': `calc(${anchor.y}px + 8px)`, + } as React.CSSProperties) : undefined; return ( @@ -54,7 +59,7 @@ export const FormSheet: React.FC = ({ className={`fixed inset-x-0 bottom-[var(--kb-inset)] max-h-[var(--vv-max)] panel-surface rounded-t-2xl border-t border-border shadow-panel p-4 space-y-3 overflow-y-auto sm:inset-x-auto sm:bottom-auto sm:max-h-[85vh] sm:w-full sm:rounded-card sm:border ${ anchor - ? 'sm:max-w-[16.5rem] sm:left-[var(--sheet-left)] sm:top-[var(--sheet-top)]' + ? 'sm:max-w-[16.5rem] sm:left-[var(--sheet-x)] sm:top-[var(--sheet-y)]' : 'sm:max-w-sm sm:left-1/2 sm:top-1/2 sm:-translate-x-1/2 sm:-translate-y-1/2' }`} > diff --git a/frontend/src/features/capture/InstantCaptureBar.tsx b/frontend/src/features/capture/InstantCaptureBar.tsx index f99b7b1..3ba4752 100644 --- a/frontend/src/features/capture/InstantCaptureBar.tsx +++ b/frontend/src/features/capture/InstantCaptureBar.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState, useMemo } from 'react'; import { Mic, MicOff, - ArrowUp, + ArrowDown, Sparkles, Calendar, Check, @@ -73,6 +73,7 @@ export const InstantCaptureBar: React.FC = ({ }); const isListening = voice.state === 'listening'; const isTranscribing = voice.state === 'transcribing'; + const [isOverMaxHeight, setIsOverMaxHeight] = useState(false); const adjustHeight = (el?: HTMLTextAreaElement | null) => { const targetEl = el || inputRef.current; @@ -82,8 +83,10 @@ export const InstantCaptureBar: React.FC = ({ const scrollH = targetEl.scrollHeight; targetEl.style.height = `${Math.min(scrollH, 140)}px`; setIsMultiline(targetEl.value.includes('\n') || scrollH > 28); + setIsOverMaxHeight(scrollH > 140); } else { setIsMultiline(false); + setIsOverMaxHeight(false); } }; @@ -267,16 +270,18 @@ export const InstantCaptureBar: React.FC = ({ : isTranscribing ? 'Wird erkannt…' : hideTargetPicker || fixedTarget === 'inbox' - ? 'Quick Dump erfassen… (Enter zum Speichern)' + ? 'Quick Dump erfassen…' : target === 'task' - ? 'Neue Aufgabe direkt anlegen… (Enter / Shift+Enter für Mehrzeiler)' + ? 'Aufgabe erfassen…' : target === 'list_item' - ? `Eintrag direkt zu "${selectedList?.title || 'Liste'}" hinzufügen…` + ? `Zu „${selectedList?.title || 'Liste'}“ hinzufügen…` : target === 'document' - ? 'Neue Workspace-Notiz direkt anlegen… (Enter / Shift+Enter für Mehrzeiler)' - : 'Quick Dump: Gedanke reinrotzen… (C / Enter, Shift+Enter für Mehrzeiler)' + ? 'Notiz erfassen…' + : 'Quick Dump…' } - className="w-full bg-transparent text-main placeholder-faint text-xs sm:text-sm focus:outline-none resize-none leading-5 py-0.5 overflow-y-auto" + className={`w-full bg-transparent text-main placeholder-faint text-xs sm:text-sm focus:outline-none resize-none leading-5 py-0.5 ${ + isOverMaxHeight ? 'overflow-y-auto' : 'overflow-hidden' + }`} style={{ minHeight: '22px', maxHeight: '140px' }} autoComplete="off" /> @@ -360,7 +365,7 @@ export const InstantCaptureBar: React.FC = ({ ) : ( <> - + {hideTargetPicker || (fixedTarget || target) === 'inbox' ? 'Quick Dump' diff --git a/frontend/src/features/triage/TriageDeck.tsx b/frontend/src/features/triage/TriageDeck.tsx index 0936501..41a178c 100644 --- a/frontend/src/features/triage/TriageDeck.tsx +++ b/frontend/src/features/triage/TriageDeck.tsx @@ -725,7 +725,73 @@ export const TriageDeck: React.FC = ({ )} - {/* Primary Triage Decision Bar: Hidden on mobile (handled via Swipe + Long-Press), shown on Desktop */} + {/* Mobile Quick Action Buttons under the card (Touch targets >= 44px) */} +
+ + + + + + + +
+ + {/* Primary Triage Decision Bar: Hidden on mobile (handled via Mobile Quick Actions / Swipe), shown on Desktop */}