Scope the Type List header checkbox to the displayed rows - #1871
Merged
Conversation
The header bulk toggle read `actionableTypes`, which honored Show Empty and the search box but not Filter Types by Frame. It also reached hierarchy types hidden under collapsed branches or folded into the shared-lineage breadcrumb. A user could see a few rows, check the header, and act on types the list did not show, including through the delete button. Build the final row model and intersect it with the filtered candidates. This excludes frame-filtered types, context-only ancestors, breadcrumbed ancestors, and collapsed descendants. A parent row's checkbox is unchanged and still owns its complete subtree. An empty list also reported the header as checked, because a difference against nothing is empty. Ordering the two state checks the other way round reports unchecked instead, and the control is disabled. Filter Types by Frame had no key in the default settings, so on a profile that never stored one the switch wrote a non-reactive property and the list did not respond until reload. Give it a default. The Type List builds its model the same way with and without a hierarchy, so this changes flat datasets too.
The candidate set admitted every type with a child, so a branch whose whole subtree is unannotated took a row while Show Empty was off. Its own leaves stayed hidden, leaving a parent that led nowhere and, once the header cleared the visible rows, rendered indeterminate against a descendant the list never showed. Build the set from the ancestors of used types instead. Paths back to each root survive because an ancestor of a used type is one of them; branches with nothing annotated do not. A parent's tri-state still rolls up its complete subtree, so an ancestor of a used type can still read indeterminate against a hidden checked descendant. That is the row's documented meaning and is left alone.
An empty list looked the same whether the dataset defined no types or the filters excluded every one it does define, leaving nothing to act on and no account of why. Name the two cases apart, and use the list's own noun so the group panel reads correctly.
The button read every checked type, so it deleted annotations of types the list was not showing: a type hidden by Show Empty, a frame filter, a search, a collapsed branch, or the shared-lineage breadcrumb was still deleted, and the button stayed enabled when the only checked types were hidden ones. Read the same rows the header acts on. The confirmation lists exactly what will be deleted, and an empty intersection disables the button.
The empty-state text re-derived "does this dataset define anything" from the raw type sources, which is the union the model already builds, and read it off the per-frame row projection rather than the row model itself. Report it from the model and read the rows. The candidate set walked ancestors by hand next to the helper that does it, and the delete set hand-rolled an ordered intersection beside a sibling that uses lodash for the same pair of lists. The empty text says "types" in both panels, matching the heading the panel already shows.
The Type List header checkbox and the delete button both act on "checked and displayed". That rule was expressed three ways in the component: an intersection for delete, a difference for the header tri-state, and the model's own row/actionable intersection. buildTypeListModel now returns actionableCheckedTypes alongside actionableTypes, and the component reads both.
Both branches of the header toggle rebuilt the same "checked but not displayed" difference; hoist it to one computed and let the toggle read as the union or the remainder.
Scoping the header and the delete button to displayed rows dropped the descendants a collapsed row hides, even though that row's own checkbox owns them. Delete matches a track's displayed type and does not cascade, so deleting a collapsed parent removed nothing while still prompting; the header likewise checked the parent alone and left its row showing the mixed state it had just resolved. actionableTypes now expands a collapsed row to its subtree and an expanded row to itself, then keeps only what the filters allowed, so a frame-filtered or searched-out type is still left alone either way.
The header acts on every candidate the filters allowed, minus the ancestors a breadcrumb hides. Deriving that from the row list instead restated the same set in terms of what flatten happened to emit, which is why a collapsed row's branch had to be added back by hand.
PaulHax
marked this pull request as ready for review
August 29, 2026 17:08
BryonLewis
approved these changes
Aug 29, 2026
BryonLewis
left a comment
Collaborator
There was a problem hiding this comment.
Just pulled and tested, made a small PR to align with the other vitest PR about the jsdom #1872. Thanks for doing this.
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.
Scope the Type List header checkbox to the displayed rows
Follow-up to Bryon's #1867 review.
With Filter Types by Frame on, the list showed only the current frame's types but the header
checkbox still toggled hidden types. Those selections also feed the delete button.
Changes
collapsed branches, and Compact Parents.
types the list was not showing, and stayed enabled when the only checked types were hidden.
see."
empty because nothing is defined or because the filters excluded everything.
profiles.
every type with a child, so an unannotated branch held a row whose own leaves stayed hidden.
Frame-filtered rows disappear when unchecked; turning the frame filter off brings them back. This
matches existing per-row behavior.
A parent's tri-state still rolls up its complete subtree, so an ancestor of a used type can read
indeterminate against a hidden checked descendant. That is the row's documented meaning.