Skip to content

DS::Pill: reconsider show_dot: true default in badge mode (marker: false) #2001

@gariasf

Description

@gariasf

Problem

DS::Pill defaults show_dot: true for both modes (marker: true stage-markers and marker: false status/category badges). In badge mode this default produces a colored dot before every label by default — and the codebase evidence suggests this default is miscalibrated.

Evidence — authors are actively fighting the default

Survey of marker: false callsites in app/views/:

Callsite show_dot:
app/views/accounts/_tax_treatment_badge.html.erb:11 explicit false
app/views/import/qif_category_selections/show.html.erb:86 explicit false
app/views/investment_activity/_badge.html.erb:14 explicit false
app/views/settings/providers/_maturity_badge.html.erb:3 explicit false
app/views/shared/_badge.html.erb:16 explicit false
app/views/sophtron_items/_sophtron_item.html.erb:27 explicit false
app/views/transactions/_transfer_match.html.erb:10,18 explicit false (×2)
app/views/reports/_investment_performance.html.erb:121 default true
app/views/settings/providers/_status_pill.html.erb:10 default true
app/views/transactions/_header.html.erb:25 default true
app/views/transactions/_split_parent_row.html.erb:39 default true
app/views/transactions/_transaction.html.erb:101,133 default true (×2)

7+ explicit show_dot: false overrides vs. ~6 callsites that kept the default. When more than half the badge-mode usage opts out of the default, the default is wrong.

UX reasoning

A status/category badge already carries semantic signal via:

  1. Pill shape (rounded-full, distinct from buttons / inline text)
  2. Tone color (:success, :warning, :error, :neutral, :info)
  3. Label text itself ("Active", "Pending", "Member")

Adding a dot on top of all three is redundant in most contexts, and noisy in dense ones.

Where the dot earns its space (legitimately additive)

  • Sparse contexts — single status pill in a card header, a sidebar entry
  • States with temporal or live semantics — "Syncing", "Active session", "Live" — dot reads as an indicator light
  • When the pill sits next to non-pill text and the dot helps anchor it as a discrete UI element

Where the dot hurts

  • Dense lists / tables — every row gets a dot → repeated visual rhythm, fights with row scanning. Example: app/views/admin/users/index.html.erb family list (PR fix: replace hand-rolled badges with DS::Pill in admin users view #1988 introduces 5 dots in a vertical stack of role descriptions)
  • Self-describing labels — "Member", "Guest", "Admin" — the dot adds zero information beyond what the label and tone already convey
  • Multiple pills in a row (category tags, tag clouds) — dots cluster together and compete with the labels
  • Short labels (3–5 chars) — the dot visually dominates the pill

Industry precedent

Stripe, Linear, GitHub, Notion all make the dot opt-in for status badges, not default. They reserve the dot specifically for:

  • Live state indicators (with animation: pulsing, blinking)
  • Real-time presence ("online", "available")
  • Temporal signals that the user is meant to monitor, not just read

None of them dot every taxonomy badge by default.

Concrete impact in current PRs

In both PRs the dot was almost certainly not a deliberate visual choice — it's the default winning by inertia.

Proposal

Flip the badge-mode default:

# app/components/DS/pill.rb
def initialize(label: nil, tone: :violet, style: :soft, size: :sm,
               show_dot: nil,    # was: true
               dot_only: false, title: nil, icon: nil, marker: true)
  # …
  # Default per mode:
  #   marker: true  → show_dot defaults to true  (stage markers keep their dot)
  #   marker: false → show_dot defaults to false (badges/tags clean by default)
  @show_dot = show_dot.nil? ? marker : show_dot
end

Migration impact (badge-mode callsites that relied on the default true and would lose the dot):

  • app/views/reports/_investment_performance.html.erb:121
  • app/views/settings/providers/_status_pill.html.erb:10probably wants show_dot: true kept — this is the genuine "status" case
  • app/views/transactions/_header.html.erb:25
  • app/views/transactions/_split_parent_row.html.erb:39
  • app/views/transactions/_transaction.html.erb:101,133

Each callsite would need a one-line review: keep the dot (add explicit show_dot: true because it's genuine status) or drop it (no change needed, new default).

The 7 explicit show_dot: false overrides become redundant noise and can be cleaned up.

PillComponentPreview#status_pending, status_failed, etc. would need updating since they rely on the default.

Alternative if the default change is too disruptive

Document the convention in the DS::Pill docstring more loudly:

Default show_dot: true is for live/temporal status pills only. For taxonomy badges, category tags, or any label whose tone+text already conveys the meaning, pass show_dot: false. The DS team is reconsidering the default — see #XXXX.

…and update the existing PillComponentPreview to make the dot-less variants more prominent so PR authors see them first.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions