mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-01 15:03:57 +08:00
- Introduced comprehensive documentation for the queue management feature, detailing its pain points, core functionalities, and component structure. - Added terminal dashboard documentation, highlighting its layout, core features, and usage examples. - Created an index page in Chinese for Claude Code Workflow, summarizing its purpose and core features, along with quick links to installation and guides.
608 lines
22 KiB
Markdown
608 lines
22 KiB
Markdown
# Dashboard
|
|
|
|
## One-Liner
|
|
**The Dashboard provides an at-a-glance overview of your project's workflow status, statistics, and recent activity through an intuitive widget-based interface.**
|
|
|
|
---
|
|
|
|
## Pain Points Solved
|
|
|
|
| Pain Point | Current State | Dashboard Solution |
|
|
|------------|---------------|-------------------|
|
|
| **No project visibility** | Can't see overall project health | Project info banner with tech stack and development index |
|
|
| **Scattered metrics** | Stats across multiple locations | Centralized statistics with sparklines |
|
|
| **Unknown workflow status** | Hard to track session progress | Pie chart with status breakdown |
|
|
| **Lost in recent work** | No quick access to active sessions | Session carousel with task details |
|
|
| **Indexing status unclear** | Don't know if code is indexed | Real-time index status indicator |
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
**Location**: `ccw/frontend/src/pages/HomePage.tsx`
|
|
|
|
**Purpose**: Dashboard home page providing project overview, statistics, workflow status, and recent activity monitoring.
|
|
|
|
**Access**: Navigation → Dashboard (default home page at `/`)
|
|
|
|
**Layout**:
|
|
```
|
|
+--------------------------------------------------------------------------+
|
|
| Dashboard Header (title + refresh) |
|
|
+--------------------------------------------------------------------------+
|
|
| WorkflowTaskWidget (Combined Card) |
|
|
| +--------------------------------------------------------------------+ |
|
|
| | Project Info Banner (expandable) | |
|
|
| | - Project name, description, tech stack badges | |
|
|
| | - Quick stats (features, bugfixes, enhancements) | |
|
|
| | - Index status indicator | |
|
|
| +----------------------------------+---------------------------------+ |
|
|
| | Stats Section | Workflow Status | Task Details (Carousel) | |
|
|
| | - 6 mini cards | - Pie chart | - Session nav | |
|
|
| | - Sparklines | - Legend | - Task list (2 columns) | |
|
|
| +----------------+-----------------+-------------------------------+ |
|
|
+--------------------------------------------------------------------------+
|
|
| RecentSessionsWidget |
|
|
| +--------------------------------------------------------------------+ |
|
|
| | Tabs: All Tasks | Workflow | Lite Tasks | |
|
|
| | +---------------+---------------+-------------------------------+ | |
|
|
| | | Task cards with status, progress, tags, time | | |
|
|
| | +---------------------------------------------------------------+ | |
|
|
+--------------------------------------------------------------------------+
|
|
```
|
|
|
|
---
|
|
|
|
## Live Demo
|
|
|
|
:::demo DashboardOverview
|
|
# dashboard-overview.tsx
|
|
/**
|
|
* Dashboard Overview Demo
|
|
* Shows the main dashboard layout with widgets
|
|
*/
|
|
export function DashboardOverview() {
|
|
return (
|
|
<div className="space-y-6 p-6 bg-background min-h-[600px]">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h1 className="text-2xl font-bold">Dashboard</h1>
|
|
<p className="text-sm text-muted-foreground">
|
|
Project overview and activity monitoring
|
|
</p>
|
|
</div>
|
|
<button className="px-3 py-1.5 text-sm border rounded-md hover:bg-accent">
|
|
Refresh
|
|
</button>
|
|
</div>
|
|
|
|
{/* Workflow Stats Widget */}
|
|
<div className="border rounded-lg overflow-hidden">
|
|
<div className="p-4 border-b bg-muted/30">
|
|
<h2 className="font-semibold">Project Overview & Statistics</h2>
|
|
</div>
|
|
<div className="p-4">
|
|
<div className="grid grid-cols-3 gap-4">
|
|
<div className="space-y-3">
|
|
<div className="text-xs font-medium text-muted-foreground">Statistics</div>
|
|
<div className="grid grid-cols-2 gap-2">
|
|
{[
|
|
{ label: 'Active Sessions', value: '12', color: 'text-blue-500' },
|
|
{ label: 'Total Tasks', value: '48', color: 'text-green-500' },
|
|
{ label: 'Completed', value: '35', color: 'text-emerald-500' },
|
|
{ label: 'Pending', value: '8', color: 'text-amber-500' },
|
|
].map((stat, i) => (
|
|
<div key={i} className="p-2 bg-muted/50 rounded">
|
|
<div className={`text-lg font-bold ${stat.color}`}>{stat.value}</div>
|
|
<div className="text-xs text-muted-foreground truncate">{stat.label}</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-3">
|
|
<div className="text-xs font-medium text-muted-foreground">Workflow Status</div>
|
|
<div className="flex items-center justify-center h-24">
|
|
<div className="relative w-20 h-20">
|
|
<svg className="w-full h-full -rotate-90" viewBox="0 0 36 36">
|
|
<circle cx="18" cy="18" r="15" fill="none" stroke="currentColor" strokeWidth="3" className="text-muted opacity-20"/>
|
|
<circle cx="18" cy="18" r="15" fill="none" stroke="currentColor" strokeWidth="3" className="text-blue-500" strokeDasharray="70 100"/>
|
|
</svg>
|
|
<div className="absolute inset-0 flex items-center justify-center text-xs font-bold">70%</div>
|
|
</div>
|
|
</div>
|
|
<div className="text-xs text-center space-y-1">
|
|
<div className="flex items-center justify-center gap-1">
|
|
<div className="w-2 h-2 rounded-full bg-blue-500"/>
|
|
<span>Completed: 70%</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-3">
|
|
<div className="text-xs font-medium text-muted-foreground">Recent Session</div>
|
|
<div className="p-3 bg-accent/20 rounded border">
|
|
<div className="flex items-center justify-between mb-2">
|
|
<span className="text-sm font-medium">Feature: Auth Flow</span>
|
|
<span className="text-xs px-2 py-0.5 rounded-full bg-green-500/20 text-green-600">Running</span>
|
|
</div>
|
|
<div className="space-y-1.5">
|
|
<div className="flex items-center gap-2 text-xs">
|
|
<div className="w-3 h-3 rounded bg-green-500"/>
|
|
<span>Implement login</span>
|
|
</div>
|
|
<div className="flex items-center gap-2 text-xs">
|
|
<div className="w-3 h-3 rounded bg-amber-500"/>
|
|
<span>Add OAuth</span>
|
|
</div>
|
|
<div className="flex items-center gap-2 text-xs">
|
|
<div className="w-3 h-3 rounded bg-muted"/>
|
|
<span className="text-muted-foreground">Test flow</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Recent Sessions Widget */}
|
|
<div className="border rounded-lg overflow-hidden">
|
|
<div className="border-b bg-muted/30">
|
|
<div className="flex gap-1 p-2">
|
|
{['All Tasks', 'Workflow', 'Lite Tasks'].map((tab, i) => (
|
|
<button
|
|
key={tab}
|
|
className={`px-3 py-1.5 text-xs rounded-md transition-colors ${
|
|
i === 0 ? 'bg-background text-foreground' : 'text-muted-foreground hover:bg-foreground/5'
|
|
}`}
|
|
>
|
|
{tab}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div className="p-4">
|
|
<div className="grid grid-cols-3 gap-3">
|
|
{[
|
|
{ name: 'Refactor UI Components', status: 'In Progress', progress: 65 },
|
|
{ name: 'Fix Login Bug', status: 'Pending', progress: 0 },
|
|
{ name: 'Add Dark Mode', status: 'Completed', progress: 100 },
|
|
].map((task, i) => (
|
|
<div key={i} className="p-3 bg-muted/30 rounded border cursor-pointer hover:border-primary/30">
|
|
<div className="flex items-center justify-between mb-2">
|
|
<span className="text-xs font-medium line-clamp-1">{task.name}</span>
|
|
<span className={`text-xs px-1.5 py-0.5 rounded ${
|
|
task.status === 'Completed' ? 'bg-green-500/20 text-green-600' :
|
|
task.status === 'In Progress' ? 'bg-blue-500/20 text-blue-600' :
|
|
'bg-gray-500/20 text-gray-600'
|
|
}`}>{task.status}</span>
|
|
</div>
|
|
{task.progress > 0 && task.progress < 100 && (
|
|
<div className="w-full h-1.5 bg-muted rounded-full overflow-hidden">
|
|
<div className="h-full bg-blue-500 rounded-full" style={{ width: `${task.progress}%` }}/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
:::
|
|
|
|
---
|
|
|
|
## Core Features
|
|
|
|
| Feature | Description |
|
|
|---------|-------------|
|
|
| **Project Info Banner** | Expandable banner showing project name, description, tech stack (languages, frameworks, architecture), development index (features/bugfixes/enhancements), and real-time index status |
|
|
| **Statistics Section** | 6 mini stat cards (Active Sessions, Total Tasks, Completed Tasks, Pending Tasks, Failed Tasks, Today Activity) with 7-day sparkline trends |
|
|
| **Workflow Status Pie Chart** | Donut chart showing session status breakdown (completed, in progress, planning, paused, archived) with percentages |
|
|
| **Session Carousel** | Auto-rotating (5s) session cards with task list, progress bar, and manual navigation arrows |
|
|
| **Recent Sessions Widget** | Tabbed view of recent tasks across all task types with filtering, status badges, and progress indicators |
|
|
| **Real-time Updates** | Auto-refresh every 60 seconds for stats and 30 seconds for index status |
|
|
|
|
---
|
|
|
|
## Component Hierarchy
|
|
|
|
```
|
|
HomePage
|
|
├── DashboardHeader
|
|
│ ├── Title
|
|
│ └── Refresh Action Button
|
|
├── WorkflowTaskWidget
|
|
│ ├── ProjectInfoBanner (expandable)
|
|
│ │ ├── Project Name & Description
|
|
│ │ ├── Tech Stack Badges
|
|
│ │ ├── Quick Stats Cards
|
|
│ │ ├── Index Status Indicator
|
|
│ │ ├── Architecture Section
|
|
│ │ ├── Key Components
|
|
│ │ └── Design Patterns
|
|
│ ├── Stats Section
|
|
│ │ └── MiniStatCard (6 cards with Sparkline)
|
|
│ ├── WorkflowStatusChart
|
|
│ │ └── Pie Chart with Legend
|
|
│ └── SessionCarousel
|
|
│ ├── Navigation Arrows
|
|
│ └── Session Cards (Task List)
|
|
└── RecentSessionsWidget
|
|
├── Tab Navigation (All | Workflow | Lite)
|
|
├── Task Grid
|
|
│ └── TaskItemCard
|
|
└── Loading/Empty States
|
|
```
|
|
|
|
---
|
|
|
|
## Props API
|
|
|
|
### HomePage Component
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| - | - | - | This page component accepts no props (data fetched via hooks) |
|
|
|
|
### WorkflowTaskWidget
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `className` | `string` | `undefined` | Additional CSS classes for styling |
|
|
|
|
### RecentSessionsWidget
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `className` | `string` | `undefined` | Additional CSS classes |
|
|
| `maxItems` | `number` | `6` | Maximum number of items to display |
|
|
|
|
---
|
|
|
|
## Usage Examples
|
|
|
|
### Basic Dashboard
|
|
|
|
```tsx
|
|
import { HomePage } from '@/pages/HomePage'
|
|
|
|
// The dashboard is automatically rendered at the root route (/)
|
|
// No props needed - data is fetched via hooks
|
|
```
|
|
|
|
### Embedding WorkflowTaskWidget
|
|
|
|
```tsx
|
|
import { WorkflowTaskWidget } from '@/components/dashboard/widgets/WorkflowTaskWidget'
|
|
|
|
function CustomDashboard() {
|
|
return (
|
|
<div className="p-6">
|
|
<WorkflowTaskWidget />
|
|
</div>
|
|
)
|
|
}
|
|
```
|
|
|
|
### Custom Recent Sessions Widget
|
|
|
|
```tsx
|
|
import { RecentSessionsWidget } from '@/components/dashboard/widgets/RecentSessionsWidget'
|
|
|
|
function ActivityFeed() {
|
|
return (
|
|
<div className="p-6">
|
|
<RecentSessionsWidget maxItems={10} />
|
|
</div>
|
|
)
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## State Management
|
|
|
|
### Local State
|
|
|
|
| State | Type | Description |
|
|
|-------|------|-------------|
|
|
| `hasError` | `boolean` | Error tracking for critical failures |
|
|
| `projectExpanded` | `boolean` | Project info banner expansion state |
|
|
| `currentSessionIndex` | `number` | Active session index in carousel |
|
|
| `activeTab` | `'all' \| 'workflow' \| 'lite'` | Recent sessions widget filter tab |
|
|
|
|
### Store Selectors (Zustand)
|
|
|
|
| Store | Selector | Purpose |
|
|
|-------|----------|---------|
|
|
| `appStore` | `selectIsImmersiveMode` | Check if immersive mode is active |
|
|
|
|
### Custom Hooks (Data Fetching)
|
|
|
|
| Hook | Description | Refetch Interval |
|
|
|------|-------------|------------------|
|
|
| `useWorkflowStatusCounts` | Session status distribution data | - |
|
|
| `useDashboardStats` | Statistics with sparkline data | 60 seconds |
|
|
| `useProjectOverview` | Project information and tech stack | - |
|
|
| `useIndexStatus` | Real-time index status | 30 seconds |
|
|
| `useSessions` | Active sessions data | - |
|
|
| `useLiteTasks` | Lite tasks data for recent widget | - |
|
|
|
|
---
|
|
|
|
## Interactive Demos
|
|
|
|
### Statistics Cards Demo
|
|
|
|
:::demo MiniStatCards
|
|
# mini-stat-cards.tsx
|
|
/**
|
|
* Mini Stat Cards Demo
|
|
* Individual statistics cards with sparkline trends
|
|
*/
|
|
export function MiniStatCards() {
|
|
const stats = [
|
|
{ label: 'Active Sessions', value: 12, trend: [8, 10, 9, 11, 10, 12, 12], color: 'blue' },
|
|
{ label: 'Total Tasks', value: 48, trend: [40, 42, 45, 44, 46, 47, 48], color: 'green' },
|
|
{ label: 'Completed', value: 35, trend: [25, 28, 30, 32, 33, 34, 35], color: 'emerald' },
|
|
{ label: 'Pending', value: 8, trend: [12, 10, 11, 9, 8, 7, 8], color: 'amber' },
|
|
{ label: 'Failed', value: 5, trend: [3, 4, 3, 5, 4, 5, 5], color: 'red' },
|
|
{ label: 'Today Activity', value: 23, trend: [5, 10, 15, 18, 20, 22, 23], color: 'purple' },
|
|
]
|
|
|
|
const colorMap = {
|
|
blue: 'text-blue-500 bg-blue-500/10',
|
|
green: 'text-green-500 bg-green-500/10',
|
|
emerald: 'text-emerald-500 bg-emerald-500/10',
|
|
amber: 'text-amber-500 bg-amber-500/10',
|
|
red: 'text-red-500 bg-red-500/10',
|
|
purple: 'text-purple-500 bg-purple-500/10',
|
|
}
|
|
|
|
return (
|
|
<div className="p-6 bg-background">
|
|
<h3 className="text-sm font-semibold mb-4">Statistics with Sparklines</h3>
|
|
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
|
{stats.map((stat, i) => (
|
|
<div key={i} className="p-4 border rounded-lg bg-card">
|
|
<div className="flex items-center justify-between mb-2">
|
|
<span className="text-xs text-muted-foreground">{stat.label}</span>
|
|
<div className={`w-2 h-2 rounded-full ${colorMap[stat.color].split(' ')[1]}`}/>
|
|
</div>
|
|
<div className={`text-2xl font-bold ${colorMap[stat.color].split(' ')[0]}`}>{stat.value}</div>
|
|
<div className="mt-2 h-8 flex items-end gap-0.5">
|
|
{stat.trend.map((v, j) => (
|
|
<div
|
|
key={j}
|
|
className="flex-1 rounded-t"
|
|
style={{
|
|
height: `${(v / Math.max(...stat.trend)) * 100}%`,
|
|
backgroundColor: v === stat.value ? 'currentColor' : 'rgba(59, 130, 246, 0.3)',
|
|
}}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
:::
|
|
|
|
### Project Info Banner Demo
|
|
|
|
:::demo ProjectInfoBanner
|
|
# project-info-banner.tsx
|
|
/**
|
|
* Project Info Banner Demo
|
|
* Expandable project information with tech stack
|
|
*/
|
|
export function ProjectInfoBanner() {
|
|
const [expanded, setExpanded] = React.useState(false)
|
|
|
|
return (
|
|
<div className="p-6 bg-background">
|
|
<h3 className="text-sm font-semibold mb-4">Project Info Banner</h3>
|
|
<div className="border rounded-lg overflow-hidden">
|
|
{/* Banner Header */}
|
|
<div className="p-4 bg-muted/30 flex items-center justify-between">
|
|
<div>
|
|
<h4 className="font-semibold">My Awesome Project</h4>
|
|
<p className="text-sm text-muted-foreground">A modern web application built with React</p>
|
|
</div>
|
|
<button
|
|
onClick={() => setExpanded(!expanded)}
|
|
className="p-2 rounded-md hover:bg-accent"
|
|
>
|
|
<svg className={`w-5 h-5 transition-transform ${expanded ? 'rotate-180' : ''}`} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
{/* Tech Stack Badges */}
|
|
<div className="px-4 pb-3 flex flex-wrap gap-2">
|
|
{['TypeScript', 'React', 'Vite', 'Tailwind CSS', 'Zustand'].map((tech) => (
|
|
<span key={tech} className="px-2 py-1 text-xs rounded-full bg-primary/10 text-primary">
|
|
{tech}
|
|
</span>
|
|
))}
|
|
</div>
|
|
|
|
{/* Expanded Content */}
|
|
{expanded && (
|
|
<div className="p-4 border-t bg-muted/20 space-y-4">
|
|
<div>
|
|
<h5 className="text-xs font-semibold mb-2">Architecture</h5>
|
|
<div className="text-sm text-muted-foreground space-y-1">
|
|
<div>• Component-based UI architecture</div>
|
|
<div>• Centralized state management</div>
|
|
<div>• RESTful API integration</div>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<h5 className="text-xs font-semibold mb-2">Key Components</h5>
|
|
<div className="grid grid-cols-2 gap-2 text-sm">
|
|
{['Session Manager', 'Dashboard', 'Task Scheduler', 'Analytics'].map((comp) => (
|
|
<div key={comp} className="flex items-center gap-2">
|
|
<div className="w-1.5 h-1.5 rounded-full bg-primary"/>
|
|
{comp}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
:::
|
|
|
|
### Session Carousel Demo
|
|
|
|
:::demo SessionCarousel
|
|
# session-carousel.tsx
|
|
/**
|
|
* Session Carousel Demo
|
|
* Auto-rotating session cards with navigation
|
|
*/
|
|
export function SessionCarousel() {
|
|
const [currentIndex, setCurrentIndex] = React.useState(0)
|
|
const sessions = [
|
|
{
|
|
name: 'Feature: User Authentication',
|
|
status: 'running',
|
|
tasks: [
|
|
{ name: 'Implement login form', status: 'completed' },
|
|
{ name: 'Add OAuth provider', status: 'in-progress' },
|
|
{ name: 'Create session management', status: 'pending' },
|
|
],
|
|
},
|
|
{
|
|
name: 'Bug Fix: Memory Leak',
|
|
status: 'running',
|
|
tasks: [
|
|
{ name: 'Identify leak source', status: 'completed' },
|
|
{ name: 'Fix cleanup handlers', status: 'in-progress' },
|
|
{ name: 'Add unit tests', status: 'pending' },
|
|
],
|
|
},
|
|
{
|
|
name: 'Refactor: API Layer',
|
|
status: 'planning',
|
|
tasks: [
|
|
{ name: 'Design new interface', status: 'pending' },
|
|
{ name: 'Migrate existing endpoints', status: 'pending' },
|
|
{ name: 'Update documentation', status: 'pending' },
|
|
],
|
|
},
|
|
]
|
|
|
|
const statusColors = {
|
|
completed: 'bg-green-500',
|
|
'in-progress': 'bg-amber-500',
|
|
pending: 'bg-muted',
|
|
}
|
|
|
|
React.useEffect(() => {
|
|
const timer = setInterval(() => {
|
|
setCurrentIndex((i) => (i + 1) % sessions.length)
|
|
}, 5000)
|
|
return () => clearInterval(timer)
|
|
}, [sessions.length])
|
|
|
|
return (
|
|
<div className="p-6 bg-background">
|
|
<h3 className="text-sm font-semibold mb-4">Session Carousel (auto-rotates every 5s)</h3>
|
|
<div className="border rounded-lg p-4 bg-card">
|
|
<div className="flex items-center justify-between mb-3">
|
|
<span className="text-sm font-medium">Session {currentIndex + 1} of {sessions.length}</span>
|
|
<div className="flex gap-1">
|
|
{sessions.map((_, i) => (
|
|
<button
|
|
key={i}
|
|
onClick={() => setCurrentIndex(i)}
|
|
className={`w-2 h-2 rounded-full transition-colors ${
|
|
i === currentIndex ? 'bg-primary' : 'bg-muted-foreground/30'
|
|
}`}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="p-4 bg-accent/20 rounded border">
|
|
<div className="flex items-center justify-between mb-3">
|
|
<span className="font-medium">{sessions[currentIndex].name}</span>
|
|
<span className={`text-xs px-2 py-1 rounded-full ${
|
|
sessions[currentIndex].status === 'running' ? 'bg-green-500/20 text-green-600' : 'bg-blue-500/20 text-blue-600'
|
|
}`}>
|
|
{sessions[currentIndex].status}
|
|
</span>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
{sessions[currentIndex].tasks.map((task, i) => (
|
|
<div key={i} className="flex items-center gap-2 text-sm">
|
|
<div className={`w-3 h-3 rounded ${statusColors[task.status]}`}/>
|
|
<span className={task.status === 'pending' ? 'text-muted-foreground' : ''}>{task.name}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex justify-between mt-3">
|
|
<button
|
|
onClick={() => setCurrentIndex((i) => (i - 1 + sessions.length) % sessions.length)}
|
|
className="px-3 py-1.5 text-sm border rounded-md hover:bg-accent"
|
|
>
|
|
← Previous
|
|
</button>
|
|
<button
|
|
onClick={() => setCurrentIndex((i) => (i + 1) % sessions.length)}
|
|
className="px-3 py-1.5 text-sm border rounded-md hover:bg-accent"
|
|
>
|
|
Next →
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
:::
|
|
|
|
---
|
|
|
|
## Accessibility
|
|
|
|
- **Keyboard Navigation**:
|
|
- <kbd>Tab</kbd> - Navigate through interactive elements
|
|
- <kbd>Enter</kbd>/<kbd>Space</kbd> - Activate buttons and cards
|
|
- <kbd>Arrow</kbd> keys - Navigate carousel sessions
|
|
|
|
- **ARIA Attributes**:
|
|
- `aria-label` on navigation buttons
|
|
- `aria-expanded` on expandable sections
|
|
- `aria-live` regions for real-time updates
|
|
|
|
- **Screen Reader Support**:
|
|
- All charts have text descriptions
|
|
- Status indicators include text labels
|
|
- Navigation is announced properly
|
|
|
|
---
|
|
|
|
## Related Links
|
|
|
|
- [Sessions](/features/sessions) - View and manage all sessions
|
|
- [Terminal Dashboard](/features/terminal) - Terminal-first monitoring interface
|
|
- [Queue](/features/queue) - Issue execution queue management
|
|
- [Memory](/features/memory) - Persistent memory management
|
|
- [Settings](/features/settings) - Global application settings
|