Repository navigation
feat(tree, list, chat, expansion-panel, tabs): skip off-screen items and make collapsed content findable - #2594
Merged
rkaraivanov merged 11 commits intoNov 12, 2026
Conversation
Tree items, list items and chat messages far from the view skip style, layout and paint (content-visibility: auto with contain-intrinsic-size). Style and layout take 70-90% less time, and the first render of a tree with 2,000 items takes 41% less. - Tree: only collapsed items skip, with the row height as their size. The active and the focused item always render, because Firefox and WebKit do not scroll to an element in skipped content. - List: an estimated size per --ig-size until the first render. - Chat: a resize observer on the message list keeps the list at the bottom while messages render late. Each scroll of the chat records its position, so a scroll event that merges it with a scroll of the user still stops the follow. - Specs: 8 new. 5 chat template specs read textContent, because innerText of skipped content is empty.
Groundwork for find-in-page in collapsed content. The controller binds hidden="until-found" on the content of a collapsible host and opens the host on beforematch, through its user path with events. The attribute stays the browser's until the next task, because a removal in the microtasks after the event stops the reveal of the outer ancestors in Chromium and WebKit. A refused open sets plain hidden, and live() restores until-found after the reveal. - The component base sheet no longer forces display: none on hidden="until-found". - lit-analyzer treats hidden as a global attribute, because its data still calls hidden boolean.
…page Find-in-page, a text fragment or a link to an element in the content now opens a collapsed expansion panel. The content uses hidden="until-found" through the hidden-until-found controller, and the panel opens through the user path: igcOpening (cancelable) and igcOpened. A disabled panel stays closed, with plain hidden. - The content shows, and is inert, only during the close animation. The open animation removes hidden first, so it measures the content. - While a reveal runs in any host (isRevealing()), panels open and close without their animation. Before, a single-expand accordion that animated a panel closed above the match left the match out of view. - Specs reveal with a real click on a link (clickWithMouse). The 6 lines that asserted inert now assert hidden.
Find-in-page, a text fragment or a link to an element in the children of a collapsed tree item now expands the collapsed items above it. The children container uses hidden="until-found" through the hidden-until-found controller, and each item expands through the user path, from the inside out: igcItemExpanding (cancelable) and igcItemExpanded. A disabled item stays collapsed, with plain hidden. - The children show, and are inert, only during the collapse animation. The expand animation removes hidden first, so it measures them. - Items expand and collapse without their animation while a reveal runs. - singleBranchExpand keeps the items below the revealed item expanded during a reveal. Before, the outer item of the path collapsed the inner one that the browser had just revealed. - WebKit expands the path but does not scroll to a match in a collapsed leaf item that skips its rendering. Documented in the spec. - Specs reveal with a real click on a link. The assertion of inert children now asserts hidden.
Find-in-page, a text fragment or a link to an element in a panel that is not selected now selects its tab. The panels use hidden="until-found" through the hidden-until-found controller, and the tab is selected as a click does, with igcChange, but without moving the focus or following the link of a link tab. The panel of a disabled tab has plain hidden. - A hidden panel takes no height and does not scroll, so it does not cover the selected panel in their shared area. - A hidden tab panel and the children container of a collapsed tree item get aria-hidden. The browser keeps their box for find-in-page, and Chromium exposed them as empty containers. - Specs reveal with a real click on a link. The checks for inert and for display: none on unselected panels now check hidden.
In Safari before 26, which includes iOS 18, find-in-page does not find the text of an item that skips its rendering (content-visibility: auto). The spec files of the tree, the list and the chat, and the CHANGELOG entry of the change, now say so.
The HelpCenter story of the expansion panel keeps the answers of a help page in closed panels. Find-in-page, the links under "Popular answers" and a text fragment open the panel with the match, and a status line shows the igcOpened event. The AdvancedSettings description now says that the content of a closed panel is hidden, not inert.
…oller The hidden-until-found controller now plays the open and close animation of its host. It skips the animation during a reveal, shows the content before an open measures it, and keeps the content visible and inert while a close runs. The expansion panel and the tree item drop their own copies of these steps. The controller uses createTimer and a set of the revealing controllers, the spec helpers reuse getCenterPoint, and long comments are shorter.
A tab panel that is not selected keeps its box for find-in-page. Its zero height, padding and border are now important, so styles of the tab-body part cannot give it a box that covers the selected panel and takes its clicks. With singleBranchExpand, a reveal keeps the expanded items in the item that it expands: the browser does not tell where the match is, and a collapse could hide it. The tree spec documents this and a test keeps it. A tree spec also checks the animations in the item shadow roots.
…-visibility-find-in-page
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Two web platform features applied to the components that hold long or collapsed content:
content-visibility: autoon tree items, list items and chat messages. Items far from the view skip style, layout and paint until they come near it.hidden="until-found"on the collapsed content of the expansion panel (also in the accordion), the tree item and the tab panel. Find-in-page (Ctrl+F), text fragments and links to an element inside now open the container, with the same events as a user toggle.Performance (Chromium, median of 5 runs)
A resize or a change of
--ig-sizecosts 80–90% less. Small trees, lists and chats do not change.Find-in-page
igcOpening/igcOpened,igcItemExpanding/igcItemExpanded, or theigcChangeof the tabs. If a handler cancels the event, the container stays closed.single-expandor treesingleBranchExpand, the other panels or branches also close without animation.hidden, so the browser does not search it.until-foundhide the content as before.Behavior changes and known limits
content-visibility:innerTextof a skipped item is an empty string;textContentworks.position: fixedchildren.content-visibility: visibleonigc-tree-item,igc-list-itemorigc-chat::part(message-item).until-foundneeds Chrome 102, Firefox 139 or Safari 26.2. Firefox before 148 and Safari 26.2 open the container but do not scroll to the match. Safari before 26 does not find text in skipped items.singleBranchExpand: a reveal keeps the expanded items inside the item that it expands. The browser does not tell where the match is, so a collapse could hide it.Type of Change
Checklist
npm run public-api:updateand committedpublic-api.jsonandapi-reference/CHANGELOG.mdentry under[Unreleased]