Skip to content

fix(docs): standardize missing accessibility and UX features#51

Merged
jonathanperis merged 1 commit into
mainfrom
docs/standardize-missing-features
May 3, 2026
Merged

fix(docs): standardize missing accessibility and UX features#51
jonathanperis merged 1 commit into
mainfrom
docs/standardize-missing-features

Conversation

@jonathanperis
Copy link
Copy Markdown
Owner

@jonathanperis jonathanperis commented May 3, 2026

Summary

  • Add prefers-reduced-motion CSS media queries (no-preference + reduce) for accessibility compliance
  • Add Firefox scrollbar support (scrollbar-color, scrollbar-width) — was Webkit-only
  • Add window.__docsSlug via define:vars for route-based deep link auto-scroll
  • Scrollspy now scrolls active nav item into view (block: 'nearest')
  • Nav click now closes mobile menu on screens ≤768px

Changes

  • docs/src/styles/docs.css: +43 lines (reduced motion, global scrollbar)
  • docs/src/pages/docs/[...slug].astro: +31/-13 lines (auto-scroll, scrollspy, mobile menu)

Verification

  • npm run build
  • tsc --noEmit ✓ (pre-existing tsconfig deprecation warning only)

Summary by CodeRabbit

  • New Features
    • Added smooth scrolling behavior across the entire site for improved navigation
    • Implemented custom branded scrollbars with enhanced visual styling throughout the site
    • Automatic accessibility improvements that respect user motion preferences and reduce animations accordingly
    • Improved documentation navigation with better auto-scroll targeting for specific sections
    • Mobile-optimized navigation sidebar now automatically closes when selecting items on smaller viewports

Add prefers-reduced-motion CSS media queries, Firefox scrollbar support,
window.__docsSlug for route-based deep links, scrollspy nav auto-scroll,
and mobile menu close on nav click to match standardized pattern
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

📝 Walkthrough

Walkthrough

The documentation page's navigation and scrolling behavior is enhanced with server-injected slug data and updated client-side logic. Simultaneously, global CSS rules add prefers-reduced-motion accessibility support and site-wide scrollbar styling.

Changes

Documentation Page Navigation & Scroll Behavior

Layer / File(s) Summary
Server-side Data Injection
docs/src/pages/docs/[...slug].astro
Inline script exposes requestedSlug and isRoot state to the browser as window.__docsSlug and window.__isRoot.
Client-side Auto-Scroll Logic
docs/src/pages/docs/[...slug].astro
Client script derives isRoot from injected window value and updates auto-scroll behavior to target the requested section slug (when present) or fall back to URL hash.
Scrollspy & Mobile Navigation
docs/src/pages/docs/[...slug].astro
Root pages with multiple sections now toggle active nav item, scroll the active nav item into view, and close the mobile sidebar/menu on nav-click for small viewports.
Accessibility & Visual Styling
docs/src/styles/docs.css
Global prefers-reduced-motion rules control smooth scrolling and animation durations; site-wide custom scrollbar styling added via standard and WebKit selectors.

Sequence Diagram

sequenceDiagram
    participant Server as Astro Server
    participant Browser as Browser
    participant DOM as Page DOM
    participant Nav as Navigation Menu

    Server->>Browser: Render docs page with inline script
    Note over Server: window.__docsSlug, window.__isRoot injected
    
    Browser->>DOM: Auto-scroll to requestedSlug or URL hash
    activate DOM
    DOM->>Browser: Section is now in view
    deactivate DOM

    Browser->>Nav: Initialize scrollspy listener
    Note over Browser: Track active section via IntersectionObserver

    loop As user scrolls
        DOM->>Nav: Section enters/exits viewport
        Nav->>Nav: Update active nav item highlight
        Nav->>Nav: scrollIntoView() active nav item
    end

    alt User clicks nav item (small screen)
        Nav->>Browser: Click handler fires
        Browser->>Nav: Close mobile sidebar (aria-expanded = false)
    end
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

The changes involve understanding server-to-client data flow via script injection, client-side scrollspy logic with UI synchronization, and mobile interaction handling. The scrollbar and motion-preference CSS additions are straightforward but require verification of cross-browser compatibility.

