[feature] Add st.iframe command#14433
Conversation
Implements st.iframe as specified in #14373, consolidating st.components.v1.iframe and st.components.v1.html into a single, discoverable command in the main namespace. Features: - Auto-detects input type: URL, Path object, existing file, or HTML string - Supports absolute URLs (http/https/data:), relative URLs (/app/static/...) - Embeds local HTML files via srcdoc, non-HTML files via media storage - Width/height parameters with "stretch", "content", and pixel values - tab_index parameter for accessibility/keyboard navigation Closes #12977 Co-Authored-By: Claude Opus 4.6 <[email protected]>
✅ PR preview is ready!
|
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
There was a problem hiding this comment.
Pull request overview
Adds a new public st.iframe command to the main Streamlit namespace, consolidating existing iframe embedding behavior into a more discoverable API and extending it to handle URLs, HTML strings, and local files.
Changes:
- Implement
st.iframeinIframeMixin, including tab index validation and local file handling (HTML viasrcdoc, non-HTML via media storage). - Export
iframefromstreamlit.__init__so it’s available asst.iframe. - Add/extend Python unit tests and new Playwright E2E coverage for
st.iframe.
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/streamlit/elements/iframe.py | Adds st.iframe implementation, shared tab_index validation, and local file processing logic. |
| lib/streamlit/init.py | Exposes st.iframe in the public Streamlit namespace. |
| lib/tests/streamlit/elements/iframe_test.py | Refactors/extends unit tests for tab index validation and st.iframe behaviors (URL/HTML/local HTML). |
| e2e_playwright/st_iframe.py | Adds an E2E example app exercising key st.iframe scenarios. |
| e2e_playwright/st_iframe_test.py | Adds E2E tests for rendering, sandboxing, scrolling, and tab index behavior. |
|
The AI review job failed to complete. Please check the workflow run for details. You can retry by adding the 'ai-review' label again or manually triggering the workflow. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
When using height='content' with HTML strings or local HTML files, the iframe now automatically sizes to fit its content: - Injects JavaScript into srcdoc content to measure and report height - Frontend listens for postMessage and applies height dynamically - URLs still fall back to 400px due to cross-origin restrictions This enables a more natural user experience where iframe content displays without unnecessary scrollbars or extra whitespace. Co-Authored-By: Claude Opus 4.6 <[email protected]>
The previous height measurement used scrollHeight which rounds to integers, but content can have fractional pixel heights. This caused a tiny scrollbar to appear when content height was e.g. 194.4375px but the iframe was sized to 194px. Now using getBoundingClientRect().height with Math.ceil() to properly round up and fully contain the content without scrollbars. Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Add Final type annotations to module constants - Consolidate duplicated frontend test cases for sandbox/feature policies - Replace wait_for_timeout with proper expect assertion for height updates - Fix misleading comments about iframe index and scrolling Co-Authored-By: Claude Opus 4.6 <[email protected]>
|
The AI review job failed to complete. Please check the workflow run for details. You can retry by adding the 'ai-review' label again or manually triggering the workflow. |
- Add iframe to element_mocks.py for public API tests - Fix falsy check bug in IFrame.tsx (handle height=0) - Add save_media_data call for caching compatibility - Add unit test for non-HTML local file handling Co-Authored-By: Claude Opus 4.6 <[email protected]>
## Describe your changes Automated snapshot updates for #14433 created via the snapshot autofix CI workflow. This workflow was triggered by adding the `update-snapshots` label to a PR after Playwright E2E tests failed with snapshot mismatches. **Updated snapshots:** 1 file(s)⚠️ **Please review the snapshot changes carefully** - they could mask visual bugs if accepted blindly. This PR targets a feature branch and can be merged without review approval. Co-authored-by: Streamlit Bot <[email protected]>
WebKit can be slower at processing postMessage from iframes. Increase the timeout from default 5s to 10s to reduce flakiness. Co-Authored-By: Claude Opus 4.6 <[email protected]>
fb4ba39 to
21f20dd
Compare
WebKit's postMessage timing is inherently unreliable in CI environments, causing the test_iframe_auto_sizing_height test to fail intermittently. Skip this test on webkit following the pattern used by other similar tests. Co-Authored-By: Claude Opus 4.6 <[email protected]>
The deprecation wrapper for components.v1.iframe changed the string representation from a bound method to a wrapped function. Update the tests to expect the new representation format. Co-Authored-By: Claude Opus 4.6 <[email protected]>
There was a problem hiding this comment.
Summary
This PR introduces st.iframe as a new public API that consolidates st.components.v1.iframe and st.components.v1.html into a single, discoverable command in the main st namespace. Key capabilities include auto-detection of input type (URL, Path object, existing file, relative URL, or HTML string), auto-sizing height via height="content" using injected JavaScript and postMessage, local file embedding (HTML via srcdoc, non-HTML via media storage), and graceful deprecation of the legacy components APIs.
All three reviewers (claude-4.6-opus-high-thinking, gemini-3.1-pro, gpt-5.3-codex-high) completed their reviews and unanimously approved the PR.
Code Quality
Consensus: Well-structured, follows Streamlit patterns. All reviewers agree the implementation is clean and well-organized:
- The backend
IframeMixincleanly separates input detection, proto construction, dimension handling, and local file processing. - The frontend
useEffectforpostMessagelistening is properly scoped with cleanup, source validation, and height validation. - The deprecation utility additions (
include_st_prefix,show_in_browser,show_once) are backward-compatible with sensible defaults. - The auto-height measurement script is comprehensive, using multiple measurement strategies (
getBoundingClientRect,scrollHeight,offsetHeight) withMutationObserverfor dynamic content andlastHeightdeduplication.
One reviewer (gemini-3.1-pro) noted a minor robustness concern with _is_file() — it should guard against very long strings and ValueError from null bytes. This is covered in the inline comments.
Test Coverage
Consensus: Thorough and comprehensive. All reviewers praised the test coverage:
- Python unit tests (40+ tests): Cover URL handling, HTML detection, local files (HTML, non-HTML,
Path,.htm), dimensions,tab_indexvalidation,height="content"fallback, and error paths. - Frontend unit tests: Cover
useContentHeightbehavior — listener registration/cleanup, valid/invalid height messages, source validation, and edge cases (NaN, Infinity, negative, zero). - E2E tests (9 tests): Cover rendering, HTML content, fixed dimensions, data URLs, scrolling, sandbox policy, tab index, CSS class, and auto-sizing height. Webkit is wisely skipped for
postMessagetiming flakiness. - Typing tests:
iframe_types.pycovers parameter combinations withassert_type.
One gap noted (gpt-5.3-codex-high, gemini-3.1-pro): No @pytest.mark.external_test coverage for the new iframe boundary behavior in externally hosted/embedded environments. See the external test recommendation below.
Backwards Compatibility
Consensus: Fully backward-compatible. All reviewers agree:
st.iframeis a purely additive new API — no existing APIs removed.st.components.v1.htmlandst.components.v1.iframecontinue to work, emitting console-only, show-once deprecation warnings.- The protobuf change (field #9
use_content_height) is additive — older frontends ignore it, older backends don't set it. - The
deprecation_utilchanges use defaults preserving existing behavior. - E2E test updates correctly reflect the
<function ...>repr from thedeprecate_func_namewrapper.
Security & Risk
Consensus: Low risk, well-handled. All reviewers agree the security-relevant aspects are properly addressed:
- The
postMessagewith'*'target origin is safe: it only runs inside sandboxedsrcdoccontent, the payload is only a height integer, and the frontend validatesevent.source === iframe.contentWindow. - The sandbox policy reuses
DEFAULT_IFRAME_SANDBOX_POLICY, consistent with existing components. - Local file reading is consistent with how
st.image,st.audio, etc., handle files. - Height values are validated as finite and non-negative before CSS application.
- No new external dependencies, no changes to auth/XSRF/cookies/session management.
External test recommendation
Split opinion, leaning toward Yes (2 of 3 recommend):
- claude-4.6-opus-high-thinking: No — the
postMessagemechanism is entirely internal tost.iframe, not affecting Streamlit's own embedding behavior. High confidence. - gemini-3.1-pro: Yes — triggered categories: embedding/iframe boundary, static/component asset serving. Suggests testing auto-height in nested iframes and media file loading under different proxy/CORS rules. High confidence.
- gpt-5.3-codex-high: Yes — same triggered categories. Suggests testing auto-resize in externally hosted embedded apps, media-backed file embedding behind proxies/base-paths, and behavior under stricter host-page CSP. Medium confidence.
Consolidated recommendation: Yes, external test coverage is recommended as a follow-up. While the postMessage mechanism is internal to st.iframe, the nested iframe scenario (Streamlit app itself embedded in a host page) creates a multi-level postMessage context worth validating. The media-backed file serving (/media/...) for non-HTML files behind external proxies is also a relevant concern. This does not need to block the merge but should be addressed soon after.
- Triggered categories: 4 (Embedding and iframe boundary), 5 (Static and component asset serving)
- Suggested focus areas: (1)
height="content"auto-resize when app is embedded in a host-page iframe; (2) media-backed non-HTML file embedding behind external proxies/base-paths; (3) iframe behavior under stricter host-page CSP. - Confidence: Medium-High
- Assumptions and gaps: Assessment is based on static diff review; no runtime execution in an external/embedded environment was performed.
Accessibility
Consensus: Appropriately handled.
- The
tab_indexparameter maps correctly to the HTMLtabindexattribute with proper validation (None,-1,0, positive integers). - The iframe has
title="st.iframe"for screen reader identification. - Keyboard navigation is properly controllable via
tab_index.
One reviewer (gemini-3.1-pro) suggested allowing a custom title parameter in the future for better screen reader support — a reasonable enhancement for a follow-up.
Recommendations
- Harden
_is_file(): Add a length guard before filesystem checks on long strings, and catchValueErrorfor null-byte strings (see inline comments). - External test follow-up: Add at least one
@pytest.mark.external_testscenario covering embedded-host auto-resize and media-file iframe behavior — either before merge or immediately after. - Document
Path()preference: Consider adding a note in the Parameters section recommendingPath()objects for unambiguous file intent, since string-based_is_file()is CWD-dependent. - E2E assertion style: Replace raw
assertwithexpect-based assertions in E2E tests for consistency and auto-wait behavior (see inline comments).
Verdict
APPROVED: All three reviewers unanimously approved. The implementation is well-structured, thoroughly tested, backward-compatible, and security-conscious. The recommendations above are improvements, not blockers. The external test coverage is the most significant follow-up item but does not need to block the merge.
Consolidated AI review by claude-4.6-opus-high-thinking, synthesizing reviews from claude-4.6-opus-high-thinking, gemini-3.1-pro, and gpt-5.3-codex-high.
This review also includes 3 inline comment(s) on specific code lines.
…st.iframe - Remove custom `use_content_height` proto field in favor of standard `widthConfig` and `heightConfig` from the Element proto - Add support for `width="content"` auto-sizing (falls back to stretch for cross-origin URLs) - Rename auto-height script to auto-size script that reports both width and height via postMessage - Update frontend to accept widthConfig/heightConfig props and apply measured dimensions for content sizing - Update all tests (Python unit, frontend unit, E2E, typing) Co-Authored-By: Claude Opus 4.6 <[email protected]>
Inline width == "content" and height == "content" comparisons since they're only used once in the immediately following conditional. Co-Authored-By: Claude Opus 4.6 <[email protected]>
There was a problem hiding this comment.
Summary
This PR introduces st.iframe, a new public Streamlit command that consolidates st.components.v1.iframe and st.components.v1.html into a single, discoverable API in the main st. namespace. Key capabilities include auto-detection of input type (URLs, Path objects, local files, raw HTML strings), content-based auto-sizing via injected JavaScript that measures and reports dimensions through postMessage, graceful fallbacks for URLs where cross-origin restrictions prevent measurement, and deprecation of the legacy APIs with console-only warnings shown once per message.
All three reviewers (claude-4.6-opus-high-thinking, gemini-3.1-pro, gpt-5.3-codex-high) completed their reviews successfully. No expected models failed.
Code Quality
Consensus: Strong — All three reviewers agreed the code is well-structured and follows Streamlit's established patterns.
- Backend (
lib/streamlit/elements/iframe.py): TheIframeMixin.iframe()method cleanly separates input detection, proto population, and layout configuration. Helper functions (_is_file,_validate_tab_index,_inject_auto_size_script) are appropriately extracted. Local file processing handles both HTML and non-HTML files with proper error handling and uses the existing media file manager. - Frontend (
frontend/lib/src/components/elements/IFrame/IFrame.tsx): ThepostMessagelistener is correctly implemented as auseEffect(an external system subscription) with proper cleanup. ThesetContentDimensionsupdater uses referential equality checks to avoid unnecessary re-renders. - Deprecation utilities: The additions to
deprecate_func_name(include_st_prefix,show_in_browser,show_once) are backwards-compatible with well-chosen defaults. Theshow_in_browser=False, show_once=Trueconfiguration is a thoughtful choice for soft deprecation. - Protobuf: Only adds field 9 to the reserved list — safe and follows proto guidance for released messages.
Test Coverage
Consensus: Comprehensive — All reviewers praised the test coverage across all layers.
- Python unit tests (~42 tests): Cover URL handling, HTML string detection, local file handling (HTML and non-HTML), dimension parameters, tab_index validation, content sizing fallbacks, and error cases.
- Frontend unit tests (~27 tests): Cover rendering, auto-sizing behavior (postMessage handling), source validation, invalid dimension rejection, event listener lifecycle, and config changes.
- E2E tests (~10 tests): Cover rendering, content verification, sandbox/scrolling policies, tab_index, auto-sizing, and visual snapshots. WebKit is skipped for postMessage timing tests.
- Typing tests: Verify parameter combinations via mypy
assert_type. - Element mocks:
st.iframeis added to the element mocks list for integration tests.
One reviewer (gpt-5.3-codex-high) noted a gap in @pytest.mark.external_test coverage. See the External Test Recommendation section for the consolidated assessment.
Backwards Compatibility
Consensus: Fully compatible — All three reviewers agreed this PR is fully backwards compatible.
st.components.v1.html()andst.components.v1.iframe()continue to work identically, now with soft deprecation warnings (console-only, shown once).- The internal
_iframe()and_html()methods are unchanged. - The protobuf only adds field 9 to the reserved list.
- New parameters in
deprecate_func_nameandshow_deprecation_warningall have default values matching prior behavior. st.iframeis a net-new addition to thest.namespace.
Security & Risk
Consensus: Low risk with appropriate guards — All reviewers confirmed the security model is sound.
- postMessage handling: The auto-size script uses
postMessage('*'), but this is confined to srcdoc iframes (same-origin, sandboxed) and only transmits integer dimensions. The frontend receiver validatesevent.source === iframeRef.current?.contentWindowand checks that dimensions are finite, non-negative numbers. One minor edge case (bothevent.sourceandcontentWindowbeingnull) is noted in inline comments. - Sandbox policy: Uses
DEFAULT_IFRAME_SANDBOX_POLICYwithallow-scriptsandallow-same-origin, consistent with existing iframe behavior. - Local file reading: Consistent with existing Streamlit patterns (
st.image,st.audio). Path traversal risk is limited since the server runs with the user's permissions. - Auto-size script injection: Only applies to srcdoc content; cannot be injected into external URL iframes.
- No new dependencies introduced on either backend or frontend.
External test recommendation
Disagreement across reviewers:
- claude-4.6-opus-high-thinking: No (high confidence) — changes are confined to a new element using existing proto, layout config, and media infrastructure. No changes to routing, auth, websocket, server endpoints, or embedding infrastructure.
- gemini-3.1-pro: Yes — concerns about reverse proxies, CSP, and cross-origin embedding.
- gpt-5.3-codex-high: Yes — concerns about embed boundary, static asset serving, and cross-origin behavior.
Consolidated assessment: No (blocking) / Yes (recommended follow-up)
The underlying infrastructure used by st.iframe — the iframe proto, sandbox policies, media file manager, and postMessage within srcdoc — is unchanged from existing behavior. The new code is a higher-level API over existing mechanisms. No server endpoints, routing, auth, or embedding framework code is modified. The postMessage auto-sizing is contained within same-origin srcdoc iframes and doesn't cross external boundaries. Therefore, missing external test coverage is not a blocking concern for this PR.
However, adding @pytest.mark.external_test coverage for iframe rendering and media URL behavior in hosted environments would be a valuable follow-up, particularly for:
height="content"/width="content"when the Streamlit app itself is embedded in a parent iframe.- Non-HTML local files rendered via media URLs (
/media/...) in externally hosted deployments.
Accessibility
Consensus: Good — All reviewers confirmed accessibility is well-addressed.
- The
tab_indexparameter is well-documented and follows web specifications. Valid values (-1, 0, positive integers) are correctly validated. - The
title="st.iframe"attribute provides a consistent accessible name for screen readers. - The
tabIndexattribute is correctly passed through to the rendered iframe element. - One reviewer (gemini-3.1-pro) suggested allowing developers to customize the
titleattribute for better screen reader support — a reasonable future enhancement.
Recommendations
- Address the
event.sourcenull guard inIFrame.tsx:82— add a truthy check before comparing to prevent the edge case where both values arenull. (See inline comment.) - Consider adding a lenient WebKit assertion for auto-sizing tests to provide at least basic coverage across all browsers, rather than skipping entirely.
- Add
@pytest.mark.external_testcoverage as a follow-up for iframe rendering in hosted/embedded environments. - Replace bare
assertwith Playwright'sexpectin E2E tests for consistency and reduced flakiness risk. - Future enhancements to consider: customizable
titleattribute for screen readers, customizablesandboxparameter for advanced users, fast-path heuristic in_is_fileto skip filesystem checks for obvious HTML strings.
Verdict
APPROVED: This is a well-designed, thoroughly tested new feature that follows Streamlit's established patterns. All three reviewers agreed the implementation is solid, the test coverage is comprehensive, and backwards compatibility is fully preserved. Two of three reviewers approved outright; the third requested changes primarily for external test coverage, which the consolidated assessment determines is a valuable follow-up but not a blocking concern. The inline comments note minor defensive improvements and best-practice alignments that can be addressed before or after merge.
This is a consolidated AI review by claude-4.6-opus-high-thinking, synthesizing reviews from claude-4.6-opus-high-thinking, gemini-3.1-pro, and gpt-5.3-codex-high.
This review also includes 7 inline comment(s) on specific code lines.
- Fix TypeScript type error by extracting validated dimensions to local variables before setState, allowing proper type narrowing - Add truthy guard on event.source in postMessage handler - Add document.body guard in auto-size script for malformed HTML - Improve _is_file() with length guard and ValueError catch - Update E2E tests to use expect assertions instead of bare assert - Add comments explaining inline styles and effect behavior Co-Authored-By: Claude Opus 4.6 <[email protected]>
🧪 Significant E2E test count increase detectedThis PR has added 31 E2E test cases (threshold: 30)
|
…spec Update the st.iframe product spec to document that width="content" falls back to "stretch" for URLs (in addition to the existing note about height="content" falling back to 400px). Co-Authored-By: Claude Opus 4.6 <[email protected]>
There was a problem hiding this comment.
Summary
This PR introduces a new st.iframe command in the main Streamlit namespace, consolidating st.components.v1.iframe and st.components.v1.html into a unified, more discoverable API. Key capabilities include auto-detection of input type (URL, Path object, local file, or HTML string), content-based auto-sizing via injected JavaScript that measures dimensions and reports them via postMessage, and local file handling (HTML embedded via srcdoc, non-HTML uploaded to media storage). The old APIs are preserved with gentle, log-only deprecation warnings.
Reviewer consensus: All three reviewers (claude-4.6-opus-high-thinking, gemini-3.1-pro, gpt-5.3-codex-high) completed their reviews. Two approved; one requested changes citing implementation-level robustness concerns and missing external test coverage.
Code Quality
All three reviewers agreed the implementation is well-structured and follows established Streamlit patterns across backend, frontend, proto, and test layers. Specific points of agreement:
- Backend: Clean separation of concerns with well-named module-level helpers (
_is_file,_validate_tab_index,_inject_auto_size_script,_process_local_file). The input detection order is logical and documented. - Frontend: The
useEffectfor message handling follows React best practices with proper cleanup, source validation viaevent.source === iframeRef.current?.contentWindow, and a functionalsetStateupdater. TheshouldMeasureContentderived value correctly gates both the effect and dimension style application. - Deprecation: The new
show_in_browser=Falseandshow_once=Trueoptions todeprecate_func_nameprovide a less intrusive deprecation path. - Proto: Minimal change—only adding reserved field 9.
The inline style prop on the iframe (line 146 of IFrame.tsx) technically conflicts with the frontend AGENTS.md guideline to avoid inline styles, but the code justifies this as necessary for dynamic pixel values received via postMessage. All reviewers accepted this as a valid exception.
Test Coverage
All three reviewers agreed test coverage is comprehensive:
- Python unit tests (42 tests): URL handling, HTML string detection, local file handling, Path objects, dimension parameters, tab_index validation, content sizing fallbacks, and error cases.
- Frontend unit tests (27 tests): Rendering, auto-sizing behavior, message validation (NaN, Infinity, negative), source validation, and config change handling.
- E2E tests (10 tests): Full-stack rendering, content verification, sandbox policy, scrolling, tab index, auto-sizing, and snapshot tests.
- Typing tests: Parameter and return type validation via mypy
assert_type. - Deprecation tests: New coverage for
show_in_browser,show_once, andinclude_st_prefixparameters.
The auto-sizing E2E tests appropriately skip WebKit (@pytest.mark.skip_browser("webkit")) due to postMessage timing flakiness in CI.
Backwards Compatibility
All reviewers confirmed no breaking changes:
st.components.v1.htmlandst.components.v1.iframecontinue to work with log-only deprecation warnings (show_in_browser=False, show_once=True).- The new
st.iframeintroduces different defaults (e.g.,height="content"instead of150px,scrolling=Trueinstead ofFalse), which is appropriate for a new command. - Proto compatibility maintained—only reserved field 9 added.
- Existing E2E tests updated to expect
functools.wrapsstring representation changes.
Security & Risk
All three reviewers confirmed the postMessage security implementation is sound:
- The auto-size script uses
postMessage('*'), but this is safe because: (1) it only runs inside srcdoc (same-origin, sandboxed), (2) the payload contains only dimension integers, and (3) the frontend validatesevent.source === iframe.contentWindow. - The existing
DEFAULT_IFRAME_SANDBOX_POLICYis unchanged. - Message validation on the frontend checks type, source, and dimension values (finite, non-negative).
- Local file access via
_process_local_fileis consistent with Streamlit's trust model (other APIs likest.image,st.videohave the same pattern). - No new backend dependencies or injection paths introduced.
External test recommendation
- Recommend external_test: No
- Triggered categories: 4 (Embedding and iframe boundary)
- Evidence:
lib/streamlit/elements/iframe.py: Auto-size script useswindow.parent.postMessagewithin srcdocfrontend/lib/src/components/elements/IFrame/IFrame.tsx: Newmessageevent listener for iframe sizing
- Confidence: High
Reviewer disagreement: gemini-3.1-pro and gpt-5.3-codex-high recommended external tests; claude-4.6-opus-high-thinking did not.
Resolution: The postMessage communication is strictly between the Streamlit app and its own srcdoc iframe (same-origin). It does not affect how Streamlit itself is embedded in host pages. No changes are made to Streamlit's iframe sandbox/allow policies, embedding behavior, host-to-guest communication, routing, auth, or session handling. The DEFAULT_IFRAME_SANDBOX_POLICY is unchanged. While verifying nested iframe behavior is a reasonable future enhancement, external test coverage is not warranted for this PR.
Accessibility
- Tab index support: Properly implemented with validation for valid values (-1, 0, positive integers).
- Title attribute: The iframe has
title="st.iframe"for screen reader identification. gemini-3.1-pro suggested adding a user-configurabletitleparameter for better accessibility—this is a good enhancement to consider in a follow-up but not blocking. - Sandbox policy: Includes
allow-same-originandallow-scriptsfor functional content (unchanged from existing behavior).
Recommendations
- Consider resetting
contentDimensionsstate whensrcDocchanges to avoid a brief flash of stale dimensions (see inline comment onIFrame.tsx). This is low-risk but improves robustness. - Consider adding a user-configurable
titleparameter tost.iframein a follow-up PR, allowing users to provide descriptive iframe titles for screen readers (currently hardcoded to"st.iframe"). - The
_shown_warningsset indeprecation_util.pyis module-level and never cleared. This is fine for the intended use case (small, finite set of deprecation messages), but a brief comment documenting the lifetime assumption would help future maintainers.
Verdict
APPROVED: Well-implemented new st.iframe command with comprehensive test coverage, clean backwards compatibility via gentle deprecation, and proper security practices. The majority of reviewers approved, and the issues raised by the dissenting review are non-critical enhancements rather than blocking concerns. The one medium-severity item (stale content dimensions) is addressed via inline comment as a recommended improvement.
This is a consolidated AI review by claude-4.6-opus-high-thinking, synthesizing reviews from claude-4.6-opus-high-thinking, gemini-3.1-pro, and gpt-5.3-codex-high. Please verify the feedback and use your judgment.
This review also includes 3 inline comment(s) on specific code lines.
Field 9 (use_content_height) was added and removed within the same PR, so it was never shipped in a release and doesn't need to be reserved. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Change deprecation warnings for st.components.v1.html and st.components.v1.iframe to log on every call instead of just once, making it easier for developers to notice during debugging. Also improve e2e test to use Playwright's expect assertion. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Move the auto-size measurement script from backend (Python) to frontend (TypeScript) for better separation of concerns. The script and its message listener are tightly coupled, so co-locating them in the frontend makes the code easier to maintain and test. - Add AUTO_SIZE_SCRIPT constant and injectAutoSizeScript() to IFrame.tsx - Remove _AUTO_SIZE_SCRIPT and _inject_auto_size_script() from iframe.py - Backend now passes raw srcdoc; frontend injects script when needed - Add frontend tests for script injection behavior - Update Python tests to verify raw srcdoc passthrough Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Remove unnecessary type assertion in IFrame.tsx (eslint) - Fix E2E test to use direct assertion for tabindex absence - Remove unused ty:ignore comment in st_table.py - Add deprecation notices for components.v1.iframe and components.v1.html - Add width/height props to StyledIframe for content-based sizing Co-Authored-By: Claude Opus 4.6 <[email protected]>
The iframe auto-sizing dimensions are set as HTML attributes (width, height) on the iframe element, not as inline style properties. Updated the tests to check the correct attributes. Also fixed tabindex absence test to use expect() with regex for consistency. Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Move JavaScript auto-size measurement script from Python backend to frontend IFrame component (single source of truth) - Move URL height fallback logic to frontend, using 25rem instead of 400px - Remove use_content_height proto field (frontend uses layout config) - Simplify backend: just pass width/height through to layout config Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Strings starting with `/` are now always treated as relative URLs and never checked against the filesystem. This prevents accidentally reading filesystem data when the user intends a relative URL (e.g., for static file serving). To read an absolute path from disk, use Path() explicitly. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Move mimetypes, caching, url_util, validate_height, validate_width, and Path imports from inside functions to module-level imports. Co-Authored-By: Claude Opus 4.6 <[email protected]>
The backend now correctly handles the fallback logic for height="content" and width="content" when the source is a URL (not srcdoc): - height="content" falls back to 400px for URLs - width="content" falls back to "stretch" for URLs Also fixes the detection order so that existing Unix file paths (starting with /) are correctly identified as files before being treated as relative URLs. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Remove underscore prefix from Path import now that the TYPE_CHECKING import is no longer needed. Co-Authored-By: Claude Opus 4.6 <[email protected]>

Describe your changes
Implements
st.iframeas specified in #14373, consolidatingst.components.v1.iframeandst.components.v1.htmlinto a single, discoverable command in the main Streamlit namespace.Features:
http://,https://,data:), relative URLs (/app/static/...)srcdoc, non-HTML files via media storagewidth/heightparameters with"stretch","content", and pixel valuesheight="content"auto-sizes to content for srcdoc (falls back to 400px for URLs)width="content"auto-sizes to content for srcdoc (falls back to stretch for URLs)widthConfig/heightConfiglayout system (no custom proto fields)tab_indexparameter for accessibility/keyboard navigationUsage:
GitHub Issue Link (if applicable)
st.iframecommand #12977Testing Plan
Agent metrics