Skip to content
+

Chat - Model selector

Add a model picker to the conversation header using the conversationHeaderActions slot.

This demo shows how to place a MUI Select inside the conversation header so users can switch between AI models. No new component is needed — drop any MUI control into slots.conversationHeaderActions.

  • slots.conversationHeaderActions accepting a custom component that renders a Select
  • Controlled model state owned by the selector component
  • The Select placed inline in the header via marginInlineStart: 'auto' (applied automatically by ChatConversationHeaderActions)
MUI Assistant
Material UI chat
Styled with your active MUI theme
Material UI chat

Styled with your active MUI theme

MUI Assistant
MUI Assistant

Hello! I am styled using your active Material UI theme. Try sending a message.

You
You

Great — the bubble colors come from palette.primary and the typography from the theme.

Press Enter to start editing

The pattern

function MyModelSelector() {
  const [model, setModel] = React.useState('gpt-4o');
  return (
    <Select value={model} onChange={(e) => setModel(e.target.value)} size="small">
      <MenuItem value="gpt-4o">GPT-4o</MenuItem>
      <MenuItem value="claude-3-5-sonnet">Claude 3.5 Sonnet</MenuItem>
    </Select>
  );
}

<ChatBox slots={{ conversationHeaderActions: MyModelSelector }} />;

Passing the model to the adapter

The demo above keeps model state inside the selector. To also pass the selected model to adapter.sendMessage, hoist state up to the parent and construct the adapter with React.useMemo:

export default function App() {
  const [model, setModel] = React.useState('gpt-4o');

  const adapter = React.useMemo(
    () => ({
      async sendMessage({ message, signal }) {
        const res = await fetch('/api/chat', {
          method: 'POST',
          body: JSON.stringify({ message, model }),
          signal,
        });
        return res.body;
      },
    }),
    [model],
  );

  // Stable reference — defined outside or memoized to avoid remounts
  const HeaderActions = React.useMemo(
    () =>
      function ModelSelector() {
        return (
          <Select
            value={model}
            onChange={(e) => setModel(e.target.value)}
            size="small"
          >
            <MenuItem value="gpt-4o">GPT-4o</MenuItem>
            <MenuItem value="claude-3-5-sonnet">Claude 3.5 Sonnet</MenuItem>
          </Select>
        );
      },
    [model],
  );

  return (
    <ChatBox
      adapter={adapter}
      slots={{ conversationHeaderActions: HeaderActions }}
    />
  );
}

Implementation notes

  • ChatConversationHeaderActions already applies marginInlineStart: 'auto' so the selector floats to the right automatically.
  • Define the slot component outside the render function, or stabilize it with React.useMemo, to avoid remounting the header on every render.
  • Use size="small" on Select to match the default header height.

See also

API