Skip to content

[x-chat] Add ChatBox layout slots with context-based slot distribution - #22482

Closed
hasdfa wants to merge 78 commits into
mui:masterfrom
hasdfa:x-chat-chatbox-layout-slots-codemod
Closed

hasdfa wants to merge 78 commits into
mui:masterfrom
hasdfa:x-chat-chatbox-layout-slots-codemod

Conversation

@hasdfa

@hasdfa hasdfa commented May 17, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Adds ChatBox layout slots plus the related conversation, message, composer, indicator, suggestions, and confirmation slot surface.
  • Distributes slots/slotProps through a new internal ChatSlotsProvider / useChatSlots context instead of prop-drilling, so a top-level override reaches deep message rows (including the virtualized list) without threading.
  • Uses a flat, prefixed slot vocabulary (messageAvatar, conversationHeader, composerSendButton, …) — consistent with GridSlotsComponent / Charts and with what @mui/x-chat already ships.

What changed from the earlier iteration of this PR

An earlier revision nested the slots by family (message.avatar, composer.send, …) and added a v9.0.0/chat/migrate-slots codemod. That has been reverted:

  • The public API is back to the flat vocabulary (the shape already published in 9.0.0-alpha).
  • The chat/migrate-slots codemod and its preset-safe entry were removed. The nested vocabulary was never released (it lived only on this branch), so there is nothing for a codemod to migrate.
  • Net effect versus master is additive — four new optional slots (conversationRoot, messageInlineMeta, messageError, messageAuthorName) plus the context refactor. No renames, no removals, no breaking change.

Details

  • Flat ChatBoxSlots / ChatBoxSlotProps are composed from prefixed per-family interfaces; only the composed types are public.
  • Two vocabularies, one rule: the pipeline (ChatBox, ChatMessageList, ChatMessageGroup) uses the flat prefixed keys; leaf components (ChatMessage, ChatComposer, ChatConversation) keep their short local keys, with the flat→short translation at a single seam.
  • Presentational slots accept null to hide-and-collapse; the features object toggles capabilities — both preserved.
  • Updates demos, the slots-and-composition reference page, and regenerates the X Chat API docs / proptypes.
  • Includes two correctness fixes for the new slot surface: the styled wrappers now resolve { ...slots, <key>: slots?.<key> ?? Default } so an undefined override no longer clobbers the default root, and compact ChatMessage renders the slot-driven tree alongside the headless group's injected author label.

Addressed review feedback

Refinements from the review pass on this PR:

  • Documented every ChatBox slot with JSDoc so the API docs no longer render blank slot descriptions.
  • DefaultMessageItem spreads slotProps.messageGroup before the required row props, and ChatBox's renderItem forwards the rendered index/items so grouping is computed against the rendered list (correct when slotProps.messageList.items narrows the thread).
  • Removed the conversation-list scroller's dead width-based @container { display: none } (the headless ConversationListRoot always pins an inline display: flex, so it never fired and would only have blanked a forced layoutMode="standard" sidebar).
  • innerRef typed as useRef<HTMLDivElement | null> with a useCallback ref callback (no MutableRefObject cast); test descriptions aligned to the flat slot keys.

Validation

  • pnpm --filter "@mui/x-chat" run typescript
  • pnpm --filter "@mui/x-codemod" run typescript
  • pnpm test:unit --project "x-chat" --run (170 passed / 5 skipped)
  • pnpm test:browser --project "x-chat" --run (175 passed)
  • pnpm test:unit --project "x-codemod" --run (275 passed)
  • pnpm proptypes
  • pnpm docs:api
  • pnpm docs:typescript:formatted
  • pnpm eslint (changed chat / docs / codemod paths)
  • pnpm valelint

Batch merge structure

Merge top to bottom. #22478 can merge independently, but it should land before #22483 because #22483 assumes the new docs IA.

