# Search menu

> **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/).

This recipe adds an app menu next to the search bar above the channel list: a Menu button that opens a list with Profile, New Group and Sign Out. The search bar is the `SearchBar` override key, so the recipe wraps the default bar and keeps search working. The search components are explained in [Search](https://getstream.io/chat/docs/sdk/react/v15/features/channels/search/).

## Example

The menu is a plain list. It calls `close` after an item is picked:

```tsx title="src/AppMenu.tsx"
import "./AppMenu.css";

type AppMenuProps = {
  close: () => void;
};

export const AppMenu = ({ close }: AppMenuProps) => {
  const handleSelect = () => {
    // Open the profile, start a group or sign out here.
    close();
  };

  return (
    <div className="app-menu__container">
      <ul className="app-menu__item-list">
        <li>
          <button
            className="app-menu__item"
            onClick={handleSelect}
            type="button"
          >
            Profile
          </button>
        </li>
        <li>
          <button
            className="app-menu__item"
            onClick={handleSelect}
            type="button"
          >
            New Group
          </button>
        </li>
        <li>
          <button
            className="app-menu__item"
            onClick={handleSelect}
            type="button"
          >
            Sign Out
          </button>
        </li>
      </ul>
    </div>
  );
};
```

```css title="src/AppMenu.css"
.search-bar-with-menu {
  position: relative;
}

.search-bar-with-menu__button {
  left: 0.75rem;
  position: absolute;
  top: 0.75rem;
  z-index: 2;
}

.search-bar-with-menu .str-chat__search-bar {
  padding-left: 4rem;
}

.app-menu__container {
  background-color: white;
  border-radius: 5px;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.15);
  left: 0.75rem;
  position: absolute;
  top: 3.25rem;
  z-index: 3;
}

.app-menu__item-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.app-menu__item {
  background: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  padding: 0.5rem 1rem;
  text-align: start;
  width: 100%;
}

.app-menu__item:hover {
  background-color: lightgrey;
}
```

The search bar with the menu renders the default `SearchBar` beside the button. Register it under the `SearchBar` key, around `ChannelNavigation`, which renders the channel list header, the search and the channel lists:

```tsx title="src/App.tsx"
import { useState } from "react";
import {
  ChannelHeader,
  ChannelNavigation,
  Chat,
  MessageComposer,
  MessageList,
  SearchBar,
  ThreadHeader,
  WithComponents,
} from "stream-chat-react";
import {
  ChannelSlot,
  ChatView,
  ThreadSlot,
} from "stream-chat-react/slot-layout";
import type { LayoutDescriptor } from "stream-chat-react/slot-layout";
import { AppMenu } from "./AppMenu";

const SearchBarWithMenu = () => {
  const [menuOpen, setMenuOpen] = useState(false);

  return (
    <div className="search-bar-with-menu">
      <button
        aria-expanded={menuOpen}
        className="search-bar-with-menu__button"
        onClick={() => setMenuOpen((open) => !open)}
        type="button"
      >
        Menu
      </button>
      {menuOpen && <AppMenu close={() => setMenuOpen(false)} />}
      <SearchBar />
    </div>
  );
};

// Declared once, so WithComponents gets the same object on every render.
const overrides = { SearchBar: SearchBarWithMenu };

const layouts: LayoutDescriptor[] = [
  { id: "channels", slots: ["channel", "thread"] },
];

const ChannelsView = () => (
  <>
    <WithComponents overrides={overrides}>
      <ChannelNavigation />
    </WithComponents>
    <ChannelSlot slot="channel">
      <ChannelHeader />
      <MessageList />
      <MessageComposer />
    </ChannelSlot>
    <ThreadSlot slot="thread">
      <ThreadHeader />
      <MessageList />
      <MessageComposer />
    </ThreadSlot>
  </>
);

export const App = () => (
  <Chat client={client}>
    <ChatView layouts={layouts} views={{ channels: <ChannelsView /> }} />
  </Chat>
);
```

`SearchBar` reads the search from `Search`, so it keeps working inside the wrapper: typing searches, and the results replace the channel lists while the search is active. The channel lists come from the paginators registered on `client.channelManager`, as in the [Quick start](https://getstream.io/chat/docs/sdk/react/v15/getting-started/quick-start/#add-a-channel-list-with-chatview).

This menu closes only when an item is picked or the button is clicked again. For one that also closes on Escape and on clicks outside it, and moves the focus into it, open it as a `ContextMenu`: see [Dialogs](https://getstream.io/chat/docs/sdk/react/v15/ui/customizing/dialogs/).

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/v15/recipes/app/search-menu/](https://getstream.io/chat/docs/sdk/react/v15/recipes/app/search-menu/).