Skip to content

Plumb isSelectable into ApplyItemContentInfo#623

Merged
RoyalPineapple merged 2 commits into
mainfrom
RoyalPineapple/plumb-isselectable-info
Jun 16, 2026
Merged

Plumb isSelectable into ApplyItemContentInfo#623
RoyalPineapple merged 2 commits into
mainfrom
RoyalPineapple/plumb-isselectable-info

Conversation

@RoyalPineapple

@RoyalPineapple RoyalPineapple commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Why

A ListableUI item's selection behavior lives in its wrapper — Item.selectionStyle drives the tap handling, highlight, and selection state at the list level. The contained ItemContent view that actually renders on screen has no way to know that its surrounding cell is interactive.

That's a problem for accessibility: when a row is tappable, the content view often needs to represent that itself (for example by applying the .button accessibility trait so VoiceOver announces the row as actionable). Without this signal, the content view is blind to the interaction happening in its wrapper and can't reflect it.

What

Adds an isSelectable flag to ApplyItemContentInfo, so a content view is told — at apply(to:for:with:) time — whether the item it lives in is interactive.

It's populated in PresentationState.ItemState.applyTo from selectionStyle.isSelectable:

  • true for .tappable, .selectable, and .toggles
  • false for .notSelectable

Live selection/highlight state is already available via info.state; this fills the remaining gap of "is this row interactive at all." No trait is forced at the ListableUI/Blueprint level — what to do with the signal stays each content view's call.

TBHFUZZ-165

Checklist

Please do the following before merging:

  • Ensure any public-facing changes are reflected in the changelog. Include them in the Main section.

This issue was discovered via agentic fuzz testing using The Button Heist.

🤖 Generated with Claude Code

Add an `isSelectable` property to `ApplyItemContentInfo`, populated from
the item's `selectionStyle.isSelectable`. This lets content views know
when an item is interactive (`.tappable`, `.selectable`, `.toggles`) so
they can represent themselves accordingly, e.g. by applying the `.button`
accessibility trait for VoiceOver.

TBHFUZZ-165

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@RoyalPineapple RoyalPineapple force-pushed the RoyalPineapple/plumb-isselectable-info branch from 4b2dc6e to c2f8aef Compare June 4, 2026 15:27
Drops the `= false` default on the new public `isSelectable` property so it
matches the sibling `isReorderable` (no default) and makes any future internal
construction site that omits it a compile-time error rather than a silent
wrong default.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@RoyalPineapple RoyalPineapple marked this pull request as ready for review June 4, 2026 15:54
@RoyalPineapple RoyalPineapple merged commit 049cca4 into main Jun 16, 2026
10 checks passed
@RoyalPineapple RoyalPineapple deleted the RoyalPineapple/plumb-isselectable-info branch June 16, 2026 13:49
RoyalPineapple added a commit that referenced this pull request Jun 22, 2026
Regenerates the Listable and BlueprintUILists docs to document the
`isSelectable` property added to `ApplyItemContentInfo` in #623, which
was missed when that change merged. The only meaningful change is the
new `isSelectable` entry on `ApplyItemContentInfo.html` (plus the search
index / docset mirrors).

Docs were generated with Jazzy 0.15.3 under Ruby 3.3.9 — matching the
17.2.0 docs build — because `Scripts/generate_docs.sh` hangs in
sourcekitten under the repo-pinned Ruby 3.2.2 on this macOS runtime.

### Checklist

Please do the following before merging:

- [x] Ensure any public-facing changes are reflected in the
[changelog](https://github.com/square/Listable/blob/main/CHANGELOG.md).
Include them in the `Main` section. _(The `isSelectable` changelog entry
landed with #623; this PR is docs-only.)_

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
RoyalPineapple added a commit that referenced this pull request Jun 22, 2026
Cuts the 17.3.0 release for the `isSelectable` change in #623. Bumps
`LISTABLE_VERSION` to `17.3.0` and moves the `isSelectable` entry from
the `Main` section of the changelog into a dated `17.3.0` section.

### Release notes

#### Added

- Added `isSelectable` to `ApplyItemContentInfo`, reflecting whether the
item's `selectionStyle` is interactive (`.tappable`, `.selectable`, or
`.toggles`). `ItemContent` implementations can read this to represent
themselves as interactive, for example by applying the `.button`
accessibility trait so VoiceOver users know the item responds to taps.

### Notes

- Docs were **not** regenerated in this PR: `Scripts/generate_docs.sh`
hangs during sourcekitten parsing under the local Ruby 3.2.2 toolchain
(the same environment issue noted in the 17.2.0 bump, #622). Docs can be
regenerated in a follow-up under Ruby 3.3.x.

### Checklist

Please do the following before merging:

- [x] Ensure any public-facing changes are reflected in the
[changelog](https://github.com/square/Listable/blob/main/CHANGELOG.md).
Include them in the `Main` section.
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.

2 participants