master
|-- #22478 [docs] Reorganize existing chat docs navigation
`-- #22479 [chat-headless] Add built-in chat adapters
    `-- #22480 [chat-headless] Harden runtime model and message errors
        `-- #22670 [x-chat] Harden material message surfaces
            `-- #22482 [x-chat] Add ChatBox layout slots with context-based slot distribution
                `-- #22483 [docs] Add chat docs page shells (after #22478)
                    `-- #22484 [docs] Add chat playground infrastructure
                        |-- #22485 [docs] Update chat quickstart and backend adapters
                        |-- #22486 [docs] Update chat basics display and behavior
                        |-- #22487 [docs] Update chat customization core material and headless docs
                        `-- #22488 [docs] Update chat overview and component gallery

hasdfa added 3 commits May 17, 2026 20:16
Two built-in adapters that ship with @mui/x-chat-headless: a simple
echo adapter for examples and an AI SDK adapter that bridges Vercel
AI SDK UIMessage streams into ChatMessageChunk events. Wire both
through the headless core barrel so they can be imported from
'@mui/x-chat-headless' and '@mui/x-chat-headless/core'.
@code-infra-dashboard

code-infra-dashboard Bot commented May 17, 2026 •

Copy link
Copy Markdown

Deploy preview

Bundle size

Bundle Parsed size Gzip size
@mui/x-data-grid 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-pro 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-premium 0B(0.00%) 0B(0.00%)
@mui/x-charts 0B(0.00%) 0B(0.00%)
@mui/x-charts-pro 0B(0.00%) 0B(0.00%)
@mui/x-charts-premium 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers-pro 0B(0.00%) 0B(0.00%)
@mui/x-tree-view 0B(0.00%) 0B(0.00%)
@mui/x-tree-view-pro 0B(0.00%) 0B(0.00%)
@mui/x-license 0B(0.00%) 0B(0.00%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

@hasdfa hasdfa added scope: chat Changes related to the AI chat. type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature. package: codemod Specific to codemod. labels May 17, 2026
@hasdfa
hasdfa force-pushed the x-chat-chatbox-layout-slots-codemod branch 2 times, most recently from e5c6424 to a421025 Compare May 18, 2026 09:50
@hasdfa
hasdfa marked this pull request as ready for review May 18, 2026 13:14
Copilot AI review requested due to automatic review settings May 18, 2026 13:14

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a42102514d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands the X Chat component composition surface by introducing nested “layout slots” for ChatBox (and related components), and ships a v9 codemod (chat/migrate-slots) + preset-safe wiring to migrate existing flat slot keys to the new nested structure. It also introduces/exports new message error primitives and message-scoped error state, and updates docs/API generation outputs and demos to match.

Changes:

  • Add nested slot families to ChatBox (conversation/messagesList/message/composer + layout regions) and update Material components to accept/forward sx where needed.
  • Add message-scoped errors (messageErrorsById, selectors/hooks, primitives) and new ChatMessageError surface + theme augmentation.
  • Add v9.0.0/chat/migrate-slots codemod, wire into v9.0.0/preset-safe, and update docs/API pages + demos accordingly.

Reviewed changes

Copilot reviewed 223 out of 223 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
scripts/x-chat.exports.json Updates the exported symbol list for new chat types/components/functions.
scripts/buildApiDocs/chatSettings/index.ts Excludes new internal implementation file from API docs generation.
packages/x-codemod/src/v9.0.0/preset-safe/index.ts Adds chat preset into the v9 safe preset pipeline.
packages/x-codemod/src/v9.0.0/chat/preset-safe/index.ts New chat preset runner that applies chat codemods.
packages/x-codemod/src/v9.0.0/chat/migrate-slots/index.ts Implements the slot migration codemod (flat → nested families) with idempotency.
packages/x-codemod/src/v9.0.0/chat/migrate-slots/migrate-slots.test.ts Adds unit tests for the codemod runner and idempotency.
packages/x-codemod/src/v9.0.0/chat/migrate-slots/actual.spec.tsx Codemod “actual” fixture for post-rename flat keys.
packages/x-codemod/src/v9.0.0/chat/migrate-slots/expected.spec.tsx Codemod “expected” fixture for nested-family output.
packages/x-codemod/src/v9.0.0/chat/migrate-slots/pre-rename.actual.spec.tsx Codemod “actual” fixture for pre-rename flat keys.
packages/x-codemod/src/v9.0.0/chat/migrate-slots/pre-rename.expected.spec.tsx Codemod “expected” fixture for nested-family output from pre-rename keys.
packages/x-codemod/README.md Documents the new chat codemod and usage.
packages/x-chat/src/themeAugmentation/props.ts Adds theme defaultProps typing for MuiChatMessageError.
packages/x-chat/src/themeAugmentation/overrides.ts Adds class key typing for MuiChatMessageError overrides.
packages/x-chat/src/themeAugmentation/components.ts Adds MuiChatMessageError entry to theme components augmentation.
packages/x-chat/src/internals/useCopyToClipboard.ts Adds reusable clipboard hook used by message/code surfaces.
packages/x-chat/src/index.ts Exports new chat types, error surfaces, and re-exports built-in adapters.
packages/x-chat/src/ChatSuggestions/ChatSuggestions.tsx Adds sx support and surfaces alwaysVisible docs/propTypes.
packages/x-chat/src/ChatSuggestions/ChatSuggestions.test.tsx Updates expectations: suggestions can render even with existing messages.
packages/x-chat/src/ChatMessageSources/ChatMessageSources.tsx Adds sx prop support.
packages/x-chat/src/ChatMessageSkeleton/ChatMessageSkeleton.tsx Adds sx prop support.
packages/x-chat/src/ChatMessageList/DefaultMessageItem.tsx Adds shared default row component used by ChatBox and ChatMessageList.
packages/x-chat/src/ChatMessageList/ChatMessageList.test.tsx Adds tests for standalone default row, custom renderItem, and slot overrides.
packages/x-chat/src/ChatMessageError/index.ts Adds barrel exports for ChatMessageError and its classes.
packages/x-chat/src/ChatMessageError/chatMessageErrorClasses.ts Adds utility classes + hook for ChatMessageError.
packages/x-chat/src/ChatMessage/index.ts Re-exports ChatMessageError via ChatMessage barrel.
packages/x-chat/src/ChatMessage/ChatMessageMeta.tsx Switches alignment logic to isOwnMessage ownerState.
packages/x-chat/src/ChatMessage/ChatMessageInlineMeta.tsx Switches contrast logic to isOwnMessage ownerState.
packages/x-chat/src/ChatMessage/ChatMessageGroup.test.tsx Adds tests for author label default/override/null behavior via nested slots.
packages/x-chat/src/ChatMessage/ChatMessageContent.test.tsx Updates locale expectations and tool-part rendering tests.
packages/x-chat/src/ChatMessage/chatMessageClasses.ts Adds noAvatar utility class and docs.
packages/x-chat/src/ChatMessage/ChatMessageActions.tsx Aligns actions based on isOwnMessage ownerState.
packages/x-chat/src/ChatMessage/ChatMessage.test.tsx Updates slotProps shape test; adds “own message” resolution test.
packages/x-chat/src/ChatMessage/ChatDateDivider.tsx Adds sx prop support.
packages/x-chat/src/ChatIndicators/ChatUnreadMarker.tsx Adds sx prop support.
packages/x-chat/src/ChatIndicators/ChatTypingIndicator.tsx Adds sx prop support.
packages/x-chat/src/ChatIndicators/ChatScrollToBottomAffordance.tsx Adds sx prop support.
packages/x-chat/src/ChatConversationList/ChatConversationList.test.tsx Enables conversation list feature in tests; stabilizes async selection assertions.
packages/x-chat/src/ChatConfirmation/ChatConfirmation.tsx Adds sx prop support.
packages/x-chat/src/ChatComposer/ChatComposerTextArea.test.tsx Updates slotProps path to nested composer family.
packages/x-chat/src/ChatComposer/ChatComposerSendButton.test.tsx Updates slotProps path to nested composer family.
packages/x-chat/src/ChatComposer/ChatComposerAttachmentList.tsx Reads composer state via store hook to support layouts without ChatComposer.
packages/x-chat/src/ChatComposer/ChatComposerAttachButton.test.tsx Updates slotProps path to nested composer family.
packages/x-chat/src/ChatComposer/ChatComposer.tsx Removes z-index; documents external onSubmit behavior in propTypes.
packages/x-chat/src/ChatComposer/ChatComposer.test.tsx Updates slotProps path to nested composer family.
packages/x-chat/src/ChatCodeBlock/ChatCodeBlock.tsx Adds sx prop + refactors clipboard logic to useCopyToClipboard.
packages/x-chat/src/ChatBox/index.ts Exposes new layout-mode types from ChatBox.types.
packages/x-chat-headless/src/types/chat-state.ts Adds message-scoped error map to internal state.
packages/x-chat-headless/src/types/chat-entities.ts Adds message author getter types/props and docs.
packages/x-chat-headless/src/suggestions/SuggestionsRoot.tsx Adds alwaysVisible behavior and prop.
packages/x-chat-headless/src/stream/streamTextDeltaBuffer.ts Fixes parallel stream isolation and “revive done part” issues via streamId mapping.
packages/x-chat-headless/src/stream/streamHelpers.ts Ensures streamed assistant messages get a createdAt timestamp.
packages/x-chat-headless/src/stream/processStream.test.ts Adds regression test for interleaved parallel streams.
packages/x-chat-headless/src/store/ChatStore.test.ts Adds coverage for message-scoped error lifecycle and dispose cleanup.
packages/x-chat-headless/src/selectors/chatSelectors.ts Adds messageAuthor and messageError selectors + export.
packages/x-chat-headless/src/selectors/chatSelectors.test.ts Adds tests for message-scoped errors vs global runtime error.
packages/x-chat-headless/src/message/parts/ToolPart.tsx Adds sectionSummary slot + preview metadata in ownerState; expands input visibility rules.
packages/x-chat-headless/src/message/parts/MessageParts.test.tsx Updates reasoning label expectation; tests sectionSummary ownerState.
packages/x-chat-headless/src/message/MessageRoot.tsx Introduces resolved author, isOwnMessage, and data attribute + aria-label updates.
packages/x-chat-headless/src/message/MessageMeta.tsx Suppresses generic “Error” status when a per-message error is present.
packages/x-chat-headless/src/message/MessageError.tsx Adds headless per-message error primitive with retry action binding.
packages/x-chat-headless/src/message/MessageContent.tsx Refactors default render helpers for data/step-start parts (typing clarity).
packages/x-chat-headless/src/message/MessageAvatar.tsx Uses resolved author fields for avatar URL + display name.
packages/x-chat-headless/src/message/MessageAuthorLabel.tsx Uses resolved author displayName (no raw role/id fallback here).
packages/x-chat-headless/src/message/message.types.ts Adds resolved author, own-message flag, and MessageError ownerState typing.
packages/x-chat-headless/src/message/internals/MessageContext.tsx Extends default context values for resolved author and isOwnMessage.
packages/x-chat-headless/src/message/index.ts Exports MessageError primitive and ownerState types.
packages/x-chat-headless/src/message-list/useMessageListBehavior.ts Adds SSR/rAF guards and StrictMode-safe mount tracking for resize-driven auto-scroll.
packages/x-chat-headless/src/message-list/MessageListRoot.tsx Adds rAF/cancelAnimationFrame guards in ResizeObserver path.
packages/x-chat-headless/src/message-list/MessageListRoot.test.tsx Adds streaming row growth tests (skipped in JSDOM) incl. StrictMode regression.
packages/x-chat-headless/src/message-group/messageGroup.types.ts Adds isOwnMessage to group ownerState.
packages/x-chat-headless/src/message-group/MessageGroup.tsx Resolves author for grouping and ownership; updates author label source.
packages/x-chat-headless/src/message-group/MessageGroup.test.tsx Adds member resolution + getter-based grouping tests; ensures role label isn’t shown spuriously.
packages/x-chat-headless/src/internals/useChatInstance/useChatInstance.ts Adds explicit controlled/uncontrolled tracking for activeConversationId.
packages/x-chat-headless/src/internals/useChatInstance/useChatInstance.test.tsx Updates tests for new controlled flag + rerender-with-undefined behavior.
packages/x-chat-headless/src/internals/useChatController/useChatControllerHelpers.ts Adds helper to extract messageId from errors.
packages/x-chat-headless/src/internals/useChatController/useChatController.ts Routes messageId-scoped runtime errors to message error state; adds stream-producer error dedupe; adds rollback for tool approval optimistic update.
packages/x-chat-headless/src/internals/useChatController/realtimeActions.test.ts Adds end-to-end test for discarding in-flight load after realtime removal.
packages/x-chat-headless/src/internals/useChatController/conversationActions.ts Avoids eager message reset during conversation switch to prevent blanking wrong thread.
packages/x-chat-headless/src/index.ts Exports new hooks/selectors/primitives + adapter exports + author getter types.
packages/x-chat-headless/src/hooks/useMessageError.ts Adds hook for per-message error selection.
packages/x-chat-headless/src/hooks/useMessageError.test.tsx Adds coverage for message-scoped error selection rules.
packages/x-chat-headless/src/hooks/useMessageAuthor.ts Adds hook for resolved author selection with locale-driven role labels.
packages/x-chat-headless/src/hooks/useChatComposer.ts Fixes preview URL lifecycle/ownership transfer and cleanup on message removal.
packages/x-chat-headless/src/hooks/useChat.test.tsx Updates expectations for createdAt; adds regression test for double-load on mount.
packages/x-chat-headless/src/hooks/index.ts Re-exports useMessageError.
packages/x-chat-headless/src/core/index.ts Exports built-in adapters + author getter types from core entry.
packages/x-chat-headless/src/conversation-list/ConversationListRoot.tsx Adds PageUp/PageDown + type-ahead navigation and cleanup.
packages/x-chat-headless/src/conversation-list/ConversationListItem.tsx Adds data-conversation-id attribute for automation/styling hooks.
packages/x-chat-headless/src/composer/ComposerSendButton.tsx Allows sending when draft has attachments even if text is empty.
packages/x-chat-headless/src/composer/ComposerRoot.tsx Adds external onSubmit semantics while always preventing native navigation.
packages/x-chat-headless/src/composer/ComposerRoot.test.tsx Adds tests for attachment-only submit and onSubmit suppression behavior.
packages/x-chat-headless/src/composer/ComposerHelperText.tsx Ensures helper text uses role="alert" when showing error content.
packages/x-chat-headless/src/ChatProvider.tsx Adds controlled tracking for activeConversationId; threads author getters into store params.
packages/x-chat-headless/src/ChatProvider.test.tsx Strengthens streamFlushInterval behavior test using fake timers + buffered deltas.
packages/x-chat-headless/src/chat/internals/chatLocaleText.ts Adds new locale labels and updates default wording (“Thoughts”, “Tool called/result”).
packages/x-chat-headless/src/chat/ChatRoot.tsx Avoids passing activeConversationId prop when uncontrolled; threads author getters.
packages/x-chat-headless/src/chat/ChatLayout.tsx Adjusts layout containers to flex-column and hides overflow to support responsive panes.
packages/x-chat-headless/src/chat/ChatComposition.test.tsx Updates variable names in focus/keyboard tests (no behavior change).
packages/x-chat-headless/src/adapters/index.ts Exports built-in adapters from adapters entrypoint.
packages/x-chat-headless/src/adapters/createEchoAdapter.ts Adds built-in demo echo adapter implementation.
docs/translations/api-docs/chat/message-error/message-error.json Adds API translation stub for new MessageError primitive.
docs/translations/api-docs/chat/composer-root/composer-root.json Documents new onSubmit behavior.
docs/translations/api-docs/chat/chat-suggestions/chat-suggestions.json Documents new alwaysVisible prop.
docs/translations/api-docs/chat/chat-root/chat-root.json Updates generated propDescriptions (removes stale entries).
docs/translations/api-docs/chat/chat-provider/chat-provider.json Updates generated propDescriptions (removes stale entries).
docs/translations/api-docs/chat/chat-message-meta/chat-message-meta.json Adds noAvatar class description.
docs/translations/api-docs/chat/chat-message-list/chat-message-list.json Documents renderItem and autoScroll behavior.
docs/translations/api-docs/chat/chat-message-group/chat-message-group.json Adds noAvatar class description.
docs/translations/api-docs/chat/chat-message-error/chat-message-error.json Adds API translation stub for ChatMessageError.
docs/translations/api-docs/chat/chat-message-content/chat-message-content.json Adds noAvatar class description.
docs/translations/api-docs/chat/chat-message-avatar/chat-message-avatar.json Adds noAvatar class description.
docs/translations/api-docs/chat/chat-message-author-label/chat-message-author-label.json Adds noAvatar class description.
docs/translations/api-docs/chat/chat-message-actions/chat-message-actions.json Adds noAvatar class description.
docs/translations/api-docs/chat/chat-date-divider/chat-date-divider.json Adds noAvatar class description.
docs/translations/api-docs/chat/chat-box/chat-box.json Updates ChatBox docs for nested slots/slotProps, author getters, and layout settings.
docs/src/modules/components/overview/chat/mainDemo/MessengerDemo.tsx Migrates demo usage to nested slots/slotProps + enables conversationList feature.
docs/src/modules/components/overview/chat/mainDemo/AgentDemo.tsx Migrates demo usage to nested slots/slotProps + enables conversationList feature.
docs/pages/x/api/chat/message-error.json Adds generated API page content for MessageError (headless).
docs/pages/x/api/chat/message-error.js Adds API page wrapper for MessageError (headless).
docs/pages/x/api/chat/chat-suggestions.json Adds generated prop entry for alwaysVisible.
docs/pages/x/api/chat/chat-message-meta.json Adds noAvatar class entry.
docs/pages/x/api/chat/chat-message-list.json Adds generated prop entry for renderItem.
docs/pages/x/api/chat/chat-message-group.json Adds noAvatar class entry.
docs/pages/x/api/chat/chat-message-error.json Adds generated API page content for ChatMessageError (material).
docs/pages/x/api/chat/chat-message-error.js Adds API page wrapper for ChatMessageError (material).
docs/pages/x/api/chat/chat-message-content.json Adds noAvatar class entry.
docs/pages/x/api/chat/chat-message-avatar.json Adds noAvatar class entry.
docs/pages/x/api/chat/chat-message-author-label.json Adds noAvatar class entry.
docs/pages/x/api/chat/chat-message-actions.json Adds noAvatar class entry.
docs/pages/x/api/chat/chat-date-divider.json Adds noAvatar class entry.
docs/data/chatApiPages.ts Registers new API page routes for ChatMessageError and MessageError.
docs/data/chat/material/thread/PaperBubble.tsx Migrates demo to nested slots.message.content.
docs/data/chat/material/thread/PaperBubble.js Generated JS demo updated for nested slot shape.
docs/data/chat/material/thread/GradientHeader.tsx Migrates demo to nested slots.conversation.header.
docs/data/chat/material/thread/GradientHeader.js Generated JS demo updated for nested slot shape.
docs/data/chat/material/thread/BubbleWithStatus.tsx Migrates demo to nested slots.message.content.
docs/data/chat/material/thread/BubbleWithStatus.js Generated JS demo updated for nested slot shape.
docs/data/chat/material/thread/AdaptiveSendButton.tsx Migrates demo to nested slots.composer.send.
docs/data/chat/material/thread/AdaptiveSendButton.js Generated JS demo updated for nested slot shape.
docs/data/chat/material/slot-overrides/ThemeAndSlotCombination.tsx Migrates demo to nested slots.message.avatar.
docs/data/chat/material/slot-overrides/ThemeAndSlotCombination.js Generated JS demo updated for nested slot shape.
docs/data/chat/material/slot-overrides/SlotPropsCustomization.tsx Migrates demo to nested slotProps.messagesList.root and slotProps.composer.input.
docs/data/chat/material/slot-overrides/SlotPropsCustomization.js Generated JS demo updated for nested slotProps shape.
docs/data/chat/material/slot-overrides/SlotBasicReplacement.tsx Migrates demo to nested slots.message.avatar.
docs/data/chat/material/slot-overrides/SlotBasicReplacement.js Generated JS demo updated for nested slot shape.
docs/data/chat/material/message-list/MessageGrouping.tsx Migrates demo to nested slotProps.messagesList.group.
docs/data/chat/material/message-list/MessageGrouping.js Generated JS demo updated for nested slotProps shape.
docs/data/chat/material/message-list/DateDividerFormat.tsx Migrates demo to nested slotProps.messagesList.dateDivider.
docs/data/chat/material/message-list/DateDividerFormat.js Generated JS demo updated for nested slotProps shape.
docs/data/chat/material/hooks/CustomComposer.tsx Migrates demo to nested slots.composer.root.
docs/data/chat/material/hooks/CustomComposer.js Generated JS demo updated for nested slot shape.
docs/data/chat/material/examples/slot-overrides/SlotOverrides.tsx Migrates demo to nested slots.message.content.
docs/data/chat/material/examples/slot-overrides/SlotOverrides.js Generated JS demo updated for nested slot shape.
docs/data/chat/material/examples/responsive-drawer/ResponsiveDrawer.tsx Enables built-in conversation list feature for the demo.
docs/data/chat/material/examples/responsive-drawer/ResponsiveDrawer.js Generated JS demo updated accordingly.
docs/data/chat/material/examples/multi-conversation/MultiConversation.tsx Enables built-in conversation list feature for the demo.
docs/data/chat/material/examples/multi-conversation/MultiConversation.js Generated JS demo updated accordingly.
docs/data/chat/material/examples/model-selector/ModelSelector.tsx Migrates demo to nested slots.conversation.headerActions.
docs/data/chat/material/examples/model-selector/ModelSelector.js Generated JS demo updated for nested slot shape.
docs/data/chat/material/examples/compact-variant/CompactVariant.tsx Enables built-in conversation list feature for the demo.
docs/data/chat/material/examples/compact-variant/CompactVariant.js Generated JS demo updated accordingly.
docs/data/chat/material/examples/agentic-code/ToolStylingC.tsx Enables conversation list feature; migrates message content slotProps nesting.
docs/data/chat/material/examples/agentic-code/ToolStylingC.js Generated JS demo updated accordingly.
docs/data/chat/material/examples/agentic-code/ToolStylingB.tsx Enables conversation list feature; migrates message content slotProps nesting.
docs/data/chat/material/examples/agentic-code/ToolStylingB.js Generated JS demo updated accordingly.
docs/data/chat/material/examples/agentic-code/ToolStylingA.tsx Enables conversation list feature; migrates message content slotProps nesting.
docs/data/chat/material/examples/agentic-code/ToolStylingA.js Generated JS demo updated accordingly.
docs/data/chat/material/examples/agentic-code/AgenticCode.tsx Enables built-in conversation list feature for the demo.
docs/data/chat/material/examples/agentic-code/AgenticCode.js Generated JS demo updated accordingly.
docs/data/chat/material/conversation-list/ThemedAvatar.tsx Enables conversation list feature; migrates nested conversation list slotProps.
docs/data/chat/material/conversation-list/ThemedAvatar.js Generated JS demo updated accordingly.
docs/data/chat/material/conversation-list/RichItemContent.tsx Enables conversation list feature; migrates nested conversation list slotProps.
docs/data/chat/material/conversation-list/RichItemContent.js Generated JS demo updated accordingly.
docs/data/chat/material/conversation-list/FullCustomRow.tsx Enables conversation list feature; migrates nested conversation list slotProps.
docs/data/chat/material/conversation-list/FullCustomRow.js Generated JS demo updated accordingly.
docs/data/chat/material/conversation-list/CompactRow.tsx Enables conversation list feature; migrates nested conversation list slotProps.
docs/data/chat/material/conversation-list/CompactRow.js Generated JS demo updated accordingly.
docs/data/chat/material/composer/ComposerDisabled.tsx Migrates demo to nested slotProps.composer.root.
docs/data/chat/material/composer/ComposerDisabled.js Generated JS demo updated accordingly.
docs/data/chat/material/composer/ComposerCustomPlaceholder.tsx Migrates demo to nested slotProps.composer.input.
docs/data/chat/material/composer/ComposerCustomPlaceholder.js Generated JS demo updated accordingly.
docs/data/chat/display/message-actions/RoleBasedMessageActions.tsx Migrates demo to nested slots.message.actions.
docs/data/chat/display/message-actions/RoleBasedMessageActions.js Generated JS demo updated accordingly.
docs/data/chat/display/message-actions/BasicMessageActions.tsx Migrates demo to nested slots.message.actions.
docs/data/chat/display/message-actions/BasicMessageActions.js Generated JS demo updated accordingly.
docs/data/chat/behavior/error-handling/error-handling.md Updates docs frontmatter to include new error components.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@hasdfa
hasdfa force-pushed the x-chat-chatbox-layout-slots-codemod branch from a421025 to 2593e1e Compare May 18, 2026 14:28
@hasdfa
hasdfa force-pushed the x-chat-chatbox-layout-slots-codemod branch from 2593e1e to 0781c8b Compare May 18, 2026 14:44
@hasdfa
hasdfa force-pushed the x-chat-chatbox-layout-slots-codemod branch from 0781c8b to 07b4810 Compare May 18, 2026 14:51
@hasdfa

hasdfa commented Jun 5, 2026

Copy link
Copy Markdown
Member Author

@codex review. Report all actionable issues, including lower-severity ones, but skip subjective style nits. Group findings by severity and explain why each one matters.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 729e5aac64

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 187 out of 187 changed files in this pull request and generated 7 comments.

hasdfa added 10 commits June 5, 2026 13:38
The master merge brought in chat demos whose generated .tsx.preview outputs
were not committed (their .js was newer than the .tsx, so the cached
formattedTSDemos run skipped them). CI regenerates them with --disable-cache
and fails the 'docs:typescript:formatted changes committed?' gate. Generate
and commit the six missing previews (all flat slot vocabulary).
The responsive-layout assertion checked `scroller` for `width: '100%'`,
which only holds in JSDOM (it returns the specified value). A real browser
resolves it against the 220px layout pane, so test_browser failed with
'220px'. Gate the test with `it.skipIf(isJSDOM)` and assert the resolved
`220px` — the value the pane's --ChatBox-conversationListWidth drives.
- DefaultMessageItem: spread `slotProps.messageGroup` before the required
  row props (messageId/index/items/slots/slotProps) so a consumer's group
  slotProps can no longer clobber them.
- Rename test descriptions to the flat ChatBox slot keys (messageRoot,
  messageAuthorName) to match the keys the test bodies actually use.
- Add JSDoc descriptions to every ChatBox slot so the API docs no longer
  render blank slot documentation; regenerate chat-box API docs/translations.
- ChatBox: type innerRef as `useRef<HTMLDivElement | null>` and use
  `useCallback` for the ref callback, dropping the MutableRefObject cast.
- ChatBox renderItem now forwards the rendered `index`/`items` to
  DefaultMessageItem so the message group computes prev/next grouping against
  the rendered list — fixes wrong grouping when `slotProps.messageList.items`
  narrows the thread. useMessageIds() is a stable ref, so row memoization holds.
- Remove the conversation-list scroller's width-based `@container { display:none }`:
  the headless ConversationListRoot pins an inline `display: flex` that always
  overrode it, and ChatBox already switches to a drawer in narrow modes — the
  rule was dead and would only have blanked a forced `layoutMode="standard"` sidebar.
- Add tests: filtered-items grouping, and forced-standard sidebar stays visible.
… demos

These two overview demos still configured ChatBox with the nested-by-family
slots/slotProps (conversation.list, composer.root) — leftover from the earlier
nested experiment that the docs flatten pass missed (they live under docs/src,
not docs/data/chat). They failed the docs typescript check against the flat
ChatBoxSlots. Rewrite to the flat keys (conversationList, conversationHeader,
composerRoot); CopilotDemo/WidgetDemo already matched master.
…n, meta classes

- DefaultMessageItem always renders ChatMessageGroup, which consumes
  slots.messageGroup as the group's wrapper element. Previously a documented
  wrapper override (e.g. slots.messageGroup='section') replaced the entire row
  and rendered empty, leaking internal messageId/index/items onto the DOM.
- Compact author label is now delivered to ChatMessage via a dedicated
  groupAuthorName prop instead of being merged into children, so a consumer's
  custom ChatMessage children render children-only in every variant (compact
  no longer appends the built-in avatar/content/meta tree).
- ChatMessageMeta no longer advertises the shared MuiChatMessage-* root classes
  (noAvatar, role/state, …) it never applies; its classes prop is narrowed to
  the meta class it owns. Regenerated chat-message-meta API docs.
- Adds tests for all three; toggle-verified as regression guards.
The ChatMessage family shares one CSS namespace (`MuiChatMessage-*`): every
sub-part is styled with name 'MuiChatMessage'. But each sub-component exposed
its own `classes` prop typed as the full `Partial<ChatMessageClasses>`, so the
API docs advertised all 18 shared classes per component — and under each
component's own (wrong) prefix (e.g. `MuiChatMessageContent-content` vs the
runtime `MuiChatMessage-content`).

Remove the per-instance `classes` prop from the slot sub-parts (ChatMessageContent,
ChatMessageAvatar, ChatMessageMeta, ChatMessageActions, ChatDateDivider,
ChatMessageGroup); they still emit the shared `MuiChatMessage-*` classes and stay
styleable via theme `styleOverrides` and `slotProps`. `ChatMessage` keeps the full
`classes` (it owns the namespace) and `ChatMessageError` keeps its own correct
`MuiChatMessageError-*` namespace. Regenerated API docs (those pages now list no
classes instead of wrong ones).
…g control

The tool Input/Output <details> in ChatMessageContent is internally
controlled (open={open} + setOpen). A consumer-supplied
partProps.tool.slotProps.section.onToggle flowed through useSlotProps into
...rest, which was spread after the internal handler and replaced setOpen.
Because the disclosure is controlled, the section then could no longer be
expanded/collapsed in that customization scenario.

Spread ...rest before the controlled open/onToggle so the control can't be
overridden, ignore a consumer-supplied open, and chain the consumer onToggle
after the internal updater so the disclosure stays observable. Adds a
regression test (consumer handler fires AND the section still toggles).
The headless MessageGroup clones a `groupAuthorName` prop onto compact group
children so the Material ChatMessage can place the author label in its CSS grid.
It is a private MessageGroup->ChatMessage channel (ChatMessage marks it
@ignore). A headless MessageRoot composition (the documented
<MessageGroup><Message.Root/></MessageGroup> pattern) owns its own layout and
does not consume the prop, so it previously forwarded `groupAuthorName` through
...other onto the root element, triggering a React 'unrecognized prop' warning
in the compact variant.

Drop `groupAuthorName` in MessageRoot (declare it as an @ignore internal prop and
pull it out of ...other) so it can never reach the DOM. Headless composers that
want a compact author label render it themselves. Adds a regression test that
fails on the leak.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d3c37af83c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

… root slotProps

Two fixes from a codex review pass on the chat slots stack:

- ComposerAttachmentList gated on the ComposerContext attachment count, whose
  default is empty outside a ChatComposer. Since the default list content reads
  attachments from the store (to support custom layouts / isolated previews),
  the wrapper now also reads the store (the source of truth), so the list renders
  standalone instead of returning null.

- A function-valued slotProps.suggestions.slotProps.root (the supported
  SlotComponentProps callback form) was silently dropped in two places: the
  above-composer (active-thread) path in ChatBoxContent spread it into { sx }, and
  ChatSuggestions spread it via '...(slotProps.root as object)'. Both now preserve
  the callback form (composing the default class/sx onto its resolved result), so
  owner-state-driven root props survive. The object form is unchanged.

Adds regression tests for both (each fails on the prior behavior).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dbb93bdb29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

hasdfa added 8 commits June 6, 2026 00:35
…omposerRoot demo

Three fixes from a codex review pass:

- ChatBoxContent resolved slots.emptyState's slotProps as a plain object, dropping
  the supported (ownerState) => props callback form (the slot is typed
  SlotComponentProps). Resolve the callback before spreading.

- The back/menu navigation lived only inside DefaultConversationHeader, which
  returns null when features.conversationHeader is false. In split layout that left
  narrow users with no way back to the conversation list. Render the nav
  affordances in a minimal bar even when the header chrome is disabled.

- The CustomComposer demo passed a plain (non-forwardRef) component to the now
  wrapper-only slots.composerRoot, producing a React ref warning and dropping the
  injected form/data props. Make it forwardRef and spread the injected props (it
  still renders its own composer UI via the headless hook).

Adds regression tests for the two source fixes.
…ders

Consolidated follow-up to the per-component codex findings:

- Add a shared `mergeSlotProps(base, consumer)` helper that preserves the
  `(ownerState) => props` callback form of `SlotComponentProps`. Material chat
  components pre-merged their default className/sx as a plain object and spread the
  consumer slot prop with `...(slotProps?.x as object)`, which silently flattened a
  callback to {} and dropped owner-state-driven props. Apply the helper across all
  ~18 affected slots (ChatMessage*, ChatComposer*, ChatConversation*, ChatIndicators*,
  ChatMessageError, ChatSuggestions). The object form is unchanged.

- Render the row-level `dateDivider` and `unreadMarker` slots in the default message
  row (DefaultMessageItem). Both headless components are self-suppressing: they read
  messageId/index/items and render only at their boundary (a new calendar day, or the
  first unread message derived from the conversation's unreadCount/readState),
  returning null otherwise. `slots.X = null` hides them. Previously these row slots were
  declared and partitioned but never rendered in the default-list path.

Adds a unit test for the helper and regression tests for ChatMessageError's callback
root slotProp and the date-divider / unread-marker rendering.
DefaultMessageItem already treats `slots.dateDivider`/`slots.unreadMarker = null`
as 'hide this row affordance' (matching the other presentational slots), but the
slot types were `React.ElementType` (non-nullable), so `slots={{ dateDivider: null }}`
failed to type-check. Widen both to `React.ElementType | null` and document the
null-to-hide behavior. Regenerated the ChatBox API docs.
The overlay's drawer-close was wired only into the conversation item's onClick
(createConversationListSlotProps). ConversationListRoot also selects on Enter,
calling setActiveConversation directly without firing the item onClick, so a
keyboard user who opened the overlay, focused an item, and pressed Enter changed
the active conversation but left the overlay open with focus trapped.

Close the drawer whenever activeConversationId changes while it is open (covers
both the pointer and keyboard paths), guarded on a previous-id ref so opening the
overlay on an already-active conversation does not self-close. Adds a regression
test that drives the keyboard Enter path.
…asses on sub-parts

- slotProps.messageGroup is typed Partial<ChatMessageGroupProps>, so it can carry
  MessageGroup-primitive props (notably groupKey for time-window grouping). The
  flat plumbing spread the whole object into the group wrapper's DOM slot, so
  groupKey never reached the headless <MessageGroup> (default author grouping was
  used) and leaked onto the wrapper. Split it: route groupKey/index/items to
  <MessageGroup> (row-structural props still win) and keep only wrapper props on
  the group slot. Adds a regression test (groupKey changes grouping → avatars).

- The ChatMessage sub-parts that share the MuiChatMessage-* namespace (Content,
  Avatar, Meta, Actions, DateDivider, Group) intentionally dropped their classes
  prop (Option B). Defensively destructure a JS/theme-injected classes out so it
  can't flow downstream through ...other. (No behavior change — it was absorbed
  harmlessly by a downstream styled component — but this keeps it from leaking.)
The type doc documented slots.messageList as wrapper-only, but ChatBoxContent
resolved it as a whole-component replacement (slots.messageList ?? ChatMessageList)
invoked with items/renderItem. Following the documented API — e.g.
slots={{ messageList: 'section' }} — produced a bare element with the list props
leaked onto it and no messages rendered.

Always render ChatMessageList and route slots.messageList into its own messageList
root slot (merged with any slotProps.messageList.slots), so a plain element wraps
the scrollable list while the default rows still render inside. This also fixes the
existing Tailwind demo (slots={{ messageList: 'div' }}). Clarified the type doc and
regenerated the ChatBox API docs; added a regression test.
The ChatLayout pane markers live on the headless ConversationListRoot/ConversationRoot,
but ChatBoxContent renders the Material ChatConversationList/ChatConversation wrappers,
which were unmarked. In split layout with the list visible and no active conversation
(e.g. after the back button, or init without an active id) the list is ChatLayout's only
child, and an unmarked single child falls back to the thread pane — so conversationsPane
slot/styles were skipped exactly in that view.

Export markChatLayoutPane from @mui/x-chat-headless and mark the Material wrappers
(ChatConversationList → conversations, ChatConversation → thread) plus the narrow
ChatBoxConversationOverlay (conversations). Marking every direct ChatLayout child keeps
pane resolution unambiguous (a mixed marked/unmarked set warns). Updated the headless
exports snapshot; added a regression test.
AboveComposerSuggestions injects the above-composer layout via slotProps.root.sx,
and ChatSuggestions applies slotProps.root after its own top-level sx — so a
consumer's top-level slotProps={{ suggestions: { sx } }} was overwritten in the
active-thread path (the empty-state path still honored it).

Fold the consumer's top-level sx into the composed root sx (defaults → top-level →
nested root, later wins) and stop spreading it separately. Adds a browser
regression test (computed color survives in the active-thread path).
@hasdfa

hasdfa commented Jun 15, 2026

Copy link
Copy Markdown
Member Author

Solved by #22488

@hasdfa hasdfa closed this Jun 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package: codemod Specific to codemod. scope: chat Changes related to the AI chat. type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants