Skip to content

Commit a46a951

Browse files
matej21claude
andcommitted
fix: split above tab group instead of inside active tab
When splitting a terminal inside a tab group, the split now wraps the entire Tabs container rather than creating a nested split within the active tab. This prevents clunky UI where tabs contain inner splits with their own tab-like appearance. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8e36aea commit a46a951

File tree

2 files changed

+26
-18
lines changed
  • crates
    • okena-views-terminal/src/layout/tabs
    • okena-workspace/src/actions

2 files changed

+26
-18
lines changed

crates/okena-views-terminal/src/layout/tabs/mod.rs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,10 @@ impl<D: ActionDispatch + Send + Sync> LayoutContainer<D> {
9999
.child(
100100
header_button_base(HeaderAction::SplitVertical, &id_suffix, ButtonSize::COMPACT, &t, None, None)
101101
.on_click(move |_, _window, cx| {
102-
let child_path = if ctx_split_v.standalone {
103-
ctx_split_v.layout_path.clone()
104-
} else {
105-
let mut p = ctx_split_v.layout_path.clone();
106-
p.push(ctx_split_v.active_tab);
107-
p
108-
};
109102
if let Some(ref dispatcher) = ctx_split_v.action_dispatcher {
110103
dispatcher.dispatch(okena_core::api::ActionRequest::SplitTerminal {
111104
project_id: ctx_split_v.project_id.clone(),
112-
path: child_path,
105+
path: ctx_split_v.layout_path.clone(),
113106
direction: SplitDirection::Vertical,
114107
}, cx);
115108
}
@@ -118,17 +111,10 @@ impl<D: ActionDispatch + Send + Sync> LayoutContainer<D> {
118111
.child(
119112
header_button_base(HeaderAction::SplitHorizontal, &id_suffix, ButtonSize::COMPACT, &t, None, None)
120113
.on_click(move |_, _window, cx| {
121-
let child_path = if ctx_split_h.standalone {
122-
ctx_split_h.layout_path.clone()
123-
} else {
124-
let mut p = ctx_split_h.layout_path.clone();
125-
p.push(ctx_split_h.active_tab);
126-
p
127-
};
128114
if let Some(ref dispatcher) = ctx_split_h.action_dispatcher {
129115
dispatcher.dispatch(okena_core::api::ActionRequest::SplitTerminal {
130116
project_id: ctx_split_h.project_id.clone(),
131-
path: child_path,
117+
path: ctx_split_h.layout_path.clone(),
132118
direction: SplitDirection::Horizontal,
133119
}, cx);
134120
}

crates/okena-workspace/src/actions/layout.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,33 @@ impl Workspace {
3939
) {
4040
log::info!("Workspace::split_terminal called for project {} at path {:?}", project_id, path);
4141

42+
// If the target node is inside a Tabs container, split the Tabs container
43+
// instead of splitting inside the tab. This avoids nested splits within tabs
44+
// which creates a clunky UI.
45+
let split_path = if let Some(project) = self.project(project_id) {
46+
if let Some(ref layout) = project.layout {
47+
if path.len() >= 1 {
48+
let parent_path = &path[..path.len() - 1];
49+
if let Some(LayoutNode::Tabs { .. }) = layout.get_at_path(parent_path) {
50+
parent_path.to_vec()
51+
} else {
52+
path.to_vec()
53+
}
54+
} else {
55+
path.to_vec()
56+
}
57+
} else {
58+
path.to_vec()
59+
}
60+
} else {
61+
path.to_vec()
62+
};
63+
4264
// Perform the split and find the new terminal's path after normalization.
4365
let new_path = if let Some(project) = self.project_mut(project_id) {
4466
if let Some(ref mut layout) = project.layout {
45-
if let Some(node) = layout.get_at_path_mut(path) {
46-
log::info!("Found node at path, splitting...");
67+
if let Some(node) = layout.get_at_path_mut(&split_path) {
68+
log::info!("Found node at path {:?}, splitting...", split_path);
4769
let old_node = node.clone();
4870
*node = LayoutNode::Split {
4971
direction,

0 commit comments

Comments
 (0)