Skip to content

[feature] Add height parameter to st.chat_input#14165

Merged
lukasmasuch merged 19 commits intodevelopfrom
lukasmasuch/chat-input-height
Mar 10, 2026
Merged

[feature] Add height parameter to st.chat_input#14165
lukasmasuch merged 19 commits intodevelopfrom
lukasmasuch/chat-input-height

Conversation

@lukasmasuch
Copy link
Copy Markdown
Collaborator

@lukasmasuch lukasmasuch commented Mar 2, 2026

Describe your changes

Adds a height parameter to st.chat_input() that allows controlling the minimum height of the chat input widget.

  • None or "content" (default): Uses default single-line height with auto-expand
  • "stretch": Fills available height of parent container
  • Integer (pixels): Fixed minimum height with auto-expand behavior

Github Issues

Testing Plan

  • Unit Tests (Python) - height config validation and protobuf field tests
  • Unit Tests (Frontend) - heightConfig rendering tests for stretch/content modes
Agent metrics
Type Name Count
skill addressing-pr-review-comments 2
skill checking-changes 2
skill debugging-streamlit 2
skill finalizing-pr 1
skill updating-internal-docs 1
subagent fixing-pr 1
subagent general-purpose 5
subagent reviewing-local-changes 2
subagent simplifying-local-changes 2

Copilot AI review requested due to automatic review settings March 2, 2026 10:52
@lukasmasuch lukasmasuch added change:feature PR contains new feature or enhancement implementation impact:users PR changes affect end users labels Mar 2, 2026
@snyk-io
Copy link
Copy Markdown
Contributor

snyk-io bot commented Mar 2, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 2, 2026

✅ PR preview is ready!

Name Link
📦 Wheel file https://core-previews.s3-us-west-2.amazonaws.com/pr-14165/streamlit-1.55.0-py3-none-any.whl
📦 @streamlit/component-v2-lib Download from artifacts
🕹️ Preview app pr-14165.streamlit.app (☁️ Deploy here if not accessible)

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new height parameter to st.chat_input() to control the widget’s minimum height via layout height config, with backend validation and frontend rendering support.

Changes:

  • Backend: Add height param to st.chat_input, validate it, and propagate it via LayoutConfig.
  • Backend tests: Add unit tests for height_config protobuf behavior and invalid height values.
  • Frontend: Apply heightConfig to ChatInput layout/styling and add corresponding widget tests; adjust element container behavior for stretch height.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
lib/tests/streamlit/elements/chat_test.py Adds unit tests for default/explicit height_config and invalid height values.
lib/streamlit/elements/widgets/chat.py Introduces height parameter, docstring docs, validation, and layout propagation.
frontend/lib/src/components/widgets/ChatInput/ChatInput.tsx Implements height behavior (stretch/pixel/content) in ChatInput rendering.
frontend/lib/src/components/widgets/ChatInput/ChatInput.test.tsx Adds frontend tests for stretch/content/undefined heightConfig.
frontend/lib/src/components/core/Block/ElementNodeRenderer.tsx Adjusts container config for chat input when stretch height is enabled.

@lukasmasuch lukasmasuch added security-assessment-completed ai-review If applied to PR or issue will run AI review workflow labels Mar 2, 2026
@github-actions github-actions bot removed the ai-review If applied to PR or issue will run AI review workflow label Mar 2, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 2, 2026

Consolidated Code Review

Summary

This PR adds a height parameter to st.chat_input() supporting three modes: None/"content" (default auto-expand), "stretch" (fill parent), and an integer (pixel minimum height). The implementation spans the Python backend (parameter validation, LayoutConfig plumbing), the React frontend (ElementContainerConfig, textarea min-height calculation, styled-component props), and test coverage (Python unit + typing tests, frontend unit tests).

Both reviewers agreed the overall direction and architecture are sound — reusing validate_height/LayoutConfig, using static ElementContainerConfig for referential stability, and deriving textarea min-height during render. However, both identified issues warranting changes before merge.

Code Quality

Pixel height behaves as fixed height, not minimum height (High — both reviewers agree)

The API documentation explicitly states pixel height is a minimum that auto-expands with content:

An integer specifying the minimum height in pixels. The widget has a fixed minimum height but still auto-expands based on text content.

However, the implementation creates a fixed-height outer container:

  • In ElementNodeRenderer.tsx (line 811-813), pixel mode uses ElementContainerConfig.DEFAULT (no style overrides).
  • useLayoutStyles.ts (line 325-328) applies pixel height as height: Xpx; overflow: auto on the outer container.
  • This constrains the chat input to a fixed height with scroll, preventing auto-expansion.

For comparison, st.text_area handles the same scenario correctly: its ElementContainerConfig always includes { height: "auto" } to override the layout-computed pixel height, letting the inner component handle it as a min-height. chatInput should follow the same pattern for pixel mode.

isStacked + isStretchHeight flex conflict (Medium — raised by opus-4.6-thinking)

In StyledTextareaWrapper (styled-components.ts, line 82-88):

flex: isStacked ? "none" : 1,
// ...
...(isStretchHeight && { flex: 1 }),

When both isStacked and isStretchHeight are true, flex: 1 overrides flex: "none". In stacked mode (narrow viewport), flex: "none" is required for the textarea to properly wrap above buttons via flex-wrap. Overriding it to flex: 1 could break the stacked layout when stretch height is active. This should either be guarded (isStretchHeight && !isStacked) or verified visually.

Hardcoded border constant (Low — raised by opus-4.6-thinking)

CONTAINER_BORDER = 2 in ChatInput.tsx (line 805) assumes 1px top + 1px bottom border. This is fragile if theme.sizes.borderWidth changes. Consider reading the actual border width from the theme.

Test Coverage

What's covered:

  • Python unit tests for all three height modes (pixel, stretch, content), default case, and invalid inputs (string, negative, zero, float). Uses @parameterized.expand.
  • Python typing tests covering height across all overloads.
  • Frontend unit tests for stretch, undefined, and content height modes.

Gaps (both reviewers agree):

  • No frontend test for pixel height mode: There is no test verifying that heightConfig: { pixelHeight: 200 } applies the correct calculated min-height to the textarea.
  • No test for isStacked + isStretchHeight interaction: Given the flex conflict noted above, this combination needs test coverage.
  • No E2E tests: Per project guidelines ("Most new user-facing features should be covered by both unit tests and E2E tests"), this user-visible layout feature needs E2E/snapshot tests for at least the three height modes in representative container contexts.

Backwards Compatibility

The change is fully backwards compatible (both reviewers agree). The height parameter defaults to None, is keyword-only, and the default code path is a no-op. No protobuf changes were required.

Security & Risk

No security concerns (both reviewers agree). Main risk is UI regression: the fixed-height container in pixel mode under realistic content-growth scenarios would clip/scroll instead of expanding.

Accessibility

No accessibility concerns (both reviewers agree). The height parameter only affects visual sizing. Semantic controls, aria-label, aria-describedby, and keyboard interactions remain intact.

