From e2fac8ab05c19e52a56e12c606d7d22a0aaddb0b Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 15 Dec 2025 16:26:25 +0200 Subject: [PATCH] feat(breadcrumb): distinguish between workspace and hoisted notes --- .../src/translations/en/translation.json | 3 +- apps/client/src/widgets/layout/Breadcrumb.tsx | 48 +++++++++++-------- packages/commons/src/lib/attribute_names.ts | 2 + 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 2482503f8..ec2d9a57f 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -2146,7 +2146,8 @@ }, "breadcrumb": { "hoisted_badge": "Hoisted", - "hoisted_badge_title": "Unhoist" + "hoisted_badge_title": "Unhoist", + "workspace_badge": "Workspace" }, "breadcrumb_badges": { "read_only_explicit": "Read-only", diff --git a/apps/client/src/widgets/layout/Breadcrumb.tsx b/apps/client/src/widgets/layout/Breadcrumb.tsx index dfcf2239d..0135cbb50 100644 --- a/apps/client/src/widgets/layout/Breadcrumb.tsx +++ b/apps/client/src/widgets/layout/Breadcrumb.tsx @@ -14,7 +14,7 @@ import ActionButton from "../react/ActionButton"; import { Badge } from "../react/Badge"; import Dropdown from "../react/Dropdown"; import { FormListItem } from "../react/FormList"; -import { useChildNotes, useNoteProperty } from "../react/hooks"; +import { useChildNotes, useNote, useNoteLabel, useNoteLabelBoolean, useNoteProperty } from "../react/hooks"; import Icon from "../react/Icon"; import NoteLink from "../react/NoteLink"; @@ -61,31 +61,38 @@ export default function Breadcrumb({ note, noteContext }: { note: FNote, noteCon function BreadcrumbRoot({ noteContext }: { noteContext: NoteContext | undefined }) { const noteId = noteContext?.hoistedNoteId ?? "root"; - - // Root note is icon only. - if (noteId === "root") { - const note = froca.getNoteFromCache("root"); - return (note && - noteContext?.setNote(note.noteId)} - onContextMenu={(e) => { - e.preventDefault(); - link_context_menu.openContextMenu(note.noteId, e); - }} - /> - ); + if (noteId !== "root") { + return ; } + // Root note is icon only. + const note = froca.getNoteFromCache("root"); + return (note && + noteContext?.setNote(note.noteId)} + onContextMenu={(e) => { + e.preventDefault(); + link_context_menu.openContextMenu(note.noteId, e); + }} + /> + ); + +} + +function BreadcrumbHoistedNoteRoot({ noteId }: { noteId: string }) { + const note = useNote(noteId); + const [ workspace ] = useNoteLabelBoolean(note, "workspace"); + // Hoisted workspace shows both text and icon and a way to exit easily out of the hoisting. - return ( + return (note && <> hoisted_note.unhoist()} /> @@ -98,7 +105,6 @@ function BreadcrumbRoot({ noteContext }: { noteContext: NoteContext | undefined ); } - function BreadcrumbLastItem({ notePath }: { notePath: string }) { const noteId = notePath.split("/").at(-1); const [ note ] = useState(() => froca.getNoteFromCache(noteId!)); diff --git a/packages/commons/src/lib/attribute_names.ts b/packages/commons/src/lib/attribute_names.ts index db1ffc9f2..afb45fcb3 100644 --- a/packages/commons/src/lib/attribute_names.ts +++ b/packages/commons/src/lib/attribute_names.ts @@ -4,6 +4,8 @@ type Labels = { color: string; iconClass: string; + workspace: boolean; + workspaceTabBackgroundColor: string; workspaceIconClass: string; executeButton: boolean; executeDescription: string;