You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Sidebar & Workspaces: "Pin" is used for two different behaviors #6994
"Pin" means two different things in the UI, and the overlap is confusing
On the Workspaces page, right-click → "Pin to Sidebar" controls whether a workspace appears in the sidebar at all (membership)
In the sidebar, right-click → "Pin" moves a workspace into the PINNED section at the top (placement)
Same word, two unrelated behaviors — unpinning from the Workspaces page removes the workspace from the sidebar entirely, not from the PINNED row
Proposal
Keep "Pin to Sidebar" / "Unpin from Sidebar" on the Workspaces page — it reads correctly as show/hide in sidebar
Rename the sidebar action to "Favorite" (or "Star"), with a FAVORITES section instead of PINNED, so membership and placement get distinct names
Environment
Superset 1.25.0, macOS (Darwin arm64)
Related
Let me pin an automation so its latest workspace stays in the sidebar #6172 — triage there confirmed pin state is workspace-scoped and machine-local (renderer-side pinnedAt, never synced), which is the same overloaded "pin" surface this issue describes. The automations-group direction discussed there would also reduce how often pinning is the only tool for sidebar visibility.
This is a naming/UX report, not a crash: the word "Pin" is bound to two independent pieces of state in the workspace sidebar model, and the two actions live one click apart. On the Workspaces page, "Pin to Sidebar" / "Unpin from Sidebar" toggles membership (sidebarState.isHidden) — whether the workspace appears in the sidebar at all. In the sidebar, "Pin" / "Unpin" toggles placement (sidebarState.pinnedAt) — whether the row floats up into the PINNED section. Both use a pushpin icon, and the Workspaces page filter chip labeled "Pinned" actually filters on membership, not on the PINNED section. The reported behavior is accurate as described.
Affected code
Two independent fields on v2WorkspaceLocalState.sidebarState:
Membership — isHidden, written by ensureWorkspaceInSidebar / hideWorkspaceInSidebar at apps/desktop/src/renderer/routes/_authenticated/hooks/useDashboardSidebarState/useDashboardSidebarState.ts:334 and :912.
Placement — pinnedAt, written by setWorkspacePinned at useDashboardSidebarState.ts:815, ordered by reorderPinnedWorkspaces at :854.
membership — matchesPinFilter reads workspace.isInSidebar (useAccessibleV2Workspaces.ts:191-199, derived at :687)
Note the third row: the sidebar's own menu already names the membership action "Remove from Sidebar", so the app currently has two different labels for one behavior and one label for two behaviors.
Root cause
Nothing is functionally broken — the two states are correctly separate and the code's internal names are unambiguous (isHidden vs pinnedAt, removeFromSidebar vs setWorkspacePinned). The collision is entirely at the label layer, introduced by giving the membership action a pushpin metaphor it doesn't need.
One real sharp edge amplifies the confusion: hiding clears the pin. tombstoneSidebarWorkspaceRecord at apps/desktop/src/renderer/routes/_authenticated/hooks/useDashboardSidebarState/sidebarMutations.ts:57-65 sets pinnedAt = null alongside isHidden = true (deliberately — the comment explains a resurrected workspace must not reappear pre-pinned). So a user who right-clicks a PINNED workspace on the Workspaces page and picks "Unpin from Sidebar" expecting it to drop out of the PINNED row instead loses both the pin and the sidebar row, and re-adding it puts it back in the project tree rather than in PINNED. That's the concrete data-loss-shaped consequence of the naming overlap.
Reproduction
Sidebar → right-click a workspace → Pin. It moves into PINNED.
Go to the Workspaces page → right-click that same workspace → Unpin from Sidebar.
Observed: the workspace disappears from the sidebar entirely (isHidden = true, pinnedAt = null), not just from PINNED.
Right-click it again → Pin to Sidebar. It returns to its project group, no longer pinned.
For a unit-level check, useDashboardSidebarState/sidebarMutations.test.ts already exercises tombstoneSidebarWorkspaceRecord; a bun:test case asserting pinnedAt === null after tombstoning a pinned row would pin down step 3's mechanism.
Fix direction
The rename is the whole fix; no state-model change is needed. Two options, and the choice is a product call:
A — the issue's proposal. Keep "Pin to Sidebar" on the Workspaces page, rename the sidebar action to Favorite/Star and the section to FAVORITES. Worth knowing before picking this: Pages already has a favorites store (favoritePageIds in providers/CollectionsProvider/dashboardSidebarLocal/schema.ts:411, usePageFavorites) whose UI is labeled "Pin"/"Pinned" (pages/.../PageCard/PageCard.tsx:151-155, PagesView.tsx:67) — so this option swaps the two words relative to Pages unless Pages is renamed in the same pass. Marketing copy also leans on the pin metaphor for the sidebar section (marketing.roadmap.item.workspacePinningBulkActions: "Pin workspaces above your projects").
B — smaller churn. Leave PINNED alone (it's the conventional "pinned tab" meaning: placement) and rename the Workspaces-page action to "Add to Sidebar" / "Remove from Sidebar", matching the sidebar menu's existing "Remove from Sidebar" entry and the code's own addToSidebar/removeFromSidebar names. Swap RiPushpin* for a non-pin icon (LuPlus/LuX) at V2WorkspaceContextMenu.tsx:162,169, and relabel the filter at v2WorkspacesFilterStore.ts:66-77 to "In sidebar" / "Not in sidebar" — that chip is arguably the most misleading string of the set today, since it sits on the same page as a PINNED section that means something else.
Either way, packages/i18n/README.md §"Editing English copy under a stable ID" applies: IDs are stable, so changing the JSX text alone doesn't change what ships — locales/en/messages.po must be regenerated and all 16 locales updated, with bun run --cwd packages/i18n check gating it in CI. Affected IDs: dashboard.workspaces.contextMenu.pinToSidebar / .unpinFromSidebar, dashboard.v2Workspaces.pinFilter*, dashboard.workspaces.header.pinnedFilter, and (under option A) dashboard.sidebar.workspaceMenu.pin / .unpin, dashboard.sidebar.sectionPinned, dashboard.sidebar.pinnedSection.dropToPin, dashboard.sidebar.projectContent.dropToUnpin, dashboard.sidebar.sessionsSection.dropToUnpin.
Activity
github-actions commentedon Aug 29, 2026
Summary
This is a naming/UX report, not a crash: the word "Pin" is bound to two independent pieces of state in the workspace sidebar model, and the two actions live one click apart. On the Workspaces page, "Pin to Sidebar" / "Unpin from Sidebar" toggles membership (
sidebarState.isHidden) — whether the workspace appears in the sidebar at all. In the sidebar, "Pin" / "Unpin" toggles placement (sidebarState.pinnedAt) — whether the row floats up into the PINNED section. Both use a pushpin icon, and the Workspaces page filter chip labeled "Pinned" actually filters on membership, not on the PINNED section. The reported behavior is accurate as described.Affected code
Two independent fields on
v2WorkspaceLocalState.sidebarState:isHidden, written byensureWorkspaceInSidebar/hideWorkspaceInSidebaratapps/desktop/src/renderer/routes/_authenticated/hooks/useDashboardSidebarState/useDashboardSidebarState.ts:334and:912.pinnedAt, written bysetWorkspacePinnedatuseDashboardSidebarState.ts:815, ordered byreorderPinnedWorkspacesat:854.Surfaces that say "pin":
v2-workspaces/components/V2WorkspaceContextMenu/V2WorkspaceContextMenu.tsx:157-174RiPushpinFill/RiPushpinLine)addToSidebar/removeFromSidebar(:65,:81)DashboardSidebar/.../DashboardSidebarWorkspaceContextMenu.tsx:109-121LuPin/LuPinOff)onTogglePin→setWorkspacePinnedDashboardSidebarWorkspaceContextMenu.tsx:248-253DashboardSidebarPinnedSection.tsx:73,:110v2-workspaces/stores/v2WorkspacesFilterStore/v2WorkspacesFilterStore.ts:59-78matchesPinFilterreadsworkspace.isInSidebar(useAccessibleV2Workspaces.ts:191-199, derived at:687)Note the third row: the sidebar's own menu already names the membership action "Remove from Sidebar", so the app currently has two different labels for one behavior and one label for two behaviors.
Root cause
Nothing is functionally broken — the two states are correctly separate and the code's internal names are unambiguous (
isHiddenvspinnedAt,removeFromSidebarvssetWorkspacePinned). The collision is entirely at the label layer, introduced by giving the membership action a pushpin metaphor it doesn't need.One real sharp edge amplifies the confusion: hiding clears the pin.
tombstoneSidebarWorkspaceRecordatapps/desktop/src/renderer/routes/_authenticated/hooks/useDashboardSidebarState/sidebarMutations.ts:57-65setspinnedAt = nullalongsideisHidden = true(deliberately — the comment explains a resurrected workspace must not reappear pre-pinned). So a user who right-clicks a PINNED workspace on the Workspaces page and picks "Unpin from Sidebar" expecting it to drop out of the PINNED row instead loses both the pin and the sidebar row, and re-adding it puts it back in the project tree rather than in PINNED. That's the concrete data-loss-shaped consequence of the naming overlap.Reproduction
isHidden = true,pinnedAt = null), not just from PINNED.For a unit-level check,
useDashboardSidebarState/sidebarMutations.test.tsalready exercisestombstoneSidebarWorkspaceRecord; abun:testcase assertingpinnedAt === nullafter tombstoning a pinned row would pin down step 3's mechanism.Fix direction
The rename is the whole fix; no state-model change is needed. Two options, and the choice is a product call:
A — the issue's proposal. Keep "Pin to Sidebar" on the Workspaces page, rename the sidebar action to Favorite/Star and the section to FAVORITES. Worth knowing before picking this: Pages already has a favorites store (
favoritePageIdsinproviders/CollectionsProvider/dashboardSidebarLocal/schema.ts:411,usePageFavorites) whose UI is labeled "Pin"/"Pinned" (pages/.../PageCard/PageCard.tsx:151-155,PagesView.tsx:67) — so this option swaps the two words relative to Pages unless Pages is renamed in the same pass. Marketing copy also leans on the pin metaphor for the sidebar section (marketing.roadmap.item.workspacePinningBulkActions: "Pin workspaces above your projects").B — smaller churn. Leave PINNED alone (it's the conventional "pinned tab" meaning: placement) and rename the Workspaces-page action to "Add to Sidebar" / "Remove from Sidebar", matching the sidebar menu's existing "Remove from Sidebar" entry and the code's own
addToSidebar/removeFromSidebarnames. SwapRiPushpin*for a non-pin icon (LuPlus/LuX) atV2WorkspaceContextMenu.tsx:162,169, and relabel the filter atv2WorkspacesFilterStore.ts:66-77to "In sidebar" / "Not in sidebar" — that chip is arguably the most misleading string of the set today, since it sits on the same page as a PINNED section that means something else.Either way,
packages/i18n/README.md§"Editing English copy under a stable ID" applies: IDs are stable, so changing the JSX text alone doesn't change what ships —locales/en/messages.pomust be regenerated and all 16 locales updated, withbun run --cwd packages/i18n checkgating it in CI. Affected IDs:dashboard.workspaces.contextMenu.pinToSidebar/.unpinFromSidebar,dashboard.v2Workspaces.pinFilter*,dashboard.workspaces.header.pinnedFilter, and (under option A)dashboard.sidebar.workspaceMenu.pin/.unpin,dashboard.sidebar.sectionPinned,dashboard.sidebar.pinnedSection.dropToPin,dashboard.sidebar.projectContent.dropToUnpin,dashboard.sidebar.sessionsSection.dropToUnpin.Kitenite commentedon Aug 29, 2026
Very true, I like the suggestion let me see if there's something else like show on sidebar instead of pin on the workspace view
docs(workspaces): list the Filter menu items the app shows today