@@ -15,6 +15,7 @@ interface PaneHeaderProps {
1515 windowModeSelected ?: boolean ;
1616 floating ?: boolean ;
1717 showActions ?: boolean ;
18+ quickSettings ?: PaneHeaderQuickSetting [ ] ;
1819 onHeaderMouseMove ?: ( event : any ) => void ;
1920 onHeaderMouseDown ?: ( event : any ) => void ;
2021 onHeaderMouseDrag ?: ( event : any ) => void ;
@@ -24,6 +25,15 @@ interface PaneHeaderProps {
2425 onCloseMouseDown ?: ( event : any ) => void ;
2526}
2627
28+ export interface PaneHeaderQuickSetting {
29+ key : string ;
30+ icon : "zap" ;
31+ label : string ;
32+ description ?: string ;
33+ active : boolean ;
34+ onMouseDown ?: ( event : any ) => void ;
35+ }
36+
2737function truncateTitle ( title : string , maxWidth : number ) : string {
2838 return truncateToDisplayWidth ( title , maxWidth ) ;
2939}
@@ -43,9 +53,15 @@ function captureTerminalPointerDrag(renderer: unknown, renderable: unknown): voi
4353function DesktopPaneButton ( {
4454 icon,
4555 onMouseDown,
56+ color = colors . textDim ,
57+ label,
58+ pressed,
4659} : {
4760 icon : ReactNode ;
4861 onMouseDown ?: ( event : any ) => void ;
62+ color ?: string ;
63+ label ?: string ;
64+ pressed ?: boolean ;
4965} ) {
5066 return (
5167 < Box
@@ -54,6 +70,9 @@ function DesktopPaneButton({
5470 justifyContent = "center"
5571 onMouseDown = { onMouseDown }
5672 data-gloom-interactive = { onMouseDown ? "true" : undefined }
73+ aria-label = { label }
74+ aria-pressed = { pressed }
75+ title = { label }
5776 style = { {
5877 borderRadius : 4 ,
5978 minWidth : 20 ,
@@ -69,7 +88,7 @@ function DesktopPaneButton({
6988 justifyContent : "center" ,
7089 width : 12 ,
7190 height : 12 ,
72- color : colors . textDim ,
91+ color,
7392 } }
7493 >
7594 { icon }
@@ -92,7 +111,7 @@ function TerminalPaneButton({
92111 return (
93112 < Box
94113 height = { 1 }
95- width = { text . length }
114+ width = { displayWidth ( text ) }
96115 flexDirection = "row"
97116 data-gloom-role = { role }
98117 data-gloom-interactive = { onMouseDown ? "true" : undefined }
@@ -110,6 +129,7 @@ export function PaneHeader({
110129 windowModeSelected = false ,
111130 floating = false ,
112131 showActions = false ,
132+ quickSettings = [ ] ,
113133 onHeaderMouseMove,
114134 onHeaderMouseDown,
115135 onHeaderMouseDrag,
@@ -125,6 +145,7 @@ export function PaneHeader({
125145 const backgroundColor = floating ? floatingPaneTitleBg ( visuallyFocused ) : paneTitleBg ( visuallyFocused ) ;
126146 const actionText = showActions ? PANE_HEADER_ACTION : " " ;
127147 const closeText = floating ? PANE_HEADER_CLOSE : "" ;
148+ const terminalQuickSettingsWidth = quickSettings . reduce ( ( total ) => total + displayWidth ( " ⚡ " ) , 0 ) ;
128149 const textColor = paneTitleText ( visuallyFocused , floating ) ;
129150 const handleTerminalHeaderMouseDown = useCallback ( ( event : any ) => {
130151 captureTerminalPointerDrag ( nativeRenderer , terminalHeaderRef . current ) ;
@@ -158,7 +179,7 @@ export function PaneHeader({
158179 < Text fg = { visuallyFocused ? colors . borderFocused : colors . textMuted } selectable = { false } data-gloom-role = "pane-grip" >
159180 { PANE_HEADER_GRIP }
160181 </ Text >
161- < Box flexGrow = { 1 } minWidth = { 0 } overflow = "hidden" >
182+ < Box minWidth = { 0 } flexShrink = { 1 } overflow = "hidden" >
162183 < Text
163184 fg = { textColor }
164185 selectable = { false }
@@ -173,6 +194,25 @@ export function PaneHeader({
173194 { title }
174195 </ Text >
175196 </ Box >
197+ { quickSettings . map ( ( setting ) => (
198+ < Box key = { setting . key } data-gloom-role = "pane-quick-setting" data-setting-key = { setting . key } >
199+ < DesktopPaneButton
200+ onMouseDown = { setting . onMouseDown }
201+ color = { setting . active ? colors . warning : colors . textDim }
202+ label = { `${ setting . label } : ${ setting . active ? "on" : "off" } ` }
203+ pressed = { setting . active }
204+ icon = { (
205+ < svg viewBox = "0 0 12 12" width = "12" height = "12" fill = "none" aria-hidden = "true" >
206+ < path
207+ d = "M7.1 1.2 2.7 6.5h3.1l-.7 4.3 4.4-5.5H6.4l.7-4.1Z"
208+ fill = "currentColor"
209+ />
210+ </ svg >
211+ ) }
212+ />
213+ </ Box >
214+ ) ) }
215+ < Box flexGrow = { 1 } minWidth = { 0 } />
176216 < Box data-gloom-role = "pane-action" >
177217 { showActions ? (
178218 < DesktopPaneButton
@@ -213,10 +253,10 @@ export function PaneHeader({
213253 // Reserve 2 for corners, 1 for ─ after ┌, 1 for ─ before ┐
214254 const borderColor = visuallyFocused ? colors . borderFocused : colors . border ;
215255 const innerWidth = Math . max ( 0 , width - 4 ) ;
216- const contentWidth = PANE_HEADER_GRIP . length + closeText . length + actionText . length ;
256+ const contentWidth = PANE_HEADER_GRIP . length + terminalQuickSettingsWidth + closeText . length + actionText . length ;
217257 const titleWidth = Math . max ( 0 , innerWidth - contentWidth ) ;
218258 const clippedTitle = truncateTitle ( title , titleWidth ) ;
219- const fillLen = Math . max ( 0 , innerWidth - PANE_HEADER_GRIP . length - displayWidth ( clippedTitle ) - actionText . length - closeText . length ) ;
259+ const fillLen = Math . max ( 0 , innerWidth - PANE_HEADER_GRIP . length - displayWidth ( clippedTitle ) - terminalQuickSettingsWidth - actionText . length - closeText . length ) ;
220260 const fill = "─" . repeat ( fillLen ) ;
221261
222262 return (
@@ -233,6 +273,15 @@ export function PaneHeader({
233273 >
234274 < Text fg = { borderColor } selectable = { false } > { "┌─" } </ Text >
235275 < Text fg = { textColor } selectable = { false } > { `${ PANE_HEADER_GRIP } ${ clippedTitle } ` } </ Text >
276+ { quickSettings . map ( ( setting ) => (
277+ < TerminalPaneButton
278+ key = { setting . key }
279+ text = " ⚡ "
280+ fg = { setting . active ? colors . warning : colors . textDim }
281+ role = "pane-quick-setting"
282+ onMouseDown = { setting . onMouseDown }
283+ />
284+ ) ) }
236285 < Text fg = { borderColor } selectable = { false } > { fill } </ Text >
237286 < TerminalPaneButton
238287 text = { actionText }
@@ -253,7 +302,7 @@ export function PaneHeader({
253302 ) ;
254303 }
255304
256- const titleWidth = Math . max ( 0 , width - PANE_HEADER_GRIP . length - actionText . length - closeText . length ) ;
305+ const titleWidth = Math . max ( 0 , width - PANE_HEADER_GRIP . length - terminalQuickSettingsWidth - actionText . length - closeText . length ) ;
257306 const clippedTitle = truncateTitle ( title , titleWidth ) ;
258307 const padding = " " . repeat ( Math . max ( 0 , titleWidth - displayWidth ( clippedTitle ) ) ) ;
259308
@@ -272,6 +321,15 @@ export function PaneHeader({
272321 < Text fg = { textColor } selectable = { false } >
273322 { `${ PANE_HEADER_GRIP } ${ clippedTitle } ${ padding } ` }
274323 </ Text >
324+ { quickSettings . map ( ( setting ) => (
325+ < TerminalPaneButton
326+ key = { setting . key }
327+ text = " ⚡ "
328+ fg = { setting . active ? colors . warning : colors . textDim }
329+ role = "pane-quick-setting"
330+ onMouseDown = { setting . onMouseDown }
331+ />
332+ ) ) }
275333 < TerminalPaneButton
276334 text = { actionText }
277335 fg = { textColor }
0 commit comments