diff --git a/app/components/DS/toggle.html.erb b/app/components/DS/toggle.html.erb
index 6845686c4..5b9fe94de 100644
--- a/app/components/DS/toggle.html.erb
+++ b/app/components/DS/toggle.html.erb
@@ -1,5 +1,8 @@
<%= hidden_field_tag name, unchecked_value, id: nil %>
- <%= check_box_tag name, checked_value, checked, class: "sr-only peer", disabled: disabled, id: id, **opts %>
+ <%# `role="switch"` upgrades the underlying checkbox so AT users hear
+ "switch, on" / "switch, off" instead of "checkbox, checked". The
+ visual already reads as a switch — semantics now match. %>
+ <%= check_box_tag name, checked_value, checked, class: "sr-only peer", disabled: disabled, id: id, role: "switch", **opts %>
<%= label_tag name, " ".html_safe, class: label_classes, for: id %>
diff --git a/app/components/DS/toggle.rb b/app/components/DS/toggle.rb
index c384a2969..a795574d8 100644
--- a/app/components/DS/toggle.rb
+++ b/app/components/DS/toggle.rb
@@ -13,13 +13,20 @@ class DS::Toggle < DesignSystemComponent
def label_classes
class_names(
- "block w-9 h-5 cursor-pointer",
- "rounded-full bg-gray-100 theme-dark:bg-gray-700",
- "transition-colors duration-300",
+ "relative block w-9 h-5 cursor-pointer",
+ "rounded-full bg-surface-inset",
+ # `motion-safe:` gates the bg + thumb-translate transitions on
+ # `prefers-reduced-motion`; reduced-motion users get a snap.
+ "motion-safe:transition-colors motion-safe:duration-300",
"after:content-[''] after:block after:bg-white after:absolute after:rounded-full",
"after:top-0.5 after:left-0.5 after:w-4 after:h-4",
- "after:transition-transform after:duration-300 after:ease-in-out",
- "peer-checked:bg-green-600 peer-checked:after:translate-x-4",
+ "motion-safe:after:transition-transform motion-safe:after:duration-300 motion-safe:after:ease-in-out",
+ "peer-checked:bg-success peer-checked:after:translate-x-4",
+ # Focus ring driven from the sr-only input via `peer-focus-visible:`.
+ # Offset places the ring outside the track so it lands on the
+ # surrounding chrome regardless of theme.
+ "peer-focus-visible:ring-2 peer-focus-visible:ring-offset-2",
+ "peer-focus-visible:ring-alpha-black-300 theme-dark:peer-focus-visible:ring-alpha-white-300",
"peer-disabled:opacity-70 peer-disabled:cursor-not-allowed"
)
end