Skip to content

feat(pointer,rich_text): a hand that closes on click, and pill spans - #397

Merged
LeadcodeDev merged 2 commits into
mainfrom
feat/pointer-hand-and-pills
Sep 27, 2026
Merged

LeadcodeDev merged 2 commits into
mainfrom
feat/pointer-hand-and-pills

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Closes #381. Closes #382. Refs #388.

#381 — a hand glyph that closes on click

PointerGlyph (arrow default, hand, grab) plus glyph and click_glyph. glyph_path() is one match arm dispatching to three path builders, mirroring how colors() already dispatches fill and outline — the same shape, not a parallel mechanism.

It reuses the existing click signal. active_glyph() consumes click_progress, the same Option that already drives the click ring, so there is no second clock to keep in sync. A path waypoint clicking on arrival closes the hand for exactly as long as it rings.

Both new glyphs put their reference point at local (0, 0) like the arrow's tip, so path and click_at coordinates mean the same thing whichever glyph is chosen. grab is the fist alone, so closing removes exactly the finger's pixels.

Red proof:

before any click the open hand must paint its extended finger (white fill),
got (17, 24, 39, 255)
  left:  (17, 24, 39, 255)
  right: (255, 255, 255, 255)

#382 — pill spans in rich_text

RichTextSpan gains background, padding, border-radius and rotation.

The padding affects layout, which is the part that is easy to get wrong. A post-wrap reflow pass adds padding.left to a pill run's first token and padding.right to its last, cumulatively, so following spans shift over. RichTextIntrinsic calls compute_layout, so the node's measured size agrees with what is painted without a second code path.

Red proof:

a pill's horizontal padding must be added to the line's advance, moving the
following span over by left+right padding:
plain x=66.71875, pill x=66.71875, expected shift 32

Wrapped pills get box-decoration-break: clone — grouping is per rendered line, not per source span, so a pill that wraps gets its own padded box per fragment instead of one box straddling two lines. The issue asked for it literally and there is a dedicated test.

Rotation turns the box and its glyphs together about the pill's own centre, inside a saved canvas state — layout is never touched, which its test asserts alongside the pixel check.

Verification

Eight new tests (four per issue), each proven red by reverting the fix. cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings, cargo test --workspace (1640) all clean. Comment count still 0.

Three things to know

  • click_glyph without glyph: "hand" is legal but inert — nothing ever shows a resting grab. Documented rather than rejected.
  • A pill's wrap decision is made on unpadded text width, so a pill sitting right at the boundary can overflow slightly instead of wrapping a word earlier. Documented as a known approximation.
  • box_builder.rs was touched outside the stated ownership: its two hand-written RichTextSpan literals are the only other exhaustive construction sites in the tree, and adding four fields broke them. Four Nones, no logic. Flagged rather than buried.

Written comment-free, per the codebase-wide rule from #345.

…in rich_text

#381 — pointer gains glyph/click_glyph (arrow default, hand, grab). The
hotspot stays the tip/fingertip in local (0,0) regardless of glyph, so
switching shape never moves the point a waypoint aims at. click_glyph reuses
the existing click_progress window instead of a second clock: it only shows
during click_duration, then reverts to glyph. Extends colors()'s one-match-arm
shape rather than adding a parallel dispatch mechanism.

#382 — rich_text spans gain background/padding/border-radius/rotation to
paint a pill behind their own glyph run. Horizontal padding is folded into
compute_layout's line-advance so RichTextIntrinsic (which just calls
compute_layout) sizes correctly for free; vertical padding only grows the
box, never line-height. Grouping is done per rendered line, so a pill that
wraps gets its own padded box per line fragment (box-decoration-break:
clone), not one box stretched across two lines. Rotation is paint-only,
applied around the box's own centre, and never touches layout.

box_builder.rs's two RichTextSpan test literals were extended with the four
new fields — the only other construction site in the tree, needed to keep
`cargo test --workspace` green.
@LeadcodeDev LeadcodeDev added the enhancement New feature or request label Sep 27, 2026
@LeadcodeDev LeadcodeDev self-assigned this Sep 27, 2026
@LeadcodeDev
LeadcodeDev merged commit 00ea2e3 into main Sep 27, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rich_text: pill spans with their own background, padding, radius and rotation pointer: a hand glyph that closes on click

1 participant