Skip to content

feat(frontend): add Sidebar component (T-128)#62

Merged
mpiton merged 1 commit into
mainfrom
feat/T-128-sidebar
May 10, 2026
Merged

feat(frontend): add Sidebar component (T-128)#62
mpiton merged 1 commit into
mainfrom
feat/T-128-sidebar

Conversation

@mpiton
Copy link
Copy Markdown
Owner

@mpiton mpiton commented May 10, 2026

Closes #43.

Summary

  • src/features/onboarding/components/Sidebar.tsx + Sidebar.test.tsx — collapsible left-nav Sidebar (T-128, F-068, blocks T-130 App.tsx mount).
  • 5 nav links (tasks/roadmap/insights/ideation/settings) with Lucide icons + i18n labels, Tooltip wrap when collapsed, 4 inert bottom indicator pills (placeholders for S5/S6).
  • Width transitions w-60 ↔ w-16 via transition-[width] duration-200 ease-in-out.

Why

Sprint 1 deliverable per DESIGN S2 / PRD F-068. Visible app shell that subsequent sprints (T-130 mount, S5 indicators, S6 telemetry) depend on.

Changes

  • src/features/onboarding/components/Sidebar.tsx — props { expanded, onToggle, activeRoute, onNavigate }, top PanelLeft/PanelLeftClose toggle, roving tabindex (activeRoute item is tabIndex=0, others -1), ArrowDown/ArrowUp keyboard nav with modulo wrap-around.
  • src/features/onboarding/components/Sidebar.test.tsx — 13 vitest cases across 3 describe blocks (rendering / interactions / accessibility). Module-level afterEach(cleanup) to prevent landmark bleed across consecutive renders.
  • src/shared/i18n/locales/{en,fr}.json — new keys sidebar.landmark (Sidebar / Barre latérale) and sidebar.navigation (Main navigation / Navigation principale) for <aside aria-label> + <nav aria-label>.
  • CHANGELOG.md[Unreleased] / Added entry.

Accessibility

  • <aside aria-label> + <nav aria-label> translated landmarks.
  • aria-current="page" on active nav item.
  • aria-label on every nav button so screen readers announce labels even when collapsed (icon is aria-hidden, no visible text in collapsed mode).
  • Roving tabindex pattern (only one tabbable item, arrow keys move focus).
  • aria-expanded on toggle button.
  • focus-visible:ring-2 inherited from Button primitive.

Testing

  • pnpm exec tsc -b — clean.
  • pnpm exec oxlint src/features/onboarding — 0 warnings / 0 errors after fixing sort-imports (multi → single ordering with case-sensitive alphabetical), array-type (Array<X>(X)[]), max-statements (split single describe with 13 it into 3 describes ≤6 each), id-length (useT translator aliased to translate), and no-magic-numbers (extracted FOCUS_STEP_NEXT/FOCUS_STEP_PREV/TAB_INDEX_FOCUSED/TAB_INDEX_INERT).
  • pnpm exec oxfmt --check — clean.
  • pnpm exec vitest run80/80 pass (13 new for Sidebar).

