Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/www/src/content/docs/components/accordion/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 motion preferences: icon rotation and panel expand/collapse motion is enabled only when `prefers-reduced-motion: no-preference`
Original file line number Diff line number Diff line change
Expand Up @@ -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 motion preferences: alert dialog panel motion is enabled only when `prefers-reduced-motion: no-preference`
1 change: 1 addition & 0 deletions apps/www/src/content/docs/components/button/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 motion preferences: button loader rotation is enabled only when `prefers-reduced-motion: no-preference`
1 change: 1 addition & 0 deletions apps/www/src/content/docs/components/collapsible/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 motion preferences: panel expand/collapse motion is enabled only when `prefers-reduced-motion: no-preference`
1 change: 1 addition & 0 deletions apps/www/src/content/docs/components/dialog/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 motion preferences: dialog panel motion is enabled only when `prefers-reduced-motion: no-preference`
1 change: 1 addition & 0 deletions apps/www/src/content/docs/components/drawer/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 motion preferences: drawer slide motion is enabled only when `prefers-reduced-motion: no-preference`

1 change: 1 addition & 0 deletions apps/www/src/content/docs/components/link/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
- Hover feedback uses an opacity transition
1 change: 1 addition & 0 deletions apps/www/src/content/docs/components/popover/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 motion preferences: popover entry motion is enabled only when `prefers-reduced-motion: no-preference`
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,4 @@ Control the position of the preview card relative to its trigger.
- Closes when the pointer leaves the trigger or content area
- Content is accessible to screen readers when open
- Trigger renders as a semantic `<a>` element
- Respects motion preferences: preview card open/close motion is enabled only when `prefers-reduced-motion: no-preference`
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/components/sidebar/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ Set `hideCollapsedItemTooltip` to disable tooltips on navigation items when the

The Sidebar implements the following accessibility features:

- **Reduced motion** — Respects the user's motion preferences. When the system "Reduce motion" setting is enabled, collapse/expand and hover transitions are disabled so the sidebar updates without animation.
- **Reduced motion** — Sidebar collapse/expand motion is enabled only when `prefers-reduced-motion: no-preference`.

- Proper ARIA roles and attributes

Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/components/skeleton/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 motion preferences: skeleton shimmer is enabled only when `prefers-reduced-motion: no-preference`
- Supports both block and inline layouts
1 change: 1 addition & 0 deletions apps/www/src/content/docs/components/spinner/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 motion preferences: spinner rotation is enabled only when `prefers-reduced-motion: no-preference`
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/components/tabs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,4 @@ Renders the content panel for a tab.
- Uses `role="tablist"`, `role="tab"`, and `role="tabpanel"`
- Active tab is indicated with `aria-selected`
- Leading icon is wrapped with `aria-hidden` so it is not announced (treated as decorative)
- Respects `prefers-reduced-motion: reduce`: the tab indicator does not animate when the user has requested reduced motion in OS/browser settings
- Respects motion preferences: tab indicator motion is enabled only when `prefers-reduced-motion: no-preference`
1 change: 1 addition & 0 deletions apps/www/src/content/docs/components/toast/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 motion preferences: toast enter/exit motion is enabled only when `prefers-reduced-motion: no-preference`
4 changes: 4 additions & 0 deletions apps/www/src/content/docs/components/tooltip/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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:

<Demo data={arrowDemo} />

## Accessibility

- Respects motion preferences: tooltip entry motion is enabled only when `prefers-reduced-motion: no-preference`
14 changes: 11 additions & 3 deletions packages/raystack/components/accordion/accordion.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,13 @@
color: var(--rs-color-foreground-base-secondary);
pointer-events: none;
flex-shrink: 0;
transition: transform 150ms ease-in-out;
width: var(--rs-space-4);
height: var(--rs-space-4);
}

.accordion-content {
height: var(--accordion-panel-height);
overflow: hidden;
transition: height 150ms ease-out;
}

.accordion-content[data-starting-style],
Expand All @@ -78,4 +76,14 @@
align-self: stretch;
padding: var(--rs-space-5) var(--rs-space-4);
border-top: 0px;
}
}

