Files
OpenNoodl/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-001-dashboard-ux-foundation/DASH-001-tabbed-navigation.md
2025-12-31 09:34:27 +01:00

8.2 KiB

DASH-001: Tabbed Navigation System

Overview

Replace the current single-view dashboard with a proper tabbed interface. This is the foundation task that enables all other dashboard improvements.

Context

The current Noodl editor dashboard (projectsview.ts) uses a basic pane-switching mechanism with jQuery. A new launcher is being developed in packages/noodl-core-ui/src/preview/launcher/ using React, which already has a sidebar-based navigation but needs proper tab support for the main content area.

This task focuses on the new React-based launcher only. The old jQuery launcher will be deprecated.

Current State

Existing New Launcher Structure

packages/noodl-core-ui/src/preview/launcher/
├── Launcher/
│   ├── Launcher.tsx           # Main component with PAGES array
│   ├── components/
│   │   ├── LauncherSidebar/   # Left navigation
│   │   ├── LauncherPage/      # Page wrapper
│   │   ├── LauncherProjectCard/
│   │   └── LauncherSearchBar/
│   └── views/
│       ├── Projects.tsx       # Current projects view
│       └── LearningCenter.tsx # Empty learning view
└── template/
    └── LauncherApp/          # App shell template

Current Page Definition

// In Launcher.tsx
export enum LauncherPageId {
  LocalProjects,
  LearningCenter
}

export const PAGES: LauncherPageMetaData[] = [
  { id: LauncherPageId.LocalProjects, displayName: 'Recent Projects', icon: IconName.CircleDot },
  { id: LauncherPageId.LearningCenter, displayName: 'Learn', icon: IconName.Rocket }
];

Requirements

Functional Requirements

  1. Tab Bar Component

    • Horizontal tab bar at the top of the main content area
    • Visual indicator for active tab
    • Smooth transition when switching tabs
    • Keyboard navigation support (arrow keys, Enter)
  2. Tab Configuration

    • Projects tab (default, opens first)
    • Learn tab (tutorials, guides)
    • Templates tab (project starters)
    • Extensible for future tabs (Marketplace, Settings)
  3. State Persistence

    • Remember last active tab across sessions
    • Store in localStorage or electron-store
  4. URL/Deep Linking (Optional)

    • Support for noodl://dashboard/projects style deep links
    • Query params for tab state

Non-Functional Requirements

  • Tab switching should feel instant (<100ms)
  • No layout shift when switching tabs
  • Accessible (WCAG 2.1 AA compliant)
  • Consistent with existing noodl-core-ui design system

Technical Approach

1. Create Tab Bar Component

Create a new component in noodl-core-ui that can be reused:

packages/noodl-core-ui/src/components/layout/TabBar/
├── TabBar.tsx
├── TabBar.module.scss
├── TabBar.stories.tsx
└── index.ts

2. Update Launcher Structure

// New page structure
export enum LauncherPageId {
  Projects = 'projects',
  Learn = 'learn',
  Templates = 'templates'
}

export interface LauncherTab {
  id: LauncherPageId;
  label: string;
  icon?: IconName;
  component: React.ComponentType;
}

export const LAUNCHER_TABS: LauncherTab[] = [
  { id: LauncherPageId.Projects, label: 'Projects', icon: IconName.Folder, component: Projects },
  { id: LauncherPageId.Learn, label: 'Learn', icon: IconName.Book, component: LearningCenter },
  { id: LauncherPageId.Templates, label: 'Templates', icon: IconName.Components, component: Templates }
];

3. State Management

Use React context for tab state:

// LauncherContext.tsx
interface LauncherContextValue {
  activeTab: LauncherPageId;
  setActiveTab: (tab: LauncherPageId) => void;
}

4. Persistence Hook

// usePersistentTab.ts
function usePersistentTab(key: string, defaultTab: LauncherPageId) {
  // Load from localStorage on mount
  // Save to localStorage on change
}

