# Workspace navigation API

> **Info:** This is release candidate documentation for **Stream Chat React SDK v15**. For the latest stable version, see the [latest version (v14)](https://getstream.io/chat/docs/sdk/react/).

`WorkspaceNavigation` is the interface the SDK's components navigate through: they open, close and check channels and threads with it, without knowing the layout. `useWorkspaceNavigation()` returns it. [Navigation](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/navigation/) explains how it's used, and [Moving between channels, threads and messages](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/moving-between-channels-threads-and-messages/) lists every component that calls it.

## Why an adapter sits here

The SDK's components depend on the interface, not on a layout. `ChatView` implements it over its slots and provides it to the components inside it. Outside a provider, `useWorkspaceNavigation()` returns a default whose operations do nothing: `openChannels` and `openThreads` are empty, and every check returns `false`. The first call of each of `openChannel`, `openThread`, `closeChannel`, `closeThread` and `goBack` also logs a console warning. `defaultWorkspaceNavigation` has the same members without the warnings. [Without a layout](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/navigation/#without-a-layout) lists what that means for each component.

| Export                        | From                            | What it is                                                                                                                                                                         |
| ----------------------------- | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `useWorkspaceNavigation()`    | `stream-chat-react`             | Returns the `WorkspaceNavigation` of the nearest provider, or a no-op default that warns on first use.                                                                             |
| `WorkspaceNavigationProvider` | `stream-chat-react`             | Gives the components below it the navigation passed as `value`. See [Providing your own navigation](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/navigation/#providing-your-own-navigation). |
| `defaultWorkspaceNavigation`  | `stream-chat-react`             | The default that does nothing. Spread it to fill the members your own navigation leaves out.                                                                                       |
| `useWorkspacePanel()`         | `stream-chat-react`             | The panel the calling component renders in, or `undefined` outside one.                                                                                                            |
| `WorkspacePanelProvider`      | `stream-chat-react`             | Declares the panel, its `panel` prop, that its children render in. `Slot`, `ChannelSlot` and `ThreadSlot` render one with their slot name.                                         |
| `WorkspaceNavigationAdapter`  | `stream-chat-react/slot-layout` | `ChatView`'s implementation. `ChatView` renders it, so an app doesn't.                                                                                                             |

## The API

The descriptions are what `ChatView`'s implementation does. A navigation of your own decides its own behaviour.

| Member                 | Type                                                                       | Description                                                                                                                                                                                                                 |
| ---------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `openChannel`          | `(channel: Channel, options?: WorkspaceNavigationOptions) => void`         | Opens the channel. It places the channel; it doesn't load it. [Where an opened channel or thread lands](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/workspace-with-chatview/#where-an-opened-channel-or-thread-lands) has the rules. |
| `openThread`           | `(target: OpenThreadTarget, options?: WorkspaceNavigationOptions) => void` | Opens a `Thread`, or the thread of `{ channel, message }`, which it gets from `client.threads.ensure()`.                                                                                                                    |
| `closeChannel`         | `(cid?: string, options?: WorkspaceNavigationOptions) => void`             | Closes the panel that shows the channel. A panel beside the main one closes with everything stacked in it. The main panel loses its top layer, or is emptied when nothing is stacked on it.                                 |
| `closeThread`          | `(threadId?: string, options?: WorkspaceNavigationOptions) => void`        | Closes the panel that shows the thread, the same way. Without `threadId`, or when no panel shows it, the first panel holding a thread. It doesn't deactivate the thread.                                                    |
| `goBack`               | `(key?: string, options?: WorkspaceNavigationOptions) => void`             | Removes the channel or thread with `key`, a `cid` or a thread id, from the top of its panel, and shows what's beneath. Does nothing when `canGoBack` is `false`.                                                            |
| `canGoBack`            | `(key?: string, panel?: string) => boolean`                                | Whether the panel showing `key` has something beneath it.                                                                                                                                                                   |
| `isChannelActive`      | `(cid?: string) => boolean`                                                | Whether the channel is on screen: shown in a panel of the shown view, not covered by something stacked on top of it.                                                                                                        |
| `isThreadActive`       | `(threadId?: string) => boolean`                                           | The same, for a thread.                                                                                                                                                                                                     |
| `isChannelDismissable` | `(cid?: string, panel?: string) => boolean`                                | Whether its panel can be closed. Only a channel opened beside another one can.                                                                                                                                              |
| `isThreadDismissable`  | `(threadId?: string, panel?: string) => boolean`                           | Whether its panel can be closed. In the channels view, `true` for every thread. In the threads view, only for a thread beside the view's main thread.                                                                       |
| `isThreadsView`        | `boolean`                                                                  | Whether the threads view is shown.                                                                                                                                                                                          |
| `openChannels`         | `Channel[]`                                                                | The channels the shown view's slots hold, underneath any layers.                                                                                                                                                            |
| `openThreads`          | `Thread[]`                                                                 | The threads the shown view's slots hold, underneath any layers.                                                                                                                                                             |

`Channel` and `Thread` are the `stream-chat` classes.

### Options

`openChannel`, `openThread`, `closeChannel`, `closeThread` and `goBack` take the same options, a `WorkspaceNavigationOptions`:

| Option     | Type                              | Description                                                                                                                                                                                     |
| ---------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `additive` | `boolean`                         | Opens beside the current content instead of replacing it. A layout with one slot ignores it.                                                                                                    |
| `layer`    | `boolean`                         | Opens on top of what the panel shows. Going back reveals what was beneath.                                                                                                                      |
| `event`    | `WorkspaceNavigationTriggerEvent` | The click, key press or touch that started the navigation. The channel list, search results and header buttons pass it. The SDK doesn't act on it: an override reads the ⌘ or ctrl key from it. |
| `panel`    | `string`                          | The panel the call comes from, for a channel or thread open in two panels. Without it, the first panel showing it. The close and back operations use it.                                        |

The types they name:

| Type                              | Definition                                                      |
| --------------------------------- | --------------------------------------------------------------- |
| `OpenThreadTarget`                | `Thread`, or `{ channel: Channel; message: LocalMessage }`      |
| `WorkspaceNavigationTriggerEvent` | `React.MouseEvent`, `React.KeyboardEvent` or `React.TouchEvent` |
| `WorkspacePanelId`                | `string`                                                        |

[Beside and on top](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/navigation/#beside-and-on-top) and [Panels](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/navigation/#panels) show the options at work.

## Overriding navigation

`ChatView`'s `deriveWorkspaceNavigation` prop changes what its navigation does. It's a `DeriveWorkspaceNavigation`, `(base: WorkspaceNavigation) => Partial<WorkspaceNavigation>`: it receives the navigation `ChatView` built, and returns only the members to replace. Every member it leaves out, or sets to `undefined`, keeps `ChatView`'s behaviour. Call `base` to keep that behaviour around your own:

```tsx
import type { DeriveWorkspaceNavigation } from "stream-chat-react/slot-layout";

// Declared outside the component, so ChatView gets the same function on every render.
export const deriveWorkspaceNavigation: DeriveWorkspaceNavigation = (base) => ({
  openChannel: (channel, options) => {
    console.info("Opening", channel.cid);
    base.openChannel(channel, options);
  },
});
```

Pass it as `<ChatView deriveWorkspaceNavigation={deriveWorkspaceNavigation}>`. Keep it stable: declare it outside the component, or wrap it in `useCallback`. A new function on every render rebuilds the navigation on every render.

The override reaches every component that calls `useWorkspaceNavigation()`, selecting a pinned message and **Send direct message** in channel details included. Those two call `openChannel(channel)` with no options, so an override that reads `options.event` gets no event from them.

[Changing navigation behaviour](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/workspace-with-chatview/#changing-navigation-behaviour) opens a channel beside the open one on ⌘/ctrl-click, and [⌘/ctrl-click opens beside](https://getstream.io/chat/docs/sdk/react/v15/recipes/layout/ctrl-click-opens-beside/) walks through it. To replace the navigation outside `ChatView`, render a `WorkspaceNavigationProvider` with your own.

## See also

- [Navigation](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/navigation/): the interface, opening beside and on top, panels, and navigation without a layout.
- [Workspace with ChatView](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/workspace-with-chatview/): where `ChatView` puts what the navigation opens.
- [Slot layout](https://getstream.io/chat/docs/sdk/react/v15/component-reference/layout/slot-layout/): `useChatViewNavigation()`, which opens anything in a named slot.
- [Slot geometry](https://getstream.io/chat/docs/sdk/react/v15/component-reference/layout/slot-geometry/): which panels are covered on screen.

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/v15/component-reference/layout/workspace-navigation-api/](https://getstream.io/chat/docs/sdk/react/v15/component-reference/layout/workspace-navigation-api/).