Skip to content

Exclude collapsed expander content from browser find-in-page (Cmd+F)#13818

Merged
lukasmasuch merged 5 commits intodevelopfrom
lukasmasuch/expander-search-fix
Feb 4, 2026
Merged

Exclude collapsed expander content from browser find-in-page (Cmd+F)#13818
lukasmasuch merged 5 commits intodevelopfrom
lukasmasuch/expander-search-fix

Conversation

@lukasmasuch
Copy link
Copy Markdown
Collaborator

@lukasmasuch lukasmasuch commented Feb 4, 2026

Describe your changes

Add the inert attribute to expander content panels when collapsed, preventing browsers from including hidden text in find-in-page (Cmd+F) searches. This solves the issue where users see search matches on collapsed content they can't see.

Testing Plan

  • Unit tests added to verify inert attribute is correctly applied when collapsed and removed when expanded, plus toggling behavior
  • All existing expander tests pass
  • TypeScript type checking and linting pass

Contribution License Agreement

By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

Add the inert attribute to the expander content panel when collapsed, which tells browsers to exclude it from find-in-page searches. This prevents users from being confused by search matches on hidden text in collapsed expanders. Includes unit tests to verify the inert attribute is correctly applied and toggled when expanding/collapsing.

Co-Authored-By: Claude (claude-haiku-4-5) <[email protected]>
Copilot AI review requested due to automatic review settings February 4, 2026 11:13
@snyk-io
Copy link
Copy Markdown
Contributor

snyk-io bot commented Feb 4, 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 Feb 4, 2026

✅ PR preview is ready!

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

@lukasmasuch lukasmasuch added security-assessment-completed change:feature PR contains new feature or enhancement implementation impact:users PR changes affect end users labels Feb 4, 2026
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

This PR adds the HTML inert attribute to expander content panels when collapsed, preventing browsers from including hidden text in find-in-page (Cmd+F) searches. This improves the user experience by ensuring search matches only highlight visible content.

Changes:

  • Added inert attribute to StyledDetailsPanel when the expander is collapsed
  • Created comprehensive unit tests to verify the attribute is correctly applied/removed based on expanded state
  • Documented the technical approach and considerations

Reviewed changes

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

File Description
frontend/lib/src/components/elements/Expander/styled-components.ts Added StyledDetailsPanelProps interface with inert property definition
frontend/lib/src/components/elements/Expander/Expander.tsx Applied inert attribute conditionally based on expanded state
frontend/lib/src/components/elements/Expander/Expander.test.tsx Added three tests verifying inert attribute behavior (collapsed, expanded, toggle)
expander-search-plan.md Planning documentation explaining the implementation approach and alternatives

lukasmasuch and others added 2 commits February 4, 2026 12:18
Co-Authored-By: Claude (claude-opus-4-5) <[email protected]>
@sfc-gh-lmasuch sfc-gh-lmasuch added the ai-review If applied to PR or issue will run AI review workflow label Feb 4, 2026
@github-actions github-actions bot removed the ai-review If applied to PR or issue will run AI review workflow label Feb 4, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 4, 2026

Summary

This PR adds the inert HTML attribute to the expander content panel when collapsed, which excludes the hidden content from browser find-in-page (Cmd+F / Ctrl+F) searches. This is a UX improvement that prevents confusing situations where users see search matches in content they cannot see because it's inside a collapsed expander.

Files Changed:

  • frontend/lib/src/components/elements/Expander/Expander.tsx - Added inert attribute to StyledDetailsPanel
  • frontend/lib/src/components/elements/Expander/styled-components.ts - Added TypeScript interface for the inert prop
  • frontend/lib/src/components/elements/Expander/Expander.test.tsx - Added 3 unit tests for the new behavior

Code Quality

The implementation is clean and follows established patterns in the codebase:

Positives:

  • The inert attribute is the correct semantic HTML solution for this use case - it makes content non-interactive and excludes it from browser search
  • Using "" instead of true is correct for HTML boolean attributes and ensures consistent behavior in jsdom tests (as noted in the comment at line 261-262 of Expander.tsx)
  • The TypeScript interface StyledDetailsPanelProps properly types the inert prop as "" | undefined
  • JSDoc comment in styled-components.ts (lines 124-127) clearly explains the attribute's purpose
  • The styled component follows the Styled prefix convention

No issues identified with the code structure or patterns.

