feat: add disabled parameter to mo.ui.chat#8214
Conversation
Add a `disabled` parameter that prevents user interaction with the chat input. When `disabled=True`, the form area uses the HTML `inert` attribute to block all input, with reduced opacity to visually indicate the disabled state. This enables patterns like conditionally disabling the chatbot until an API key is provided via another input element. Fixes marimo-team#3823
There was a problem hiding this comment.
Pull request overview
Adds a disabled parameter to mo.ui.chat so the chat input area can be made non-interactive (intended for gating interaction until prerequisites like API keys are provided), propagating the flag through Python serialization into the frontend chat plugin.
Changes:
- Add
disabled: bool = Falseto the Pythonui.chatAPI and serialize it into component args. - Extend the chat plugin schema/props to accept
disabledon the frontend. - Disable chat form interaction in the UI (via
inert) and add a Python test for the new arg.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| tests/_plugins/ui/_impl/chat/test_chat.py | Adds coverage for disabled arg serialization into _component_args. |
| marimo/_plugins/ui/_impl/chat/chat.py | Introduces disabled parameter in the ui.chat constructor and passes it to frontend args. |
| frontend/src/plugins/impl/chat/ChatPlugin.tsx | Adds disabled to plugin data schema and forwards it to the Chatbot component. |
| frontend/src/plugins/impl/chat/chat-ui.tsx | Uses disabled to short-circuit submit and applies inert + disabled styling on the form. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -462,7 +466,12 @@ export const Chatbot: React.FC<Props> = (props) => { | |||
| resetInput(); | |||
| }} | |||
| ref={formRef} | |||
| className="flex w-full border-t border-(--slate-6) px-2 py-1 items-center" | |||
| // biome-ignore lint/a11y/useSemanticElements: inert is used to disable the entire form | |||
| inert={props.disabled || undefined} | |||
| className={cn( | |||
| "flex w-full border-t border-(--slate-6) px-2 py-1 items-center", | |||
| props.disabled && "opacity-50 cursor-not-allowed", | |||
| )} | |||
There was a problem hiding this comment.
Relying on the HTML inert attribute alone means the “disabled” behavior may be incomplete in environments where inert isn’t supported, and it also removes the form controls from the accessibility tree (screen readers won’t discover a disabled input). Consider also wiring props.disabled into the actual control disabling (e.g., disabled/isDisabled props on the send button, attachment button, PromptInput/editor) and/or using a <fieldset disabled> approach with appropriate aria-disabled so the UI remains discoverable but non-interactive.
| }} | ||
| ref={formRef} | ||
| className="flex w-full border-t border-(--slate-6) px-2 py-1 items-center" | ||
| // biome-ignore lint/a11y/useSemanticElements: inert is used to disable the entire form |
There was a problem hiding this comment.
The biome-ignore lint/a11y/useSemanticElements suppression doesn’t appear to match what’s happening here (a <form> is already a semantic element, and inert isn’t related to that rule). Please remove the suppression or replace it with the specific rule that actually triggers, so real a11y issues aren’t accidentally masked.
| // biome-ignore lint/a11y/useSemanticElements: inert is used to disable the entire form |

Summary
Adds a
disabledparameter tomo.ui.chatthat prevents user interaction when set toTrue. Uses the HTMLinertattribute on the form container so all child inputs, buttons, and links are automatically non-interactive.Closes #3823
Test Plan
opacity-50 cursor-not-allowedstyling when disabled