Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const summary = (
id: `p-${kind}-${totalUsd}`,
name: kind,
kind,
isPersonal: false,
threadId: null,
createdAt: "",
updatedAt: ""
Expand Down
12 changes: 11 additions & 1 deletion web/src/components/workspace/WorkspaceShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ const WorkspaceShell = () => {
[theme, isDragging]
);
const tabs = useWorkspaceTabsStore((state) => state.tabs);
const activeProjectId = useWorkspaceTabsStore(
(state) => state.activeProjectId
);
const activeTabId = useWorkspaceTabsStore((state) => state.activeTabId);
const setTitle = useWorkspaceTabsStore((state) => state.setTitle);
const setCurrentWorkflowId = useWorkflowManager(
Expand All @@ -128,6 +131,13 @@ const WorkspaceShell = () => {
() => tabs.find((tab) => tab.id === activeTabId) ?? null,
[tabs, activeTabId]
);
const visibleTabs = useMemo(
() =>
activeProjectId
? tabs.filter((tab) => tab.projectId === activeProjectId)
: tabs.filter((tab) => tab.projectId === undefined),
[activeProjectId, tabs]
);

// The left rail (PanelLeft) is position:fixed, so its open drawer normally
// floats over the content. The node canvas keeps the overlay so it stays
Expand Down Expand Up @@ -185,7 +195,7 @@ const WorkspaceShell = () => {
className="workspace-content"
style={{ marginLeft: contentMarginLeft }}
>
{tabs.length === 0 && (
{visibleTabs.length === 0 && (
<div className="workspace-empty">
<Suspense fallback={null}>
<NewProjectSurface />
Expand Down
15 changes: 11 additions & 4 deletions web/src/components/workspace/WorkspaceTabBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,13 @@ const WorkspaceTabBar = React.memo(function WorkspaceTabBar() {
const activeProjectId = useWorkspaceTabsStore(
(state) => state.activeProjectId
);
const visibleTabs = useMemo(
() =>
activeProjectId
? tabs.filter((tab) => tab.projectId === activeProjectId)
: tabs.filter((tab) => tab.projectId === undefined),
[activeProjectId, tabs]
);

const activeTab = useMemo(
() => tabs.find((tab) => tab.id === activeTabId) ?? null,
Expand All @@ -328,11 +335,11 @@ const WorkspaceTabBar = React.memo(function WorkspaceTabBar() {
// The store keeps its tabs in render order — the open project's tabs are one
// contiguous run behind the scope chip — so the bar renders `tabs` as they
// come and a tab's index on screen is its index in the store.
const firstGroupedTabId = tabs.find(
const firstGroupedTabId = visibleTabs.find(
(tab) => tab.projectId === activeProjectId
)?.id;
const groupName =
tabs.find((tab) => tab.type === "project" && tab.ref === activeProjectId)
visibleTabs.find((tab) => tab.type === "project" && tab.ref === activeProjectId)
?.title ?? "Project";

const newTabButtonRef = useRef<HTMLButtonElement>(null);
Expand Down Expand Up @@ -628,7 +635,7 @@ const WorkspaceTabBar = React.memo(function WorkspaceTabBar() {
</button>
{isMobile ? (
<MobileDocumentSelector
tabs={tabs}
tabs={visibleTabs}
activeTabId={activeTabId}
typeColor={TYPE_COLOR}
typeGlyph={TYPE_GLYPH}
Expand All @@ -638,7 +645,7 @@ const WorkspaceTabBar = React.memo(function WorkspaceTabBar() {
/>
) : (
<div className="tabs">
{tabs.map((tab) => (
{visibleTabs.map((tab) => (
<Fragment key={tab.id}>
{tab.id === firstGroupedTabId && activeProjectId && (
<ProjectScopeChip
Expand Down
Loading
Loading