mirror of
https://github.com/we-promise/sure.git
synced 2026-05-25 21:44:56 +00:00
* feat(design-system): extend DS::Pill with badge mode + semantic tones (#1751) Adds two extensions to the existing `DS::Pill` (originally landed as a stage marker primitive in #1829) so it can also serve as the shared status / category badge across the app — the use case tracked by #1751. **Badge mode (`marker: false`)** The original `DS::Pill` was intentionally sub-12px (text-[10px] / text-[11px]) + uppercase + tracking-wide so it reads as a marker (`Beta`, `Canary`, `NEW`), not a label. That shape is wrong for status badges where the surrounding context is regular UI copy and the pill needs to feel like a chip (`Pending`, `Active`, `Past due`, `Failed`). The new `marker: false` flag drops the uppercase + arbitrary sub-12px text and snaps the chrome to the DS text scale: - `marker: false, size: :sm` → `text-xs` (12px), normal case - `marker: false, size: :md` → `text-sm` (14px), normal case - `marker: true` (default) → existing #1829 behavior, unchanged **Semantic tone aliases** Status badges read more naturally with semantic tone names than with the underlying palette colors: | Alias | Resolves to | |---|---| | `:success` | `:green` | | `:warning` | `:amber` | | `:error` / `:destructive` | `:red` (new tone, added here) | | `:info` | `:indigo` | | `:neutral` | `:gray` | Visual-name tones (`:violet`, `:indigo`, `:fuchsia`, `:amber`, `:green`, `:gray`, `:red`) still work as before — semantic aliases resolve through `SEMANTIC_TONE_ALIASES` at component init time, so the callsite can pick whichever name reads better. Unknown tones still fall back to `:violet` (existing behavior). **Red palette** Adds the `:red` tone (palette already present in `design/tokens/sure.tokens.json` — `red-50/100/200/500/700/tint-10`). Needed for `:error` / `:destructive` status badges. **Icon slot** Adds an `icon:` option (already documented in the component's doc-comment as planned). When set, the Lucide glyph replaces the colored dot inside the pill — useful for status badges that read better with a glyph (`circle-check`, `triangle-alert`, `loader`, etc.) than the generic dot. **Scope** API + tests + Lookbook preview only. No callsite migrations in this PR — that's the next slice of #1751, done as separate per-bucket PRs (transaction badges, provider badges, misc) to keep diffs small. DS::Pill currently has no in-app callsites (#1829 shipped the primitive ahead of consumers), so this is a pure-additive change. Existing API is fully backwards-compatible — `marker:` defaults to `true`, so without that flag the pill renders exactly as it does today. * fix(test): use assert_no_selector for dot-suppression assertion `refute_selector ..., count: 1` only fails when there are exactly 1 matches — it would silently pass for 0 OR 2+. The intent is "no dots should render when an icon is set"; `assert_no_selector` strictly asserts zero matches. Flagged by coderabbit on #1902.
69 lines
1.9 KiB
Ruby
69 lines
1.9 KiB
Ruby
class PillComponentPreview < ViewComponent::Preview
|
|
# @param tone select ["violet", "indigo", "fuchsia", "amber", "green", "gray", "red", "success", "warning", "error", "info", "neutral"]
|
|
# @param style select ["soft", "filled", "outline"]
|
|
# @param size select ["sm", "md"]
|
|
# @param label text
|
|
# @param show_dot toggle
|
|
# @param dot_only toggle
|
|
# @param marker toggle
|
|
# @param icon text
|
|
def default(tone: "violet", style: "soft", size: "sm", label: "Preview", show_dot: true, dot_only: false, marker: true, icon: nil)
|
|
render DS::Pill.new(
|
|
label: label,
|
|
tone: tone.to_sym,
|
|
style: style.to_sym,
|
|
size: size.to_sym,
|
|
show_dot: show_dot,
|
|
dot_only: dot_only,
|
|
marker: marker,
|
|
icon: icon.presence
|
|
)
|
|
end
|
|
|
|
# @!group Stage markers (marker: true — original #1829 shape)
|
|
def canary
|
|
render DS::Pill.new(label: "Canary", tone: :fuchsia)
|
|
end
|
|
|
|
def beta
|
|
render DS::Pill.new(label: "Beta", tone: :violet)
|
|
end
|
|
|
|
def new_marker
|
|
render DS::Pill.new(label: "New", tone: :indigo)
|
|
end
|
|
|
|
def dot_only_collapsed_sidebar
|
|
render DS::Pill.new(dot_only: true, tone: :violet)
|
|
end
|
|
# @!endgroup
|
|
|
|
# @!group Status badges (marker: false, semantic tones)
|
|
def status_active
|
|
render DS::Pill.new(label: "Active", tone: :success, marker: false)
|
|
end
|
|
|
|
def status_pending
|
|
render DS::Pill.new(label: "Pending", tone: :warning, marker: false)
|
|
end
|
|
|
|
def status_failed
|
|
render DS::Pill.new(label: "Failed", tone: :error, marker: false, icon: "circle-alert")
|
|
end
|
|
|
|
def status_archived
|
|
render DS::Pill.new(label: "Archived", tone: :neutral, marker: false)
|
|
end
|
|
|
|
def status_info
|
|
render DS::Pill.new(label: "Syncing", tone: :info, marker: false, icon: "loader")
|
|
end
|
|
# @!endgroup
|
|
|
|
# @!group Sizes (md)
|
|
def status_md
|
|
render DS::Pill.new(label: "Past due", tone: :error, marker: false, size: :md)
|
|
end
|
|
# @!endgroup
|
|
end
|