fix(app): use the iPhone Duo top band beside the status region (#8901)

On the iPhone Duo inner screen in portrait, the workspace header, the left
sidebar's first row and the explorer tab rail now use the top band beside
the status region. The status region is published as the window's top-right
obstruction, the same slot desktop window controls use, so the row owning
that corner pads past it. Content gains 56pt.

Refs #7924

Co-authored-by: Elsa Granger <zeyugao@outlook.com>
This commit is contained in:
Mohamed Boudra
2026-11-09 22:03:21 +07:00
committed by GitHub
co-authored by Elsa Granger
parent 0fa7f840b4
commit e0f545fed4
12 changed files with 318 additions and 39 deletions
@@ -11,6 +11,7 @@ const { theme, imageMetadata, useAttachmentPreviewUrlMock } = vi.hoisted(() => {
spacing: { 1: 4, 2: 8, 3: 12, 4: 16 },
iconSize: { sm: 14, md: 18, lg: 22 },
borderWidth: { 1: 1 },
opacity: { 50: 0.5 },
borderRadius: { full: 999, md: 6, lg: 8 },
fontSize: { xs: 11, sm: 13, base: 15 },
fontWeight: { normal: "400" },
@@ -12,8 +12,13 @@ import {
iconButtonChromeGlyphSize,
mutedIconColorMapping,
} from "@/components/ui/icon-button-chrome";
import { HEADER_INNER_HEIGHT_MOBILE, HEADER_TOP_PADDING_MOBILE } from "@/constants/layout";
import {
HEADER_INNER_HEIGHT,
HEADER_INNER_HEIGHT_MOBILE,
HEADER_TOP_PADDING_MOBILE,
} from "@/constants/layout";
import type { ShortcutKey } from "@/utils/format-shortcut";
import { useTopBand } from "@/window-layout";
const ThemedArrowLeft = withUnistyles(ArrowLeft);
@@ -39,7 +44,8 @@ interface CompactHeaderProps {
* left-aligned between them. Neither the header nor its islands draw a background, so it reads the
* same in flow and floating over content (see `FloatingHeaderLayout`, whose fade gives the icons
* contrast). Its height matches the old flat header, so anything
* offset by the header height still lines up.
* offset by the header height still lines up. In a window's top band it takes the top bar's
* place, like the full header. The column hosting it reserves any window-chrome corner it owns.
*/
export function CompactHeader({
navigation,
@@ -51,22 +57,23 @@ export function CompactHeader({
actions,
}: CompactHeaderProps) {
const insets = useSafeAreaInsets();
const inTopBand = useTopBand() !== null;
const rootStyle = useMemo(
() => [
styles.root,
{
paddingTop: insets.top + HEADER_TOP_PADDING_MOBILE,
paddingTop: insets.top + (inTopBand ? 0 : HEADER_TOP_PADDING_MOBILE),
marginLeft: insets.left,
marginRight: insets.right,
},
],
[insets.top, insets.left, insets.right],
[inTopBand, insets.top, insets.left, insets.right],
);
return (
<IconButtonChromeProvider value="header-island">
<View style={rootStyle}>
<View style={styles.row}>
<View style={inTopBand ? styles.topBandRow : styles.row}>
<View style={styles.island}>
{navigation === "menu" ? <SidebarMenuToggle /> : <BackButton onBack={onBack} />}
</View>
@@ -148,6 +155,12 @@ const styles = StyleSheet.create((theme) => ({
alignItems: "center",
gap: theme.spacing[2],
},
topBandRow: {
height: HEADER_INNER_HEIGHT,
flexDirection: "row",
alignItems: "center",
gap: theme.spacing[2],
},
titleGroup: {
flex: 1,
minWidth: 0,
+6 -4
View File
@@ -31,7 +31,7 @@ import {
resolveDesktopSidebarInsetLeft,
resolveDesktopSidebarWidth,
} from "@/components/desktop-sidebar-layout";
import { useWindowLayout, resolveDesktopDivisionLayout } from "@/window-layout";
import { useTopBand, useWindowLayout, resolveDesktopDivisionLayout } from "@/window-layout";
import {
SIDEBAR_RESIZE_ACTIVATION_OFFSET,
SIDEBAR_RESIZE_FAIL_OFFSET,
@@ -807,9 +807,11 @@ function DesktopSidebar({
],
[insetsTop, insets.bottom, insets.left, overlay, divisionLayout],
);
// Below the window controls' row, or in the top band's place, the first row starts flush.
const inTopBand = useTopBand() !== null;
const sidebarHeaderGroupStyle = useMemo(
() => [styles.sidebarHeaderGroup, ownsTopLeft && styles.sidebarHeaderGroupBelowChrome],
[ownsTopLeft],
() => [styles.sidebarHeaderGroup, (ownsTopLeft || inTopBand) && styles.sidebarHeaderGroupFlush],
[ownsTopLeft, inTopBand],
);
return (
<MobilePanelOverlay
@@ -938,7 +940,7 @@ const styles = StyleSheet.create((theme) => ({
borderBottomWidth: 1,
borderBottomColor: theme.colors.border,
},
sidebarHeaderGroupBelowChrome: {
sidebarHeaderGroupFlush: {
paddingTop: 0,
},
// The nav block caps at half the sidebar; a long item list scrolls inside the