Files
sure/test/components/previews/pill_component_preview.rb
Guillem Arias Fauste d88d6e9e58 fix(ds): canonical transaction-row — stop category pills truncating (#2147)
* fix(ds): canonical transaction-row — stop category pills truncating (#2137)

The desktop transaction grid gave the name column col-span-8 (67%, usually
half-empty) and the category column only col-span-2 (17%), so the category
pill's name area was clamped to ~44px and ellipsized nearly every value
("Misc...", "Shop...", "Rest...") despite the empty space the audit flagged.

- Rebalance the lg:grid-cols-12 row: name col-span-8 -> 7, category 2 -> 3
  (amount unchanged; still 12). Category gains 50% width from the over-wide
  name column.
- categories/_badge: the pill was `flex w-full` (stretched to fill the column);
  make it `inline-flex max-w-full` so it hugs its content and short names render
  fully, capping + truncating only when genuinely too long.

Verified on /transactions: visible-row category truncation dropped 7/7 -> 2/7
even in the compressed (AI-panel-open) view; Payment / Shopping / Restaurants
now render in full. Fixes both the interactive categories/menu and the static
transfer categories/badge (menu reuses the badge partial).

* feat(ds): lift categories/_badge onto DS::Pill

Addresses the Drift Patrol finding (and jjmata's request) properly
instead of patching the bespoke span: the badge becomes a DS::Pill in
badge mode. The pill primitive grows the three capabilities the badge
needed and the bot's one-liner glossed over:

- truncate: pills that may shrink inside min-w-0 columns drop their
  shrink-0/whitespace-nowrap and ellipsize the label instead of
  overflowing (the transaction-row category cell this PR fixes).
- label_testid: stamps data-testid on the label span; five test files
  target [data-testid='category-name'].
- icon_size: passthrough to the icon helper (badge keeps its
  established sm glyph; default stays xs).

custom_color was already the sanctioned escape hatch for user-chosen
hues. Owned visual deltas from pill standardization: px-1.5/py-1 ->
px-2/py-0.5, gap-1 -> gap-1.5, border mix 10% -> 20%; bg mix, hex text,
radius, text scale, icon size, truncation and testid are parity.

Label wrapper only renders when truncate/label_testid ask for it, so
existing pill DOM (and the find("span", text:) assertions on it) is
unchanged. Four new pill tests + a Lookbook case cover the recipe.
2026-06-06 16:28:22 +02:00

88 lines
2.6 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)
# Badge mode is dot-less by default — tone + label carry the signal. Opt the
# dot back in with show_dot: true only where it's genuinely additive (live /
# temporal status, or a single sparse pill). status_active below shows the
# opt-in; status_pending / status_archived show the clean default.
def status_active
render DS::Pill.new(label: "Active", tone: :success, marker: false, show_dot: true)
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
# The categories/_badge recipe: user-chosen hex via custom_color, icon at
# "sm", and truncate so the label ellipsizes inside a tight min-w-0 column.
# @display container_classes max-w-[140px]
def category_badge_truncating
render DS::Pill.new(
label: "Subscriptions & Memberships",
custom_color: "#7c3aed",
icon: "credit-card",
icon_size: "sm",
marker: false,
size: :md,
truncate: true
)
end
end