A dropdown can match its field's width and close on an outside click (RFC-0036) - #242
Open
Briany4717 wants to merge 1 commit into
Open
A dropdown can match its field's width and close on an outside click (RFC-0036)#242Briany4717 wants to merge 1 commit into
Briany4717 wants to merge 1 commit into
Conversation
…k away (RFC-0036) The two tails RFC-0036 left off. Both read the anchor's resolved rect, which is why they arrive together and why they share a diagnostic. `width: match(searchField)` sizes a panel to its anchor. Not by widening the finished rect, which is the obvious extension of how placement works and is wrong: the panel's own children were laid out against the width it had, so its rows would sit in a box they no longer fill. The anchor's width is written onto the panel's node once the main tree has painted, and layout runs again. That is not the layout cycle the RFC worried about. The dependency runs one way, the overlay cannot influence its anchor, and no amount of iterating would change either answer. What it *is* is a cost, so the second pass is skipped whenever the width has not moved, which is every steady frame; `set_style` marks a node dirty in Taffy whether or not the value changed, so re-applying it unconditionally would have turned the retained path back into a full one for any screen with a dropdown open. The test states that as a difference against the same screen with a fixed width rather than as an absolute count, because a frame already runs one retained pass of its own and that number is nobody's invariant. `dismiss =>` on an anchored child is an observer, not a scrim. The modal dismissal that already exists is the wrong mechanism here: its scrim covers the viewport, raises the router's modal floor and swallows every event beneath it. An autocomplete that froze the page under it would be a worse bug than the one it solves. So this blocks nothing, fires on a press outside both the panel and its anchor, and answers to Escape. Keeping the anchor's rect is the half that is easy to leave out, and its absence looks like a rendering glitch rather than a logic error: the press that opens a dropdown would also be the press that closes it. There is a test for it, and one for the page underneath still receiving its events, which is what fails if somebody reaches for the scrim after all. Both were watched failing: the width tests with each half of the mechanism removed in turn, the dismiss tests with the anchor rect dropped and then with a scrim substituted. Either tail on an element that anchors to nothing is a diagnostic. There is no rect to read, so the property would quietly do nothing, and a `width:` that quietly does nothing reads as a bug in the panel.
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.
Stacked on #241. This diff is the top commit only.
The two tails RFC-0036 left off. Both read the anchor's resolved rect, which is why they arrive together and why they share a diagnostic.
width: match(ref)Sizes a panel to its anchor. Not by widening the finished rect, which is the obvious extension of how placement already works and is wrong: the panel's own children were laid out against the width it had, so its rows would sit in a box they no longer fill. There is a test for exactly that, and it is the one that fails against the cheap version.
Instead the anchor's width is written onto the panel's node once the main tree has painted, and layout runs again. That is not the layout cycle the RFC worried about: the dependency runs one way and the overlay cannot influence its anchor, so no amount of iterating would change either answer.
What it is is a cost. The second pass is skipped whenever the width has not moved, which is every steady frame —
set_stylemarks a node dirty in Taffy whether or not the value changed, so re-applying it unconditionally would turn the retained path back into a full one for any screen with a dropdown open. The test states this as a difference against the same screen with a fixed width rather than as an absolute count, because a frame already runs one retained pass of its own and that number is nobody's invariant.on dismissAn observer, not a scrim. The modal dismissal that already exists is the wrong mechanism here: its scrim covers the viewport, raises the router's modal floor, and swallows every event beneath it. An autocomplete that froze the page under it would be a worse bug than the one it solves. So this blocks nothing, fires on a press outside both the panel and its anchor, and answers to
Escape.Keeping the anchor's rect is the half that is easy to leave out, and its absence looks like a rendering glitch rather than a logic error: the press that opens a dropdown would also be the press that closes it. There is a test for it, and one asserting the page underneath still receives its events, which is what fails if somebody reaches for the scrim after all.
Watched failing
The width tests with each half of the mechanism removed in turn; the dismiss tests with the anchor rect dropped, and then with a scrim substituted (three of the six go red).
Diagnostics
Either tail on an element that anchors to nothing is a compile error, and a
matchnaming an untagged element gets the same nearest-name hintanchor_togets. There is no rect to read, so the property would quietly do nothing.Example
crates/byard-cli/examples/anchored_overlay— two fields of different widths, onePanelview, two panels that come out different widths, with a full-width row inside each so "the panel is the right size" and "its contents are" are visibly separate claims. Rendered and eyeballed.Gates
cargo fmt --all --check,cargo clippy --locked --workspace --all-targets -- -D warnings,cargo test --locked --workspace(97 suites, 0 failures),cargo run -p byard-cli -- check crates/byard-cli/examples/anchored_overlay.