Acceptance criteria (from #43)

  • pnpm exec tsc -b no errors
  • pnpm exec vitest run features/onboarding/Sidebar passes
  • Width transitions smoothly between 64px and 240px
  • Collapsed mode shows tooltips on hover
  • Active route shows visible state
  • Keyboard ArrowUp/ArrowDown navigates between items
  • Lighthouse a11y ≥ 95 — manual run pending app mount (T-130)

Test plan

  • CI green (tsc, oxlint, oxfmt, vitest, knip, cargo deny)
  • Visual check after T-130 mount in App.tsx
  • Lighthouse a11y audit once Sidebar renders in dev shell

Summary by CodeRabbit

  • New Features
    • Added collapsible onboarding Sidebar component with expand/collapse toggle
    • Keyboard navigation via arrow keys and active route highlighting
    • Tooltips display navigation labels when sidebar is collapsed
    • Full accessibility support including ARIA landmarks and keyboard focus management
    • English and French translations included

Review Change Stack

Closes #43.

- src/features/onboarding/components/Sidebar.tsx — collapsible left nav
  (240px <-> 64px) with 5 nav links, Lucide icons, i18n labels,
  Tooltip on hover when collapsed, 4 placeholder bottom pills.
- Roving tabindex + ArrowUp/ArrowDown keyboard nav with wrap-around.
- aria-label on all nav buttons so screen readers announce when
  collapsed (icon is aria-hidden), aria-current="page" on active.
- New i18n keys sidebar.landmark / sidebar.navigation in en + fr.
- 13 vitest cases / pnpm exec tsc -b / oxlint / oxfmt / vitest 80/80
  all clean.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 10, 2026

📝 Walkthrough

Walkthrough

This PR introduces a new collapsible onboarding Sidebar component supporting 5 navigation routes, expand/collapse toggle, keyboard arrow navigation, tooltips when collapsed, i18n labels in English and French, and comprehensive accessibility features including roving tabindex and aria-current states.

Changes

Onboarding Sidebar Component

Layer / File(s) Summary
Types and Component Interface
src/features/onboarding/components/Sidebar.tsx
Exported SidebarRoute type ("tasks" | "roadmap" | "insights" | "ideation" | "settings") and Sidebar component function with props for expanded, onToggle, activeRoute, and onNavigate.
Navigation Configuration
src/features/onboarding/components/Sidebar.tsx
NAV_ITEMS array maps routes to Lucide icons and i18n label keys; constants defined for pill styling and keyboard focus behavior.
Keyboard Navigation Logic
src/features/onboarding/components/Sidebar.tsx
Focus management using refs array for nav buttons and keyboard handler supporting ArrowUp/ArrowDown with index wraparound.
Component Rendering
src/features/onboarding/components/Sidebar.tsx
Sidebar layout with expandable container (64px ↔ 240px), toggle button, navigation buttons with active route highlighting, tooltips when collapsed, and bottom status pills.
Internationalization
src/shared/i18n/locales/en.json, src/shared/i18n/locales/fr.json
Added sidebar.landmark and sidebar.navigation translation keys in English ("Sidebar", "Main navigation") and French ("Barre latérale", "Navigation principale").
Test Setup and Rendering
src/features/onboarding/components/Sidebar.test.tsx
Test helper renderSidebar, lifecycle setup for i18n and cleanup, and rendering suite covering nav item labels, landmark labels (English/French), width classes, and indicator text content.
Interaction Tests
src/features/onboarding/components/Sidebar.test.tsx
Verify onToggle callback on collapse/expand, correct button labels when collapsed, and onNavigate callback with expected route key.
Accessibility and Keyboard Tests
src/features/onboarding/components/Sidebar.test.tsx
Verify aria-current="page" on active route, roving tabindex (only active item tabbable), ArrowUp/ArrowDown navigation with wraparound, accessible names when collapsed, and async focus updates.
Documentation
CHANGELOG.md
Changelog entry documenting Sidebar props, behavior, accessibility attributes, i18n additions, and test coverage.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • mpiton/forgent#59: i18n setup providing the foundational locale structure and configuration that this PR extends with sidebar-specific translation keys.

Poem

🐰 Hop, skip, and sidebar leap!
Five nav routes in a bundle so neat,
Collapsed and expanded with keyboard delight,
Tooltips and focus in accessible light—
A fuzzy friend's navigation complete!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

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.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(frontend): add Sidebar component (T-128)' accurately and concisely describes the main change—introducing a new Sidebar component for the onboarding feature.
Linked Issues check ✅ Passed The PR implements all major coding requirements from issue #43 (T-128): collapsible Sidebar with two widths, navigation links with icons/i18n, keyboard navigation with roving tabindex, aria-current for active route, tooltip wrapping when collapsed, bottom indicator pills, comprehensive tests, and clean typecheck/linting.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #43 (T-128): Sidebar component, tests, i18n translations, and CHANGELOG documentation. No unrelated modifications are present.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/T-128-sidebar

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 (1)
src/features/onboarding/components/Sidebar.tsx (1)

32-44: ⚡ Quick win

Remove duplicated route/labelKey source of truth.

Line 35 duplicates the same domain already represented by route, which can drift later. Prefer deriving labels directly from route.

♻️ Proposed simplification
 interface NavItem {
   route: SidebarRoute;
   icon: ComponentType<{ className?: string }>;
-  labelKey: "tasks" | "roadmap" | "insights" | "ideation" | "settings";
 }

 const NAV_ITEMS: readonly NavItem[] = [
-  { route: "tasks", icon: CheckSquare, labelKey: "tasks" },
-  { route: "roadmap", icon: Map, labelKey: "roadmap" },
-  { route: "insights", icon: MessageSquare, labelKey: "insights" },
-  { route: "ideation", icon: Lightbulb, labelKey: "ideation" },
-  { route: "settings", icon: Settings, labelKey: "settings" },
+  { route: "tasks", icon: CheckSquare },
+  { route: "roadmap", icon: Map },
+  { route: "insights", icon: MessageSquare },
+  { route: "ideation", icon: Lightbulb },
+  { route: "settings", icon: Settings },
 ] as const;

-const label = translate(item.labelKey);
+const label = translate(item.route);

Also applies to: 100-101

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/onboarding/components/Sidebar.tsx` around lines 32 - 44, Remove
the duplicated labelKey property: update the NavItem type to omit labelKey and
change NAV_ITEMS to only include route and icon (keep the same route strings
like "tasks", "roadmap", etc.), then change any usage of item.labelKey in the
Sidebar rendering to derive the label key from item.route (e.g., use item.route
as the translation key or a small helper like getLabelKeyFromRoute(route)), and
apply the same removal/fix for the other duplicate array in this file that also
defines route+labelKey; ensure all references now use the derived label key
instead of the removed property.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/features/onboarding/components/Sidebar.tsx`:
- Around line 32-44: Remove the duplicated labelKey property: update the NavItem
type to omit labelKey and change NAV_ITEMS to only include route and icon (keep
the same route strings like "tasks", "roadmap", etc.), then change any usage of
item.labelKey in the Sidebar rendering to derive the label key from item.route
(e.g., use item.route as the translation key or a small helper like
getLabelKeyFromRoute(route)), and apply the same removal/fix for the other
duplicate array in this file that also defines route+labelKey; ensure all
references now use the derived label key instead of the removed property.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d5b659d1-3a1e-4fd3-8fa2-0b6fa3a0a6a6

📥 Commits

Reviewing files that changed from the base of the PR and between 9d5eab3 and ec7bcbf.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • src/features/onboarding/components/Sidebar.test.tsx
  • src/features/onboarding/components/Sidebar.tsx
  • src/shared/i18n/locales/en.json
  • src/shared/i18n/locales/fr.json

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 10, 2026

Merging this PR will not alter performance

✅ 7 untouched benchmarks


Comparing feat/T-128-sidebar (ec7bcbf) with main (9d5eab3)

Open in CodSpeed

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 5 files

@mpiton mpiton merged commit 474716c into main May 10, 2026
14 checks passed
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.

[T-128] features/onboarding/Sidebar.tsx

1 participant