From 7a0665a8f6c5f8cd9959ffc6f8a5e92add4af5e8 Mon Sep 17 00:00:00 2001 From: Guillem Arias Fauste Date: Sat, 6 Jun 2026 17:00:54 +0200 Subject: [PATCH] fix(ds): one height rail for icon and text buttons (#2202) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(ds): put icon buttons on the text-button height rail Icon-only DS::Button containers were 32/44/48px squares while text buttons of the same nominal size render ~28/36/48px tall, so every mixed header row (icon menu trigger next to text buttons — the transactions index, account pages, the app header) sat misaligned. - buttonish SIZES: icon containers now share the text rail (sm w-7, md w-9, lg w-12 unchanged). - DS::Popover's hand-rolled w-11 trigger joins the rail at w-9. - The layout's hand-rolled privacy toggle (mobile + desktop) matches the md icon-button chrome: w-9, rounded-lg, container-inset hover — it sat at w-8 with a different hover next to a DS icon button. - DS::Select's panel adopts shadow-border-lg, the elevation Menu and Popover already use, replacing the weaker shadow-lg+border-xs combo. Measured on the transactions header after the change: 36/38/36px. * fix(ds): keep the 44px touch target on coarse pointers The height rail trades icon-button size for row alignment, which is a pointer-precision tradeoff: WCAG 2.5.5's 44x44 minimum is about fingers, not mice. sm/md icon containers (and the two off-rail consumers: the popover trigger and the layout privacy toggles) gain pointer-coarse:w-11/h-11, so touch devices keep the full target while fine-pointer layouts get the aligned 36px row. Measured via Playwright: desktop 36x36, iPhone emulation 44x44 on both the menu trigger and the privacy toggle. --- app/components/DS/buttonish.rb | 13 +++++++++++-- app/components/DS/popover.html.erb | 2 +- app/components/DS/select.html.erb | 2 +- app/views/layouts/application.html.erb | 4 ++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/app/components/DS/buttonish.rb b/app/components/DS/buttonish.rb index 3806cec43..9d43d1aff 100644 --- a/app/components/DS/buttonish.rb +++ b/app/components/DS/buttonish.rb @@ -34,16 +34,25 @@ class DS::Buttonish < DesignSystemComponent } }.freeze + # Icon-only containers share a height rail with the text buttons of the + # same size (sm ≈ 28px, md ≈ 36px, lg ≈ 48px), so a mixed row — icon + # trigger next to text buttons, the most common header layout — lines up + # instead of mixing 32/44px squares with 36px buttons. + # + # pointer-coarse restores the 44px square on touch devices: the visual + # rail is a pointer-precision tradeoff, and WCAG 2.5.5's 44x44 target + # minimum is about fingers, not mice. Coarse-pointer users get the full + # target; fine-pointer users get the aligned row. SIZES = { sm: { container_classes: "px-2 py-1", - icon_container_classes: "inline-flex items-center justify-center w-8 h-8", + icon_container_classes: "inline-flex items-center justify-center w-7 h-7 pointer-coarse:w-11 pointer-coarse:h-11", radius_classes: "rounded-md", text_classes: "text-sm" }, md: { container_classes: "px-3 py-2", - icon_container_classes: "inline-flex items-center justify-center w-11 h-11", + icon_container_classes: "inline-flex items-center justify-center w-9 h-9 pointer-coarse:w-11 pointer-coarse:h-11", radius_classes: "rounded-lg", text_classes: "text-sm" }, diff --git a/app/components/DS/popover.html.erb b/app/components/DS/popover.html.erb index 7c73246da..1f5baf58b 100644 --- a/app/components/DS/popover.html.erb +++ b/app/components/DS/popover.html.erb @@ -9,7 +9,7 @@ the fallback `ds.popover.avatar_default_label` is used. %>