Test Coverage

The unit tests are well-written and follow RTL best practices:

  1. "sets inert attribute on collapsed content" (lines 158-167) - Tests initial collapsed state
  2. "removes inert attribute on expanded content" (lines 169-178) - Tests initial expanded state (positive + negative assertion pair)
  3. "toggles inert attribute when expanding" (lines 180-194) - Tests user interaction toggling

Strengths:

  • Uses getByTestId appropriately for the panel element
  • Uses userEvent for interaction testing (per RTL best practices)
  • Includes complementary positive/negative assertions (has attribute vs. does not have attribute)

Minor observation: There is no test for the reverse toggle (expanded → collapsed), though the existing tests cover the core behavior adequately. The E2E tests already cover expand/collapse interactions, and browser find-in-page behavior cannot be tested in Playwright, so the current unit test coverage is reasonable.

Backwards Compatibility

No breaking changes. This is a purely frontend UX enhancement:

  • No API changes
  • No proto changes
  • No Python code changes
  • Existing functionality remains intact

Behavior change (expected): Users will notice that collapsed expander content no longer appears in browser find-in-page results. This is the intended improvement.

Accessibility note: The inert attribute also removes content from the accessibility tree and prevents keyboard focus when applied. This is actually more correct behavior for visually hidden content - previously, users could potentially tab into collapsed content they couldn't see.

Security & Risk

No security concerns. This is a presentational change that uses a standard HTML attribute.

Low regression risk:

  • The inert attribute has excellent browser support (all modern browsers)
  • The change is isolated to the Expander component
  • Existing E2E tests (st_expander_test.py) cover expand/collapse interactions and visual snapshots

Recommendations

No blocking issues. The PR is ready for merge.

Optional enhancement (non-blocking):

  1. Consider adding a test for the reverse toggle (expanded → collapsed removes the content from search). This would provide symmetrical test coverage:
it("adds inert attribute when collapsing", async () => {
  const user = userEvent.setup()
  const props = getProps({ expanded: true })
  render(
    <Expander {...props}>
      <div>test</div>
    </Expander>
  )

  const panel = screen.getByTestId("stExpanderDetails")
  expect(panel).not.toHaveAttribute("inert")

  await user.click(screen.getByText("hi"))
  expect(panel).toHaveAttribute("inert")
})

However, this is not required as the current tests adequately validate the feature.

Verdict

APPROVED: Clean implementation of a useful UX improvement using semantic HTML. Tests are well-written and follow best practices. No backwards compatibility or security concerns.


This is an automated AI review using opus-4.5-thinking. Please verify the feedback and use your judgment.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 4, 2026

📈 Frontend coverage change detected

The frontend unit test (vitest) coverage has increased by 0.0600%

  • Current PR: 86.4600% (13842 lines, 1874 missed)
  • Latest develop: 86.4000% (13841 lines, 1882 missed)

🎉 Great job on improving test coverage!

📊 View detailed coverage comparison

- Add test for expanded → collapsed transition (adds inert)
- Add comment explaining why StyledDetailsPanelProps is needed

Co-Authored-By: Claude (claude-opus-4-5) <[email protected]>
@sfc-gh-lwilby
Copy link
Copy Markdown
Collaborator

I agree with this approach here, but some of the work I did for dynamic expanders may make it more viable to not render the content when the expander is closed in the future. I had to make changes to the animation in order to support the content being sent after the expander is opened and the script re-runs. I could test that as a follow up, if we think there may be other benefits like having a cleaner DOM.

@lukasmasuch
Copy link
Copy Markdown
Collaborator Author

lukasmasuch commented Feb 4, 2026

to not render the content when the expander is closed in the future.

It's definitely something we can explore, but we will need a closer evaluation since we had a couple of issues with that in the past. E.g. when not rendering content of tabs, expander, popover the child components will get unmounted (and stats get reset). We have some limited capabilities (state reconstruction) to make it work slightly better, but it's still not the smoothest experience. I also think there were some issues with sizing. That's why all these components are currently configured to render all. But there are also benefits to not rendering the content.

@lukasmasuch lukasmasuch merged commit b86dad7 into develop Feb 4, 2026
42 checks passed
@lukasmasuch lukasmasuch deleted the lukasmasuch/expander-search-fix branch February 4, 2026 16:14
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 impact:users PR changes affect end users

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants