Skip to content

Commit 57172c5

Browse files
jonathanlabclaude
andauthored
Add plus button tab (#54)
Co-authored-by: Claude <[email protected]>
1 parent b00baa9 commit 57172c5

File tree

5 files changed

+218
-3
lines changed

5 files changed

+218
-3
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
I'll analyze the codebase to create a detailed implementation plan for adding a plus button tab based on the requirements.
2+
Now let me check how the command menu is implemented to understand how to open it:
3+
Perfect! Now let me check for the PlusIcon import to confirm it's available:
4+
Excellent! Now I have all the information I need. Let me create a comprehensive implementation plan based on the requirements:
5+
6+
**Requirements Summary:**
7+
1. Add a plus button tab next to existing tabs
8+
2. Should be inside the scrollable area
9+
3. Should match tab styling
10+
4. Should open the Command Box when clicked
11+
# Implementation Plan: Add Plus Button Tab
12+
13+
**Task ID:** eab37807-a48e-410a-90de-3cd2ad0bf59a
14+
**Generated:** 2025-10-22
15+
16+
## Summary
17+
18+
Add a plus button tab positioned after the last tab within the scrollable tab bar area. The button will match existing tab styling and open the Command Menu (Command Box) when clicked. This provides a quick visual way for users to access the command palette without keyboard shortcuts.
19+
20+
## Implementation Steps
21+
22+
### 1. Analysis ✓
23+
- ✅ Identified TabBar component location: `/Users/jonathan/dev/Array/src/renderer/components/TabBar.tsx`
24+
- ✅ Reviewed tab styling patterns: borders, hover states, transitions
25+
- ✅ Confirmed PlusIcon availability from `@radix-ui/react-icons`
26+
- ✅ Identified Command Menu integration pattern in MainLayout
27+
28+
### 2. Core Implementation
29+
- [ ] Add `onOpenCommandMenu` callback prop to TabBar component
30+
- [ ] Import PlusIcon from `@radix-ui/react-icons`
31+
- [ ] Add plus button inside scrollable Flex container, after the tabs.map() loop
32+
- [ ] Style button to match tab appearance (same height, borders, colors, hover states)
33+
- [ ] Wire up onClick handler to call `onOpenCommandMenu`
34+
- [ ] Ensure button scrolls with tabs (already inside scrollable container)
35+
36+
### 3. Integration with MainLayout
37+
- [ ] Pass `setCommandMenuOpen` callback to TabBar as `onOpenCommandMenu` prop
38+
- [ ] Test that clicking plus button opens the Command Menu
39+
40+
## File Changes
41+
42+
### Modified Files
43+
44+
**`/Users/jonathan/dev/Array/src/renderer/components/TabBar.tsx`**
45+
- Add `onOpenCommandMenu?: () => void` to component props interface
46+
- Import `PlusIcon` from `@radix-ui/react-icons`
47+
- Add plus button element after tabs.map() loop, inside the scrollable Flex container
48+
- Style to match tab appearance:
49+
- Same 40px height constraint
50+
- Similar border styling (border-gray-6, border-r)
51+
- Same hover state (hover:bg-gray-3, hover:text-gray-12)
52+
- Text color: text-gray-11 (muted state)
53+
- Padding: px-4 (matches tabs)
54+
- Transitions: transition-colors
55+
- Use Flex for centering the icon
56+
- Apply `no-drag` class for proper window dragging behavior
57+
58+
**`/Users/jonathan/dev/Array/src/renderer/components/MainLayout.tsx`**
59+
- Pass `onOpenCommandMenu={() => setCommandMenuOpen(true)}` prop to `<TabBar />` component
60+
61+
## Considerations
62+
63+
### Design Decisions
64+
- **Positioning**: Inside scrollable area (as specified) - button will scroll with tabs if many tabs are open
65+
- **Styling**: Matches tab appearance with subtle differentiation (no active state since it's an action button)
66+
- **Icon**: Using PlusIcon which is consistent with existing UI patterns in the app
67+
68+
### Visual Consistency
69+
- Button uses same height (40px) as tabs
70+
- Same border and spacing treatment
71+
- Same hover interaction pattern
72+
- Subtle appearance to not compete with tabs, but discoverable
73+
74+
### Interaction Behavior
75+
- Clicking opens Command Menu (same as Cmd+K, Cmd+P, Cmd+T shortcuts)
76+
- Button remains visible but scrolls with tabs when needed
77+
- No active/selected state needed (it's a trigger, not a destination)
78+
79+
### Accessibility
80+
- Uses semantic button interaction
81+
- Consistent with existing keyboard shortcuts
82+
- Visual icon is universally understood (plus = add/create/open)
83+
84+
### Edge Cases
85+
- Button will scroll if tabs overflow (matches spec: "inside scrollable area")
86+
- Works independently of tab count
87+
- Does not interfere with drag-and-drop tab reordering
88+
89+
### Testing Approach
90+
1. Verify plus button appears after last tab
91+
2. Confirm button matches tab styling visually
92+
3. Test clicking opens Command Menu
93+
4. Verify button scrolls with tabs when many tabs are open
94+
5. Ensure hover states work correctly
95+
6. Check that tab drag-and-drop still works
96+
7. Test with different tab counts (1 tab, many tabs)
97+
98+
---
99+
100+
*Generated by PostHog Agent*
101+
102+
The plan is ready for your review! This is a straightforward implementation that requires:
103+
- **2 files modified** (TabBar.tsx and MainLayout.tsx)
104+
- **No new files needed**
105+
- **Simple prop passing** to wire up the command menu
106+
107+
The plus button will be visually integrated with the existing tabs while serving as a discoverable trigger for the Command Menu.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"questions": [
3+
{
4+
"id": "1",
5+
"question": "What should the plus button do when clicked?",
6+
"options": ["Open task modal", "Create new tab", "Something else"]
7+
},
8+
{
9+
"id": "2",
10+
"question": "Where should it be placed?",
11+
"options": ["Inside scrollable area", "Fixed position", "Something else"]
12+
},
13+
{
14+
"id": "3",
15+
"question": "Should it match tab styling or use a button-like appearance?",
16+
"options": [
17+
"Match tab styling",
18+
"Use a button-like appearance",
19+
"Something else"
20+
]
21+
},
22+
{
23+
"id": "4",
24+
"question": "Any keyboard shortcuts needed?",
25+
"options": ["Yes, specify", "No", "Something else"]
26+
}
27+
],
28+
"answered": true,
29+
"answers": [
30+
{
31+
"questionId": "1",
32+
"selectedOption": "Something else",
33+
"customInput": "Open the Command Box"
34+
},
35+
{
36+
"questionId": "2",
37+
"selectedOption": "Inside scrollable area"
38+
},
39+
{
40+
"questionId": "3",
41+
"selectedOption": "Match tab styling"
42+
}
43+
]
44+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
I'll explore the codebase to understand how tabs are implemented and generate clarifying questions for adding a plus button tab.
2+
Great! Let me examine the TabBar component which is likely where I need to add the plus button.
3+
Perfect! Now let me check the tab store to understand how tabs are created:
4+
Now let me check for icon usage in the codebase to see what plus icon is available:
5+
Perfect! Now let me check the shared types to understand tab types better:
6+
Now let me check the CommandMenu to see how new tabs can be created via the command menu:
7+
Now let me search for how buttons are styled in the application to match the visual style:
8+
Let me check the StatusBar to see if there are any similar button implementations:
9+
Excellent! Now I have a comprehensive understanding of the codebase. Let me create the research questions based on my findings.
10+
11+
Based on my analysis of the codebase, I can now create clarifying questions for implementing the plus button tab feature. Here's what I've learned:
12+
13+
1. **TabBar Component** (`/Users/jonathan/dev/Array/src/renderer/components/TabBar.tsx`): Contains the tab rendering logic with drag-and-drop support, keyboard shortcuts, and close buttons
14+
2. **Tab Store** (`/Users/jonathan/dev/Array/src/renderer/stores/tabStore.ts`): Manages tab state with `createTab` function
15+
3. **Tab Types**: Defined in `/Users/jonathan/dev/Array/src/shared/types.ts` - currently supports "task-list", "task-detail", "backlog", "settings", "recordings"
16+
4. **Icon Usage**: The app uses `@radix-ui/react-icons` (e.g., `PlusIcon` is available and used in TaskList)
17+
5. **Button Styling**: Uses `IconButton` from `@radix-ui/themes` with variants like "ghost" and size options
18+
19+
Now let me create the research questions:
20+
I've completed my research of the codebase and identified the key implementation questions. Here's what I found:
21+
22+
## Codebase Analysis Summary
23+
24+
**Key Files:**
25+
- `TabBar.tsx` - Main tab rendering component with drag-and-drop, keyboard shortcuts (Cmd+1-9, Cmd+W, etc.)
26+
- `tabStore.ts` - Zustand store managing tab state with `createTab()` function
27+
- `types.ts` - Defines TabState with types: "task-list", "task-detail", "backlog", "settings", "recordings"
28+
- The app uses `@radix-ui/react-icons` (PlusIcon available) and `@radix-ui/themes` components
29+
30+
**Current Tab Structure:**
31+
- Tabs are in a scrollable container with a 40px height
32+
- Each tab has similar styling with borders, hover states, and active indicators
33+
- Tabs support drag-and-drop reordering and context menus
34+
- Close buttons appear on hover (except when only 1 tab exists)
35+
36+
## Clarifying Questions
37+
38+
I've identified 4 key questions that will guide the implementation:
39+
40+
1. **Functionality**: What should the plus button do when clicked? (Open task modal vs create new tab)
41+
2. **Positioning**: Where should it be placed? (Inside scrollable area vs fixed position)
42+
3. **Styling**: Should it match tab styling or use a button-like appearance?
43+
4. **Interactions**: Any keyboard shortcuts needed?
44+
45+
Each question includes 2-3 concrete options based on existing patterns I found in the codebase, plus a "something else" option for flexibility.
46+
47+
Ready to present these questions for your input!

src/renderer/components/MainLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export function MainLayout() {
8484

8585
return (
8686
<Flex direction="column" height="100vh">
87-
<TabBar />
87+
<TabBar onOpenCommandMenu={() => setCommandMenuOpen(true)} />
8888

8989
<Box flexGrow="1" overflow="hidden">
9090
{activeTab?.type === "task-list" && (

src/renderer/components/TabBar.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Cross2Icon } from "@radix-ui/react-icons";
1+
import { Cross2Icon, PlusIcon } from "@radix-ui/react-icons";
22
import {
33
Box,
44
ContextMenu,
@@ -12,7 +12,11 @@ import { useCallback, useEffect, useRef, useState } from "react";
1212
import { useHotkeys } from "react-hotkeys-hook";
1313
import { useTabStore } from "../stores/tabStore";
1414

15-
export function TabBar() {
15+
interface TabBarProps {
16+
onOpenCommandMenu?: () => void;
17+
}
18+
19+
export function TabBar({ onOpenCommandMenu }: TabBarProps) {
1620
const {
1721
tabs,
1822
activeTabId,
@@ -320,6 +324,19 @@ export function TabBar() {
320324
</ContextMenu.Root>
321325
);
322326
})}
327+
328+
{/* Plus button to open Command Menu */}
329+
<Flex
330+
className="no-drag cursor-pointer border-gray-6 border-r text-gray-11 transition-colors hover:bg-gray-3 hover:text-gray-12"
331+
align="center"
332+
justify="center"
333+
px="4"
334+
flexShrink="0"
335+
onClick={() => onOpenCommandMenu?.()}
336+
title="Open Command Menu"
337+
>
338+
<PlusIcon width="16" height="16" />
339+
</Flex>
323340
</Flex>
324341

325342
{showScrollGradient && (

0 commit comments

Comments
 (0)