feat(mobile): add context-sensitive MindSift logo menu, slide-over file drawer, and larger touch targets
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 58s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 58s
This commit is contained in:
1 parent
cb0999325f
commit
212cb32bb0
8 files changed
+943
-111
No files matched your search
@@ -53,6 +53,7 @@ import { api, getToken, triggerHaptic } from '../../lib/api';
|
||||
import { CodeBlockItem } from './CodeBlockItem';
|
||||
import { UserAutocomplete } from '../UserAutocomplete';
|
||||
import { UnifiedShareModal } from '../../components/UnifiedShareModal';
|
||||
import { useMobileActions } from '../../context/MobileActionContext';
|
||||
|
||||
interface WorkspaceViewProps {
|
||||
currentUser?: User | null;
|
||||
@@ -99,6 +100,9 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
initialDocId,
|
||||
onStatsChange,
|
||||
}) => {
|
||||
const { setGroups } = useMobileActions();
|
||||
const [showMobileFileDrawer, setShowMobileFileDrawer] = useState(false);
|
||||
|
||||
// Top Workspace Tab Mode: 'editor' vs 'todos' vs 'tags'
|
||||
const [workspaceMode, setWorkspaceMode] = useState<'editor' | 'todos' | 'tags'>('editor');
|
||||
const [selectedTag, setSelectedTag] = useState<string | null>(null);
|
||||
@@ -2714,6 +2718,132 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
return workspaceTags.filter((t) => t.tag.toLowerCase().includes(q));
|
||||
}, [workspaceTags, tagSearchQuery]);
|
||||
|
||||
// Register context-sensitive mobile menu groups behind the MindSift logo
|
||||
useEffect(() => {
|
||||
const openTodosCount = allWorkspaceTodos.filter((t) => !t.block.checked).length;
|
||||
setGroups([
|
||||
{
|
||||
id: 'ws-view-files',
|
||||
title: 'Workspace-Ansicht & Dateien',
|
||||
items: [
|
||||
{
|
||||
id: 'ws-open-tree',
|
||||
label: 'Dateibaum & Ordner öffnen',
|
||||
icon: <FolderTree className="w-4 h-4 text-accent" />,
|
||||
badge: docs.length,
|
||||
variant: 'accent',
|
||||
active: showMobileFileDrawer,
|
||||
onClick: () => {
|
||||
setWorkspaceMode('editor');
|
||||
setShowMobileFileDrawer(true);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'ws-mode-editor',
|
||||
label: 'Notizen & Editor',
|
||||
icon: <Layers className="w-4 h-4" />,
|
||||
active: workspaceMode === 'editor' && !showMobileFileDrawer,
|
||||
onClick: () => {
|
||||
setWorkspaceMode('editor');
|
||||
setShowMobileFileDrawer(false);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'ws-mode-tags',
|
||||
label: 'Themen & Hashtags',
|
||||
icon: <Hash className="w-4 h-4" />,
|
||||
badge: workspaceTags.length,
|
||||
active: workspaceMode === 'tags',
|
||||
onClick: () => {
|
||||
setWorkspaceMode('tags');
|
||||
setShowMobileFileDrawer(false);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'ws-mode-todos',
|
||||
label: 'Globale To-Dos',
|
||||
icon: <CheckSquare className="w-4 h-4" />,
|
||||
badge: openTodosCount,
|
||||
active: workspaceMode === 'todos',
|
||||
onClick: () => {
|
||||
setWorkspaceMode('todos');
|
||||
setShowMobileFileDrawer(false);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'ws-doc-actions',
|
||||
title: 'Erstellen & Dokument-Aktionen',
|
||||
items: [
|
||||
{
|
||||
id: 'ws-new-doc',
|
||||
label: 'Neue Datei erstellen',
|
||||
icon: <FilePlus className="w-4 h-4 text-accent" />,
|
||||
onClick: () => {
|
||||
setShowMobileFileDrawer(false);
|
||||
handleCreateDoc(null);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'ws-new-folder',
|
||||
label: 'Neuer Ordner',
|
||||
icon: <FolderPlus className="w-4 h-4" />,
|
||||
onClick: () => {
|
||||
setWorkspaceMode('editor');
|
||||
setShowMobileFileDrawer(true);
|
||||
handleStartCreateFolder(null);
|
||||
},
|
||||
},
|
||||
...(selectedDoc
|
||||
? [
|
||||
{
|
||||
id: 'ws-share-doc',
|
||||
label: `Notiz "${selectedDoc.title || 'Unbenannt'}" teilen`,
|
||||
icon: <Users className="w-4 h-4" />,
|
||||
onClick: () => openShareModal(),
|
||||
},
|
||||
{
|
||||
id: 'ws-pin-doc',
|
||||
label: selectedDoc.isPinned ? 'Von Favoriten lösen' : 'Oben in Favoriten anpinnen',
|
||||
icon: <Pin className="w-4 h-4" />,
|
||||
active: Boolean(selectedDoc.isPinned),
|
||||
onClick: () => persistDocument({ ...selectedDoc, isPinned: !selectedDoc.isPinned }, true),
|
||||
},
|
||||
{
|
||||
id: 'ws-export-md',
|
||||
label: 'Als Markdown exportieren (.md)',
|
||||
icon: <Download className="w-4 h-4" />,
|
||||
onClick: () => handleExportMarkdown(),
|
||||
},
|
||||
{
|
||||
id: 'ws-delete-doc',
|
||||
label: selectedDoc.isOwner !== false ? 'Notiz löschen' : 'Geteilte Notiz verlassen',
|
||||
icon: <Trash2 className="w-4 h-4" />,
|
||||
variant: 'danger' as const,
|
||||
onClick: () => {
|
||||
if (selectedDoc.isOwner !== false) {
|
||||
handleDeleteDoc(selectedDoc.id);
|
||||
} else {
|
||||
handleLeaveShare();
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
},
|
||||
]);
|
||||
}, [
|
||||
workspaceMode,
|
||||
showMobileFileDrawer,
|
||||
docs.length,
|
||||
workspaceTags.length,
|
||||
allWorkspaceTodos,
|
||||
selectedDoc,
|
||||
setGroups,
|
||||
]);
|
||||
|
||||
const renderDocItem = (doc: Document, depth: number) => {
|
||||
const isSelected = selectedDoc?.id === doc.id && workspaceMode === 'editor';
|
||||
const isDragging = draggingDocId === doc.id;
|
||||
@@ -2732,9 +2862,10 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
setSelectedDoc(doc);
|
||||
setZoomedBlockId(null);
|
||||
setWorkspaceMode('editor');
|
||||
setShowMobileFileDrawer(false);
|
||||
}}
|
||||
style={{ paddingLeft: `${depth * 14 + 16}px` }}
|
||||
className={`group flex items-center justify-between py-1.5 pr-2 border-l-2 transition-all cursor-pointer text-xs ${
|
||||
className={`group flex items-center justify-between py-2.5 sm:py-1.5 pr-2 border-l-2 transition-all cursor-pointer text-sm sm:text-xs ${
|
||||
isDragging ? 'opacity-40 scale-[0.98]' : ''
|
||||
} ${
|
||||
isSelected
|
||||
@@ -2744,15 +2875,15 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
title={`${doc.title || 'Notiz'} (Ziehen zum Verschieben in Ordner)`}
|
||||
>
|
||||
<div className="flex items-center gap-2 min-w-0 flex-1">
|
||||
<span className="text-sm flex-shrink-0">{doc.icon || '📄'}</span>
|
||||
<span className="text-base sm:text-sm flex-shrink-0">{doc.icon || '📄'}</span>
|
||||
<span className="truncate">{doc.title || 'Unbenannt'}</span>
|
||||
{doc.isPinned && <Pin className="w-2.5 h-2.5 text-accent flex-shrink-0" />}
|
||||
{doc.isPinned && <Pin className="w-3 h-3 sm:w-2.5 sm:h-2.5 text-accent flex-shrink-0" />}
|
||||
{doc.isOwner === false && (
|
||||
<span
|
||||
title={`Geteilt von ${doc.ownerName || 'anderem Nutzer'} (${doc.permission === 'read' ? 'Nur Lesen' : 'Schreibrecht'})`}
|
||||
className="text-accent flex-shrink-0"
|
||||
>
|
||||
<Users className="w-3 h-3" />
|
||||
<Users className="w-3.5 h-3.5 sm:w-3 sm:h-3" />
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -2816,7 +2947,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
onDragEnd={() => setDraggingFolderPath(null)}
|
||||
onClick={() => toggleFolder(node.path)}
|
||||
style={{ paddingLeft: `${node.depth * 14 + 8}px` }}
|
||||
className={`group flex items-center justify-between py-1.5 pr-2 cursor-pointer transition-colors text-xs ${
|
||||
className={`group flex items-center justify-between py-2.5 sm:py-1.5 pr-2 cursor-pointer transition-colors text-sm sm:text-xs ${
|
||||
isDraggingThisFolder ? 'opacity-40 scale-[0.98]' : ''
|
||||
} ${
|
||||
isDragOver
|
||||
@@ -2828,31 +2959,32 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
<div className="flex items-center gap-1.5 min-w-0">
|
||||
<span className="text-faint hover:text-muted">
|
||||
{isExpanded ? (
|
||||
<ChevronDown className="w-3 h-3 flex-shrink-0" />
|
||||
<ChevronDown className="w-3.5 h-3.5 sm:w-3 sm:h-3 flex-shrink-0" />
|
||||
) : (
|
||||
<ChevronRight className="w-3 h-3 flex-shrink-0" />
|
||||
<ChevronRight className="w-3.5 h-3.5 sm:w-3 sm:h-3 flex-shrink-0" />
|
||||
)}
|
||||
</span>
|
||||
{isExpanded ? (
|
||||
<FolderOpen className="w-3.5 h-3.5 text-accent flex-shrink-0" />
|
||||
<FolderOpen className="w-4 h-4 sm:w-3.5 sm:h-3.5 text-accent flex-shrink-0" />
|
||||
) : (
|
||||
<Folder className="w-3.5 h-3.5 text-muted flex-shrink-0" />
|
||||
<Folder className="w-4 h-4 sm:w-3.5 sm:h-3.5 text-muted flex-shrink-0" />
|
||||
)}
|
||||
<span className="font-medium text-xs text-main truncate">{node.name}</span>
|
||||
<span className="font-medium text-sm sm:text-xs text-main truncate">{node.name}</span>
|
||||
<span className="text-[10px] text-faint font-mono">({totalItems})</span>
|
||||
</div>
|
||||
|
||||
<div className="opacity-0 group-hover:opacity-100 flex items-center gap-1 transition-opacity">
|
||||
<div className="opacity-100 sm:opacity-0 sm:group-hover:opacity-100 flex items-center gap-1 transition-opacity">
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setShowMobileFileDrawer(false);
|
||||
handleCreateDoc(node.path);
|
||||
}}
|
||||
className="p-1 hover:bg-panel-elevated text-muted hover:text-main rounded-btn"
|
||||
className="p-1.5 sm:p-1 hover:bg-panel-elevated text-muted hover:text-main rounded-btn"
|
||||
title="Neue Datei in diesem Ordner"
|
||||
>
|
||||
<FilePlus className="w-3 h-3" />
|
||||
<FilePlus className="w-3.5 h-3.5 sm:w-3 sm:h-3" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -2860,10 +2992,10 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
e.stopPropagation();
|
||||
handleStartCreateFolder(node.path);
|
||||
}}
|
||||
className="p-1 hover:bg-panel-elevated text-muted hover:text-main rounded-btn"
|
||||
className="p-1.5 sm:p-1 hover:bg-panel-elevated text-muted hover:text-main rounded-btn"
|
||||
title="Neuer Unterordner"
|
||||
>
|
||||
<FolderPlus className="w-3 h-3" />
|
||||
<FolderPlus className="w-3.5 h-3.5 sm:w-3 sm:h-3" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -2871,10 +3003,10 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
e.stopPropagation();
|
||||
handleDeleteFolder(node.path, node.name);
|
||||
}}
|
||||
className="p-1 hover:bg-red-500/10 text-muted hover:text-red-400 rounded-btn transition-colors"
|
||||
className="p-1.5 sm:p-1 hover:bg-red-500/10 text-muted hover:text-red-400 rounded-btn transition-colors"
|
||||
title="Ordner löschen"
|
||||
>
|
||||
<Trash2 className="w-3 h-3" />
|
||||
<Trash2 className="w-3.5 h-3.5 sm:w-3 sm:h-3" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2882,9 +3014,9 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
{isCreatingSubfolder && (
|
||||
<div
|
||||
style={{ paddingLeft: `${(node.depth + 1) * 14 + 8}px` }}
|
||||
className="py-1 pr-2 flex items-center gap-1 bg-canvas"
|
||||
className="py-1.5 sm:py-1 pr-2 flex items-center gap-1 bg-canvas"
|
||||
>
|
||||
<Folder className="w-3 h-3 text-muted flex-shrink-0" />
|
||||
<Folder className="w-3.5 h-3.5 sm:w-3 sm:h-3 text-muted flex-shrink-0" />
|
||||
<input
|
||||
type="text"
|
||||
autoFocus
|
||||
@@ -2895,23 +3027,23 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
if (e.key === 'Escape') setIsCreatingFolder(false);
|
||||
}}
|
||||
placeholder="Unterordner…"
|
||||
className="flex-1 h-6 px-1.5 input-field text-xs"
|
||||
className="flex-1 h-8 sm:h-6 px-2 sm:px-1.5 input-field text-xs"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleConfirmCreateFolder}
|
||||
className="p-1 text-accent hover:text-main rounded-btn"
|
||||
className="p-1.5 sm:p-1 text-accent hover:text-main rounded-btn"
|
||||
title="Bestätigen"
|
||||
>
|
||||
<Check className="w-3.5 h-3.5" />
|
||||
<Check className="w-4 h-4 sm:w-3.5 sm:h-3.5" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsCreatingFolder(false)}
|
||||
className="p-1 text-muted hover:text-main rounded-btn"
|
||||
className="p-1.5 sm:p-1 text-muted hover:text-main rounded-btn"
|
||||
title="Abbrechen"
|
||||
>
|
||||
<X className="w-3.5 h-3.5" />
|
||||
<X className="w-4 h-4 sm:w-3.5 sm:h-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
@@ -2938,8 +3070,52 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
|
||||
return (
|
||||
<div className="w-full space-y-2">
|
||||
{/* Top Navigation Mode Switcher: Notizen & Outliner vs. Globales To-Do Dashboard */}
|
||||
<div className="flex flex-wrap items-center justify-between gap-2 border-b border-border pb-2">
|
||||
{/* Mobile Compact Workspace Bar (Options & mode switching live in MindSift Logo Menu) */}
|
||||
<div className="flex sm:hidden items-center justify-between gap-2 px-3 py-2 rounded-btn bg-panel border border-border">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setWorkspaceMode('editor');
|
||||
setShowMobileFileDrawer(true);
|
||||
}}
|
||||
className="flex items-center gap-2 min-w-0 text-left py-0.5"
|
||||
title="Dateibaum & Ordner öffnen"
|
||||
>
|
||||
<FolderTree className="w-4 h-4 text-accent flex-shrink-0" />
|
||||
<span className="text-sm font-semibold text-main truncate">
|
||||
{workspaceMode === 'tags'
|
||||
? 'Themen & Hashtags'
|
||||
: workspaceMode === 'todos'
|
||||
? 'Globale To-Dos'
|
||||
: selectedDoc
|
||||
? `${selectedDoc.icon || '📄'} ${selectedDoc.title || 'Unbenannt'}`
|
||||
: 'Dateibaum öffnen'}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<div className="flex items-center gap-1.5 flex-shrink-0">
|
||||
{workspaceMode === 'editor' && selectedDoc && (
|
||||
<span className="badge-accent text-[10px]">
|
||||
<Check className="w-2.5 h-2.5" />
|
||||
{saveState === 'saving' ? 'Speichert…' : 'Gespeichert'}
|
||||
</span>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setWorkspaceMode('editor');
|
||||
setShowMobileFileDrawer(true);
|
||||
}}
|
||||
className="btn-action min-h-[36px] px-2.5 text-xs flex items-center gap-1"
|
||||
>
|
||||
<Folder className="w-3.5 h-3.5 text-accent" />
|
||||
<span>Dateien</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Top Navigation Mode Switcher: Notizen & Outliner vs. Globales To-Do Dashboard (Desktop) */}
|
||||
<div className="hidden sm:flex flex-wrap items-center justify-between gap-2 border-b border-border pb-2">
|
||||
<div className="flex items-center gap-1">
|
||||
<button
|
||||
type="button"
|
||||
@@ -3015,38 +3191,71 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
{/* ===================================================================== */}
|
||||
{workspaceMode === 'editor' && (
|
||||
<div className="grid grid-cols-1 lg:grid-cols-12 gap-2">
|
||||
{/* Left Document & Folder Explorer Tree */}
|
||||
<div className="lg:col-span-4 panel-surface flex flex-col self-start">
|
||||
<div className="p-2 panel-header space-y-2">
|
||||
{/* Mobile Backdrop for File Tree Slide-Over Drawer */}
|
||||
{showMobileFileDrawer && (
|
||||
<div
|
||||
className="fixed inset-0 bg-black/50 backdrop-blur-xs z-40 lg:hidden animate-in fade-in duration-150"
|
||||
onClick={() => setShowMobileFileDrawer(false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Left Document & Folder Explorer Tree (Desktop Sidebar + Mobile Slide-Over Drawer) */}
|
||||
<div
|
||||
className={`${
|
||||
showMobileFileDrawer
|
||||
? 'fixed inset-y-0 left-0 z-50 w-[86vw] max-w-sm bg-panel border-r border-border shadow-2xl flex'
|
||||
: 'hidden lg:flex'
|
||||
} lg:col-span-4 panel-surface flex-col self-start max-h-screen lg:max-h-none`}
|
||||
>
|
||||
{/* Mobile Drawer Top Header */}
|
||||
<div className="flex lg:hidden items-center justify-between px-3.5 py-3 border-b border-border bg-panel">
|
||||
<div className="flex items-center gap-2">
|
||||
<FolderTree className="w-4 h-4 text-accent" />
|
||||
<span className="text-sm font-bold text-main">Dateibaum & Ordner</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowMobileFileDrawer(false)}
|
||||
className="p-1.5 text-muted hover:text-main rounded-btn"
|
||||
title="Schließen"
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="p-2.5 sm:p-2 panel-header space-y-2">
|
||||
<div className="relative">
|
||||
<Search className="w-3.5 h-3.5 text-muted absolute left-2.5 top-1/2 -translate-y-1/2" />
|
||||
<Search className="w-4 h-4 sm:w-3.5 sm:h-3.5 text-muted absolute left-2.5 top-1/2 -translate-y-1/2" />
|
||||
<input
|
||||
type="text"
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
placeholder="Dateien durchsuchen…"
|
||||
className="w-full h-7 pl-7 pr-2 input-field text-xs"
|
||||
className="w-full h-9 sm:h-7 pl-8 sm:pl-7 pr-2 input-field text-sm sm:text-xs"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-1.5">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleCreateDoc(null)}
|
||||
className="flex-1 btn-action"
|
||||
onClick={() => {
|
||||
setShowMobileFileDrawer(false);
|
||||
handleCreateDoc(null);
|
||||
}}
|
||||
className="flex-1 btn-action min-h-[38px] sm:min-h-0 justify-center"
|
||||
title="Neue Datei erstellen"
|
||||
>
|
||||
<FilePlus className="w-3.5 h-3.5 text-muted" />
|
||||
<FilePlus className="w-4 h-4 sm:w-3.5 sm:h-3.5 text-muted" />
|
||||
<span>Neue Datei</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleStartCreateFolder(null)}
|
||||
className="flex-1 btn-action"
|
||||
className="flex-1 btn-action min-h-[38px] sm:min-h-0 justify-center"
|
||||
title="Neuen Ordner erstellen"
|
||||
>
|
||||
<FolderPlus className="w-3.5 h-3.5 text-muted" />
|
||||
<FolderPlus className="w-4 h-4 sm:w-3.5 sm:h-3.5 text-muted" />
|
||||
<span>Neuer Ordner</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -3054,7 +3263,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
|
||||
{isCreatingFolder && newFolderParent === null && (
|
||||
<div className="p-2 panel-header bg-canvas flex items-center gap-1.5">
|
||||
<Folder className="w-3.5 h-3.5 text-muted flex-shrink-0" />
|
||||
<Folder className="w-4 h-4 sm:w-3.5 sm:h-3.5 text-muted flex-shrink-0" />
|
||||
<input
|
||||
type="text"
|
||||
autoFocus
|
||||
@@ -3065,23 +3274,23 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
if (e.key === 'Escape') setIsCreatingFolder(false);
|
||||
}}
|
||||
placeholder="Neuer Ordnername…"
|
||||
className="flex-1 h-6 px-1.5 input-field text-xs"
|
||||
className="flex-1 h-8 sm:h-6 px-2 sm:px-1.5 input-field text-xs"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleConfirmCreateFolder}
|
||||
className="p-1 text-accent hover:text-main rounded-btn"
|
||||
className="p-1.5 sm:p-1 text-accent hover:text-main rounded-btn"
|
||||
title="Bestätigen"
|
||||
>
|
||||
<Check className="w-3.5 h-3.5" />
|
||||
<Check className="w-4 h-4 sm:w-3.5 sm:h-3.5" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsCreatingFolder(false)}
|
||||
className="p-1 text-muted hover:text-main rounded-btn"
|
||||
className="p-1.5 sm:p-1 text-muted hover:text-main rounded-btn"
|
||||
title="Abbrechen"
|
||||
>
|
||||
<X className="w-3.5 h-3.5" />
|
||||
<X className="w-4 h-4 sm:w-3.5 sm:h-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
@@ -3096,8 +3305,11 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleCreateDoc(null)}
|
||||
className="btn-action"
|
||||
onClick={() => {
|
||||
setShowMobileFileDrawer(false);
|
||||
handleCreateDoc(null);
|
||||
}}
|
||||
className="btn-action min-h-[38px] sm:min-h-0"
|
||||
>
|
||||
<FilePlus className="w-3.5 h-3.5 text-muted" />
|
||||
<span>Neue Datei</span>
|
||||
@@ -3105,7 +3317,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleStartCreateFolder(null)}
|
||||
className="btn-action"
|
||||
className="btn-action min-h-[38px] sm:min-h-0"
|
||||
>
|
||||
<FolderPlus className="w-3.5 h-3.5 text-muted" />
|
||||
<span>Neuer Ordner</span>
|
||||
@@ -3113,7 +3325,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="py-1 max-h-[calc(100vh-240px)] overflow-y-auto">
|
||||
<div className="py-1 flex-1 lg:max-h-[calc(100vh-240px)] overflow-y-auto">
|
||||
{/* Drag target for Root when dragging a note or a folder */}
|
||||
{(draggingDocId || draggingFolderPath) && (
|
||||
<div
|
||||
@@ -3160,7 +3372,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsPinnedCollapsed((prev) => !prev)}
|
||||
className="w-full px-2 py-1 text-[10px] font-bold text-accent uppercase tracking-wider flex items-center justify-between hover:bg-canvas/40 rounded transition-colors"
|
||||
className="w-full px-2 py-1.5 sm:py-1 text-[10px] font-bold text-accent uppercase tracking-wider flex items-center justify-between hover:bg-canvas/40 rounded transition-colors"
|
||||
title={isPinnedCollapsed ? 'Angepinnte Notizen aufklappen' : 'Angepinnte Notizen einklappen'}
|
||||
>
|
||||
<div className="flex items-center gap-1.5">
|
||||
@@ -3192,8 +3404,9 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
setSelectedDoc(doc);
|
||||
setZoomedBlockId(null);
|
||||
setWorkspaceMode('editor');
|
||||
setShowMobileFileDrawer(false);
|
||||
}}
|
||||
className={`group flex items-center justify-between px-2 py-1.5 rounded-btn transition-colors cursor-pointer text-xs ${
|
||||
className={`group flex items-center justify-between px-2 py-2.5 sm:py-1.5 rounded-btn transition-colors cursor-pointer text-sm sm:text-xs ${
|
||||
isSelected
|
||||
? 'bg-panel-elevated border-l-2 border-accent text-main font-medium'
|
||||
: 'text-muted hover:text-main hover:bg-canvas/50'
|
||||
@@ -3201,7 +3414,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
title="Angepinnte Notiz öffnen"
|
||||
>
|
||||
<div className="flex items-center gap-2 min-w-0 flex-1">
|
||||
<span className="text-sm flex-shrink-0">{doc.icon || '📄'}</span>
|
||||
<span className="text-base sm:text-sm flex-shrink-0">{doc.icon || '📄'}</span>
|
||||
<span className="truncate">{doc.title || 'Unbenannt'}</span>
|
||||
</div>
|
||||
<button
|
||||
@@ -3210,10 +3423,10 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
e.stopPropagation();
|
||||
persistDocument({ ...doc, isPinned: false }, true);
|
||||
}}
|
||||
className="opacity-0 group-hover:opacity-100 p-0.5 text-muted hover:text-accent rounded transition-opacity"
|
||||
className="opacity-100 sm:opacity-0 sm:group-hover:opacity-100 p-1 sm:p-0.5 text-muted hover:text-accent rounded transition-opacity"
|
||||
title="Von Angepinnt entfernen"
|
||||
>
|
||||
<Pin className="w-3 h-3 text-accent" />
|
||||
<Pin className="w-3.5 h-3.5 sm:w-3 sm:h-3 text-accent" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
@@ -3229,7 +3442,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsTagsCollapsed((prev) => !prev)}
|
||||
className="w-full px-2 py-1 text-[10px] font-bold text-muted uppercase tracking-wider flex items-center justify-between hover:bg-canvas/40 rounded transition-colors"
|
||||
className="w-full px-2 py-1.5 sm:py-1 text-[10px] font-bold text-muted uppercase tracking-wider flex items-center justify-between hover:bg-canvas/40 rounded transition-colors"
|
||||
title={isTagsCollapsed ? 'Themen & Hashtags aufklappen' : 'Themen & Hashtags einklappen'}
|
||||
>
|
||||
<div className="flex items-center gap-1.5 text-accent">
|
||||
@@ -3243,13 +3456,16 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
/>
|
||||
</button>
|
||||
{!isTagsCollapsed && (
|
||||
<div className="flex flex-wrap gap-1 px-1.5 py-1 mt-1 max-h-36 overflow-y-auto">
|
||||
<div className="flex flex-wrap gap-1.5 sm:gap-1 px-1.5 py-1 mt-1 max-h-36 overflow-y-auto">
|
||||
{workspaceTags.map((wt) => (
|
||||
<button
|
||||
key={wt.tag}
|
||||
type="button"
|
||||
onClick={() => openTagPage(wt.tag)}
|
||||
className={`px-2 py-0.5 rounded-pill text-[11px] font-medium border flex items-center gap-1 transition-colors ${
|
||||
onClick={() => {
|
||||
setShowMobileFileDrawer(false);
|
||||
openTagPage(wt.tag);
|
||||
}}
|
||||
className={`px-2.5 py-1 sm:px-2 sm:py-0.5 rounded-pill text-xs sm:text-[11px] font-medium border flex items-center gap-1 transition-colors ${
|
||||
selectedTag === wt.tag
|
||||
? 'bg-accent/20 border-accent text-accent font-semibold'
|
||||
: 'bg-canvas border-border text-muted hover:border-accent/40 hover:text-main'
|
||||
|
||||
Reference in new issue
Block a user