Initial public release of Warp.
Repo-Sync-Origin: warpdotdev/warp-internal@12af1d983b
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
# APP-3648: Vertical Tabs Panel — Search + Control Bar
|
||||
|
||||
## Overview
|
||||
|
||||
Add a fixed control bar at the top of the vertical tabs panel containing a search input and a "new tab" button. This bar sits above the scrollable tab groups and is always visible when the panel is open.
|
||||
|
||||
## Milestone 1 Scope
|
||||
|
||||
- **Search input**: Renders as a full-width text field with placeholder text (e.g. "Search tabs...") and a magnifying glass icon. **Non-functional** — the input does not accept text and is not focusable. Hovering anywhere on the search input shows a tooltip: **"Not yet implemented"**.
|
||||
- **Plus button**: A single icon button (`+`) to the right of the search input. Left-click creates a new tab (equivalent to `WorkspaceAction::AddTab`). Right-click opens the new session dropdown menu (equivalent to `WorkspaceAction::ToggleNewSessionMenu`).
|
||||
- **Configs button**: Out of scope for this milestone.
|
||||
|
||||
## Behavior
|
||||
|
||||
### Search Input
|
||||
- Visually resembles a standard search field: magnifying glass icon on the left, placeholder text, themed background/border consistent with the panel.
|
||||
- The field is **inert** — clicking it does nothing (no focus, no cursor, no text entry).
|
||||
- On hover, a tooltip appears with the text **"Not yet implemented"**.
|
||||
- The search input stretches to fill all available horizontal space to the left of the plus button.
|
||||
|
||||
### Plus Button
|
||||
- Renders as a small icon button with a `+` icon.
|
||||
- **Left-click**: Creates a new tab (same as the existing `AddTab` action — opens a welcome tab or terminal tab depending on feature flags).
|
||||
- **Right-click**: Opens the new session dropdown menu, anchored below the plus button at the bottom edge of the control bar.
|
||||
- On hover, shows a tooltip with label **"New Tab"** and the keybinding for the new tab action (Cmd+Shift+T / Ctrl+Shift+T).
|
||||
- The dropdown menu contains the same items as the existing new session menu (shell options, launch configs, tab configs).
|
||||
|
||||
### Layout
|
||||
- The control bar is a horizontal row at the top of the vertical tabs panel, above the scrollable tab group list.
|
||||
- It is **not scrollable** — it stays fixed at the top as tab groups scroll.
|
||||
- It has horizontal padding consistent with the rest of the panel (12px).
|
||||
- Vertical padding provides comfortable spacing from the panel's top edge and the first tab group below.
|
||||
|
||||
## Edge Cases
|
||||
|
||||
1. **Narrow panel widths**: At the minimum panel width (200px), the search input text truncates but the plus button remains fully visible and usable. The plus button has a fixed size; the search input absorbs all remaining width.
|
||||
2. **Tooltip clipping**: The "Not yet implemented" tooltip and the new session dropdown menu must not clip outside the window bounds. Use window-aware positioning.
|
||||
3. **Focus**: Since the search input is inert, clicking it must **not** steal focus from the active terminal or editor. The control bar itself does not participate in focus management.
|
||||
4. **Panel toggle**: The control bar is only visible when the vertical tabs panel is open. No special behavior on open/close.
|
||||
5. **Dropdown menu lifecycle**: The new session dropdown menu follows the same open/close lifecycle as the existing top bar menu — it closes on item selection, clicking outside, or pressing Escape.
|
||||
6. **Multiple windows**: Each window's vertical tabs panel has its own independent control bar instance. Dropdown menus are scoped to their window.
|
||||
@@ -0,0 +1,84 @@
|
||||
# APP-3648: Tech Spec — Vertical Tabs Control Bar
|
||||
|
||||
## Current State
|
||||
|
||||
The vertical tabs panel is rendered in `app/src/workspace/view/vertical_tabs.rs` via the free function `render_vertical_tabs_panel`. The panel layout is:
|
||||
|
||||
```
|
||||
Resizable (drag-right edge)
|
||||
└─ Container (background + right border)
|
||||
└─ Flex::column
|
||||
└─ Shrinkable(ClippedScrollable::vertical(tab groups))
|
||||
```
|
||||
|
||||
There is currently no control bar — tab groups fill the entire panel. The panel is resizable (min 200px, max 50% window width) with state managed in `VerticalTabsPanelState`.
|
||||
|
||||
The "new tab" split button in the top bar (`render_new_session_button` in `view.rs`) dispatches `WorkspaceAction::AddTab` on left-click and `WorkspaceAction::ToggleNewSessionMenu { position }` on right-click/chevron-click. The dropdown menu is rendered as an overlay in the workspace's main `Stack`, positioned at the stored `show_new_session_dropdown_menu` coordinates.
|
||||
|
||||
## Proposed Changes
|
||||
|
||||
### 1. Add state handles to `VerticalTabsPanelState`
|
||||
|
||||
`vertical_tabs.rs (struct VerticalTabsPanelState)`:
|
||||
- `search_mouse_state: MouseStateHandle` — drives the tooltip on the search input
|
||||
- `add_tab_mouse_state: MouseStateHandle` — drives the plus button hover/click states
|
||||
|
||||
Initialize both with `Default::default()` in the existing `Default` impl.
|
||||
|
||||
### 2. Add `render_control_bar` function
|
||||
|
||||
New free function in `vertical_tabs.rs`:
|
||||
|
||||
```
|
||||
render_control_bar(state, app) -> Box<dyn Element>
|
||||
```
|
||||
|
||||
Layout: `Flex::row` with `CrossAxisAlignment::Center`, padded with horizontal `GROUP_HORIZONTAL_PADDING` (12px) and vertical padding ~8px.
|
||||
|
||||
**Search input** (left, fills remaining space via `Shrinkable`):
|
||||
- `Hoverable` wrapping a `Container` styled as an inert search field:
|
||||
- Left: `WarpIcon::Search` magnifying glass icon (12px, sub-text color)
|
||||
- Right: `Text::new_inline("Search tabs...", ...)` placeholder in sub-text color, clipped
|
||||
- Background: `fg_overlay_1` or similar subtle fill; rounded corners
|
||||
- Height: ~24px to match icon button sizing
|
||||
- On hover: show tooltip "Not yet implemented" via `ui_builder.tool_tip_on_element(...)` (overlay variant, so it's not clipped by the panel's `Clipped` wrapper)
|
||||
- No click handler, no cursor change — remains inert
|
||||
|
||||
**Plus button** (right, fixed width):
|
||||
- Use `icon_button(appearance, Icon::Plus, false, state.add_tab_mouse_state.clone())`
|
||||
- Wrap in a `Hoverable` to add a tooltip with "New Tab" + keybinding sublabel
|
||||
- `.on_click(|ctx, _, _| ctx.dispatch_typed_action(WorkspaceAction::AddTab))`
|
||||
- `.on_right_click(|ctx, _, position| ctx.dispatch_typed_action(WorkspaceAction::ToggleNewSessionMenu { position }))`
|
||||
- Wrap in `SavePosition` with a dedicated position ID (e.g. `"vertical_tabs_add_tab_button"`) so the dropdown menu can anchor to it
|
||||
|
||||
### 3. Integrate into `render_vertical_tabs_panel`
|
||||
|
||||
Change the `Flex::column` to include the control bar as the first child, outside the scrollable:
|
||||
|
||||
```
|
||||
Flex::column()
|
||||
.with_main_axis_size(MainAxisSize::Max)
|
||||
.with_child(render_control_bar(state, app)) // NEW — fixed at top
|
||||
.with_child(Shrinkable::new(1., scrollable_groups)) // existing — scrolls
|
||||
.finish()
|
||||
```
|
||||
|
||||
The control bar stays fixed because it's a sibling of the `Shrinkable`-wrapped scrollable, not inside it.
|
||||
|
||||
### 4. Dropdown menu positioning
|
||||
|
||||
No changes needed to the workspace-level menu rendering. The existing `ToggleNewSessionMenu { position }` flow stores the click position and renders the menu in the workspace `Stack` overlay. The right-click on the plus button passes its screen position directly, so the menu will appear below the button naturally. If the menu clips at the panel edge, `ParentOffsetBounds::WindowByPosition` (already used for the shell-selector variant) will reposition it within the window.
|
||||
|
||||
## Edge Cases Handled
|
||||
|
||||
- **Narrow panel (200px min)**: Search input uses `Shrinkable` so it compresses; plus button has fixed width and remains usable.
|
||||
- **Focus**: No focus handlers on the search input; clicking it does nothing.
|
||||
- **Tooltip clipping**: Use the overlay tooltip variant (`overlay_tool_tip_on_element`) so the tooltip renders above the `Clipped` scrollable.
|
||||
|
||||
## Parallelism
|
||||
|
||||
This is a single-file change (`vertical_tabs.rs`) with a minor dependency on imports from `buttons.rs` and `icons.rs`. No sub-agents needed — the work is sequential and localized.
|
||||
|
||||
## Files Changed
|
||||
|
||||
- `app/src/workspace/view/vertical_tabs.rs` — all substantive changes (state, rendering, control bar)
|
||||
Reference in New Issue
Block a user