fix(tui): keep FUSION header from wrapping under flex pressure
Yoga's default flexShrink: 1 was letting the MiniLogo and tab pills
shrink when the header row's collective content exceeded the
terminal width — driving FUSION onto a second line. Pin every
fixed-content header child (logo, dividers, tab pills, help-hint) to
flexShrink={0}; the trailing flexGrow filler still absorbs slack.
Belt-and-suspenders: wrap="truncate-end" on FUSION so any future
constraint truncates instead of wrapping.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -151,9 +151,11 @@ function SplashScreen({ loadingStatus }: { loadingStatus: string }) {
|
|||||||
// ── Mini inline logo (header) ─────────────────────────────────────────────────
|
// ── Mini inline logo (header) ─────────────────────────────────────────────────
|
||||||
|
|
||||||
function MiniLogo() {
|
function MiniLogo() {
|
||||||
|
// flexShrink={0} keeps FUSION from being squeezed (and wrapping) when the
|
||||||
|
// header row's other children push past the terminal width.
|
||||||
return (
|
return (
|
||||||
<Box flexDirection="row" gap={0}>
|
<Box flexDirection="row" gap={0} flexShrink={0}>
|
||||||
<Text color="cyanBright" bold>FUSION</Text>
|
<Text color="cyanBright" bold wrap="truncate-end">FUSION</Text>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -815,10 +817,14 @@ function MainHeader({ state }: { state: DashboardState }) {
|
|||||||
<Box flexDirection="row" gap={1} paddingX={1}>
|
<Box flexDirection="row" gap={1} paddingX={1}>
|
||||||
<MiniLogo />
|
<MiniLogo />
|
||||||
{activeSectionLabel && (
|
{activeSectionLabel && (
|
||||||
<Text backgroundColor="cyan" color="black" bold>{` ${activeSectionIdx + 1} ${activeSectionLabel} `}</Text>
|
<Box flexShrink={0}>
|
||||||
|
<Text backgroundColor="cyan" color="black" bold>{` ${activeSectionIdx + 1} ${activeSectionLabel} `}</Text>
|
||||||
|
</Box>
|
||||||
)}
|
)}
|
||||||
{activeInteractive && (
|
{activeInteractive && (
|
||||||
<Text backgroundColor="cyan" color="black" bold>{` ${activeInteractive.key} ${activeInteractive.label} `}</Text>
|
<Box flexShrink={0}>
|
||||||
|
<Text backgroundColor="cyan" color="black" bold>{` ${activeInteractive.key} ${activeInteractive.label} `}</Text>
|
||||||
|
</Box>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
@@ -826,13 +832,13 @@ function MainHeader({ state }: { state: DashboardState }) {
|
|||||||
return (
|
return (
|
||||||
<Box flexDirection="row" gap={1} paddingX={1} paddingY={0}>
|
<Box flexDirection="row" gap={1} paddingX={1} paddingY={0}>
|
||||||
<MiniLogo />
|
<MiniLogo />
|
||||||
{!minimal && <Text dimColor>│</Text>}
|
{!minimal && <Box flexShrink={0}><Text dimColor>│</Text></Box>}
|
||||||
{SECTION_ORDER.map((section, i) => {
|
{SECTION_ORDER.map((section, i) => {
|
||||||
const isActive = !inInteractive && section === focused;
|
const isActive = !inInteractive && section === focused;
|
||||||
const label = section.charAt(0).toUpperCase() + section.slice(1);
|
const label = section.charAt(0).toUpperCase() + section.slice(1);
|
||||||
if (minimal && !isActive) return null;
|
if (minimal && !isActive) return null;
|
||||||
return (
|
return (
|
||||||
<Box key={section} marginRight={1}>
|
<Box key={section} marginRight={1} flexShrink={0}>
|
||||||
{isActive ? (
|
{isActive ? (
|
||||||
<Text backgroundColor="cyan" color="black" bold>
|
<Text backgroundColor="cyan" color="black" bold>
|
||||||
{compactSections ? ` ${i + 1} ${label} ` : ` [${i + 1}] ${label} `}
|
{compactSections ? ` ${i + 1} ${label} ` : ` [${i + 1}] ${label} `}
|
||||||
@@ -845,12 +851,12 @@ function MainHeader({ state }: { state: DashboardState }) {
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{!minimal && <Text dimColor>│</Text>}
|
{!minimal && <Box flexShrink={0}><Text dimColor>│</Text></Box>}
|
||||||
{interactiveTabs.map(({ key, label, view }) => {
|
{interactiveTabs.map(({ key, label, view }) => {
|
||||||
const isActive = inInteractive && view === interactiveView;
|
const isActive = inInteractive && view === interactiveView;
|
||||||
if (minimal && !isActive) return null;
|
if (minimal && !isActive) return null;
|
||||||
return (
|
return (
|
||||||
<Box key={view} marginRight={1}>
|
<Box key={view} marginRight={1} flexShrink={0}>
|
||||||
{isActive ? (
|
{isActive ? (
|
||||||
<Text backgroundColor="cyan" color="black" bold>
|
<Text backgroundColor="cyan" color="black" bold>
|
||||||
{compactInteractive ? ` ${key} ${label} ` : ` [${key}] ${label} `}
|
{compactInteractive ? ` ${key} ${label} ` : ` [${key}] ${label} `}
|
||||||
@@ -864,7 +870,7 @@ function MainHeader({ state }: { state: DashboardState }) {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<Box flexGrow={1} />
|
<Box flexGrow={1} />
|
||||||
{showHelpHint && <Text dimColor>[?] help [q] quit</Text>}
|
{showHelpHint && <Box flexShrink={0}><Text dimColor>[?] help [q] quit</Text></Box>}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user