Possibly Related PRs

  • PR #50 — Modifies the same docs/src/pages/docs/[...slug].astro file and related docs scrollspy/auto-scroll behavior with associated styling changes (scrollbar and prefers-reduced-motion rules).
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly summarizes the main changes: adding accessibility features (prefers-reduced-motion, scrollbar support) and UX improvements (auto-scroll, mobile menu close behavior) to the docs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/standardize-missing-features

Review rate limit: 9/10 reviews remaining, refill in 6 minutes.

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

Copy link
Copy Markdown

@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 (3)
docs/src/pages/docs/[...slug].astro (2)

190-198: 💤 Low value

Consider extracting the close-menu logic to avoid duplication.

This duplicates the closeMenu() function defined at lines 142-146. Since closeMenu is scoped inside the if block, it's not accessible here. You could hoist closeMenu to the outer DOMContentLoaded scope so both handlers can share it.

♻️ Suggested refactor
       const prefersReducedMotion = !window.matchMedia('(prefers-reduced-motion: no-preference)').matches;

+      function closeMenu() {
+        if (sidebar && overlay && menuToggle) {
+          sidebar.classList.remove('open');
+          overlay.classList.remove('open');
+          menuToggle.setAttribute('aria-expanded', 'false');
+        }
+      }
+
       /* Mobile menu toggle */
       if (menuToggle && sidebar && overlay) {
-        function closeMenu() {
-          sidebar.classList.remove('open');
-          overlay.classList.remove('open');
-          menuToggle.setAttribute('aria-expanded', 'false');
-        }
         menuToggle.addEventListener('click', function () {

Then at lines 190-198:

         navItems.forEach(function (item) {
           item.addEventListener('click', function () {
-            if (window.innerWidth <= 768 && menuToggle && sidebar && overlay) {
-              sidebar.classList.remove('open');
-              overlay.classList.remove('open');
-              menuToggle.setAttribute('aria-expanded', 'false');
-            }
+            if (window.innerWidth <= 768) {
+              closeMenu();
+            }
           });
         });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/src/pages/docs/`[...slug].astro around lines 190 - 198, The click
handler for navItems duplicates the menu-closing logic currently implemented in
the inner closeMenu function; move (hoist) the closeMenu function out of the
inner if block into the outer DOMContentLoaded scope so both the original toggle
handler and the navItems.forEach listener can call closeMenu(); update the
navItems.forEach callback to call closeMenu() instead of repeating
sidebar.classList.remove('open'), overlay.classList.remove('open') and
menuToggle.setAttribute(...), and ensure closeMenu references the same
menuToggle, sidebar and overlay variables defined in the outer scope.

177-181: 💤 Low value

Nav auto-scroll may cause unexpected sidebar movement during fast scrolling.

When the user scrolls quickly through sections, each intersection fires scrollIntoView on the active nav item. While block: 'nearest' minimizes movement, rapid section changes could still cause noticeable sidebar jitter.

Consider debouncing the scrollIntoView call or only triggering it after scroll settles:

♻️ Optional debounce approach
+      let scrollTimeout;
       if (isRoot && sections.length > 1) {
         const observer = new IntersectionObserver(
           function (entries) {
             entries.forEach(function (entry) {
               if (entry.isIntersecting) {
                 navItems.forEach(function (item) {
                   var isActive = item.getAttribute('data-nav-id') === entry.target.id;
                   item.classList.toggle('active', isActive);
                   if (isActive) {
-                    item.scrollIntoView({ behavior: prefersReducedMotion ? 'auto' : 'smooth', block: 'nearest' });
+                    clearTimeout(scrollTimeout);
+                    scrollTimeout = setTimeout(function () {
+                      item.scrollIntoView({ behavior: prefersReducedMotion ? 'auto' : 'smooth', block: 'nearest' });
+                    }, 150);
                   }
                 });
               }
             });
           },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/src/pages/docs/`[...slug].astro around lines 177 - 181, The sidebar
jitter is caused by calling item.scrollIntoView on every intersection change;
modify the logic around the isActive check to debounce/throttle those calls:
introduce a short-lived timer (or use requestAnimationFrame + a short timeout)
associated with the nav item or a module-level variable and only call
item.scrollIntoView when the active state has persisted for a small delay (e.g.,
100–200ms) or when scrolling has settled; keep the prefersReducedMotion check
and only debounce when motion is allowed, and reference the existing symbols
(item, isActive, item.scrollIntoView, prefersReducedMotion, entry.target.id /
data-nav-id) so the change is localized to this intersection callback.
docs/src/styles/docs.css (1)

369-397: 💤 Low value

Consider consolidating duplicate scrollbar rules.

These scrollbar styles largely duplicate globals.css (lines 34-65). The difference is this file uses CSS variables (var(--rust-orange), var(--bg-deep)) while globals uses hardcoded hex values. If both files are loaded, these rules will override globals.css due to cascade order.

If this duplication is intentional for docs-specific scoping, consider adding a brief comment explaining why. Otherwise, updating globals.css to use the CSS variables would eliminate the duplication.

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

In `@docs/src/styles/docs.css` around lines 369 - 397, The scrollbar rules in
docs/src/styles/docs.css (selectors html, ::-webkit-scrollbar,
::-webkit-scrollbar-track, ::-webkit-scrollbar-thumb,
::-webkit-scrollbar-thumb:hover, ::-webkit-scrollbar-corner) duplicate
globals.css but use CSS variables; either remove this duplication by moving
these rules into globals.css and replace the hardcoded hexes there with
var(--rust-orange)/var(--bg-deep), or if the docs override is intentional, add a
brief clarifying comment above these rules stating they intentionally override
globals for the docs build (or scope them to a docs-specific container/class) so
the cascade behavior is explicit.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/src/pages/docs/`[...slug].astro:
- Around line 190-198: The click handler for navItems duplicates the
menu-closing logic currently implemented in the inner closeMenu function; move
(hoist) the closeMenu function out of the inner if block into the outer
DOMContentLoaded scope so both the original toggle handler and the
navItems.forEach listener can call closeMenu(); update the navItems.forEach
callback to call closeMenu() instead of repeating
sidebar.classList.remove('open'), overlay.classList.remove('open') and
menuToggle.setAttribute(...), and ensure closeMenu references the same
menuToggle, sidebar and overlay variables defined in the outer scope.
- Around line 177-181: The sidebar jitter is caused by calling
item.scrollIntoView on every intersection change; modify the logic around the
isActive check to debounce/throttle those calls: introduce a short-lived timer
(or use requestAnimationFrame + a short timeout) associated with the nav item or
a module-level variable and only call item.scrollIntoView when the active state
has persisted for a small delay (e.g., 100–200ms) or when scrolling has settled;
keep the prefersReducedMotion check and only debounce when motion is allowed,
and reference the existing symbols (item, isActive, item.scrollIntoView,
prefersReducedMotion, entry.target.id / data-nav-id) so the change is localized
to this intersection callback.

In `@docs/src/styles/docs.css`:
- Around line 369-397: The scrollbar rules in docs/src/styles/docs.css
(selectors html, ::-webkit-scrollbar, ::-webkit-scrollbar-track,
::-webkit-scrollbar-thumb, ::-webkit-scrollbar-thumb:hover,
::-webkit-scrollbar-corner) duplicate globals.css but use CSS variables; either
remove this duplication by moving these rules into globals.css and replace the
hardcoded hexes there with var(--rust-orange)/var(--bg-deep), or if the docs
override is intentional, add a brief clarifying comment above these rules
stating they intentionally override globals for the docs build (or scope them to
a docs-specific container/class) so the cascade behavior is explicit.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 07c600e3-6cd5-4125-a573-d94028f56937

📥 Commits

Reviewing files that changed from the base of the PR and between 20c12dd and 0d7d871.

📒 Files selected for processing (2)
  • docs/src/pages/docs/[...slug].astro
  • docs/src/styles/docs.css

@jonathanperis jonathanperis merged commit d00a3f8 into main May 3, 2026
5 checks passed
@jonathanperis jonathanperis deleted the docs/standardize-missing-features branch May 3, 2026 01:46
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