Files
sure/app/components/DS/disclosure.html.erb
Guillem Arias Fauste 34d6f4d8d6 fix(design-system): DS::Disclosure focus ring + motion-safe chevron (#1841)
Closes #1741. Two small a11y polishes on the native `<details>` /
`<summary>` primitive:

- Add a token-backed focus-visible ring on `<summary>`. Previously
  inherited only the browser default outline, which was thin and
  inconsistent across engines. Match the new pattern from #1738:
  `outline-2 outline-offset-2 outline-gray-900` plus
  `theme-dark:outline-white` so the ring lands on the page chrome
  outside the disclosure regardless of mode. (WCAG 2.4.7.)

- Gate the chevron rotation behind `motion-safe:transition-transform`
  + `motion-safe:duration-150`. The chevron now slides between
  closed/open states for users who haven't opted out of motion, and
  snap-rotates instantly under `prefers-reduced-motion: reduce`.
  (WCAG 2.3.3, AAA.)

While here: drop the no-op `group-open:transform` class. Tailwind
v4 applies `rotate-90` / `rotate-180` directly without needing the
explicit `transform` utility — it was a v3 holdover.
2026-05-20 18:10:16 +02:00

29 lines
1.1 KiB
Plaintext

<details class="group" <%= "open" if open %>>
<%= tag.summary class: class_names(
"px-3 py-2 rounded-xl cursor-pointer flex items-center justify-between bg-surface",
"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-900 theme-dark:focus-visible:outline-white"
) do %>
<% if summary_content? %>
<%= summary_content %>
<% else %>
<div class="flex items-center gap-3">
<% if align == :left %>
<%= helpers.icon "chevron-right", class: "group-open:rotate-90 motion-safe:transition-transform motion-safe:duration-150" %>
<% end %>
<%= tag.span class: class_names("font-medium", align == :left ? "text-sm text-primary" : "text-xs uppercase text-secondary") do %>
<%= title %>
<% end %>
</div>
<% if align == :right %>
<%= helpers.icon "chevron-down", class: "group-open:rotate-180 motion-safe:transition-transform motion-safe:duration-150" %>
<% end %>
<% end %>
<% end %>
<div class="mt-2">
<%= content %>
</div>
</details>