Skip to content

feat: sidebar improvements#665

Open
paanSinghCoder wants to merge 9 commits intomainfrom
fix/sidebar-css
Open

feat: sidebar improvements#665
paanSinghCoder wants to merge 9 commits intomainfrom
fix/sidebar-css

Conversation

@paanSinghCoder
Copy link
Contributor

@paanSinghCoder paanSinghCoder commented Mar 3, 2026

Issue-577
Issue-600

Description

  • fix: Horizontal and vertical UI shift on collapse and expand.
  • feat: Add prefers-reduced-motion: reduce media query to tell browser to not use transitions for these settings enabled in browser.
  • fix: Use CSS variables instead of hardcoded width/height values.
  • Update docs and examples.
  • fix: Tooltip not working for collapsed sidebar.
  • fix: Update ARIA roles in Sidebar components for improved accessibility.
  • chore: remove inline css.
  • style: update SidebarItem to always display text and improve hidden state styling for sr-only.

Sidebar docs before:
Screenshot 2026-03-03 at 5 34 01 PM

Sidebar docs after:
Screenshot 2026-03-03 at 5 34 44 PM

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactor (no functional changes, no bug fixes just code improvements)
  • Chore (changes to the build process or auxiliary tools and libraries such as documentation generation)
  • Style (changes that do not affect the meaning of the code (white-space, formatting, etc))
  • Test (adding missing tests or correcting existing tests)
  • Improvement (Improvements to existing code)
  • Other (please specify)

How Has This Been Tested?

Manual and unit tests

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (.mdx files)
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works

Screenshots (if appropriate):

[Add screenshots here]

Related Issues

