feat(mobile): workspace views in the top menu, taller note rows, equal header bars
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m31s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sandrodachandClaude Opus 5.5 committed 2026-10-31 10:21:08 +01:00
1 parent 66d6b97aff
commit 21dd5e504e
7 files changed
+99 -50

No files matched your search

@@ -1022,7 +1022,8 @@ export const SharedListsView: React.FC<SharedListsViewProps> = ({ onRefreshGloba
</div>
{/* Mobile Compact Header Bar (List switching & actions 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 !mt-0">
{/* Same height with or without the 36 px share button (Tasks, Shopping lists) */}
<div className="flex sm:hidden items-center justify-between gap-2 px-3 py-2 min-h-[54px] rounded-btn bg-panel border border-border !mt-0">
<div className="flex items-center gap-2 min-w-0">
<span className="text-sm font-semibold text-main truncate">
{activeList ? `${activeList.icon} ${activeList.title}` : '🛒 Einkaufsliste'}
+2 -1
View File
@@ -1589,7 +1589,8 @@ export const TasksView: React.FC<TasksViewProps> = ({
</div>
{/* Mobile Compact Context Bar (replaces cluttered button rows; options 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 !mt-0">
{/* Same height with or without the 36 px share button (Tasks, Shopping lists) */}
<div className="flex sm:hidden items-center justify-between gap-2 px-3 py-2 min-h-[54px] rounded-btn bg-panel border border-border !mt-0">
<div className="flex items-center gap-2 min-w-0">
<span className="text-sm font-semibold text-main truncate">
{currentSelectedList ? `${currentSelectedList.icon} ${currentSelectedList.title}` : '📋 Alle Aufgaben'}
@@ -141,7 +141,7 @@ const FolderTreeItem: React.FC<FolderTreeItemProps> = ({
}}
onDrop={(e) => handleDropOnFolder(node.fullPath, e)}
style={{ paddingLeft: `${depth * 12 + 8}px` }}
className={`group flex items-center justify-between pr-1.5 h-7 rounded-btn text-xs cursor-pointer border-l-2 transition-colors ${
className={`group flex items-center justify-between pr-1.5 h-11 sm:h-7 rounded-btn text-sm sm:text-xs cursor-pointer border-l-2 transition-colors ${
isDragOver
? 'bg-accent/20 border-accent text-main font-semibold'
: 'border-transparent hover:bg-panel-elevated text-muted'
@@ -262,7 +262,7 @@ const FolderTreeItem: React.FC<FolderTreeItemProps> = ({
{...docDropProps(d.id)}
onClick={() => onSelectDoc(d.id)}
style={{ paddingLeft: `${(depth + 1) * 12 + 16}px` }}
className={`w-full flex items-center gap-2 pr-2 py-1.5 rounded-btn text-left text-xs cursor-pointer border transition-colors ${
className={`w-full flex items-center gap-2 pr-2 py-1.5 min-h-11 sm:min-h-0 rounded-btn text-left text-sm sm:text-xs cursor-pointer border transition-colors ${
mergeHoverId === d.id
? 'border-accent bg-accent/15 ring-2 ring-accent/30 text-main'
: selectedDocId === d.id && subView === 'editor'
@@ -654,43 +654,6 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
setMobileShowDetail(true);
}, [reloadTrash]);
// Register mobile FAB actions
useEffect(() => {
setPrimaryAction(() => handleCreateDocument(''));
setGroups([
{
id: 'workspace-actions',
title: 'Notizen & Ordner',
items: [
{
id: 'new-note',
label: 'Neue Notiz',
icon: <FilePlus className="w-4 h-4" />,
variant: 'accent',
onClick: () => handleCreateDocument(''),
},
{
id: 'new-folder',
label: 'Neuer Ordner',
icon: <FolderPlus className="w-4 h-4" />,
onClick: () => setShowNewFolderModal(true),
},
{
id: 'trash',
label: 'Papierkorb',
icon: <Trash2 className="w-4 h-4" />,
badge: trash.length,
onClick: openTrash,
},
],
},
]);
return () => {
setGroups([]);
setPrimaryAction(undefined);
};
}, [handleCreateDocument, setGroups, setPrimaryAction, trash.length, openTrash]);
const handleDeleteDocument = useCallback(
async (docId: string) => {
try {
@@ -1176,6 +1139,82 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
return count;
}, [docs]);
// Register mobile FAB actions and the menu at the top; on phones the menu also switches between
// notes, to-dos and hashtags (like the lists in Tasks and Shopping lists), the tab row is hidden there
useEffect(() => {
setPrimaryAction(() => handleCreateDocument(''));
setGroups([
{
id: 'workspace-views',
title: 'Ansicht',
items: [
{
id: 'view-notes',
label: 'Notizen',
icon: <FileText className="w-4 h-4" />,
active: subView === 'editor' || subView === 'journal' || subView === 'trash',
onClick: () => {
setSubView('editor');
setMobileShowDetail(false);
},
},
{
id: 'view-todos',
label: 'To-Dos',
icon: <Check className="w-4 h-4" />,
badge: totalOpenTodos || undefined,
active: subView === 'todos',
onClick: () => {
setSubView('todos');
setMobileShowDetail(true);
},
},
{
id: 'view-tags',
label: 'Hashtags',
icon: <Hash className="w-4 h-4" />,
badge: tagsSummary.length || undefined,
active: subView === 'tags' || subView === 'tag_detail',
onClick: () => {
setSubView('tags');
setMobileShowDetail(true);
},
},
],
},
{
id: 'workspace-actions',
title: 'Notizen & Ordner',
items: [
{
id: 'new-note',
label: 'Neue Notiz',
icon: <FilePlus className="w-4 h-4" />,
variant: 'accent',
onClick: () => handleCreateDocument(''),
},
{
id: 'new-folder',
label: 'Neuer Ordner',
icon: <FolderPlus className="w-4 h-4" />,
onClick: () => setShowNewFolderModal(true),
},
{
id: 'trash',
label: 'Papierkorb',
icon: <Trash2 className="w-4 h-4" />,
badge: trash.length,
onClick: openTrash,
},
],
},
]);
return () => {
setGroups([]);
setPrimaryAction(undefined);
};
}, [handleCreateDocument, setGroups, setPrimaryAction, trash.length, openTrash, subView, totalOpenTodos, tagsSummary.length]);
// Real-time matched blocks and all nested children for the selected hashtag
const activeTagGroups = useMemo(() => {
if (!selectedTag) return [];
@@ -1355,8 +1394,9 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
return (
<div className="w-full h-full min-h-0 flex flex-col gap-3">
{/* Top Header: Workspace Tabs & Actions */}
<div className="flex flex-wrap items-center justify-between gap-2 border-b border-border pb-2">
{/* Workspace selector tabs & left sidebar toggle; on phones the three tabs share the full width */}
{/* Phones: the views are switched in the menu at the top, so the row is hidden there */}
<div className="hidden sm:flex flex-wrap items-center justify-between gap-2 border-b border-border pb-2">
{/* Workspace selector tabs & left sidebar toggle */}
<div className="grid grid-cols-3 w-full gap-1 sm:flex sm:flex-wrap sm:items-center sm:w-auto">
<button
type="button"
@@ -1774,7 +1814,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
setSubView('editor');
setMobileShowDetail(true);
}}
className={`w-full flex items-center gap-2 px-2 py-1.5 rounded-btn text-left text-xs cursor-pointer border transition-colors ${
className={`w-full flex items-center gap-2 px-2 py-1.5 min-h-11 sm:min-h-0 rounded-btn text-left text-sm sm:text-xs cursor-pointer border transition-colors ${
mergeHoverId === d.id
? 'border-accent bg-accent/15 ring-2 ring-accent/30 text-main'
: selectedDocId === d.id && subView === 'editor'
@@ -1837,7 +1877,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
setSubView('editor');
setMobileShowDetail(true);
}}
className={`w-full flex items-center gap-2 px-2 py-1.5 rounded-btn text-left text-xs cursor-pointer border transition-colors ${
className={`w-full flex items-center gap-2 px-2 py-1.5 min-h-11 sm:min-h-0 rounded-btn text-left text-sm sm:text-xs cursor-pointer border transition-colors ${
mergeHoverId === d.id
? 'border-accent bg-accent/15 ring-2 ring-accent/30 text-main'
: selectedDocId === d.id && subView === 'editor'