feat(FN-1470): implement ScreenRouter with tab bar and keyboard navigation

- Add ScreenRouter component for multi-screen navigation in TUI
- Implement tab bar with icon labels and active state indicators
- Support keyboard navigation with arrow keys and Tab/Shift+Tab
- Add mouse click support for tab selection
- Export new screen router components from package index
- Add comprehensive unit tests for navigation behavior
- Update documentation with architecture and gap analysis
- Update TUI README with ScreenRouter usage examples
This commit is contained in:
gsxdsm
2026-04-09 20:59:00 -07:00
parent 44d2198032
commit cc4382835d
8 changed files with 551 additions and 19 deletions

View File

@@ -96,12 +96,84 @@ const projectPath = detectProjectDir("/Users/me/code/my-project/src");
The absolute path to the project root, or `null` if no project directory is detected.
### ScreenRouter
The `ScreenRouter` component provides a keyboard-navigable tab bar for switching between application screens.
```tsx
import { ScreenRouter } from "@fusion/tui";
function App() {
return (
<ScreenRouter>
{({ activeScreen }) => (
<>
{activeScreen === "board" && <BoardScreen />}
{activeScreen === "detail" && <DetailScreen />}
{activeScreen === "activity" && <ActivityScreen />}
{activeScreen === "agents" && <AgentsScreen />}
{activeScreen === "settings" && <SettingsScreen />}
</>
)}
</ScreenRouter>
);
}
```
#### Available Screens
The router manages five screens in this order:
| Index | Screen ID | Label | Shortcut |
|-------|-----------|-------|----------|
| 1 | `board` | Board | `1` |
| 2 | `detail` | Detail | `2` |
| 3 | `activity` | Activity | `3` |
| 4 | `agents` | Agents | `4` |
| 5 | `settings` | Settings | `5` |
#### Keyboard Navigation
| Key | Action |
|-----|--------|
| `1` - `5` | Jump directly to the corresponding tab |
| `Tab` | Cycle forward through tabs (wraps from end to start) |
| `Shift+Tab` | Cycle backward through tabs (wraps from start to end) |
#### Tab Bar Rendering
The tab bar displays all five tabs horizontally with:
- Active tab highlighted with bold text, cyan background, and black text
- Inactive tabs shown in white text
- A border line below the tab bar
#### Props
| Prop | Type | Description |
|------|------|-------------|
| `children` | `(props: ScreenComponentProps) => React.ReactNode` | Render function that receives `activeScreen` and returns the screen content |
#### ScreenComponentProps
| Property | Type | Description |
|----------|------|-------------|
| `activeScreen` | `ScreenId` | The currently active screen ID (`"board"` \| `"detail"` \| `"activity"` \| `"agents"` \| `"settings"`) |
#### Exports
The following are exported from `@fusion/tui`:
- `ScreenRouter` — The main router component
- `SCREENS` — Array of screen definitions with `id`, `label`, and `shortcut`
- `getScreenById(id)` — Get screen definition by ID
- `getScreenIndex(id)` — Get screen index by ID
- `type ScreenId` — Type for screen identifiers
## Example
```tsx
import React from "react";
import { render, Box, Text } from "ink";
import { FusionProvider, useFusion } from "@fusion/tui";
import { FusionProvider, useFusion, ScreenRouter } from "@fusion/tui";
function ProjectInfo() {
const { store, projectPath } = useFusion();
@@ -121,7 +193,23 @@ function ProjectInfo() {
render(
<FusionProvider>
<ProjectInfo />
<ScreenRouter>
{({ activeScreen }) => (
<Box flexDirection="column">
<Text bold>Fusion TUI</Text>
{activeScreen === "board" && (
<Box>
<Text>Board Screen - Use 1-5 to switch tabs</Text>
</Box>
)}
{activeScreen === "detail" && (
<Box>
<Text>Detail Screen</Text>
</Box>
)}
</Box>
)}
</ScreenRouter>
</FusionProvider>
);
```