Skip to content

feat(data-table): lay one element across a whole row - #53

Merged
kirillDevPro merged 1 commit into
masterfrom
feat/data-table-row-banner
Aug 25, 2026
Merged

feat(data-table): lay one element across a whole row#53
kirillDevPro merged 1 commit into
masterfrom
feat/data-table-row-banner

Conversation

@kirillDevPro

Copy link
Copy Markdown
Collaborator

What & why

Every MoonDataTable cell is overflow_hidden — that is what keeps a long value out of its
neighbour's column. It also means a row that wants to say ONE thing across its full width cannot
say it through a cell: a section heading placed in the leftmost column is cut at that column's
edge no matter how much empty room the rest of the row has. Fixing it from the caller's side is
not possible either, because the final render widths are resolved inside the table from a
measured viewport (auto_width_columns), so any offset computed outside is wrong exactly on a
narrow panel.

MoonTableRow::banner / MoonDataRow::banner take one element and paint it across the row,
after the cells and outside their clipping.

Two design points worth reviewing:

  • The banner does not occlude. GPUI stops hit-testing only at a HitboxBehavior::BlockMouse
    hitbox, set solely by occlude(), and this wrapper calls neither — so a cell underneath stays
    clickable. The consequence to design around is the opposite of occlusion: a handler on the
    banner and one on a cell beneath it both fire for a single click. Documented on the builder.
  • has_banner is a pub(crate) predicate, not an exposed field. The forward crosses a module
    boundary and nothing below it is observable without a rendering harness, so the conversion would
    otherwise be untestable; a public field would let any module in the crate move the element out
    of a row it does not own. It carries #[cfg_attr(not(test), allow(dead_code))] — conditional, so
    a real orphaning still warns.

How to verify

cargo test -p moon-ui-components          # 431 passed, 0 failed
cargo run -q -p xtask -- component-api --check-baseline   # PASS
powershell -ExecutionPolicy Bypass -File tools\run-component-guardrails.ps1   # PASS

data_row_conversion_preserves_banner_presence is mutation-proven: deleting the forward in
as_table_row reddens it, and it asserts both directions so a mutation that hard-codes true
cannot pass. The baseline refresh adds exactly the two new banner() signatures.

Every table cell is `overflow_hidden`, which is what keeps a long value out
of its neighbour's column. It also means a row that wants to say ONE thing
across its full width cannot say it through a cell: a section heading put in
the leftmost column is cut at that column's edge however much empty room the
rest of the row has, and the final render widths are resolved inside the
table from a measured viewport, so no caller-side offset can fix it either.

`MoonTableRow::banner` / `MoonDataRow::banner` take one element and paint it
across the row, after the cells and outside their clipping.

Painting last decides what the eye sees, never what the mouse reaches: the
wrapper is deliberately not occluded, so a cell underneath stays clickable.
The consequence to design around is the opposite of occlusion - a handler on
the banner and one on a cell beneath it both fire for a single click, and a
caller that wants the banner to win says so itself.

`has_banner` is a crate-internal predicate rather than an exposed field: the
forward crosses a module boundary and nothing below it is observable without
a rendering harness, so the conversion would otherwise be untestable, while
a public field would let any module move the element out of a row it does
not own.
@kirillDevPro
kirillDevPro merged commit 46f74e2 into master Aug 25, 2026
2 checks passed
@kirillDevPro
kirillDevPro deleted the feat/data-table-row-banner branch August 25, 2026 10:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant