diff --git a/apps/www/src/content/docs/components/accordion/index.mdx b/apps/www/src/content/docs/components/accordion/index.mdx index d052c8ba6..a56fa334e 100644 --- a/apps/www/src/content/docs/components/accordion/index.mdx +++ b/apps/www/src/content/docs/components/accordion/index.mdx @@ -90,3 +90,4 @@ The accordion content can contain any React elements, allowing for rich layouts - Trigger elements use `aria-expanded` to indicate open/closed state - Supports keyboard navigation with Enter and Space to toggle items - Content panels use `aria-controls` and `aria-labelledby` for association +- Respects `prefers-reduced-motion: reduce` by disabling the icon rotation transition and content height transition diff --git a/apps/www/src/content/docs/components/alert-dialog/index.mdx b/apps/www/src/content/docs/components/alert-dialog/index.mdx index 020854f7e..f7ab58848 100644 --- a/apps/www/src/content/docs/components/alert-dialog/index.mdx +++ b/apps/www/src/content/docs/components/alert-dialog/index.mdx @@ -121,3 +121,4 @@ You can nest alert dialogs for multi-step confirmation flows. When a nested aler - Uses `aria-label` or `aria-labelledby` to identify the dialog - Uses `aria-describedby` to provide additional context - Focus is trapped within the alert dialog while open +- Respects `prefers-reduced-motion: reduce` by disabling dialog overlay/panel transitions diff --git a/apps/www/src/content/docs/components/button/index.mdx b/apps/www/src/content/docs/components/button/index.mdx index c49f24a0e..8b3fab898 100644 --- a/apps/www/src/content/docs/components/button/index.mdx +++ b/apps/www/src/content/docs/components/button/index.mdx @@ -75,3 +75,4 @@ The button component accepts optional leading and/or trailing icons. - Supports keyboard activation with Enter and Space keys - Disabled state is communicated via `aria-disabled` attribute - Loading state prevents interaction and announces status to screen readers +- Respects `prefers-reduced-motion: reduce` by disabling the button loader rotation animation diff --git a/apps/www/src/content/docs/components/collapsible/index.mdx b/apps/www/src/content/docs/components/collapsible/index.mdx index 540f7abbe..dd14c49a0 100644 --- a/apps/www/src/content/docs/components/collapsible/index.mdx +++ b/apps/www/src/content/docs/components/collapsible/index.mdx @@ -72,3 +72,4 @@ The collapsible can be disabled to prevent user interaction. - The Trigger uses `aria-expanded` to indicate the open/closed state of the panel. - Supports keyboard interaction with Enter and Space to toggle the panel. - The Panel is automatically associated with the Trigger via `aria-controls`. +- Respects `prefers-reduced-motion: reduce` by disabling the panel height transition diff --git a/apps/www/src/content/docs/components/dialog/index.mdx b/apps/www/src/content/docs/components/dialog/index.mdx index 86e5d37ca..28bb0acfe 100644 --- a/apps/www/src/content/docs/components/dialog/index.mdx +++ b/apps/www/src/content/docs/components/dialog/index.mdx @@ -123,3 +123,4 @@ You can nest dialogs within one another. When a nested dialog opens, the parent - Dialog has `role="dialog"` and `aria-modal="true"` - Uses `aria-label` or `aria-labelledby` to identify the dialog - Uses `aria-describedby` to provide additional context +- Respects `prefers-reduced-motion: reduce` by disabling dialog overlay/backdrop and panel transitions diff --git a/apps/www/src/content/docs/components/drawer/index.mdx b/apps/www/src/content/docs/components/drawer/index.mdx index a54633317..c9d858642 100644 --- a/apps/www/src/content/docs/components/drawer/index.mdx +++ b/apps/www/src/content/docs/components/drawer/index.mdx @@ -80,4 +80,5 @@ The Drawer can slide in from different sides of the screen. Swipe-to-dismiss is - Focus is trapped within the drawer and restored on close - Supports dismissal with Escape key and swipe gestures - Title is announced via `aria-labelledby` +- Respects `prefers-reduced-motion: reduce` by disabling drawer slide/backdrop transitions diff --git a/apps/www/src/content/docs/components/link/index.mdx b/apps/www/src/content/docs/components/link/index.mdx index f994f6568..77d7ddaca 100644 --- a/apps/www/src/content/docs/components/link/index.mdx +++ b/apps/www/src/content/docs/components/link/index.mdx @@ -65,3 +65,4 @@ The Link component follows accessibility best practices: - External links have aria-labels indicating they open in new tabs - Download links include appropriate aria-labels - Maintains color contrast ratios for all variants +- Respects `prefers-reduced-motion: reduce` by disabling the hover opacity transition diff --git a/apps/www/src/content/docs/components/popover/index.mdx b/apps/www/src/content/docs/components/popover/index.mdx index dac86471c..c01a7a0f4 100644 --- a/apps/www/src/content/docs/components/popover/index.mdx +++ b/apps/www/src/content/docs/components/popover/index.mdx @@ -61,3 +61,4 @@ Customize how the popover aligns with its trigger. - Trigger uses `aria-haspopup` and `aria-expanded` attributes - Focus is managed when opening and closing the popover - Supports dismissal with Escape key +- Respects `prefers-reduced-motion: reduce` by disabling the popover entry animation diff --git a/apps/www/src/content/docs/components/skeleton/index.mdx b/apps/www/src/content/docs/components/skeleton/index.mdx index f8b824814..aeba7fa31 100644 --- a/apps/www/src/content/docs/components/skeleton/index.mdx +++ b/apps/www/src/content/docs/components/skeleton/index.mdx @@ -98,5 +98,5 @@ The Skeleton component follows accessibility best practices: - Uses semantic HTML elements - Provides appropriate ARIA attributes - Maintains sufficient color contrast -- Animation can be disabled for users who prefer reduced motion +- Respects `prefers-reduced-motion: reduce` by disabling the skeleton shimmer animation - Supports both block and inline layouts diff --git a/apps/www/src/content/docs/components/spinner/index.mdx b/apps/www/src/content/docs/components/spinner/index.mdx index c573fe3e1..ef3cb4af0 100644 --- a/apps/www/src/content/docs/components/spinner/index.mdx +++ b/apps/www/src/content/docs/components/spinner/index.mdx @@ -44,3 +44,4 @@ The Spinner component includes appropriate ARIA attributes for accessibility: - `role="status"`: Indicates that the element is a status indicator. - `aria-hidden="true"`: Hides the spinner from screen readers, as it's a visual indicator only. +- Respects `prefers-reduced-motion: reduce` by disabling spinner rotation animation diff --git a/apps/www/src/content/docs/components/toast/index.mdx b/apps/www/src/content/docs/components/toast/index.mdx index d53884bdf..c49ddd1b9 100644 --- a/apps/www/src/content/docs/components/toast/index.mdx +++ b/apps/www/src/content/docs/components/toast/index.mdx @@ -95,3 +95,4 @@ Create a toast, then update or close it programmatically using the returned ID. - Close button has `aria-label="Close toast"` - Supports keyboard navigation and Escape to dismiss - Swipe-to-dismiss gesture support +- Respects `prefers-reduced-motion: reduce` by disabling toast enter/exit transitions diff --git a/apps/www/src/content/docs/components/tooltip/index.mdx b/apps/www/src/content/docs/components/tooltip/index.mdx index 2c579400e..4ab069a11 100644 --- a/apps/www/src/content/docs/components/tooltip/index.mdx +++ b/apps/www/src/content/docs/components/tooltip/index.mdx @@ -83,3 +83,7 @@ Use `trackCursorAxis` prop on the Root component to make the tooltip follow the Show the arrow by setting `showArrow={true}` on the Content component: + +## Accessibility + +- Respects `prefers-reduced-motion: reduce` by disabling tooltip entry animations diff --git a/packages/raystack/components/accordion/accordion.module.css b/packages/raystack/components/accordion/accordion.module.css index a8db803e7..3132e61c2 100644 --- a/packages/raystack/components/accordion/accordion.module.css +++ b/packages/raystack/components/accordion/accordion.module.css @@ -77,3 +77,13 @@ padding: var(--rs-space-5) var(--rs-space-4); border-top: 0px; } + +@media (prefers-reduced-motion: reduce) { + .accordion-icon { + transition: none; + } + + .accordion-content { + transition: none; + } +} diff --git a/packages/raystack/components/button/button.module.css b/packages/raystack/components/button/button.module.css index 3fde77f6d..a9747b461 100644 --- a/packages/raystack/components/button/button.module.css +++ b/packages/raystack/components/button/button.module.css @@ -253,6 +253,13 @@ animation: spin 1s linear infinite; } +@media (prefers-reduced-motion: reduce) { + /* Disable button loader rotation for reduced-motion users. */ + .loader { + animation: none; + } +} + .loader-text { margin-left: var(--rs-space-3); } diff --git a/packages/raystack/components/collapsible/collapsible.module.css b/packages/raystack/components/collapsible/collapsible.module.css index d9791b672..6979a7404 100644 --- a/packages/raystack/components/collapsible/collapsible.module.css +++ b/packages/raystack/components/collapsible/collapsible.module.css @@ -18,3 +18,9 @@ .panel[data-ending-style] { height: 0; } + +@media (prefers-reduced-motion: reduce) { + .panel { + transition: none; + } +} diff --git a/packages/raystack/components/link/link.module.css b/packages/raystack/components/link/link.module.css index 844246429..8d6a2837a 100644 --- a/packages/raystack/components/link/link.module.css +++ b/packages/raystack/components/link/link.module.css @@ -7,3 +7,9 @@ .link:hover { opacity: 0.8; } + +@media (prefers-reduced-motion: reduce) { + .link { + transition: none; + } +} diff --git a/packages/raystack/components/popover/popover.module.css b/packages/raystack/components/popover/popover.module.css index 8da7a13ee..15d3389d0 100644 --- a/packages/raystack/components/popover/popover.module.css +++ b/packages/raystack/components/popover/popover.module.css @@ -29,3 +29,9 @@ transform: translateY(0); } } + +@media (prefers-reduced-motion: reduce) { + .popover { + animation: none; + } +} diff --git a/packages/raystack/components/skeleton/skeleton.module.css b/packages/raystack/components/skeleton/skeleton.module.css index 4abef1250..2654d35d2 100644 --- a/packages/raystack/components/skeleton/skeleton.module.css +++ b/packages/raystack/components/skeleton/skeleton.module.css @@ -36,3 +36,10 @@ } } +@media (prefers-reduced-motion: reduce) { + /* Disable shimmer animation for reduced-motion users. */ + .animate::after { + animation: none; + } +} + diff --git a/packages/raystack/components/spinner/spinner.module.css b/packages/raystack/components/spinner/spinner.module.css index b996568fa..a4e5f4f06 100644 --- a/packages/raystack/components/spinner/spinner.module.css +++ b/packages/raystack/components/spinner/spinner.module.css @@ -90,6 +90,13 @@ } } +@media (prefers-reduced-motion: reduce) { + /* Disable spinner rotation for reduced-motion users. */ + .pole { + animation: none; + } +} + .spinner-size-1 { width: var(--rs-space-4); height: var(--rs-space-4); diff --git a/packages/raystack/components/tooltip/tooltip.module.css b/packages/raystack/components/tooltip/tooltip.module.css index 7029ab080..166aa8c87 100644 --- a/packages/raystack/components/tooltip/tooltip.module.css +++ b/packages/raystack/components/tooltip/tooltip.module.css @@ -149,3 +149,9 @@ transform: translate(2px, 2px); } } + +@media (prefers-reduced-motion: reduce) { + .content { + animation: none !important; + } +}