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:
@@ -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>
|
||||
);
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user