@media (prefers-reduced-motion: no-preference) {
.accordion-icon {
transition: transform 150ms ease-in-out;
}

.accordion-content {
transition: height 150ms ease-out;
}
}
12 changes: 10 additions & 2 deletions packages/raystack/components/button/button.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
padding: var(--rs-space-3) var(--rs-space-4);
border-radius: var(--rs-radius-2);
text-wrap: nowrap;
transition: all 0.2s ease-in-out;
}

.button:focus-visible {
Expand Down Expand Up @@ -246,7 +245,16 @@
/* Todo: var does not exist for 10px */
width: 10px;
height: 10px;
animation: spin 1s linear infinite;
}

@media (prefers-reduced-motion: no-preference) {
.button {
transition: all 0.2s ease-in-out;
}

.loader {
animation: spin 1s linear infinite;
}
}

.loader-text {
Expand Down
2 changes: 1 addition & 1 deletion packages/raystack/components/chip/chip.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
border-radius: var(--rs-radius-2);
white-space: nowrap;
cursor: default;
transition: all 0.2s ease;
transition: var(--rs-transition-interactive);
box-sizing: border-box;
height: fit-content;
width: fit-content;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@
.panel {
height: var(--collapsible-panel-height);
overflow: hidden;
transition: height 150ms ease-out;
}

.panel[data-starting-style],
.panel[data-ending-style] {
height: 0;
}

@media (prefers-reduced-motion: no-preference) {
.panel {
transition: height 150ms ease-out;
}
}
8 changes: 3 additions & 5 deletions packages/raystack/components/dialog/dialog.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
position: fixed;
top: 50%;
left: 50%;
transition: all 150ms;
transition: opacity 150ms;
transform: translate(-50%, -50%);
}

Expand Down Expand Up @@ -84,11 +84,9 @@
z-index: var(--rs-z-index-portal);
}

@media (prefers-reduced-motion: reduce) {
.dialogOverlay,
@media (prefers-reduced-motion: no-preference) {
.dialogContent {
animation: none;
transition: none;
transition: opacity 150ms, transform 150ms;
}
}

Expand Down
14 changes: 6 additions & 8 deletions packages/raystack/components/drawer/drawer.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@
.drawerPopup-right {
width: 250px;
height: 100%;
transition: transform 450ms cubic-bezier(0.32, 0.72, 0, 1);
transform: translateX(var(--drawer-swipe-movement-x));
}

Expand All @@ -90,7 +89,6 @@
.drawerPopup-left {
width: 250px;
height: 100%;
transition: transform 450ms cubic-bezier(0.32, 0.72, 0, 1);
transform: translateX(var(--drawer-swipe-movement-x));
}

Expand All @@ -107,7 +105,6 @@
.drawerPopup-top {
width: 100%;
height: 300px;
transition: transform 450ms cubic-bezier(0.32, 0.72, 0, 1);
transform: translateY(var(--drawer-swipe-movement-y));
}

Expand All @@ -124,7 +121,6 @@
.drawerPopup-bottom {
width: 100%;
height: 300px;
transition: transform 450ms cubic-bezier(0.32, 0.72, 0, 1);
transform: translateY(var(--drawer-swipe-movement-y));
}

Expand Down Expand Up @@ -201,9 +197,11 @@
border-top: 1px solid var(--rs-color-border-base-primary);
}

