Files
yaak-mountain-loop/src-web/components/HeaderSize.tsx
Gregory Schier 242f55b609 Fix macOS Tahoe stoplight positioning and build on macOS 26
On macOS Tahoe (26+), the default title bar is 32px with 14px buttons,
so the old formula (button_height + PAD_Y = 14 + 18 = 32) produced no
change. Add TITLEBAR_EXTRA_HEIGHT to push the title bar taller than
the Tahoe default. Use OnceLock to capture the original default height
so repeated calls don't accumulate extra pixels.

Also update CI runners to macos-26 for Tahoe SDK builds and adjust
frontend padding for larger stoplights.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 14:56:19 -08:00

84 lines
2.5 KiB
TypeScript

import { type } from '@tauri-apps/plugin-os';
import { settingsAtom } from '@yaakapp-internal/models';
import classNames from 'classnames';
import { useAtomValue } from 'jotai';
import type { CSSProperties, HTMLAttributes, ReactNode } from 'react';
import { useMemo } from 'react';
import { useIsFullscreen } from '../hooks/useIsFullscreen';
import { HEADER_SIZE_LG, HEADER_SIZE_MD, WINDOW_CONTROLS_WIDTH } from '../lib/constants';
import { WindowControls } from './WindowControls';
interface HeaderSizeProps extends HTMLAttributes<HTMLDivElement> {
children?: ReactNode;
size: 'md' | 'lg';
ignoreControlsSpacing?: boolean;
onlyXWindowControl?: boolean;
hideControls?: boolean;
}
export function HeaderSize({
className,
style,
size,
ignoreControlsSpacing,
onlyXWindowControl,
children,
hideControls,
}: HeaderSizeProps) {
const settings = useAtomValue(settingsAtom);
const isFullscreen = useIsFullscreen();
const nativeTitlebar = settings.useNativeTitlebar;
const finalStyle = useMemo<CSSProperties>(() => {
const s = { ...style };
// Set the height (use min-height because scaling font size may make it larger
if (size === 'md') s.minHeight = HEADER_SIZE_MD;
if (size === 'lg') s.minHeight = HEADER_SIZE_LG;
if (nativeTitlebar) {
// No style updates when using native titlebar
} else if (type() === 'macos') {
if (!isFullscreen) {
// Add large padding for window controls
s.paddingLeft = 76 / settings.interfaceScale;
}
} else if (!ignoreControlsSpacing && !settings.hideWindowControls) {
s.paddingRight = WINDOW_CONTROLS_WIDTH;
}
return s;
}, [
ignoreControlsSpacing,
isFullscreen,
settings.hideWindowControls,
settings.interfaceScale,
size,
style,
nativeTitlebar,
]);
return (
<div
data-tauri-drag-region
style={finalStyle}
className={classNames(
className,
'pt-[1px]', // Make up for bottom border
'select-none relative',
'w-full border-b border-border-subtle min-w-0',
)}
>
{/* NOTE: This needs display:grid or else the element shrinks (even though scrollable) */}
<div
className={classNames(
'pointer-events-none h-full w-full overflow-x-auto hide-scrollbars grid',
'px-1', // Give it some space on either end for focus outlines
)}
>
{children}
</div>
{!hideControls && !nativeTitlebar && <WindowControls onlyX={onlyXWindowControl} />}
</div>
);
}