diff --git a/packages/ui/src/features/canvas/components/ChannelsList.test.tsx b/packages/ui/src/features/canvas/components/ChannelsList.test.tsx index dfb85c1f23..66582e1dad 100644 --- a/packages/ui/src/features/canvas/components/ChannelsList.test.tsx +++ b/packages/ui/src/features/canvas/components/ChannelsList.test.tsx @@ -52,6 +52,7 @@ import { showChannelList, showChannelPane, } from "@posthog/ui/features/canvas/stores/channelPaneStore"; +import { useCurrentChannelStore } from "@posthog/ui/features/canvas/stores/currentChannelStore"; import { useSidebarStore } from "@posthog/ui/features/sidebar/sidebarStore"; import { ChannelsList } from "./ChannelsList"; @@ -81,6 +82,16 @@ describe("ChannelsList", () => { useSidebarStore.setState({ collapsedSections: new Set() }); }); + it("opens a space in the sidebar without navigating the main window", async () => { + const user = userEvent.setup(); + renderList(); + + await user.click(screen.getByText("engineering")); + + expect(useCurrentChannelStore.getState().currentChannelId).toBe(ENG.id); + expect(mocks.navigate).not.toHaveBeenCalled(); + }); + it("pins #me above the channels, with its ⌘1 shortcut", () => { renderList(); const me = screen.getByText("me"); @@ -182,10 +193,8 @@ describe("ChannelsList", () => { await user.type(screen.getByLabelText("Search spaces"), "eng"); await user.keyboard("{Enter}"); - expect(mocks.navigate).toHaveBeenCalledWith({ - to: "/website/$channelId", - params: { channelId: ENG.id }, - }); + expect(useCurrentChannelStore.getState().currentChannelId).toBe(ENG.id); + expect(mocks.navigate).not.toHaveBeenCalled(); }); it("moves the highlight with the arrow keys", async () => { @@ -197,10 +206,8 @@ describe("ChannelsList", () => { await user.type(screen.getByLabelText("Search spaces"), "e"); await user.keyboard("{ArrowDown}{Enter}"); - expect(mocks.navigate).toHaveBeenCalledWith({ - to: "/website/$channelId", - params: { channelId: ENG.id }, - }); + expect(useCurrentChannelStore.getState().currentChannelId).toBe(ENG.id); + expect(mocks.navigate).not.toHaveBeenCalled(); }); // Base UI's clear button is a tabIndex=-1 decoration by default, which left @@ -247,10 +254,8 @@ describe("ChannelsList", () => { await user.click(screen.getByLabelText("Search spaces")); await user.keyboard("{ArrowDown}{Enter}"); - expect(mocks.navigate).toHaveBeenCalledWith({ - to: "/website/$channelId", - params: { channelId: ENG.id }, - }); + expect(useCurrentChannelStore.getState().currentChannelId).toBe(ENG.id); + expect(mocks.navigate).not.toHaveBeenCalled(); }); // Base UI resets the highlight when the pointer leaves a row, and @@ -266,10 +271,8 @@ describe("ChannelsList", () => { await user.unhover(row); await user.keyboard("{Enter}"); - expect(mocks.navigate).toHaveBeenCalledWith({ - to: "/website/$channelId", - params: { channelId: ENG.id }, - }); + expect(useCurrentChannelStore.getState().currentChannelId).toBe(ENG.id); + expect(mocks.navigate).not.toHaveBeenCalled(); }); // A kept-mounted collapsed row would still be an option, so ↓ would walk @@ -323,10 +326,8 @@ describe("ChannelsList", () => { // it would have been the row after it. await user.keyboard("{ArrowDown}{Enter}"); - expect(mocks.navigate).toHaveBeenCalledWith({ - to: "/website/$channelId", - params: { channelId: ENG.id }, - }); + expect(useCurrentChannelStore.getState().currentChannelId).toBe(ENG.id); + expect(mocks.navigate).not.toHaveBeenCalled(); }); it("selects a stale query so the next keystroke replaces it", async () => { diff --git a/packages/ui/src/features/canvas/components/ChannelsList.tsx b/packages/ui/src/features/canvas/components/ChannelsList.tsx index 1b648d1959..9be83a64a6 100644 --- a/packages/ui/src/features/canvas/components/ChannelsList.tsx +++ b/packages/ui/src/features/canvas/components/ChannelsList.tsx @@ -393,7 +393,7 @@ function ChannelMenu({ ); } -// One channel in the list: a "# name" row that navigates to the channel home. +// One channel in the list: a "# name" row that opens its sidebar. // No expansion — the channel's surfaces live in the in-channel top nav. function ChannelSection({ channel, @@ -434,8 +434,8 @@ function ChannelSection({ return ( - {/* A single, non-expandable row: the "# name" navigates straight to the - channel home. Right-clicking opens the same actions as the "..." menu. */} + {/* A single, non-expandable row: the "# name" opens the channel sidebar. + Right-clicking opens the same actions as the "..." menu. */} Promise; isCreating: boolean; } { + const spacesLayout = useChannelsLayout(); const navigate = useNavigate(); const setCurrentChannel = useCurrentChannelStore((s) => s.setCurrentChannel); const { channels } = useChannels(); @@ -656,18 +657,20 @@ function useOpenPersonalChannel(): { if (!channelId) return; showChannelPane(); setCurrentChannel(channelId); - void navigate({ to: "/website/$channelId", params: { channelId } }); + if (!spacesLayout) { + void navigate({ to: "/website/$channelId", params: { channelId } }); + } }; return { ensureFolderId, openPersonalChannel, isCreating }; } /** - * Navigating into a channel, shared by the tree rows and the search results. - * Slides before navigating: the route effect would get there too, but not until - * the navigation resolves. + * Opening a channel, shared by the tree rows and the search results. In the + * Spaces layout this scopes the sidebar without moving the main window. */ function useOpenChannel(): (channel: Channel) => void { + const spacesLayout = useChannelsLayout(); const navigate = useNavigate(); const setCurrentChannel = useCurrentChannelStore((s) => s.setCurrentChannel); @@ -679,10 +682,12 @@ function useOpenChannel(): (channel: Channel) => void { }); showChannelPane(); setCurrentChannel(channel.id); - void navigate({ - to: "/website/$channelId", - params: { channelId: channel.id }, - }); + if (!spacesLayout) { + void navigate({ + to: "/website/$channelId", + params: { channelId: channel.id }, + }); + } }; }