[Link any related issues here using #issue-number]

Summary by CodeRabbit

  • Bug Fixes

    • Preserve layout and spacing when collapsing the sidebar; collapsed labels remain accessible in the DOM.
  • Accessibility

    • Respects reduced-motion settings; collapse/hover animations disabled when requested. Footer/list semantics improved for assistive tech.
  • Style

    • Compact sidebar alignment and sizing updates; improved collapsed spacing and hover behaviors.
  • New Features

    • Demo preview layout options and added icons for richer sidebar examples; preview styling hook added.
  • Documentation

    • Expanded Sidebar docs: Main, Footer, collapse/tooltip behaviors, and reduced-motion guidance.
  • Tests

    • Updated tests to reflect accessibility and collapsed-state behavior changes.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

@vercel
Copy link

vercel bot commented Mar 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
apsara Ready Ready Preview, Comment Mar 3, 2026 0:13am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2026

📝 Walkthrough

Walkthrough

Reworks Sidebar styling and collapsed behavior (uses CSS variables, preserves layout via visibility/off-screen techniques, adds reduced-motion handling), adjusts Sidebar item/footer semantics and tooltip behavior, adds demo preview layout/classes and icon exports, updates demos/docs/tests, and replaces a placeholder icon with BellIcon.

Changes

Cohort / File(s) Summary
Sidebar CSS Layout & Styling
packages/raystack/components/sidebar/sidebar.module.css
Replaced hardcoded collapsed widths with CSS variables, changed collapsed alignments to flex-start, switched hidden-text handling to off-screen/visibility preservation, added .nav-fallback-avatar, adjusted resize handle width, altered nav-group header collapse behavior, and added prefers-reduced-motion rules.
Sidebar components & semantics
packages/raystack/components/sidebar/sidebar-item.tsx, packages/raystack/components/sidebar/sidebar-misc.tsx
Changed interactive roles from menuitem/group to listitem/list, always render label span (use off-screen visibility when collapsed), moved avatar cursor to CSS class, and refactored collapsed-item tooltip to use nested Tooltip.Trigger/Tooltip.Content.
Tests
packages/raystack/components/sidebar/__tests__/sidebar.test.tsx
Updated tests to query Footer by list role and adjusted assertions for collapsed-label presence (expect in-DOM sr-only visibility rather than removed).
Demo preview UI, types & styles
apps/www/src/components/demo/demo-preview.tsx, apps/www/src/components/demo/types.ts, apps/www/src/components/demo/styles.module.css
Added optional previewClassName prop/type; apply conditional wrapper/class; added .previewTop, .previewSidebar, and related preview layout styles (including dashed main-area placeholder and fixed sidebar preview height).
Demo scope & examples
apps/www/src/components/demo/demo.tsx, apps/www/src/content/docs/components/sidebar/demo.ts
Exported additional icons (BellIcon, FilterIcon, OrganizationIcon, SidebarIcon) into demo scope; introduced layout helpers (mainAreaStyle, sidebarLayout, sidebarLayoutRight); refactored demos to grouped items, added new groups/items, replaced icons, and set previewClassName: 'previewSidebar' for sidebar previews; added collapsibleDemo and hideTooltipDemo.
Docs & example usage
apps/www/src/content/docs/components/sidebar/index.mdx, apps/www/src/app/examples/page.tsx
Documented new Main/Footer usage, collapse/tooltip props (collapsible, hideCollapsedItemTooltip), added Reduced motion accessibility note, and replaced leadingIcon={0} with BellIcon in example page.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Suggested labels

Do not merge

Suggested reviewers

  • rsbh
  • rohilsurana

Poem

🐰 I slimmed the sidebar, stitched with care,
Variables whispered in the air,
Text hid gently, still sitting there,
BellIcon chimed to show it's fair,
Motion eased — the UI breathes with flair.

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'feat: sidebar improvements' is vague and generic, using a non-descriptive term 'improvements' that doesn't convey the specific changes made in the changeset. Consider a more specific title like 'feat: sidebar CSS improvements and accessibility fixes' to better reflect the key changes including CSS variables, media queries, ARIA role updates, and tooltip fixes.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/sidebar-css

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (4)
apps/www/src/components/demo/demo-preview.tsx (2)

88-103: Remove commented-out code.

This block appears to be leftover from a refactor. Dead code should be removed to keep the codebase clean. If needed for reference, it can be retrieved from version control.

🗑️ Remove these lines
-{
-  /* // {Array.isArray(codePreview) ? ( */
-}
-//   <Tabs
-//     items={codePreview.map(tab => tab.label)}
-//     className={styles.codeTabGroup}
-//   >
-//     {codePreview.map(tab => (
-//       <Tab className={styles.codeTab} value={tab.label} key={tab.label}>
-//         <Editor code={tab.code} />
-//       </Tab>
-//     ))}
-//   </Tabs>
-// ) : (
-//   <Editor code={previewCode} />
-// )}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/www/src/components/demo/demo-preview.tsx` around lines 88 - 103, Remove
the leftover commented-out JSX block that checks Array.isArray(codePreview) and
renders <Tabs>, <Tab>, and <Editor> variants; specifically delete the commented
lines referencing codePreview.map, Tabs, Tab, Editor, previewCode and
styles.codeTabGroup/codeTab so only the current active render remains—this
cleans up dead/refactor leftovers while keeping existing functional JSX intact.

43-57: Type assertion bypasses TypeScript safety.

The cast previewClassName as keyof typeof styles assumes the string is always a valid key. While cx() handles undefined gracefully, this masks potential typos in previewClassName values at compile time.

♻️ Consider a type-safe approach

Define the allowed values explicitly in the types file:

// In types.ts
export type PreviewClassName = 'previewTop' | 'previewSidebar';

export type DemoPreviewProps = {
  // ...
  previewClassName?: PreviewClassName;
};

Then in demo-preview.tsx, the lookup becomes type-safe without the assertion.

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

In `@apps/www/src/components/demo/demo-preview.tsx` around lines 43 - 57, The code
uses a unsafe type assertion previewClassName as keyof typeof styles inside the
cx(...) call which bypasses TypeScript checks; update the component props to
accept a narrower union type (e.g., export type PreviewClassName = 'previewTop'
| 'previewSidebar' and include previewClassName?: PreviewClassName on
DemoPreviewProps in your types file) and remove the cast so the
cx(styles.preview, previewClassName && styles[previewClassName]) lookup is
type-safe; adjust any imports/usages of DemoPreviewProps/previewClassName and
keep the conditional mapping for Preview's className (previewTop/previewSidebar)
as-is but rely on the new typed previewClassName instead of asserting.
apps/www/src/components/demo/styles.module.css (2)

73-81: Redundant padding-bottom declaration.

padding: 0 !important on line 74 already sets all padding sides to 0, making padding-bottom: 0 !important on line 75 redundant.

♻️ Suggested fix
 .previewContentSidebar {
   padding: 0 !important;
-  padding-bottom: 0 !important;
   margin-bottom: 0 !important;
   height: 100%;
   width: 100%;
   display: flex;
   flex-direction: column;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/www/src/components/demo/styles.module.css` around lines 73 - 81, The CSS
for the .previewContentSidebar class has a redundant padding declaration: remove
the explicit "padding-bottom: 0 !important" since "padding: 0 !important"
already sets all sides to zero; update the .previewContentSidebar block (the
class name previewContentSidebar) to drop the redundant padding-bottom line so
styling is simpler and avoids duplicated !important rules.

55-93: Consider extracting the repeated 480px height to a CSS variable.

The PR description mentions replacing hardcoded values with CSS variables. The 480px value appears three times (lines 60, 61, 92). Extracting it would improve maintainability and align with the stated objective.

♻️ Suggested approach

Define a local variable at the top of the relevant selectors or use a design token:

+/* At file level or in :root */
+/* --preview-sidebar-height: 480px; */
+
 .previewSidebar {
   display: flex;
   flex-direction: row;
   align-items: stretch;
   justify-content: flex-start;
-  min-height: 480px;
-  height: 480px;
+  min-height: var(--preview-sidebar-height, 480px);
+  height: var(--preview-sidebar-height, 480px);
   width: 100%;
   padding: 0;
 }

 /* ... */

 .previewSidebar aside {
-  height: 480px;
+  height: var(--preview-sidebar-height, 480px);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/www/src/components/demo/styles.module.css` around lines 55 - 93, Extract
the repeated 480px value into a CSS variable and use that variable wherever the
fixed height appears: define something like --preview-height: 480px at the top
scope used by these selectors (e.g., :root or the component wrapper) and replace
the hardcoded 480px in .previewSidebar (min-height/height),
.previewContentSidebar child rules if present, and .previewSidebar aside to
reference var(--preview-height); update any comments if needed to reflect the
variable usage so all three occurrences (.previewSidebar, .previewContentSidebar
> * and .previewSidebar aside) use the single token.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/www/src/components/demo/demo-preview.tsx`:
- Around line 88-103: Remove the leftover commented-out JSX block that checks
Array.isArray(codePreview) and renders <Tabs>, <Tab>, and <Editor> variants;
specifically delete the commented lines referencing codePreview.map, Tabs, Tab,
Editor, previewCode and styles.codeTabGroup/codeTab so only the current active
render remains—this cleans up dead/refactor leftovers while keeping existing
functional JSX intact.
- Around line 43-57: The code uses a unsafe type assertion previewClassName as
keyof typeof styles inside the cx(...) call which bypasses TypeScript checks;
update the component props to accept a narrower union type (e.g., export type
PreviewClassName = 'previewTop' | 'previewSidebar' and include
previewClassName?: PreviewClassName on DemoPreviewProps in your types file) and
remove the cast so the cx(styles.preview, previewClassName &&
styles[previewClassName]) lookup is type-safe; adjust any imports/usages of
DemoPreviewProps/previewClassName and keep the conditional mapping for Preview's
className (previewTop/previewSidebar) as-is but rely on the new typed
previewClassName instead of asserting.

In `@apps/www/src/components/demo/styles.module.css`:
- Around line 73-81: The CSS for the .previewContentSidebar class has a
redundant padding declaration: remove the explicit "padding-bottom: 0
!important" since "padding: 0 !important" already sets all sides to zero; update
the .previewContentSidebar block (the class name previewContentSidebar) to drop
the redundant padding-bottom line so styling is simpler and avoids duplicated
!important rules.
- Around line 55-93: Extract the repeated 480px value into a CSS variable and
use that variable wherever the fixed height appears: define something like
--preview-height: 480px at the top scope used by these selectors (e.g., :root or
the component wrapper) and replace the hardcoded 480px in .previewSidebar
(min-height/height), .previewContentSidebar child rules if present, and
.previewSidebar aside to reference var(--preview-height); update any comments if
needed to reflect the variable usage so all three occurrences (.previewSidebar,
.previewContentSidebar > * and .previewSidebar aside) use the single token.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c07c92 and b8cee0e.

📒 Files selected for processing (5)
  • apps/www/src/components/demo/demo-preview.tsx
  • apps/www/src/components/demo/demo.tsx
  • apps/www/src/components/demo/styles.module.css
  • apps/www/src/components/demo/types.ts
  • apps/www/src/content/docs/components/sidebar/demo.ts

@paanSinghCoder paanSinghCoder changed the title fix: sidebar css fixes feat: sidebar improvements Mar 3, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/raystack/components/sidebar/sidebar-item.tsx (1)

62-67: ⚠️ Potential issue | 🟠 Major

Remove role="listitem" from the anchor element.

Per ARIA-in-HTML specifications, role="listitem" is not a permitted role on interactive <a href> elements and violates accessibility standards. User agents may ignore the invalid role or produce inconsistent behavior across assistive technologies.

Recommended fix
       {
         ref,
         className: cx(styles['nav-item'], classNames?.root),
         'data-active': active,
         'data-disabled': disabled,
-        role: 'listitem',
         'aria-current': active ? 'page' : undefined,
         'aria-disabled': disabled,
         ...props
       },

If list semantics are required, apply role="listitem" to a non-interactive wrapper element (not the <a> itself), or use native <li> elements in the parent list structure.

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

In `@packages/raystack/components/sidebar/sidebar-item.tsx` around lines 62 - 67,
The anchor element in SidebarItem (props passed including ref, className:
cx(styles['nav-item'], classNames?.root), 'data-active', 'data-disabled')
incorrectly sets role="listitem"; remove the role attribute from the interactive
<a> element in the SidebarItem component (delete the role: 'listitem' entry)
and, if list semantics are needed, move that role to a non-interactive wrapper
or switch the parent to use native <li> elements instead—update SidebarItem
rendering accordingly (look for the ref/className/aria-current usage to locate
the element).
🧹 Nitpick comments (3)
apps/www/src/components/demo/styles.module.css (1)

55-63: Consolidate repeated preview height into a CSS variable.

480px is duplicated in multiple selectors. A local CSS custom property will make future adjustments safer.

♻️ Proposed refactor
 .previewSidebar {
+  --preview-sidebar-height: 480px;
   display: flex;
   flex-direction: row;
   align-items: stretch;
   justify-content: flex-start;
-  min-height: 480px;
-  height: 480px;
+  min-height: var(--preview-sidebar-height);
+  height: var(--preview-sidebar-height);
   width: 100%;
   padding: 0;
 }
@@
 .previewSidebar aside {
-  height: 480px;
+  height: var(--preview-sidebar-height);
 }

Also applies to: 90-93

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

In `@apps/www/src/components/demo/styles.module.css` around lines 55 - 63,
Consolidate the repeated 480px value by introducing a local CSS custom property
(e.g., --preview-height) and use it wherever 480px is currently hardcoded:
define the variable on a suitable container (for example :root or the component
root selector) and replace the literal 480px in .previewSidebar and the other
selectors referenced around lines 90-93 with var(--preview-height); ensure both
min-height and height properties use the variable so future adjustments require
changing only the single custom property.
packages/raystack/components/sidebar/__tests__/sidebar.test.tsx (1)

249-253: Strengthen collapsed-state assertion with role-based query.

Current check only verifies text presence. Add a role query so accessibility regressions on item semantics are caught.

✅ Suggested test addition
     it('keeps label in DOM when collapsed (sr-only for screen readers)', () => {
       render(<BasicSidebar open={false} />);
 
       expect(screen.getByText(DASHBOARD_ITEM_TEXT)).toBeInTheDocument();
+      expect(
+        screen.getByRole('link', { name: DASHBOARD_ITEM_TEXT })
+      ).toBeInTheDocument();
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/raystack/components/sidebar/__tests__/sidebar.test.tsx` around lines
249 - 253, The test "keeps label in DOM when collapsed (sr-only for screen
readers)" only asserts text presence; update it to assert via role+name to catch
accessibility regressions: render BasicSidebar(open={false}) and replace/add the
text-only expectation with a role query that matches the semantic element (for
example use screen.getByRole('link' /* or 'listitem' if appropriate */, { name:
DASHBOARD_ITEM_TEXT }) and assert toBeInTheDocument()); reference BasicSidebar
and DASHBOARD_ITEM_TEXT to locate the test and ensure the role chosen matches
how the sidebar items are rendered.
apps/www/src/content/docs/components/sidebar/demo.ts (1)

17-286: Consider reducing repeated sidebar demo markup.

Most demo exports repeat the same sidebar skeleton. A shared snippet builder (parametrized by open, position, collapsible, hideCollapsedItemTooltip) would reduce maintenance overhead.

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

In `@apps/www/src/content/docs/components/sidebar/demo.ts` around lines 17 - 286,
Multiple demo exports (preview, positionDemo, stateDemo, tooltipDemo,
collapsibleDemo, hideTooltipDemo) duplicate the same Sidebar markup; create a
shared builder function (e.g., buildSidebarSnippet or sidebarSnippet) that
accepts parameters open, defaultOpen, position, collapsible,
hideCollapsedItemTooltip and returns the composed sidebar string, then replace
each export's inline sidebarLayout/sidebarLayoutRight call with a call to that
builder using the appropriate options (ensure builder includes
Header/Main/Footer skeleton and supports right-position wrapper via a position
parameter or separate wrapper function).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/raystack/components/sidebar/sidebar.module.css`:
- Around line 127-135: Replace the deprecated clip declaration in the CSS rule
that currently contains "clip: rect(0, 0, 0, 0);" with the modern
screen-reader-only pattern by using "clip-path: inset(50%);" (keep the other
properties like position, width, height, padding, margin, overflow, white-space,
and border intact); locate the rule by searching for the declaration "clip:
rect(0, 0, 0, 0);" and swap it to "clip-path: inset(50%);" to satisfy
stylelint's property-no-deprecated rule.

---

Outside diff comments:
In `@packages/raystack/components/sidebar/sidebar-item.tsx`:
- Around line 62-67: The anchor element in SidebarItem (props passed including
ref, className: cx(styles['nav-item'], classNames?.root), 'data-active',
'data-disabled') incorrectly sets role="listitem"; remove the role attribute
from the interactive <a> element in the SidebarItem component (delete the role:
'listitem' entry) and, if list semantics are needed, move that role to a
non-interactive wrapper or switch the parent to use native <li> elements
instead—update SidebarItem rendering accordingly (look for the
ref/className/aria-current usage to locate the element).

---

Nitpick comments:
In `@apps/www/src/components/demo/styles.module.css`:
- Around line 55-63: Consolidate the repeated 480px value by introducing a local
CSS custom property (e.g., --preview-height) and use it wherever 480px is
currently hardcoded: define the variable on a suitable container (for example
:root or the component root selector) and replace the literal 480px in
.previewSidebar and the other selectors referenced around lines 90-93 with
var(--preview-height); ensure both min-height and height properties use the
variable so future adjustments require changing only the single custom property.

In `@apps/www/src/content/docs/components/sidebar/demo.ts`:
- Around line 17-286: Multiple demo exports (preview, positionDemo, stateDemo,
tooltipDemo, collapsibleDemo, hideTooltipDemo) duplicate the same Sidebar
markup; create a shared builder function (e.g., buildSidebarSnippet or
sidebarSnippet) that accepts parameters open, defaultOpen, position,
collapsible, hideCollapsedItemTooltip and returns the composed sidebar string,
then replace each export's inline sidebarLayout/sidebarLayoutRight call with a
call to that builder using the appropriate options (ensure builder includes
Header/Main/Footer skeleton and supports right-position wrapper via a position
parameter or separate wrapper function).

In `@packages/raystack/components/sidebar/__tests__/sidebar.test.tsx`:
- Around line 249-253: The test "keeps label in DOM when collapsed (sr-only for
screen readers)" only asserts text presence; update it to assert via role+name
to catch accessibility regressions: render BasicSidebar(open={false}) and
replace/add the text-only expectation with a role query that matches the
semantic element (for example use screen.getByRole('link' /* or 'listitem' if
appropriate */, { name: DASHBOARD_ITEM_TEXT }) and assert toBeInTheDocument());
reference BasicSidebar and DASHBOARD_ITEM_TEXT to locate the test and ensure the
role chosen matches how the sidebar items are rendered.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b8cee0e and a2f8abc.

📒 Files selected for processing (7)
  • apps/www/src/components/demo/styles.module.css
  • apps/www/src/content/docs/components/sidebar/demo.ts
  • apps/www/src/content/docs/components/sidebar/index.mdx
  • packages/raystack/components/sidebar/__tests__/sidebar.test.tsx
  • packages/raystack/components/sidebar/sidebar-item.tsx
  • packages/raystack/components/sidebar/sidebar-misc.tsx
  • packages/raystack/components/sidebar/sidebar.module.css

Comment on lines +127 to +135
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, check if the file exists and read the relevant section
cat -n packages/raystack/components/sidebar/sidebar.module.css | sed -n '120,140p'

Repository: raystack/apsara

Length of output: 556


🏁 Script executed:

# Verify the deprecated clip property using the provided script
rg -nP '^\s*clip\s*:' packages/raystack/components/sidebar/sidebar.module.css

Repository: raystack/apsara

Length of output: 88


🏁 Script executed:

# Check for any stylelint configuration files
find . -maxdepth 2 -name '.stylelintrc*' -o -name 'stylelint.config.*' 2>/dev/null | head -20

Repository: raystack/apsara

Length of output: 78


🏁 Script executed:

# Search for any existing clip-path usage in the codebase to understand patterns
rg 'clip-path' packages/raystack/components/sidebar/ -A 2 -B 2

Repository: raystack/apsara

Length of output: 41


🏁 Script executed:

# Check stylelint configuration
cat .stylelintrc.json

Repository: raystack/apsara

Length of output: 1065


🏁 Script executed:

# Search for any documentation or comments about clip property replacement
rg -i 'visually.hidden|screen.reader|a11y' packages/raystack/components/sidebar/ -B 3 -A 3

Repository: raystack/apsara

Length of output: 776


🌐 Web query:

CSS clip property deprecated clip-path inset replacement modern visually hidden

💡 Result:

  • The legacy clip property is deprecated; MDN explicitly recommends using clip-path instead. [1]
  • The modern equivalent of clip: rect(...) is typically clip-path: inset(...) (e.g., inset(50%) for “clip everything to nothing”). [2]

Modern “visually hidden (screen-reader only)” pattern (no clip):

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

This is the direction major codebases have taken as well (e.g., WordPress removed clip from .screen-reader-text as part of modernizing the pattern). [3]

Sources: [1] (developer.mozilla.org) [2] (developer.mozilla.org) [3] (make.wordpress.org)

Citations:


Replace deprecated clip with clip-path for modern visually-hidden pattern.

The clip property at line 133 is deprecated and triggers stylelint's property-no-deprecated rule (inherited from stylelint-config-standard-scss). Replace it with the modern clip-path: inset(50%); equivalent, which is the standard approach for screen-reader-only content across major projects.

🛠️ Proposed fix
 .root[data-closed] .nav-text {
   position: absolute;
   width: 1px;
   height: 1px;
   padding: 0;
   margin: -1px;
   overflow: hidden;
-  clip: rect(0, 0, 0, 0);
+  clip-path: inset(50%);
   white-space: nowrap;
   border: 0;
 }
📝 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
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
🧰 Tools
🪛 Stylelint (17.3.0)

[error] 133-133: Unexpected deprecated property "clip" (property-no-deprecated)

(property-no-deprecated)

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

In `@packages/raystack/components/sidebar/sidebar.module.css` around lines 127 -
135, Replace the deprecated clip declaration in the CSS rule that currently
contains "clip: rect(0, 0, 0, 0);" with the modern screen-reader-only pattern by
using "clip-path: inset(50%);" (keep the other properties like position, width,
height, padding, margin, overflow, white-space, and border intact); locate the
rule by searching for the declaration "clip: rect(0, 0, 0, 0);" and swap it to
"clip-path: inset(50%);" to satisfy stylelint's property-no-deprecated rule.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant