fix(app): avoid settings header offset
This commit is contained in:
@@ -18,6 +18,7 @@ interface ScreenHeaderProps {
|
||||
leftStyle?: StyleProp<ViewStyle>;
|
||||
rightStyle?: StyleProp<ViewStyle>;
|
||||
borderless?: boolean;
|
||||
windowControlsPaddingRole?: "header" | "detailHeader";
|
||||
onRowLayout?: (event: LayoutChangeEvent) => void;
|
||||
}
|
||||
|
||||
@@ -31,12 +32,13 @@ export function ScreenHeader({
|
||||
leftStyle,
|
||||
rightStyle,
|
||||
borderless,
|
||||
windowControlsPaddingRole = "header",
|
||||
onRowLayout,
|
||||
}: ScreenHeaderProps) {
|
||||
const { theme } = useUnistyles();
|
||||
const insets = useSafeAreaInsets();
|
||||
const isMobile = useIsCompactFormFactor();
|
||||
const padding = useWindowControlsPadding("header");
|
||||
const padding = useWindowControlsPadding(windowControlsPaddingRole);
|
||||
// Only add extra padding on mobile for better touch targets; on desktop, only use safe area insets
|
||||
const topPadding = isMobile ? HEADER_TOP_PADDING_MOBILE : 0;
|
||||
const baseHorizontalPadding = theme.spacing[2];
|
||||
|
||||
@@ -898,6 +898,7 @@ export default function SettingsScreen({ view }: SettingsScreenProps) {
|
||||
<View style={desktopStyles.contentPane}>
|
||||
<ScreenHeader
|
||||
borderless={!detailHeader}
|
||||
windowControlsPaddingRole="detailHeader"
|
||||
left={
|
||||
detailHeader ? (
|
||||
<>
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveWindowControlsPadding } from "@/utils/desktop-window";
|
||||
|
||||
const rawPadding = {
|
||||
left: 80,
|
||||
right: 48,
|
||||
top: 28,
|
||||
};
|
||||
|
||||
describe("resolveWindowControlsPadding", () => {
|
||||
it("pads the main header for window controls when the app sidebar is closed", () => {
|
||||
expect(
|
||||
resolveWindowControlsPadding({
|
||||
role: "header",
|
||||
rawPadding,
|
||||
sidebarClosed: true,
|
||||
explorerOpen: false,
|
||||
focusModeEnabled: false,
|
||||
}),
|
||||
).toEqual({
|
||||
left: 80,
|
||||
right: 48,
|
||||
top: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it("does not add left padding to detail headers with their own sidebar", () => {
|
||||
expect(
|
||||
resolveWindowControlsPadding({
|
||||
role: "detailHeader",
|
||||
rawPadding,
|
||||
sidebarClosed: true,
|
||||
explorerOpen: false,
|
||||
focusModeEnabled: false,
|
||||
}),
|
||||
).toEqual({
|
||||
left: 0,
|
||||
right: 48,
|
||||
top: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -17,7 +17,12 @@ type RawWindowControlsPadding = {
|
||||
top: number;
|
||||
};
|
||||
|
||||
type WindowControlsPaddingRole = "sidebar" | "header" | "tabRow" | "explorerSidebar";
|
||||
type WindowControlsPaddingRole =
|
||||
| "sidebar"
|
||||
| "header"
|
||||
| "detailHeader"
|
||||
| "tabRow"
|
||||
| "explorerSidebar";
|
||||
|
||||
// Module-level cache so hook remounts (e.g., on navigation) don't briefly
|
||||
// fall back to the default `false` while the async fullscreen check resolves.
|
||||
@@ -114,22 +119,59 @@ export function useWindowControlsPadding(role: WindowControlsPaddingRole): {
|
||||
const rawPadding = useRawWindowControlsPadding();
|
||||
const sidebarClosed = !sidebarOpen;
|
||||
|
||||
let left = 0;
|
||||
let right = 0;
|
||||
let top = 0;
|
||||
|
||||
if (role === "sidebar") {
|
||||
left = rawPadding.left;
|
||||
top = rawPadding.top;
|
||||
} else if (role === "header") {
|
||||
left = sidebarClosed ? rawPadding.left : 0;
|
||||
right = explorerOpen ? 0 : rawPadding.right;
|
||||
} else if (role === "tabRow") {
|
||||
left = sidebarClosed && focusModeEnabled ? rawPadding.left : 0;
|
||||
right = focusModeEnabled && !explorerOpen ? rawPadding.right : 0;
|
||||
} else if (role === "explorerSidebar") {
|
||||
right = rawPadding.right;
|
||||
}
|
||||
const { left, right, top } = resolveWindowControlsPadding({
|
||||
role,
|
||||
rawPadding,
|
||||
sidebarClosed,
|
||||
explorerOpen,
|
||||
focusModeEnabled,
|
||||
});
|
||||
|
||||
return useMemo(() => ({ left, right, top }), [left, right, top]);
|
||||
}
|
||||
|
||||
export function resolveWindowControlsPadding(input: {
|
||||
role: WindowControlsPaddingRole;
|
||||
rawPadding: RawWindowControlsPadding;
|
||||
sidebarClosed: boolean;
|
||||
explorerOpen: boolean;
|
||||
focusModeEnabled: boolean;
|
||||
}): RawWindowControlsPadding {
|
||||
if (input.role === "sidebar") {
|
||||
return {
|
||||
left: input.rawPadding.left,
|
||||
right: 0,
|
||||
top: input.rawPadding.top,
|
||||
};
|
||||
}
|
||||
|
||||
if (input.role === "header") {
|
||||
return {
|
||||
left: input.sidebarClosed ? input.rawPadding.left : 0,
|
||||
right: input.explorerOpen ? 0 : input.rawPadding.right,
|
||||
top: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (input.role === "detailHeader") {
|
||||
return {
|
||||
left: 0,
|
||||
right: input.rawPadding.right,
|
||||
top: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (input.role === "tabRow") {
|
||||
return {
|
||||
left: input.sidebarClosed && input.focusModeEnabled ? input.rawPadding.left : 0,
|
||||
right: input.focusModeEnabled && !input.explorerOpen ? input.rawPadding.right : 0,
|
||||
top: 0,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
left: 0,
|
||||
right: input.rawPadding.right,
|
||||
top: 0,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user