Recommendations

  1. [Blocking] Fix pixel-height container behavior: For pixel mode, override the outer container height to "auto" (similar to textArea's ElementContainerConfig) so the pixel value is only applied as an inner min-height, enabling true auto-expansion as documented.

  2. [Blocking] Investigate and fix the isStacked + isStretchHeight flex conflict: Guard the override with ...(isStretchHeight && !isStacked && { flex: 1 }) or verify the combined behavior is correct.

  3. [Should have] Add frontend unit test for pixel height mode: Test that heightConfig: { pixelHeight: 200 } applies the correct calculated min-height.

  4. [Should have] Add E2E tests: At minimum, snapshot tests for the three height modes in representative containers (e.g., inside a container with fixed height for stretch mode).

  5. [Nice to have] Use theme border width instead of hardcoded CONTAINER_BORDER = 2.

Verdict

CHANGES REQUESTED: Both reviewers independently requested changes. The pixel-height behavior contradicts the documented API contract (fixed height instead of minimum height), and the isStacked/isStretchHeight flex conflict is a potential layout bug. Both issues should be resolved, and test gaps (especially frontend pixel-height tests and E2E coverage) should be addressed before merge.


Consolidated review by opus-4.6-thinking. Based on reviews from gpt-5.3-codex-high and opus-4.6-thinking.


📋 Review by `gpt-5.3-codex-high`

Summary

This PR adds a new height parameter to st.chat_input (Python API + typing), forwards it through layout config, and updates frontend chat input rendering for stretch/content behavior. The overall direction is good, but there is one blocking behavior mismatch for pixel height.

Code Quality

The implementation is clean and mostly consistent with existing layout patterns, but there is a high-severity semantic mismatch:

  • High: Pixel height is implemented as a fixed container height, not a minimum height, which conflicts with the public API contract.
    • API docs explicitly describe pixel height as a minimum that still auto-expands (lib/streamlit/elements/widgets/chat.py:728-741).
    • The backend always forwards pixel height via LayoutConfig(height=height) (lib/streamlit/elements/widgets/chat.py:1013-1015).
    • Frontend layout currently interprets pixel height as fixed height and adds overflow scrolling (frontend/lib/src/components/core/Layout/useLayoutStyles.ts:325-328).
    • chatInput only has a special container config for useStretch, so pixel mode still uses the fixed-height default path (frontend/lib/src/components/core/Block/ElementNodeRenderer.tsx:810-813).
    • ChatInput sets textarea minHeight for pixel mode (frontend/lib/src/components/widgets/ChatInput/ChatInput.tsx:802-811), but this cannot restore true outer auto-expansion when the parent container is fixed.

Test Coverage

Coverage is decent for Python API validation and typing:

  • Added backend tests for default/valid/invalid height values in lib/tests/streamlit/elements/chat_test.py.
  • Added typing assertions for height in lib/tests/streamlit/typing/chat_input_types.py.

Gaps:

  • Frontend tests only verify stretch/content style toggles (frontend/lib/src/components/widgets/ChatInput/ChatInput.test.tsx:891-914), not pixel-height behavior.
  • No e2e coverage was added for the new user-visible sizing behavior (especially pixel minimum-height + growth behavior).

Backwards Compatibility

The API change is additive (height is optional and defaults to prior behavior), so source compatibility is generally good. However, the current pixel-height behavior may break user expectations because it behaves like a fixed-height container rather than a minimum-height chat input.

Security & Risk

No direct security issue identified. Main risk is UI regression: clipped/scrolling chat input container behavior in pixel mode under realistic content growth scenarios.

Accessibility

No new a11y violations found in the changed code paths. Existing semantic controls/labels remain intact.

Recommendations

  1. Align pixel-height behavior with the documented contract by avoiding fixed outer container height for chatInput pixel mode (similar to existing textArea handling), and apply the pixel value as an inner minimum height target.
  2. Add frontend unit tests that assert pixel mode preserves growth behavior (not just static style assertions).
  3. Add at least one e2e scenario covering st.chat_input(height=<int>) with multiline growth and container behavior.

Verdict

CHANGES REQUESTED: Pixel height currently behaves as fixed height instead of minimum height, which conflicts with the documented API behavior and should be corrected before merge.


This is an automated AI review by gpt-5.3-codex-high. Please verify the feedback and use your judgment.

📋 Review by `opus-4.6-thinking`

Summary

This PR adds a height parameter to st.chat_input() that supports three modes:

  • None or "content" (default): Standard single-line height with auto-expand.
  • "stretch": Fills available height of the parent container.
  • Integer (pixels): Fixed minimum height with auto-expand behavior.

Changes span the Python backend (parameter validation, protobuf integration via LayoutConfig), the React frontend (styled-component prop plumbing, textarea min-height calculation, ElementContainerConfig.STRETCH_HEIGHT), and test coverage (Python unit tests, typing tests, frontend unit tests).

Code Quality

Good patterns observed:

  • The STRETCH_HEIGHT static config in ElementContainerConfig ensures referential stability, following the repo's guidance on avoiding inline object creation per render.
  • Height validation reuses the existing validate_height / LayoutConfig infrastructure from layout_utils.py.
  • The heightConfig is correctly propagated through widgetProps (via elementProps spread) in ElementNodeRenderer.tsx.
  • The getTextareaMinHeight function correctly derives values during render rather than using a useEffect, following the "You Might Not Need an Effect" guidelines.

Issues / observations:

  1. Potential layout conflict between isStacked and isStretchHeight (styled-components.ts, line 88): In StyledTextareaWrapper, when both isStacked and isStretchHeight are true, the spread ...(isStretchHeight && { flex: 1 }) overrides flex: "none" from isStacked. In stacked mode, flex: "none" is needed so the textarea wrapper can wrap to its own line (via flex-wrap). Overriding it with flex: 1 when stretch height is active could cause unexpected layout behavior where the textarea doesn't properly wrap above the buttons.

  2. Hardcoded border constant (ChatInput.tsx, line 805): CONTAINER_BORDER = 2 assumes the border is always 1px top + 1px bottom. This is fragile if theme.sizes.borderWidth changes. Consider reading the actual border width from the theme instead.

  3. getTextareaMinHeight defined as a nested function (ChatInput.tsx, lines 791-814): While it correctly depends on reactive values (heightConfig, theme), it's only called once immediately after definition. Inlining the logic (or using a useMemo) would be cleaner and avoid the function allocation on every render. This is a minor style concern.

  4. Pixel values for min-height (ChatInput.tsx, line 810): The frontend AGENTS.md says "Avoid using pixel sizes for styling, always use rem, em, percentage, or other relative units." However, since the user specifies height in pixels, returning a pixel value is acceptable here. No action needed, just noting the tradeoff.

Test Coverage

Python unit tests (chat_test.py): Good coverage of the height config protobuf fields for all three modes (pixel, stretch, content), the default case (no height_config field), and invalid inputs (string, negative, zero, float). Uses @parameterized.expand per best practices.

Python typing tests (chat_input_types.py): Comprehensive coverage of the height parameter across all overloads, including None, "content", "stretch", and integer values. Combined parameter tests also updated.

Frontend unit tests (ChatInput.test.tsx): Tests cover stretch, undefined, and content modes. However:

  • Missing test for pixel height mode: There's no test verifying that heightConfig: { pixelHeight: 200 } applies the correct calculated min-height to the textarea.
  • Missing test for interaction between stretch height and stacked layout: Given the potential conflict noted above, this would be valuable.

Missing E2E tests: Per the project's testing strategy ("Most new user-facing features should be covered by both unit tests and E2E tests"), this feature is missing E2E tests entirely. For a user-visible layout feature like this, E2E/snapshot tests would help verify the visual behavior across different configurations.

Backwards Compatibility

This change is fully backwards compatible:

  • The height parameter defaults to None, preserving existing behavior.
  • The protobuf HeightConfig message is already defined and used by other elements. No protobuf changes were needed.
  • The ElementContainerConfig.DEFAULT is used when height is not stretch, maintaining existing container behavior.
  • The height parameter is keyword-only across all overloads, so it won't interfere with positional arguments.

Security & Risk

No security concerns identified. The feature only affects layout/rendering. Input validation properly rejects invalid height values (negative, zero, float, invalid strings).

Low regression risk for existing users since the default behavior (height=None) is a no-op path through all the new code.

Accessibility

No accessibility concerns. The height parameter only affects visual sizing. The textarea remains fully accessible with proper aria-label, aria-describedby, and keyboard interaction regardless of height configuration. Focus management is unaffected.

Recommendations

  1. Add a frontend unit test for pixel height mode: Test that heightConfig: { pixelHeight: 200 } applies the correct min-height calculation to the textarea.

  2. Investigate the isStacked + isStretchHeight flex conflict: In StyledTextareaWrapper (line 88 of styled-components.ts), when both are true, flex: 1 overrides flex: "none". This may break the stacked wrapping behavior. Consider guarding the override: ...(isStretchHeight && !isStacked && { flex: 1 }) or verifying the combined behavior visually.

  3. Add E2E tests: Per project guidelines, a new user-facing feature should have E2E coverage. At minimum, snapshot tests for the three height modes (content, stretch, pixel) in different container contexts (e.g., inside a container with a fixed height for stretch mode) would be valuable.

  4. Minor: Consider using theme border width instead of hardcoded CONTAINER_BORDER = 2 in the pixel height calculation.

Verdict

CHANGES REQUESTED: The implementation is solid overall and backwards compatible. However, the potential layout bug when isStacked and isStretchHeight are both true (recommendation #2) should be investigated and tested, and E2E test coverage should be added per project guidelines. The missing pixel-height frontend unit test is a smaller gap but worth addressing.


This is an automated AI review by opus-4.6-thinking.

@github-actions github-actions bot added the do-not-merge PR is blocked from merging label Mar 2, 2026
@lukasmasuch lukasmasuch added the ai-review If applied to PR or issue will run AI review workflow label Mar 2, 2026
@github-actions github-actions bot removed the ai-review If applied to PR or issue will run AI review workflow label Mar 2, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 2, 2026

Consolidated Code Review: PR #14165 — Add height parameter to st.chat_input

Summary

This PR adds a height parameter to st.chat_input() supporting three modes: None/"content" (default auto-expand), "stretch" (fill parent), and integer pixel minimum height. Changes span Python backend validation, protobuf layout config, frontend React components (ChatInput.tsx, styled-components.ts), container-level integration (ElementNodeRenderer.tsx, ElementContainerConfig.ts), and comprehensive Python/typing/frontend tests.

Both reviewers agreed the overall implementation is clean and follows existing patterns. However, one key disagreement emerged around the correctness of the pixel-height mode at the container layout level, which verification shows to be a real issue.

Code Quality

Overall: Clean implementation with good separation of concerns. Backend validation, protobuf wiring, and frontend integration all follow established conventions.

Good practices observed (reviewers agreed):

  • Static ElementContainerConfig instances (STRETCH_HEIGHT, AUTO_HEIGHT) for referential stability.
  • textareaMinHeight correctly computed via useMemo with proper dependencies.
  • Layout/pixel calculations performed on the frontend side, consistent with project guidelines.
  • Defensive Math.max(0, ...) for pixel calculations.
  • isStretchHeight && !isStacked guard properly avoids disrupting stacked layout.

Issue 1 — Incomplete AUTO_HEIGHT style override (container layout bug):

The AUTO_HEIGHT config used for pixel-height mode sets only { height: "auto" }:

  static readonly STRETCH_HEIGHT = new ElementContainerConfig({
    styleOverrides: { height: "100%", flex: "1 1 8rem" },
  })

  // Auto height for elements that handle height internally (e.g., pixel height mode).
  // This prevents the layout from applying a fixed height to the outer container.
  static readonly AUTO_HEIGHT = new ElementContainerConfig({
    styleOverrides: { height: "auto" },
  })

However, useLayoutStyles computes additional styles from heightConfig.pixelHeight that are not overridden: specifically overflow: "auto" and flex: "0 0 <px>" (in vertical flex contexts). The styleOverrides spread only replaces height, leaving the container with a fixed flex-basis that prevents auto-expansion — directly contradicting the documented API: "a fixed minimum height but still auto-expands based on text content."

The existing textArea handler already solves this same problem correctly by also overriding flex:

      const config = new ElementContainerConfig({
        minStretchWidth: MinStretchWidth.MEDIUM,
        styleOverrides: useStretchHeight
          ? { height: "100%", flex: "1 1 8rem" }
          : // Content height text area in vertical layout cannot have flex.
            { height: "auto", ...(isInHorizontalLayout ? {} : { flex: "" }) },
      })

The AUTO_HEIGHT config should similarly neutralize flex (and potentially overflow) to match the textArea pattern. This is a small fix but is necessary for correctness.

Issue 2 — Variable shadowing (minor):

In ChatInput.tsx, the local innerHeight variable (line ~801 in the useMemo) shadows the destructured innerHeight from useWindowDimensionsContext() (line ~184). While functionally correct, it is confusing and could trigger lint warnings. Renaming to adjustedHeight or innerMinHeight would improve clarity.

Test Coverage

Python unit tests (chat_test.py): Good coverage — default behavior, parameterized tests for all three height modes, and invalid input validation. (Reviewers agreed.)

Typing tests (chat_input_types.py): Thorough coverage across all overload combinations. (Reviewers agreed.)

Frontend unit tests (ChatInput.test.tsx): Adequate for stretch/content modes but weak for pixel mode. (Reviewers agreed.) The pixel height test (line 912–917) only asserts toBeInTheDocument() without verifying the actual min-height style is applied — this test would pass even if the pixel height logic were completely broken.

Missing E2E tests: Both reviewers noted this. Per the project's testing strategy ("Most new user-facing features should be covered by both unit tests and E2E tests"), E2E tests for height="stretch" (inside a container) and height=<int> should be added. This can be addressed in a follow-up PR.

Backwards Compatibility

No breaking changes. (Reviewers agreed.) The height parameter defaults to None, preserving existing behavior. All existing overload signatures maintain their original parameter order. The height parameter is correctly excluded from key_as_main_identity since it is purely visual.

Security & Risk

No security concerns identified. (Reviewers agreed.) Height is validated server-side (rejecting invalid types/non-positive integers) and handled defensively on the frontend.

Low regression risk: changes are gated behind the new height parameter and only affect ChatInput.

Accessibility

No accessibility regressions for the default and stretch modes. (Reviewers agreed.) However, if the pixel-mode container bug produces an unintended scroll region (via overflow: auto + flex: 0 0 <px>), keyboard navigation and screen-reader behavior could degrade versus expected auto-expanding input behavior.

Recommendations

  1. Fix AUTO_HEIGHT container overrides (blocking): Update AUTO_HEIGHT to also neutralize flex and overflow for pixel-height mode, following the established textArea pattern. This ensures the documented "minimum height with auto-expand" contract is met in vertical flex layouts.

  2. Strengthen the pixel height test: The frontend test "renders textarea element in pixel height mode" should verify the actual min-height style, not just element existence.

  3. Rename shadowed variable: In ChatInput.tsx, rename the local innerHeight to adjustedHeight or innerMinHeight to avoid confusion with the outer innerHeight from useWindowDimensionsContext().

  4. Add E2E tests (can be in a follow-up): Cover height="stretch" inside a fixed-height container, height=<int> rendering, and default behavior.

  5. Note on do-not-merge label: The PR currently has a do-not-merge label — ensure it is removed when the PR is ready.

Reviewer Agreement & Disagreement

Topic gpt-5.3-codex-high opus-4.6-thinking Resolution
Code quality Good Good Agreed
Pixel-height layout Blocking bug Minor/acceptable codex is correct — verified that flex: 0 0 <px> and overflow: auto are not overridden, contradicting the textArea pattern
Python tests Good Good Agreed
Frontend pixel test Weak Weak Agreed
Missing E2E tests Noted Noted Agreed
Variable shadowing Not flagged Flagged (minor) Valid minor issue
Backwards compat Good Good Agreed
Security No issues No issues Agreed

Verdict

CHANGES REQUESTED: The pixel-height mode has a container layout bug where flex: 0 0 <px> and overflow: auto are not neutralized by the AUTO_HEIGHT config, preventing auto-expansion in vertical flex layouts. This contradicts the documented API behavior and is the same issue already solved in the textArea handler. The fix is small (extend AUTO_HEIGHT styleOverrides) but necessary before merge.


Consolidated review by opus-4.6-thinking. Individual reviews from gpt-5.3-codex-high and opus-4.6-thinking.


📋 Review by `gpt-5.3-codex-high`

Summary

This PR adds a new height parameter to st.chat_input, wires it through Python layout config, and updates frontend chat input layout/styling paths for content, stretch, and pixel modes. The API shape and typing updates are solid, but there is a blocking frontend layout issue in pixel mode that conflicts with the documented behavior.

Code Quality

The implementation is generally clean and follows existing patterns, but one functional issue stands out:

  • Blocking: In frontend/lib/src/components/core/Block/ElementContainerConfig.ts (STRETCH_HEIGHT/AUTO_HEIGHT) and frontend/lib/src/components/core/Block/ElementNodeRenderer.tsx (chatInput case), pixel mode maps to ElementContainerConfig.AUTO_HEIGHT, which only overrides height: "auto". However, the base layout engine still applies pixel-height semantics (flex: 0 0 <px> + overflow: auto) for vertical flex layouts (frontend/lib/src/components/core/Layout/useLayoutStyles.ts), so the outer container can still behave like a fixed-height scroll region rather than a true minimum-height container.
  • This conflicts with the public contract in lib/streamlit/elements/widgets/chat.py, where pixel height is documented as a minimum height that still auto-expands with text.

Test Coverage

  • Python unit coverage is good for this scope: validation, proto field mapping, and typing updates are present in lib/tests/streamlit/elements/chat_test.py and lib/tests/streamlit/typing/chat_input_types.py.
  • Frontend unit tests in frontend/lib/src/components/widgets/ChatInput/ChatInput.test.tsx do not validate the critical pixel-mode behavior end-to-end (min-height + auto-expand semantics under renderer/container layout). Current assertions mostly check presence/style basics, so the container-layout regression path is not caught.
  • No e2e test coverage was added for this user-visible feature (st.chat_input(height=...)), which leaves integration behavior under real app layout unverified.

Backwards Compatibility

The API change is additive and keyword-only, so existing callers are unlikely to break. However, the new pixel-height mode does not reliably match the documented behavior, so users adopting the new option may experience unexpected fixed-height scrolling behavior.

Security & Risk

No direct security concerns identified. Main risk is UI/behavioral regression for chat UX in pixel-height mode, especially in typical vertical container layouts.

Accessibility

No obvious new a11y violations in semantics/labels. That said, if pixel mode creates an unintended nested scroll container, keyboard navigation and screen-reader interaction can degrade versus expected auto-expanding input behavior.

Recommendations

  1. Update pixel-height container behavior for chatInput to neutralize pixel-mode fixed-layout effects at the outer container level (at least flex in vertical layout, and likely overflow as needed), similar to the existing textArea handling pattern.
  2. Add/adjust frontend tests to assert pixel-mode runtime behavior through renderer/container layout, not only isolated ChatInput component rendering.
  3. Add an e2e test case that exercises st.chat_input(height=<int>) and height="stretch" in a realistic layout to validate integration behavior.

Verdict

CHANGES REQUESTED: The feature is close, but pixel-height mode currently has a blocking layout behavior mismatch with the documented "minimum height with auto-expand" contract.


This is an automated AI review by gpt-5.3-codex-high. Please verify the feedback and use your judgment.

📋 Review by `opus-4.6-thinking`

Summary

This PR adds a height parameter to st.chat_input() that controls the minimum height of the chat input widget. It supports three modes:

  • None or "content" (default): Uses the default single-line height with auto-expand behavior (preserves current behavior).
  • "stretch": Fills the available height of the parent container.
  • Integer (pixels): Sets a fixed minimum height while retaining auto-expand.

Changes span the Python backend (chat.py), frontend React components (ChatInput.tsx, styled-components.ts, ElementNodeRenderer.tsx, ElementContainerConfig.ts), and comprehensive tests (Python unit tests, frontend unit tests, and typing tests).

Code Quality

Overall: Clean implementation that follows existing patterns in the codebase. The code is well-structured and maintainable.

Good practices observed:

  • Static ElementContainerConfig instances (STRETCH_HEIGHT, AUTO_HEIGHT) used in ElementNodeRenderer.tsx for referential stability — consistent with the AGENTS.md guidance.
  • textareaMinHeight correctly computed via useMemo with proper dependencies.
  • Layout/pixel calculations performed on the frontend side, following the lib/streamlit/AGENTS.md guideline ("Theming and layout calculations must be done in the frontend").
  • height validation only runs when height is not None, preserving the default behavior.
  • isStretchHeight && !isStacked guard in StyledTextareaWrapper properly avoids disrupting the stacked layout behavior.

Issue — Variable shadowing (ChatInput.tsx line 801):

The local innerHeight variable on line 801 shadows the destructured innerHeight from useWindowDimensionsContext() on line 184. While functionally correct (the outer value isn't needed here), it is confusing and may trigger linting warnings. Consider renaming to something like adjustedHeight or innerMinHeight.

Test Coverage

Python unit tests (chat_test.py): Good coverage including:

  • Default behavior (no height_config field present).
  • Parameterized tests for all three modes (pixel, stretch, content).
  • Invalid input validation tests (string, negative, zero, float).

Typing tests (chat_input_types.py): Thorough coverage of the height parameter across all overload combinations with accept_file and accept_audio.

Frontend unit tests (ChatInput.test.tsx): Adequate but could be stronger:

  • Tests stretch mode correctly applies height: 100%.
  • Negative cases properly check that non-stretch modes don't get height: 100%.
  • The pixel height mode test (line 912-917) only asserts the textarea element exists (toBeInTheDocument), but does not verify that the correct min-height style is applied. This test would pass even if the pixel height logic was completely broken.

Missing E2E tests: This is a new user-facing feature, and per the project's testing strategy (AGENTS.md): "Most new user-facing features should be covered by both unit tests and E2E tests." No E2E tests were added. Given that the height behavior is visual and involves CSS flex layout interactions (especially stretch mode in containers), E2E/snapshot tests would provide valuable confidence.

Backwards Compatibility

No breaking changes. The height parameter defaults to None, which preserves the existing behavior. The height_config protobuf field is optional on the Element message and was already defined before this PR. All existing overload signatures maintain their original parameter order with height appended as the last keyword argument.

The height parameter is included in compute_and_register_element_id but not in key_as_main_identity, which means changing height won't reset widget state when a user key is provided. This is the correct design choice since height is purely visual.

Security & Risk

No security concerns identified. The height parameter is validated server-side before being sent via protobuf, rejecting invalid types and non-positive integers. The frontend handles the value defensively with Math.max(0, ...) for pixel calculations.

Low regression risk: the changes only affect ChatInput and are gated behind the new height parameter. Default behavior (None) follows the existing code path.

Accessibility

No accessibility regressions introduced. The height changes are purely CSS-based and don't affect the DOM structure, ARIA attributes, keyboard navigation, or focus management. The textarea remains fully accessible regardless of height mode.

Recommendations

  1. Rename shadowed variable: In ChatInput.tsx line 801, rename const innerHeight to const adjustedHeight or const innerMinHeight to avoid confusion with the innerHeight from useWindowDimensionsContext() on line 184.

  2. Strengthen the pixel height test: The frontend test "renders textarea element in pixel height mode" (line 912-917) should verify the actual min-height style on the textarea root, not just that the textarea element exists.

  3. Add E2E tests: Consider adding E2E tests (can be in a follow-up PR) covering:

    • height="stretch" inside a fixed-height st.container.
    • height=<int> renders the widget at the specified minimum height.
    • Default behavior remains unchanged.
  4. Note on do-not-merge label: The PR currently has a do-not-merge label. Ensure this is removed when the PR is ready.

Verdict

APPROVED: Well-implemented feature with good backend validation, clean frontend integration following existing patterns, and adequate test coverage. The variable shadowing and weak pixel-height test are minor issues. Missing E2E tests can be addressed in a follow-up.


This is an automated AI review by opus-4.6-thinking.

@lukasmasuch lukasmasuch added ai-review If applied to PR or issue will run AI review workflow and removed do-not-merge PR is blocked from merging labels Mar 5, 2026
@github-actions github-actions bot removed the ai-review If applied to PR or issue will run AI review workflow label Mar 5, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 5, 2026

Consolidated Code Review: Add height parameter to st.chat_input

Summary

This PR adds a height parameter to st.chat_input() with three modes: None/"content" (default auto-expand behavior), "stretch" (fills parent container), and integer pixels (fixed minimum height with auto-expand). The implementation spans backend Python (validation, protobuf integration), frontend TypeScript (styled components, container config, textarea overrides), and comprehensive test coverage (Python unit tests, frontend unit tests, typing tests).

Both reviewers agree the feature is well-implemented and follows existing codebase patterns. The primary areas of discussion are a potential horizontal layout regression and missing E2E tests.

Code Quality

The code is well-structured and follows established patterns:

  • Backend: Proper use of existing validate_height() utility, LayoutConfig, and HeightConfig protobuf message. The parameter defaults to None for backward compatibility.
  • Frontend: Good use of static ElementContainerConfig constants for referential stability, useMemo for computed values, and clean prop threading through the styled component hierarchy.

Issues Identified

  1. Horizontal layout flex behavior difference (raised by gpt-5.3-codex-high, verified): The AUTO_HEIGHT static config unconditionally sets flex: "", which clears flex participation in all layouts including horizontal. The existing textArea handler conditionally preserves flex in horizontal layouts:

    // textArea (existing pattern - handles horizontal layout correctly):
    { height: "auto", ...(isInHorizontalLayout ? {} : { flex: "" }) }
    
    // chatInput (new code - always clears flex):
    static readonly AUTO_HEIGHT = new ElementContainerConfig({
      styleOverrides: { height: "auto", flex: "", overflow: "visible" },
    })

    Assessment: This is a valid concern. Since AUTO_HEIGHT is a static constant, it cannot access isInHorizontalLayout context. For the chatInput pixel-height case, the code should either use a dynamic config (like textArea does) or document why the static approach is acceptable for chatInput specifically. However, this is a low-severity issue in practice: st.chat_input with a pixel height inside a horizontal layout is an edge case, and the visual impact may be minimal. Both reviewers agree this warrants attention, though they differ on whether it blocks merge.

  2. Redundant flex spread in StyledTextareaWrapper (raised by opus-4.6-thinking, verified): At line 89 of styled-components.ts, the conditional ...(isStretchHeight && !isStacked && { flex: 1 }) is redundant because line 82 already sets flex: isStacked ? "none" : 1, which produces flex: 1 when !isStacked regardless of isStretchHeight. This is a minor nit — the code works correctly but contains dead logic.

  3. Stacked + stretch interaction (raised by opus-4.6-thinking): When both isStacked and isStretchHeight are true, the textarea wrapper gets flex: "none" with width: "100%", and in a wrapped flex row, align-items: stretch only stretches items to the line height. The textarea may not fully fill vertical space in this edge case. Noted as acceptable since stacked mode implies enough text to auto-expand.

Test Coverage

Both reviewers agree the test coverage is solid for unit tests:

  • Python unit tests cover default, all valid modes, and invalid inputs with parameterized tests.
  • Frontend unit tests cover stretch mode, negative tests for non-stretch modes, and pixel height rendering (with acknowledged limitation that baseweb override CSS can't be fully asserted).
  • Typing tests are thorough across accept_file combinations.

Both reviewers agree on the gap: No E2E tests were added. Per the project's testing strategy in AGENTS.md, new user-facing features should be covered by both unit tests and E2E tests. This is notable for a new user-facing parameter.

Additional gaps:

Backwards Compatibility

Both reviewers agree: Fully backward compatible. The height parameter is optional, defaults to None, produces no protobuf field change, and all existing overloads maintain their signatures.

Security & Risk

Both reviewers agree: No security concerns. Input validation is proper (rejects invalid strings, negatives, zero, and floats). Risk is limited to the horizontal layout edge case noted above.

Accessibility

Both reviewers agree: No accessibility regressions. Changes are purely visual/layout with no new interactive elements or changes to ARIA attributes, keyboard interaction, or focus management.

Reviewer Agreement & Disagreement

Topic gpt-5.3-codex-high opus-4.6-thinking Consensus
Code quality Good with one regression risk Good with minor nits Agree: well-implemented
Horizontal layout flex issue Blocking — must fix Not mentioned as blocking See resolution below
Redundant flex spread Not mentioned Minor nit Valid but non-blocking
Missing E2E tests Should be added Should be added (as follow-up) Agree: gap exists
Backward compatibility Compatible Compatible Agree
Overall verdict CHANGES_REQUESTED APPROVED See final verdict

Conflict Resolution: Horizontal Layout Flex Issue

The gpt-5.3-codex-high reviewer flagged this as a blocking regression; opus-4.6-thinking acknowledged low regression risk but approved. After verifying the code:

  • The concern is technically valid — the AUTO_HEIGHT config differs from the textArea pattern.
  • However, st.chat_input(height=<pixels>) inside a horizontal layout is an uncommon edge case.
  • The default behavior (no height parameter) is entirely unaffected.
  • The fix is straightforward (use a dynamic config like textArea does) and could be done as a fast follow-up.

Verdict on this issue: This is a valid but low-severity concern. It should be addressed (either before merge or as an immediate follow-up), but it does not constitute a critical regression that blocks the PR.

Recommendations

  1. Address horizontal layout flex handling (priority: medium): Either switch to a dynamic config for the pixel-height case (mirroring textArea) or add a comment explaining why the static approach is acceptable for chatInput. This can be done as a follow-up.

  2. Add E2E tests (priority: medium): Cover height="stretch" inside a container with defined height and height=<int> for visual rendering. Both reviewers flagged this gap, consistent with the project's testing strategy.

  3. Remove redundant flex spread (priority: low): Clean up line 89 in styled-components.ts or add a clarifying comment if the intent is documentation.

  4. Strengthen pixel-height frontend test (priority: low): Consider testing createTextAreaOverrides directly to verify computed minHeight values.

Verdict

APPROVED — The implementation is clean, well-tested at the unit level, and fully backward compatible. The horizontal layout flex concern is valid but low-severity (edge case with straightforward fix). The missing E2E tests are a notable gap per project standards but don't block merge. Both issues should be addressed as immediate follow-ups.


Consolidated review by opus-4.6-thinking. Individual reviews follow below.


📋 Review by `gpt-5.3-codex-high`

Summary

This PR adds a new height parameter to st.chat_input across backend and frontend layers, wires it into layout config/protobuf handling, and introduces Python + frontend unit tests plus typing coverage. The implementation is generally clean and consistent with existing patterns, but I found one regression risk that should be fixed before merge.

Code Quality

The code is readable and follows existing architecture well (backend API + layout config + frontend rendering).
However, there is a layout behavior regression risk:

  • Potential horizontal-layout regression for pixel height mode
    In frontend/lib/src/components/core/Block/ElementContainerConfig.ts:134, AUTO_HEIGHT forces flex: "".
    In frontend/lib/src/components/core/Block/ElementNodeRenderer.tsx:817, this config is selected for chatInput when heightConfig.pixelHeight is set.
    In horizontal flex layouts, this clears the computed flex distribution (useLayoutStyles), which can break width behavior (e.g., items no longer participating correctly in row sizing).
    This differs from the existing textArea handling pattern, which only neutralizes flex when not in horizontal layout.

Test Coverage

Coverage is improved and generally strong:

  • Python unit tests validate height_config serialization and invalid inputs in lib/tests/streamlit/elements/chat_test.py.
  • Typing tests validate new overload behavior in lib/tests/streamlit/typing/chat_input_types.py.
  • Frontend unit tests validate stretch/content/pixel mode rendering behavior in frontend/lib/src/components/widgets/ChatInput/ChatInput.test.tsx.

Remaining gap:

  • No test currently exercises chat_input(height=<pixel>) in a horizontal layout container, which is where the flex regression risk appears.
  • No e2e test was added for this new user-facing sizing behavior.

Backwards Compatibility

The API change is additive (height is optional and keyword-only), so it is broadly backwards compatible.
That said, the flex override issue above can introduce behavior changes for apps using st.chat_input(height=<int>) inside horizontal layouts.

Security & Risk

No direct security concerns identified.
Main risk is UI/layout regression in specific container configurations.

Accessibility

No new accessibility regressions are obvious from the changed code.
Existing button semantics and labels are preserved, and no new non-semantic interactive patterns were introduced by this PR.

Recommendations

  1. Update pixel-height container behavior so flex is only neutralized when not in horizontal layout (mirror the existing textArea strategy).
  2. Add a frontend unit test that renders ChatInput in a horizontal flex context with heightConfig.pixelHeight and asserts expected sizing/flex behavior.
  3. Add an e2e test covering st.chat_input(height="stretch") and st.chat_input(height=<int>) in realistic container scenarios.

Verdict

CHANGES REQUESTED: Good feature implementation overall, but the AUTO_HEIGHT flex override can regress horizontal-layout behavior and should be fixed before merge.


This is an automated AI review by gpt-5.3-codex-high. Please verify the feedback and use your judgment.

📋 Review by `opus-4.6-thinking`

Summary

This PR adds a height parameter to st.chat_input() that controls the minimum height of the chat input widget, with three modes:

  • None or "content" (default): Standard single-line height with auto-expand behavior (no change from current behavior).
  • "stretch": Fills available height of the parent container.
  • Integer (pixels): Fixed minimum height with auto-expand behavior.

The implementation spans backend (Python validation, protobuf integration via existing HeightConfig), frontend (styled components, container config, textarea overrides), and test code (Python unit tests, frontend unit tests, typing tests).

Code Quality

The code is well-structured and follows existing patterns in the codebase:

  • Backend: The height parameter is properly added to all four overloads of chat_input(), validated via the existing validate_height() utility, and flows through LayoutConfig to the protobuf HeightConfig message — the same pattern used by other elements. The height parameter defaults to None, which is the correct backward-compatible default.

  • Frontend: The ElementContainerConfig uses static constants (STRETCH_HEIGHT, AUTO_HEIGHT) for referential stability, following the class's documented pattern. The textareaMinHeight calculation correctly uses useMemo to avoid recomputation. The createTextAreaOverrides function cleanly integrates the minHeightOverride parameter.

  • Styled components: The isStretchHeight prop is threaded through StyledChatInputContainer, StyledChatInput, StyledInputRow, and StyledTextareaWrapper to correctly propagate stretch behavior down the component tree.

Minor observations:

  1. Redundant flex spread in StyledTextareaWrapper (styled-components.ts line 89): The conditional ...(isStretchHeight && !isStacked && { flex: 1 }) is redundant because the base flex: isStacked ? "none" : 1 already produces flex: 1 when !isStacked, regardless of isStretchHeight. The spread doesn't change the computed value.

  2. Stacked + stretch interaction (styled-components.ts lines 64-73, 78-90): When both isStacked (text fills width, triggers wrapped layout) and isStretchHeight are true, the textarea wrapper gets flex: "none" with width: "100%". In a wrapped flex row, align-items: stretch only stretches items to the line height, not the container height. This means the textarea won't actually fill the vertical space in stacked mode. This is likely acceptable since stacked mode implies enough text to auto-expand, but it's worth noting as a potential visual inconsistency.

Test Coverage

Python unit tests (chat_test.py): Good coverage with:

  • Default height (no height_config field present) — validated via HasField.
  • Parameterized tests for all three valid modes (pixel, stretch, content).
  • Parameterized tests for invalid inputs ("invalid", -100, 0, 100.5).

Frontend unit tests (ChatInput.test.tsx): Reasonable coverage with:

  • Stretch mode: Validates height: 100% is applied to the container.
  • Negative tests: Parameterized check that non-stretch modes don't apply height: 100%.
  • Pixel height mode: The test at line 912 acknowledges it cannot verify the actual min-height CSS value applied through baseweb overrides. It only verifies the component renders and the textarea exists — this is a known limitation but means the pixel-height CSS path is not truly asserted.

Typing tests (chat_input_types.py): Thorough coverage of height parameter with None, "content", "stretch", and integer values across different accept_file combinations.

Missing E2E tests: The PR does not include E2E tests. Per the project's testing strategy (AGENTS.md: "Most new user-facing features should be covered by both unit tests and E2E tests"), this is a notable gap. E2E tests would verify the actual rendering behavior across all three height modes, especially stretch mode within a container with defined height and pixel-height mode visual appearance.

Backwards Compatibility

This change is fully backward compatible:

  • The height parameter defaults to None, which produces no height_config field in the protobuf message, matching pre-PR behavior exactly.
  • The frontend falls through to ElementContainerConfig.DEFAULT when no heightConfig is present.
  • No existing protobuf fields or messages were modified — the HeightConfig message already existed.
  • All existing overloads maintain their signatures; height is added as an optional keyword argument.

Security & Risk

No security concerns identified. The height parameter undergoes proper server-side validation:

  • String values are restricted to "stretch" and "content".
  • Integer values must be positive (rejects 0, negatives, and floats like 100.5).
  • Invalid inputs raise StreamlitInvalidHeightError.

Regression risk: Low. The default behavior is unchanged, and the feature is additive. The most complex path (pixel height with auto-expand) involves CSS min-height calculations, but these are well-isolated in useMemo and don't affect the default code path.

Accessibility

No accessibility concerns. The changes are purely visual/layout:

  • No new interactive elements are added.
  • All existing aria-label, aria-describedby, and keyboard interaction patterns are preserved.
  • The textarea remains the same semantically; only its minimum height changes.
  • Focus management is unaffected.

Recommendations

  1. Add E2E tests: Create E2E tests covering the three height modes. At minimum, test height="stretch" inside a container with defined height, and height=<int> to verify visual rendering. This follows the project's stated testing strategy for new user-facing features.

  2. Remove redundant flex spread in StyledTextareaWrapper (styled-components.ts line 89): The conditional ...(isStretchHeight && !isStacked && { flex: 1 }) produces the same value already set by flex: isStacked ? "none" : 1 in the non-stacked case. Consider removing it or adding a comment explaining the intent if kept for documentation purposes.

  3. Strengthen pixel-height frontend test: While baseweb override style assertions are difficult, consider testing the createTextAreaOverrides function directly to verify the minHeight value matches expectations (e.g., "174px" for pixelHeight: 200). This would provide stronger coverage than only checking the component renders.

Verdict

APPROVED: Well-implemented feature with clean backend/frontend integration, proper validation, and good backward compatibility. The missing E2E tests are the main gap but don't block the merge — they should be added as a follow-up.


This is an automated AI review by opus-4.6-thinking.

@sfc-gh-lwilby
Copy link
Copy Markdown
Collaborator

Assessment: This is a valid concern. Since AUTO_HEIGHT is a static constant, it cannot access isInHorizontalLayout context. For the chatInput pixel-height case, the code should either use a dynamic config (like textArea does) or document why the static approach is acceptable for chatInput specifically. However, this is a low-severity issue in practice: st.chat_input with a pixel height inside a horizontal layout is an edge case, and the visual impact may be minimal. Both reviewers agree this warrants attention, though they differ on whether it blocks merge.

I think st.chat_input can be used in a horizontal layout as well, even if that is not the normal pattern? This seems like it will break horizontal layouts.

@sfc-gh-lwilby
Copy link
Copy Markdown
Collaborator

Add E2E tests (can be in a follow-up): Cover height="stretch" inside a fixed-height container, height= rendering, and default behavior.

It's good to include the stretch height test because I find this gets broken frequently.

styleOverrides: { overflow: "visible" },
})

static readonly STRETCH_HEIGHT = new ElementContainerConfig({
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is too specific to be STRETCH_HEIGHT for all elements, I think the config should live just with the chat input.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Changed 👍

// This prevents the layout from applying a fixed height to the outer container.
// Must also neutralize flex (prevents fixed flex-basis) and overflow (prevents scroll),
// following the same pattern as textArea to enable true auto-expand behavior.
static readonly AUTO_HEIGHT = new ElementContainerConfig({
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm not sure whether this is generally applicable to all elements?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Changed 👍

// Must also neutralize flex (prevents fixed flex-basis) and overflow (prevents scroll),
// following the same pattern as textArea to enable true auto-expand behavior.
static readonly AUTO_HEIGHT = new ElementContainerConfig({
styleOverrides: { height: "auto", flex: "", overflow: "visible" },
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think the flex: "" shouldn't be needed for horizontal layouts since this change is needed for height, but flex-basis applies to width in a horizontal layout.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Changed 👍

Add a new `height` parameter to `st.chat_input` that allows controlling
the minimum height of the chat input widget:

- `None` or `"content"` (default): Uses default single-line height and
  auto-expands based on text content
- `"stretch"`: Height stretches to fill available parent container space
- Integer (pixels): Fixed minimum height that still auto-expands

This is useful for chat interfaces where the input should take up more
vertical space or fill a container.
- Add frontend unit tests for heightConfig (stretch, content, undefined)
- Add clarifying constant for border calculation in ChatInput.tsx
- Enhance docstring to note that stretch requires parent container height
- Add static STRETCH_HEIGHT config to ElementContainerConfig for referential stability
- Move inline styles to styled-components (isStretchHeight prop)
- Add height parameter typing tests to chat_input_types.py
- Fix pixel-height container behavior: Added AUTO_HEIGHT config to
  ElementContainerConfig so pixel height acts as minimum height with
  auto-expand, matching documented API behavior
- Fix isStacked + isStretchHeight flex conflict: Guard flex: 1 override
  with !isStacked to preserve stacked layout wrapping behavior
- Use theme border width: Replace hardcoded CONTAINER_BORDER with
  theme.sizes.borderWidth for maintainability
- Refactor height calculation: Convert getTextareaMinHeight to useMemo
  for better React patterns
- Consolidate tests: Use it.each for non-stretch height mode tests
- Fix AUTO_HEIGHT to also neutralize flex and overflow, following the
  textArea pattern for correct pixel-height auto-expand behavior
- Rename innerHeight to adjustedHeight to avoid variable shadowing with
  innerHeight from useWindowDimensionsContext()
- Strengthen pixel height test with better assertions and documentation
@lukasmasuch lukasmasuch force-pushed the lukasmasuch/chat-input-height branch from e27dc58 to 75495a8 Compare March 10, 2026 14:48
Address PR review feedback from @sfc-gh-lwilby:
- Remove STRETCH_HEIGHT and AUTO_HEIGHT static configs since they're
  too specific to be general element configs
- Create inline configs in chatInput case following the textArea pattern
- Fix flex reset to only apply in vertical layouts (flex-basis affects
  width in horizontal layouts, not height)

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@lukasmasuch lukasmasuch changed the title [feature] Add height parameter to st.chat_input [feature] Add height parameter to st.chat_input Mar 10, 2026
- Remove redundant isStretchHeight logic from StyledTextareaWrapper
  (flex is already 1 when !isStacked)
- Remove unused isStretchHeight prop from ChatInput.tsx
- Remove redundant toBeInTheDocument() assertion in test

Co-Authored-By: Claude Opus 4.6 <[email protected]>
const heightConfig = node.element.heightConfig
const chatInputConfig = new ElementContainerConfig({
styleOverrides: heightConfig?.useStretch
? { height: "100%", flex: "1 1 8rem" }
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is this consistent with text_area? One potential issue with this override is that if/when we add relative stretch widths, this will break it since it overrides the flex-grow. If this is just to introduce the 8 rem flex-basis, there is the min-width option for that.

Copy link
Copy Markdown
Collaborator Author

@lukasmasuch lukasmasuch Mar 10, 2026

Choose a reason for hiding this comment

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

It's consistent with the text area, I also added the minStretchWidth that's used for the text area as well. I will play around a bit if everything works as expected with this

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

OK, maybe both of them can be improved in a follow-up. I can't remember the details of why I added that now. I should have left a comment -- or maybe a comment was removed accidentally in the refactor.

I think chat input is slightly simpler because if I remember correctly, it doesn't have the resizing with dragging by the user.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

it doesn't have the resizing with dragging by the user.

yep, but it has auto-resizing by content getting added instead


// Calculate minimum height for the textarea based on heightConfig.
// Subtracts container padding and border from pixel height to get inner textarea height.
const textareaMinHeight = useMemo((): string | undefined => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is this different than TextArea, I might have added something for this there that could be shared potentially?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The calculation here is similar, but too different for sharing it

Copy link
Copy Markdown
Collaborator

@sfc-gh-lwilby sfc-gh-lwilby left a comment

Choose a reason for hiding this comment

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

This looks good to me, I am just wondering if some of the overrides are still more than necessary and if we might share some of the code with TextArea

lukasmasuch and others added 11 commits March 10, 2026 17:24
Match TextArea's behavior by adding minStretchWidth: MinStretchWidth.MEDIUM
to the chat_input container config. This ensures consistent minimum width
behavior when chat_input is placed in horizontal layouts (e.g., st.columns).

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Add visual snapshot tests for the new height parameter:
- height=200 (pixel height)
- height="stretch" (fills parent container)

The stretch test uses a container with defined height to verify
the chat input properly fills the available space.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
When height is set to stretch or a pixel value, the submit button should
stick to the bottom of the input rather than being vertically centered.

Introduces `hasExpandedHeight` which is true for both stretch and pixel
heights, and uses `alignItems: flex-end` on the input row to keep buttons
at the bottom.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Include autoExpand.isExtended in hasExpandedHeight calculation so the
submit button sticks to the bottom when the textarea expands due to
user-added newlines, not just when height is configured via props.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
When the chat input is expanded (multiline or configured height), use a
column layout that separates the textarea from the toolbar. This creates
a dedicated bottom row for buttons (file upload, mic, submit) that text
doesn't flow into.

- Add StyledToolbarRow component for the dedicated button row
- Change StyledInputRow to column layout when hasExpandedHeight is true
- Restructure JSX to conditionally wrap buttons in toolbar row

Co-Authored-By: Claude Opus 4.6 <[email protected]>
When height is configured via props (stretch or pixel), disable the
autoExpand height constraints and use 100% height with no maxHeight.
This allows the textarea to fill the container and scroll properly
instead of overflowing.

- Add useFixedHeight parameter to createTextAreaOverrides
- Add hasConfiguredHeight to distinguish prop-based from dynamic height
- When hasConfiguredHeight is true, use height: 100% and maxHeight: none

Co-Authored-By: Claude Opus 4.6 <[email protected]>
In non-expanded (single-line) mode, use CSS order: -1 on StyledLeftCluster
to position the file upload button before the textarea, which is now
rendered first in the DOM for the expanded mode layout.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Moves the character count indicator (e.g. "4/200") from absolutely positioned
in the top-right corner to inline within StyledRightCluster. This prevents
the counter from overlapping with the submit button and places it next to
the audio/submit buttons in both normal and expanded height modes.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Remove None as a valid value for the height parameter since it was
equivalent to "content". This makes the API clearer and more explicit.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
The test was expecting no height_config field when using the default,
but with the API change (height="content" as explicit default), it
should now expect use_content: true.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@lukasmasuch lukasmasuch added the ai-review If applied to PR or issue will run AI review workflow label Mar 10, 2026
@github-actions github-actions bot removed the ai-review If applied to PR or issue will run AI review workflow label Mar 10, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Summary

This PR adds a height parameter to st.chat_input() supporting three modes: "content" (default auto-expand), "stretch" (fill parent container), and integer (pixel minimum height with auto-expand). The implementation spans backend Python (parameter validation + protobuf wiring), frontend TypeScript (layout logic in ChatInput.tsx, styled-components, and ElementNodeRenderer.tsx), and includes E2E snapshots, Python unit tests, frontend unit tests, and typing tests.

All three reviewers agreed the overall structure is clean and follows established Streamlit patterns (reusing HeightConfig protobuf, mirroring st.text_area layout config approach). However, one reviewer identified a behavioral correctness issue that warrants attention before merge.

Code Quality

Consensus strengths:

  • Cleanly reuses existing HeightConfig protobuf and LayoutConfig infrastructure — no new proto fields needed.
  • Good separation of concerns: textareaMinHeight calculation is memoized with correct dependencies.
  • Layout correctly falls back to non-expanded (row) layout during audio recording.
  • Backend validation properly rejects invalid values (floats, negatives, unknown strings).

Issues identified:

  1. Behavior mismatch for height=<int> — doc/implementation discrepancy (raised by gpt-5.3-codex-high, verified by consolidation review)

    The Python docstring states integer height "has a fixed minimum height but still auto-expands based on text content." However, the frontend implementation passes hasConfiguredHeight as useFixedHeight to createTextAreaOverrides, which sets height: "100%" and maxHeight: "none" on the textarea Input, bypassing the autoExpand hook's calculated height values. This means the textarea fills its container at the specified minimum height but does not dynamically grow with content — instead, content scrolls internally via overflowY: "auto".

    Upon code inspection, this is confirmed: when useFixedHeight=true (line 137-142 of ChatInput.tsx), the autoExpand height and maxHeight are never applied. The auto-expand hook still runs (and isExtended still drives the layout mode), but the actual CSS height of the textarea is fixed to 100% of its flex parent, not content-driven.

    Resolution: This is a real discrepancy. Either the frontend should be updated to allow auto-expand beyond the pixel minimum, or the docstring should be corrected to state that pixel height provides a fixed container with internal scrolling. Given the explicit API contract in the docstring, the frontend behavior should be aligned. This is not a crash or data-loss issue, but it is an API contract violation that will confuse users.

  2. Significant JSX duplication in ChatInput.tsx (raised by opus-4.6-thinking)

    The expanded (hasExpandedHeight && !isRecording) and non-expanded branches duplicate the entire button cluster — StyledLeftCluster, StyledRightCluster, audio buttons, error tooltips, send button, and StyledInputInstructions — approximately 100 lines of duplicated JSX. Future changes to button behavior must be replicated in both branches. Consider extracting shared button clusters into helper components.

  3. StyledInputInstructions positioning change is a global visual change (raised by opus-4.6-thinking)

    The removal of position: "absolute", top, right, and zIndex from StyledInputInstructions moves the character count indicator from a floating overlay to inline within the button row. This affects all st.chat_input() instances that use max_chars, not only those with the new height parameter. The snapshot updates confirm this. While likely an improvement, this should be explicitly documented as a visual change.

  4. parseInt assumption for border width (raised by opus-4.6-thinking, minor)

    parseInt(theme.sizes.borderWidth, 10) works for pixel values like "1px" but would return NaN for rem-based values. The || 1 fallback mitigates this, but it's theme-dependent.

Test Coverage

All reviewers agreed coverage is broad:

  • Python unit tests: default height config, parameterized tests for all three modes, invalid-input edge cases.
  • Python typing tests: assert_type checks for all height/accept_file combinations.
  • Frontend unit tests: stretch mode style verification, parameterized negative tests.
  • E2E tests: snapshot tests for height=200 and height="stretch" across browser/theme combinations.

Gaps identified (consensus between gpt-5.3-codex-high and opus-4.6-thinking):

  • No behavioral E2E test verifying that typing multiline text into a height-configured chat input actually auto-expands (or doesn't). Current tests are static snapshot checks that don't catch the doc/implementation mismatch.
  • The pixel-height frontend unit test only verifies the textarea root element exists rather than asserting the computed min-height value.

Backwards Compatibility

All reviewers confirmed the height parameter defaults to "content", preserving existing behavior. The height parameter is not included in key_as_main_identity, so changing it won't reset widget state.

The StyledInputInstructions positioning change (absolute → inline) is a visual regression for users with max_chars set, as noted by opus-4.6-thinking. This affects existing apps without user code changes.

Security & Risk

Unanimous agreement: No security concerns. Changes are confined to UI parameter validation, CSS/layout, and protobuf field reuse. No auth, routing, websocket, embedding, or storage changes.

External test recommendation

  • Recommend external_test: No (unanimous)
  • Triggered categories: None
  • Evidence: All changes are in UI element rendering (CSS layout, protobuf field reuse, parameter validation). No infrastructure impact.
  • Confidence: High

Accessibility

Unanimous agreement: No accessibility regressions. aria-label, aria-describedby, and focus management are preserved in both expanded and non-expanded layout branches.

Recommendations

  1. Fix the height=<int> auto-expand behavior to match the documented API contract, or update the docstring to accurately describe the scrolling behavior. The frontend should use auto-expand height values when content exceeds the pixel minimum.
  2. Add a behavioral E2E or unit test that types multiline text into height=<int> mode and verifies expansion behavior (or scrolling, if that's the intended design).
  3. Extract duplicated button cluster JSX into shared components to reduce the ~100 lines of duplication between expanded/non-expanded branches.
  4. Document the StyledInputInstructions positioning change in the PR description or changelog, as it is a global visual change to character count display.

Reviewer Agreement Matrix

Topic gemini-3.1-pro gpt-5.3-codex-high opus-4.6-thinking
Code quality Clean Issue found Concerns noted
height=int behavior mismatch Not flagged Blocking Not flagged
JSX duplication Not flagged Not flagged Flagged
StyledInputInstructions change Not flagged Not flagged Flagged
Test coverage gaps Not flagged Flagged Flagged
Backwards compatibility OK OK (with caveat) OK (with caveat)
Security No concerns No concerns No concerns
Accessibility No concerns No concerns No concerns
Verdict APPROVED CHANGES_REQUESTED APPROVED

Verdict

CHANGES_REQUESTED: While two of three reviewers approved, the behavior mismatch between the height=<int> API documentation ("still auto-expands based on text content") and the frontend implementation (fixed height with internal scrolling) is a substantiated API contract violation confirmed by code inspection. This should be resolved — either by fixing the frontend to truly auto-expand beyond the pixel minimum, or by updating the docstring — before merge. The JSX duplication and undocumented StyledInputInstructions visual change are additional concerns that strengthen the case for a revision pass.


Consolidated review by opus-4.6-thinking.


📋 Review by `gemini-3.1-pro`

Summary

This PR adds a height parameter to st.chat_input, allowing users to control the minimum height of the chat input widget. It supports "content" (default auto-expanding behavior), "stretch" (filling the parent container), and integer values for fixed minimum pixel heights.

Code Quality

The code changes are clean, well-structured, and follow the established patterns in the repository. The frontend changes correctly handle the different layout modes (stacked vs inline) and correctly adjust the flex and height properties based on the heightConfig. The backend changes properly validate and pass the new height parameter.

Test Coverage

The changes are well-tested:

  • E2E Tests: Added scenarios for height=200 and height="stretch" in e2e_playwright/st_chat_input.py and st_chat_input_test.py, with corresponding snapshot updates.
  • Frontend Unit Tests: Added tests in ChatInput.test.tsx to verify the correct application of styles for different heightConfig modes.
  • Python Unit Tests: Added tests in chat_test.py to verify the default behavior and the mapping of the height parameter to the protobuf height_config.
  • Typing Tests: Added assert_type checks in chat_input_types.py for the new height parameter combinations.

Backwards Compatibility

The changes are fully backwards compatible. The default value for the height parameter is "content", which preserves the existing auto-expanding behavior of the chat input widget.

Security & Risk

No security concerns or regression risks identified. The changes are limited to UI presentation and standard parameter passing, with no impact on sensitive areas like authentication, file serving, or code execution.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • The changes are purely cosmetic and structural (UI layout and parameter parsing).
    • No routing, auth, websocket, embedding, or storage logic is touched.
  • Suggested external_test focus areas: N/A
  • Confidence: High
  • Assumptions and gaps: None

Accessibility

The changes do not negatively impact accessibility. The chat input remains fully functional via keyboard and screen readers, and the new layout modes correctly preserve focus management and ARIA attributes.

Recommendations

No specific recommendations for improvement. The implementation is solid and ready for merge.

Verdict

APPROVED: The PR successfully implements the height parameter for st.chat_input with excellent test coverage and code quality.


This is an automated AI review by gemini-3.1-pro.

📋 Review by `gpt-5.3-codex-high`

Summary

This PR adds a new height parameter to st.chat_input across backend API, frontend rendering/layout, typing checks, and e2e snapshots. The implementation is generally clean and well-structured, but there is one behavior mismatch between the documented contract and frontend behavior that should be fixed before merge.

Code Quality

The overall structure follows Streamlit patterns (backend validation + layout config, frontend container config, unit/e2e updates).
One significant issue was found:

  • Behavior contract mismatch (merge-blocking): height=<int> is documented as a minimum height with auto-expand, but frontend logic currently enforces fixed-height behavior for configured heights by bypassing autoExpand.
    • Docs/contract: lib/streamlit/elements/widgets/chat.py (around lines 746-757) states integer height still auto-expands with content.
    • Implementation: frontend/lib/src/components/widgets/ChatInput/ChatInput.tsx (around lines 135-143, 820-821, 881-890) sets useFixedHeight for pixel mode and applies height: "100%" / maxHeight: "none" instead of using the autoExpand height path.
    • Resulting risk: long input in pixel-height mode can stop expanding and rely on internal scrolling, which conflicts with documented API behavior.

Test Coverage

Coverage is improved and broad:

  • Python unit tests validate height default, accepted values, and invalid values.
  • Typing tests validate overload behavior with height.
  • Frontend unit tests validate stretch/content style branches.
  • E2E coverage includes new snapshot states for height=200 and height="stretch".

Gap that matters for this change:

  • No test verifies interactive text-growth behavior for height=<int> (or stretch) while typing multiline content. Current tests are mostly static style/snapshot checks, so the contract mismatch above is not caught.

Backwards Compatibility

API-wise this is additive (height is optional with default), so call signatures are backward compatible.
However, behavior compatibility for users adopting the new parameter is currently inconsistent with docs: height=<int> does not clearly preserve the existing auto-expand expectation.

Security & Risk

No direct security issues identified (no auth/session/cookie/CORS/path handling/runtime execution changes).
Primary regression risk is user-visible widget behavior in chat UX (layout + input growth semantics), especially in multiline prompts.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • lib/streamlit/elements/widgets/chat.py: API parameter/validation + layout config wiring for chat input height.
    • frontend/lib/src/components/widgets/ChatInput/ChatInput.tsx: widget-local layout/styling behavior changes only.
    • frontend/lib/src/components/core/Block/ElementNodeRenderer.tsx: element container layout policy for chat input.
    • e2e_playwright/st_chat_input.py, e2e_playwright/st_chat_input_test.py: local app/e2e rendering updates, no external-hosting protocol changes.
  • Suggested external_test focus areas:
    • None required for this PR specifically.
  • Confidence: High
  • Assumptions and gaps: Assessment assumes no hidden changes outside this diff touching routing/auth/websocket/embed/postMessage/cross-origin policies.

Accessibility

No new critical a11y regressions spotted in this diff. Interactive icon buttons retain accessible names (aria-label), and semantic button usage remains intact.
The major concern here is behavioral (height growth), not assistive-tech semantics.

Recommendations

  1. Restore true auto-expand behavior for height=<int> in frontend/lib/src/components/widgets/ChatInput/ChatInput.tsx (keep pixel value as minimum height, but do not force fixed height: 100% for pixel mode).
  2. Add a focused frontend unit test and one e2e interaction test that type multiline text in height=200 mode and assert growth behavior (plus a negative assertion for non-regression, e.g., no premature scrollbar/fixed clipping).

Verdict

CHANGES REQUESTED: The height=<int> behavior in frontend does not currently match the API/doc contract (minimum + auto-expand), so this should be corrected before merge.


This is an automated AI review by gpt-5.3-codex-high.

📋 Review by `opus-4.6-thinking`

Summary

This PR adds a height parameter to st.chat_input() that allows controlling the minimum height of the chat input widget. The parameter supports three modes:

  • "content" (default): Standard single-line height with auto-expand behavior (unchanged from today).
  • "stretch": Fills the available height of the parent container.
  • Integer (pixels): Sets a fixed minimum height while retaining auto-expand.

The implementation spans backend (Python parameter + validation), protobuf (reuses existing HeightConfig), and frontend (new layout logic in ChatInput.tsx and styled-components.ts, plus container config in ElementNodeRenderer.tsx). E2E snapshots and unit tests (Python, TypeScript, and typing) are included.

Code Quality

Strengths:

  • Cleanly reuses the existing HeightConfig protobuf and LayoutConfig infrastructure—no new proto fields needed.
  • Follows the established pattern from st.text_area height configuration in ElementNodeRenderer.tsx (stretch uses flex: "1 1 8rem", pixel uses height: "auto" + overflow: "visible").
  • Good separation of concerns: the textareaMinHeight calculation is memoized with correct dependencies.
  • The layout correctly falls back to the non-expanded (row) layout during audio recording, even when heightConfig is set—this avoids breaking the waveform display.

Concerns:

  1. Significant code duplication in ChatInput.tsx (lines 896–1094): The expanded (hasExpandedHeight && !isRecording) and non-expanded branches duplicate the entire button cluster: StyledLeftCluster with ChatFileUploadButton, StyledRightCluster with audio buttons, error tooltips, send button, and StyledInputInstructions. This is roughly 100 lines of duplicate JSX. Any future change to button behavior must be replicated in both branches, creating a maintenance risk. Consider extracting shared button clusters into helper components or using a render function to reduce duplication.

  2. StyledInputInstructions visual positioning change affects all chat inputs: The removal of position: "absolute", top, right, and zIndex from StyledInputInstructions (styled-components.ts, lines 129–138) moves the character count indicator from a floating overlay position to inline within the button row. This is a global visual change for every st.chat_input() that uses max_chars, not only those with the new height parameter. The numerous snapshot updates confirm this. While this may be intentional (and arguably a better design), it should be explicitly called out as a visual/behavioral change to existing users.

  3. parseInt for border width (ChatInput.tsx, line 807): parseInt(theme.sizes.borderWidth, 10) works for pixel values like "1px" but would silently return NaN for rem-based values. The || 1 fallback mitigates this, but it's worth noting this assumption is theme-dependent.

Test Coverage

Python unit tests (lib/tests/streamlit/elements/chat_test.py):

  • Tests the default height config (use_content: true).
  • Parameterized tests for all three height modes (pixel, stretch, content) validating the correct protobuf field and value.
  • Parameterized invalid-input tests (invalid string, negative, zero, float).
  • Good coverage following the @parameterized.expand pattern.

Python typing tests (lib/tests/streamlit/typing/chat_input_types.py):

  • Covers height with all three modes combined with accept_file and the "all parameters" combined tests.

Frontend unit tests (ChatInput.test.tsx):

  • Tests height: 100% style for stretch mode.
  • Parameterized negative tests for undefined, content mode, and pixel height mode (correctly verifying NO height: 100%).
  • The pixel-height test ("renders with correct calculated min-height in pixel height mode") does not actually assert the computed min-height value—it only checks the textarea root element exists. The comment acknowledges baseweb style injection makes this hard. This is a gap in coverage, but understandable.

E2E tests (e2e_playwright/st_chat_input_test.py):

  • Snapshot tests for height=200 and height="stretch" are added to the existing test_chat_input_rendering aggregated test, following the established pattern.
  • The stretch test correctly screenshots the parent container (height_stretch_container) to show the widget filling it.
  • New snapshots are provided for all browser/theme combinations.
  • Missing: No behavioral E2E test verifying that text typed into a height-configured chat input actually submits correctly, or that auto-expand still works within a pixel-height input. The visual snapshots cover the static appearance, but an interaction test would increase confidence.

Backwards Compatibility

  • The height parameter defaults to "content", which preserves the existing single-line auto-expand behavior. No breaking change for existing st.chat_input() calls.
  • The height parameter is not included in key_as_main_identity, so changing it won't reset widget state. This is correct.
  • The StyledInputInstructions positioning change (absolute → inline) is a visual regression for users who have max_chars set on chat_input. While likely an improvement, it changes the appearance of existing apps without the user changing any code. This should be documented as a visual change.

Security & Risk

No security concerns identified. The changes are confined to:

  • A new validated parameter on a public API method.
  • CSS/layout changes in the frontend.
  • No new dependencies, no HTML injection, no eval, no network changes.
  • Input validation correctly rejects invalid height values (floats, negatives, unknown strings).

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • All changes are in UI element rendering (CSS layout, protobuf field reuse, parameter validation).
    • No changes to routing, auth, websocket, embedding, asset serving, CORS, storage, or security headers.
    • No changes to server-side behavior or network protocols.
  • Suggested external_test focus areas: N/A
  • Confidence: High
  • Assumptions and gaps: None. The changes are purely additive UI parameter support with no infrastructure impact.

Accessibility

  • aria-label and aria-describedby attributes are preserved in both expanded and non-expanded layout branches.
  • The StyledInputInstructions remains linked via id="stChatInputInstructions" to the textarea's aria-describedby.
  • All buttons retain their aria-label attributes ("Send message", "Start recording", "Cancel recording", "Submit recording").
  • The StyledSendIconButton components retain focus-visible styles.
  • No accessibility regressions identified. The layout restructuring doesn't affect screen reader behavior since the same semantic elements are rendered.

Recommendations

  1. Reduce JSX duplication in ChatInput.tsx: Extract the button clusters (file upload button, audio buttons, instructions, send button) into shared components or a render function to avoid maintaining identical JSX in two branches. This is the most significant maintainability concern in the PR.

  2. Explicitly document the StyledInputInstructions positioning change: The PR description only mentions the new height parameter. The global visual change to character count positioning (from absolute overlay to inline) should be mentioned in the PR description and/or changelog, as it affects all st.chat_input() usages with max_chars.

  3. Consider adding a behavioral E2E test: A test that types text into a height-configured chat input and submits it would verify that the new layout doesn't interfere with core chat input functionality (beyond visual appearance).

  4. Minor: The pixel-height frontend unit test could be strengthened: Currently it only verifies the textarea root element exists rather than asserting the actual computed min-height. If testing the baseweb override style is feasible (e.g., via getComputedStyle in the test), it would add confidence.

Verdict

APPROVED: Well-implemented feature that follows established Streamlit patterns for height configuration, with thorough backend validation, typing tests, and visual snapshot coverage. The main concern is JSX duplication in the expanded/non-expanded layout branches, which is a maintainability issue rather than a correctness bug. The implicit visual change to StyledInputInstructions positioning should be explicitly documented.


This is an automated AI review by opus-4.6-thinking.

@github-actions github-actions bot added the do-not-merge PR is blocked from merging label Mar 10, 2026
@lukasmasuch lukasmasuch merged commit fb66c1d into develop Mar 10, 2026
58 checks passed
@lukasmasuch lukasmasuch deleted the lukasmasuch/chat-input-height branch March 10, 2026 20:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:feature PR contains new feature or enhancement implementation do-not-merge PR is blocked from merging impact:users PR changes affect end users

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Configure the initial height of st.chat_input

3 participants