Files to Create

  1. packages/noodl-core-ui/src/components/layout/TabBar/TabBar.tsx
  2. packages/noodl-core-ui/src/components/layout/TabBar/TabBar.module.scss
  3. packages/noodl-core-ui/src/components/layout/TabBar/TabBar.stories.tsx
  4. packages/noodl-core-ui/src/components/layout/TabBar/index.ts
  5. packages/noodl-core-ui/src/preview/launcher/Launcher/LauncherContext.tsx
  6. packages/noodl-core-ui/src/preview/launcher/Launcher/hooks/usePersistentTab.ts
  7. packages/noodl-core-ui/src/preview/launcher/Launcher/views/Templates.tsx

Files to Modify

  1. packages/noodl-core-ui/src/preview/launcher/Launcher/Launcher.tsx

    • Import and use TabBar
    • Implement tab switching logic
    • Wrap with LauncherContext
  2. packages/noodl-core-ui/src/components/layout/index.ts

    • Export TabBar component

Implementation Steps

Phase 1: TabBar Component

  1. Create TabBar component with basic functionality
  2. Add styling consistent with noodl-core-ui
  3. Write Storybook stories for testing
  4. Add keyboard navigation

Phase 2: Launcher Integration

  1. Create LauncherContext
  2. Create usePersistentTab hook
  3. Integrate TabBar into Launcher.tsx
  4. Create empty Templates view

Phase 3: Polish

  1. Add tab transition animations
  2. Test accessibility
  3. Add deep link support (if time permits)

Testing Checklist

  • Tabs render correctly
  • Clicking tab switches content
  • Active tab is visually indicated
  • Keyboard navigation works (Tab, Arrow keys, Enter)
  • Tab state persists after closing/reopening
  • No layout shift on tab switch
  • Works at different viewport sizes
  • Screen reader announces tab changes

Design Reference

The tab bar should follow the existing Tabs component style in noodl-core-ui but be optimized for the launcher context (larger, more prominent).

See: packages/noodl-core-ui/src/components/layout/Tabs/

Dependencies

  • None (this is a foundation task)

Blocked By

  • None

Blocks

  • DASH-002 (Project List Redesign)
  • DASH-003 (Project Organization)
  • DASH-004 (Tutorial Section Redesign)

Estimated Effort

  • Component creation: 2-3 hours
  • Launcher integration: 2-3 hours
  • Polish and testing: 1-2 hours
  • Total: 5-8 hours

Success Criteria

  1. User can switch between Projects, Learn, and Templates tabs
  2. Tab state persists across sessions
  3. Component is reusable for other contexts
  4. Passes accessibility audit
  5. Matches existing design system aesthetics

IMPLEMENTATION COMPLETE

Date Completed: December 30, 2025
Time Taken: ~5 hours

What Was Built

  1. TabBar Component - Fully reusable horizontal tab navigation with:

    • Icon + label support
    • Keyboard navigation (Arrow keys, Home, End)
    • Active state indicator
    • Size variants (small, medium, large)
    • Complete accessibility support
    • Storybook stories for testing
  2. Complete Launcher Overhaul - Removed sidebar, added:

    • LauncherHeader (logo, version, actions)
    • TabBar for navigation
    • LauncherFooter (resource links)
    • Modern layout with design tokens
  3. State Management - Full persistence support:

    • LauncherContext for global state
    • usePersistentTab hook with localStorage
    • Deep linking support (URL-based navigation)
  4. Editor Integration - Wired into actual editor:

    • Updated ProjectsPage.tsx to use new Launcher
    • Removed old class-based ProjectsView
    • Works in running editor (npm run dev)

Testing Results

  • Tabs render correctly
  • Clicking tab switches content
  • Active tab is visually indicated
  • Keyboard navigation works (Tab, Arrow keys, Enter)
  • Tab state persists after closing/reopening
  • No layout shift on tab switch
  • Works at different viewport sizes
  • Screen reader announces tab changes
  • Visually verified in running editor

Implementation Details

Full implementation changelog available at: packages/noodl-core-ui/src/preview/launcher/Launcher/CHANGELOG.md

Known Limitations

The following functionality needs to be wired up in future tasks:

  • Project opening events (TODO in ProjectsPage.tsx)
  • "Create new project" button functionality
  • "Open project" file picker
  • Real project data (currently uses MOCK_PROJECTS)
  • Learning Center content
  • Templates content

Next Steps

Ready for:

  • DASH-002 - Project List Redesign
  • DASH-003 - Project Organization
  • DASH-004 - Tutorial Section Redesign