@media (prefers-reduced-motion: reduce) {
.drawerPopup,
.backdrop {
transition: none;
@media (prefers-reduced-motion: no-preference) {
.drawerPopup-right,
.drawerPopup-left,
.drawerPopup-top,
.drawerPopup-bottom {
transition: transform 450ms cubic-bezier(0.32, 0.72, 0, 1);
}
Comment on lines +200 to 206
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Reduced-motion path still allows drawer/backdrop animation.

Nice inversion to no-preference, but reduced-motion is not fully enforced because close-state duration rules (Line 84, Line 100, Line 116, Line 132) and backdrop transition (Line 8) remain active outside media gating. In reduce, this can still animate closing/fade.

Suggested fix
 `@media` (prefers-reduced-motion: no-preference) {
+  .backdrop {
+    transition: opacity 450ms cubic-bezier(0.32, 0.72, 0, 1);
+  }
+
   .drawerPopup-right,
   .drawerPopup-left,
   .drawerPopup-top,
   .drawerPopup-bottom {
     transition: transform 450ms cubic-bezier(0.32, 0.72, 0, 1);
   }
+
+  .backdrop[data-ending-style] {
+    transition-duration: calc(var(--drawer-swipe-strength, 1) * 400ms);
+  }
+
+  .drawerPopup-right[data-ending-style],
+  .drawerPopup-left[data-ending-style],
+  .drawerPopup-top[data-ending-style],
+  .drawerPopup-bottom[data-ending-style] {
+    transition-duration: calc(var(--drawer-swipe-strength, 1) * 400ms);
+  }
 }
+
+@media (prefers-reduced-motion: reduce) {
+  .backdrop,
+  .drawerPopup-right,
+  .drawerPopup-left,
+  .drawerPopup-top,
+  .drawerPopup-bottom {
+    transition: none;
+  }
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/raystack/components/drawer/drawer.module.css` around lines 200 -
206, The reduced-motion media query currently only wraps the primary open
transitions (.drawerPopup-right, .drawerPopup-left, .drawerPopup-top,
.drawerPopup-bottom) but leaves backdrop transitions and the close-state
duration rules active; update the CSS so that all transition properties for the
drawer and backdrop are either removed or set to zero inside the
prefers-reduced-motion media query: move or duplicate the backdrop selector
(backdrop) and the close-state rules (the selectors handling the close-state
durations referenced around Line 84/100/116/132) into the `@media`
(prefers-reduced-motion: reduce) block and set transition: none or
transition-duration: 0ms for those selectors to fully disable animations for
reduced-motion users.

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
border: none;
color: var(--rs-color-foreground-base-primary);
cursor: pointer;
transition: all 0.2s ease;
transition: var(--rs-transition-interactive);
padding: var(--rs-space-1);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
border-radius: var(--rs-radius-2);
border: 0.5px solid var(--rs-color-border-base-tertiary);
background: var(--rs-color-background-base-primary);
transition: all 0.2s ease;
transition: var(--rs-transition-interactive);
box-sizing: border-box;
overflow: hidden;
}
Expand Down Expand Up @@ -155,7 +155,7 @@

.has-chips {
background: var(--rs-color-background-base-primary);
transition: all 0.2s ease;
transition: var(--rs-transition-interactive);
}

.has-chips:hover {
Expand Down
12 changes: 10 additions & 2 deletions packages/raystack/components/meter/meter.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
.indicator {
height: 100%;
background-color: var(--rs-color-background-accent-emphasis);
transition: width 500ms;
}

/* Circular variant — viewBox is 72×72, SVG scales to container size */
Expand Down Expand Up @@ -83,7 +82,16 @@
(1 - var(--rs-meter-percentage, 0) / 100)
);
stroke-linecap: butt;
transition: stroke-dashoffset 500ms;
}

@media (prefers-reduced-motion: no-preference) {
.indicator {
transition: width 500ms;
}

.circularIndicatorCircle {
transition: stroke-dashoffset 500ms;
}
}

.meter-variant-circular .value {
Expand Down
7 changes: 6 additions & 1 deletion packages/raystack/components/navbar/navbar.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@
box-shadow: var(--rs-shadow-feather);
box-sizing: border-box;
min-height: var(--rs-space-11);
transition: transform 0.2s ease-in-out;
}

@media (prefers-reduced-motion: no-preference) {
.root {
transition: transform 0.2s ease-in-out;
}
}

.root[data-sticky="true"] {
Expand Down
7 changes: 6 additions & 1 deletion packages/raystack/components/popover/popover.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
box-shadow: var(--rs-shadow-soft);
border: 1px solid var(--rs-color-border-base-primary);
color: var(--rs-color-foreground-base-primary);
animation: slideUpAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes slideUpAndFade {
Expand All @@ -29,3 +28,9 @@
transform: translateY(0);
}
}

@media (prefers-reduced-motion: no-preference) {
.popover {
animation: slideUpAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1);
}
}
39 changes: 30 additions & 9 deletions packages/raystack/components/preview-card/preview-card.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
height: var(--positioner-height);
width: var(--positioner-width);
max-width: var(--available-width);
transition-property: top, left, right, bottom, transform;
transition-timing-function: var(--easing);
transition-duration: var(--animation-duration);
transition: opacity var(--animation-duration) var(--easing);
}

.popup {
Expand All @@ -25,9 +23,7 @@
width: var(--popup-width, auto);
height: var(--popup-height, auto);

transition-property: width, height, opacity, transform;
transition-timing-function: var(--easing);
transition-duration: var(--animation-duration);
transition: opacity var(--animation-duration) var(--easing);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix Stylelint violation in .popup transition block.

Line 29 is currently flagged by Stylelint (declaration-empty-line-before) and may fail CI checks. Remove the empty line before transition.

Suggested fix
 .popup {
   position: relative;
   box-sizing: border-box;
   padding: var(--rs-space-3);
   background-color: var(--rs-color-background-base-primary);
   border-radius: var(--rs-radius-2);
   border: 0.5px solid var(--rs-color-border-base-primary);
   box-shadow:
     0 1px 1px 0 rgba(0, 0, 0, 0.07),
     0 2px 5px 0 rgba(0, 0, 0, 0.07),
     0 3px 8px 0 rgba(0, 0, 0, 0.07);
   color: var(--rs-color-foreground-base-primary);
   transform-origin: var(--transform-origin);

   width: var(--popup-width, auto);
   height: var(--popup-height, auto);
-
   transition: opacity var(--animation-duration) var(--easing);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
transition: opacity var(--animation-duration) var(--easing);
.popup {
position: relative;
box-sizing: border-box;
padding: var(--rs-space-3);
background-color: var(--rs-color-background-base-primary);
border-radius: var(--rs-radius-2);
border: 0.5px solid var(--rs-color-border-base-primary);
box-shadow:
0 1px 1px 0 rgba(0, 0, 0, 0.07),
0 2px 5px 0 rgba(0, 0, 0, 0.07),
0 3px 8px 0 rgba(0, 0, 0, 0.07);
color: var(--rs-color-foreground-base-primary);
transform-origin: var(--transform-origin);
width: var(--popup-width, auto);
height: var(--popup-height, auto);
transition: opacity var(--animation-duration) var(--easing);
}
🧰 Tools
🪛 Stylelint (17.6.0)

[error] 29-29: Unexpected empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/raystack/components/preview-card/preview-card.module.css` at line
29, Remove the blank line immediately before the transition declaration inside
the .popup rule in preview-card.module.css so the `transition: opacity
var(--animation-duration) var(--easing);` declaration is directly contiguous
with the previous property (fixing the declaration-empty-line-before Stylelint
violation); locate the .popup selector and collapse the extra empty line above
the transition property.

}

.popup[data-starting-style],
Expand Down Expand Up @@ -79,9 +75,7 @@
width: var(--popup-width);
translate: 0;
opacity: 1;
transition:
translate var(--animation-duration) var(--easing),
opacity calc(var(--animation-duration) / 2) var(--easing);
transition: opacity calc(var(--animation-duration) / 2) var(--easing);
}

.viewport[data-activation-direction~="left"]
Expand All @@ -107,3 +101,30 @@
translate: -30% 0;
opacity: 0;
}

@media (prefers-reduced-motion: no-preference) {
.positioner {
transition:
top var(--animation-duration) var(--easing),
left var(--animation-duration) var(--easing),
right var(--animation-duration) var(--easing),
bottom var(--animation-duration) var(--easing),
transform var(--animation-duration) var(--easing),
opacity var(--animation-duration) var(--easing);
}

.popup {
transition:
width var(--animation-duration) var(--easing),
height var(--animation-duration) var(--easing),
opacity var(--animation-duration) var(--easing),
transform var(--animation-duration) var(--easing);
}

.viewport [data-previous],
.viewport [data-current] {
transition:
translate var(--animation-duration) var(--easing),
opacity calc(var(--animation-duration) / 2) var(--easing);
}
}
Loading
Loading