Skip to content

Commit 57e4e27

Browse files
lucyfarnikclaude
andauthored
feat: add opt-in split buttons to block headers (#3159)
Add two icon buttons (horizontal/vertical split) to every block's header bar, gated behind a new `app:showsplitbuttons` setting (default false). When enabled, the buttons appear before the settings cog. Motivation: for users who split panes frequently, having the buttons always visible speeds up the workflow vs. right-click > context menu. The split functionality already exists — this just surfaces it more conveniently. - New setting `app:showsplitbuttons` (Go + TS + default config) - Split buttons in `blockframe-header.tsx`, using existing `createBlockSplitHorizontally`/`createBlockSplitVertically` - New pane clones the current block's meta so terminals inherit shell/connection config --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 86d1a54 commit 57e4e27

File tree

7 files changed

+48
-1
lines changed

7 files changed

+48
-1
lines changed

frontend/app/block/blockenv.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export type BlockEnv = WaveEnvSubset<{
1313
getSettingsKeyAtom: SettingsKeyAtomFnType<
1414
| "app:focusfollowscursor"
1515
| "app:showoverlayblocknums"
16+
| "term:showsplitbuttons"
1617
| "window:magnifiedblockblurprimarypx"
1718
| "window:magnifiedblockopacity"
1819
>;

frontend/app/block/blockframe-header.tsx

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@ import {
1111
import { ConnectionButton } from "@/app/block/connectionbutton";
1212
import { DurableSessionFlyover } from "@/app/block/durable-session-flyover";
1313
import { getBlockBadgeAtom } from "@/app/store/badge";
14-
import { recordTEvent, refocusNode } from "@/app/store/global";
14+
import {
15+
createBlockSplitHorizontally,
16+
createBlockSplitVertically,
17+
recordTEvent,
18+
refocusNode,
19+
WOS,
20+
} from "@/app/store/global";
1521
import { globalStore } from "@/app/store/jotaiStore";
1622
import { uxCloseBlock } from "@/app/store/keymodel";
1723
import { TabRpcClient } from "@/app/store/wshrpcutil";
@@ -119,12 +125,45 @@ const HeaderEndIcons = React.memo(({ viewModel, nodeModel, blockId }: HeaderEndI
119125
const ephemeral = jotai.useAtomValue(nodeModel.isEphemeral);
120126
const numLeafs = jotai.useAtomValue(nodeModel.numLeafs);
121127
const magnifyDisabled = numLeafs <= 1;
128+
const showSplitButtons = jotai.useAtomValue(blockEnv.getSettingsKeyAtom("term:showsplitbuttons"));
122129

123130
const endIconsElem: React.ReactElement[] = [];
124131

125132
if (endIconButtons && endIconButtons.length > 0) {
126133
endIconsElem.push(...endIconButtons.map((button, idx) => <IconButton key={idx} decl={button} />));
127134
}
135+
if (showSplitButtons && viewModel?.viewType === "term") {
136+
const splitHorizontalDecl: IconButtonDecl = {
137+
elemtype: "iconbutton",
138+
icon: "columns",
139+
title: "Split Horizontally",
140+
click: (e) => {
141+
e.stopPropagation();
142+
const blockAtom = WOS.getWaveObjectAtom<Block>(WOS.makeORef("block", blockId));
143+
const blockData = globalStore.get(blockAtom);
144+
const blockDef: BlockDef = {
145+
meta: blockData?.meta || { view: "term", controller: "shell" },
146+
};
147+
createBlockSplitHorizontally(blockDef, blockId, "after");
148+
},
149+
};
150+
const splitVerticalDecl: IconButtonDecl = {
151+
elemtype: "iconbutton",
152+
icon: "grip-lines",
153+
title: "Split Vertically",
154+
click: (e) => {
155+
e.stopPropagation();
156+
const blockAtom = WOS.getWaveObjectAtom<Block>(WOS.makeORef("block", blockId));
157+
const blockData = globalStore.get(blockAtom);
158+
const blockDef: BlockDef = {
159+
meta: blockData?.meta || { view: "term", controller: "shell" },
160+
};
161+
createBlockSplitVertically(blockDef, blockId, "after");
162+
},
163+
};
164+
endIconsElem.push(<IconButton key="split-horizontal" decl={splitHorizontalDecl} />);
165+
endIconsElem.push(<IconButton key="split-vertical" decl={splitVerticalDecl} />);
166+
}
128167
const settingsDecl: IconButtonDecl = {
129168
elemtype: "iconbutton",
130169
icon: "cog",

frontend/types/gotypes.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,7 @@ declare global {
14221422
"term:bellindicator"?: boolean;
14231423
"term:osc52"?: string;
14241424
"term:durable"?: boolean;
1425+
"term:showsplitbuttons"?: boolean;
14251426
"editor:minimapenabled"?: boolean;
14261427
"editor:stickyscrollenabled"?: boolean;
14271428
"editor:wordwrap"?: boolean;

pkg/wconfig/defaultconfig/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"app:tabbar": "top",
88
"app:confirmquit": true,
99
"app:hideaibutton": false,
10+
"term:showsplitbuttons": false,
1011
"app:disablectrlshiftarrows": false,
1112
"app:disablectrlshiftdisplay": false,
1213
"app:focusfollowscursor": "off",

pkg/wconfig/metaconsts.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ const (
5959
ConfigKey_TermBellIndicator = "term:bellindicator"
6060
ConfigKey_TermOsc52 = "term:osc52"
6161
ConfigKey_TermDurable = "term:durable"
62+
ConfigKey_TermShowSplitButtons = "term:showsplitbuttons"
6263

6364
ConfigKey_EditorMinimapEnabled = "editor:minimapenabled"
6465
ConfigKey_EditorStickyScrollEnabled = "editor:stickyscrollenabled"

pkg/wconfig/settingsconfig.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ type SettingsType struct {
110110
TermBellIndicator *bool `json:"term:bellindicator,omitempty"`
111111
TermOsc52 string `json:"term:osc52,omitempty" jsonschema:"enum=focus,enum=always"`
112112
TermDurable *bool `json:"term:durable,omitempty"`
113+
TermShowSplitButtons bool `json:"term:showsplitbuttons,omitempty"`
113114

114115
EditorMinimapEnabled bool `json:"editor:minimapenabled,omitempty"`
115116
EditorStickyScrollEnabled bool `json:"editor:stickyscrollenabled,omitempty"`

schema/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@
168168
"term:durable": {
169169
"type": "boolean"
170170
},
171+
"term:showsplitbuttons": {
172+
"type": "boolean"
173+
},
171174
"editor:minimapenabled": {
172175
"type": "boolean"
173176
},

0 commit comments

Comments
 (0)