Skip to content

feat(:segmented_button_group): add count prop per segment (closes unified_ui #187)#140

Draft
ty13r wants to merge 1 commit into
mainfrom
claude/extension-segmented-button-group-count-wave-3-7
Draft

feat(:segmented_button_group): add count prop per segment (closes unified_ui #187)#140
ty13r wants to merge 1 commit into
mainfrom
claude/extension-segmented-button-group-count-wave-3-7

Conversation

@ty13r
Copy link
Copy Markdown
Member

@ty13r ty13r commented May 18, 2026

Wave 3.7 Class C extension: segmented_button_group count badge

Adds count prop per segment to canonical :segmented_button_group. DRAFT for Pascal review per substrate-gap co-maintain convention; standing auto-merge does NOT apply.

Issue reference

unified_ui #187 -- segmented_button_group count badge proposal

Substrate dependency satisfied

PR #115 (SegmentedButtonGroup Stage-4) merged 2026-05-18 via Pascal review. Existing integration plumbing intact (verified during pre-flight audit per the updated widget skill).

Extension scope

  • IUR constructor: count (optional non-negative integer, default nil) on segment options via normalize_options/1; raises ArgumentError for negative or non-integer values
  • Renderer (segmented_button_group_options/2): passes count through from IUR element attributes to the per-option map
  • Stage-4 Phoenix.Component: renders <span class="live-ui-segmented-button-group-option-count" aria-hidden="true">{count}</span> inside the button when count is non-nil; count: 0 renders "0"; count: nil or absent key renders no span
  • Tests: 6 IUR constructor tests (positive: pass-through, zero preservation, nil omission; negative: negative int, non-integer string, float) + 6 Stage-4 widget tests (positive: badge renders, aria-hidden true, zero renders "0"; negative: nil omits badge, absent key omits badge, mixed options coexist)

ARIA design decision

Per Issue #187 open question Q7: badge gets aria-hidden="true". The label text alone provides accessible context for screen readers; the count badge is a visual supplement. If Pascal prefers an explicit aria-label on the span, that is a trivial follow-up.

Zero-count behavior (Issue #187 Q3)

Adopted: show badge with "0" for explicit zero-count (e.g., "Plans (0)"); hide for nil. This matches the unread_badge constructor guard pattern and makes the caller intent explicit.

Pascal-review open questions (from Issue #187)

  1. Badge shape: inline raw number or styled badge with background? Current implementation renders just the number inside the span -- CSS theming determines the visual shape.
  2. Position: implementation is trailing (after label), matching comps.
  3. Zero-count behavior: implemented as show "0" -- confirm or prefer hide.
  4. Large counts: no capping implemented; consumer-side concern for v1. Follow-up if cap needed.
  5. Composition with :unread_badge: implemented inline (smallest delta). Composition with :unread_badge would be a separate refactor if Pascal prefers it.
  6. Loading state: not implemented in v1. Out of scope per issue.
  7. ARIA: implemented as aria-hidden="true" -- confirm or prefer aria-label.

Closest pattern reference

ash_ui PR #132 (tabs count badge) -- companion Class C extension with same count-badge shape. Both pending Pascal review. The current tabs.ex in main does not yet have count (PR #132 is DRAFT), so implementation aligns with Issue #187 own ARIA proposal directly.

Integration footprint audit (per widget skill Validation Checklist)

  • packages/live_ui/lib/live_ui/widgets/segmented_button_group.ex -- extended with count badge rendering
  • packages/live_ui/lib/live_ui/renderer.ex -- segmented_button_group_options/2 passes count through; no structural change to dispatch clause
  • packages/live_ui/lib/live_ui/widgets/form_control_and_composer.ex -- unchanged; existing family aggregation already includes SegmentedButtonGroup
  • packages/live_ui/lib/live_ui/widgets.ex -- unchanged; existing aggregation includes :form_control_and_composer
  • lib/ash_ui/rendering/iur_adapter.ex -- unchanged; :segmented_button_group routing already present (verified grep)
  • lib/ash_ui/rendering/live_ui_adapter.ex -- unchanged; dispatch already present (verified grep)
  • packages/unified_iur/lib/unified_iur/widgets/components.ex -- normalize_options/1 extended to pass through count with validation; IUR registry entry unchanged (kind already registered at line 36)

Test results

  • cd packages/live_ui && mix test -- 582 tests, 0 failures
  • cd packages/live_ui && mix test test/live_ui/widgets/segmented_button_group_test.exs -- 21 tests, 0 failures (+6 new count badge tests)
  • cd packages/unified_iur && mix test test/unified_iur/widgets/components_test.exs -- 12 tests, 0 failures (+6 new IUR count prop tests)
  • Root ash_ui rendering tests -- 163 tests, 0 failures

Generated with Claude Code

…lass C extension)

Adds optional count badge per segment to the canonical :segmented_button_group
widget, addressing comp-fidelity gap EX-6 (segments like "ADRs (12)").

- IUR constructor: count (optional non-negative integer, default nil) on segment
  options via normalize_options/1; raises ArgumentError for negative or
  non-integer values
- Renderer: passes count through segmented_button_group_options/2 helper
- Stage-4 Phoenix.Component: renders <span class="live-ui-segmented-button-group-option-count"
  aria-hidden="true"> inline when count is non-nil; zero renders "0"; nil omits
  the span
- Tests: 6 IUR (positive: count pass-through, zero, nil-omit; negative: negative int,
  non-integer, float) + 6 Stage-4 widget (positive: badge present, aria-hidden,
  zero; negative: nil, absent-key, mixed options)

Closes The-Metagraph/unified_ui#187.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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