Skip to content

Extension: :segmented_button_group count badge per segment #187

Description

@ty13r

Context

Audited under ariston-ui Wave AshUI-3.7 comp-fidelity audit. The :segmented_button_group canonical widget is missing a count prop per segment — comps show count badges like "ADRs (12)".

Canonical-kind grep proof:

  • Catalog: packages/unified-ui/lib/unified_ui/widget_components.ex:85 — kind: :segmented_button_group, family: :form_control_and_composer
  • Renderer (live_ui): packages/live_ui/lib/live_ui/renderer.ex def render(%{element: %Element{kind: :segmented_button_group}}) — confirm current option shape
  • Note: this widget recently got a Phoenix.Component module via ash_ui PR Implement desktop_ui phase 9 build, packaging, and compliance #115 (DRAFT, Pascal-review pending)

Comp gap (audit finding EX-6, extension table line 241)

Comps for Explorer filter bar show segments like "ADRs (12)", "Specs (8)", "Plans (3)" — segment label + count badge. The canonical widget currently accepts {value, label} per option.

Proposed extension

Adding optional count attr per option:

options: [
  %{
    value: term(),
    label: String.t(),
    count: integer() | nil   # NEW; default nil; when set, renders count badge after label
  }
]

Default value rationale

  • count: nil = no badge rendered (default behavior preserved)

Open questions for Pascal

  1. Badge shape: inline "(N)" parenthetical, or styled badge (rounded background, separate from label)? Comp suggests styled badge.
  2. Position: trailing (after label) or leading? Comp shows trailing.
  3. Zero-count behavior: hide badge entirely, render "0", render "—"? Comp examples don't clarify. Proposal: show badge with "0" for explicit zero-count categories; hide for nil.
  4. Large counts: cap at "99+"? Spec-it explicitly or leave it consumer-side?
  5. Composition with :unread_badge: should we compose with the existing :unread_badge canonical widget (cleanest), or render inline (smallest delta)? :unread_badge already has threshold-capping logic.
  6. Loading state: when count is being computed (e.g., async filter), should there be a :loading placeholder? Out of scope for v1?
  7. ARIA: badge gets aria-label="{count} {label}" for screen readers? Or aria-hidden="true" since the label includes the count? Per WCAG, redundant text isn't a problem.

ARIA implications

  • Badge: <span class="live-ui-segmented-button-group-option-count" aria-hidden="true">{count}</span> (label includes accessible context)
  • Alternatively: <span class="...-count" aria-label="{count} items">{count}</span> if standalone semantic

Cross-references

  • Comp-audit: ariston-ui docs/wave-ashui-3-7-comp-fidelity-audit.md extension table line 241
  • Audit finding EX-6
  • Phoenix.Component module: ash_ui PR Implement desktop_ui phase 9 build, packaging, and compliance #115 (DRAFT) — for extension implementation reference
  • :unread_badge precedent: packages/unified-ui/lib/unified_ui/widget_components.ex:204 (composition consideration per Q5)
  • Wave 3.7-A retrospective: ariston-ui docs/wave-ashui-3-7-a-retrospective.md

Status

DRAFT extension proposal — Pascal's design call on composition with :unread_badge (per Q5) determines the implementation shape. Small extension if inline; composition refactor if :unread_badge reuse.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions