From 0087e4c8ffda6c4d2057a3e0d8057967436240a3 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Thu, 15 Oct 2026 02:08:18 +0200 Subject: [PATCH] feat: open the composer as a centred panel on tablets --- App.tsx | 10 +++++---- src/screens/ComposeScreen.tsx | 38 +++++++++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/App.tsx b/App.tsx index 3b7dc402..a05666e5 100644 --- a/App.tsx +++ b/App.tsx @@ -394,6 +394,7 @@ export default function App() { // cached mail list instead of the "Restoring session" spinner; the real // JMAP session comes up in the background. const hasPersistedAccount = useAccountStore((state) => state.activeAccountId != null); + const { isSplit } = useLayout(); React.useEffect(() => { if (!hasRestoredSession) { @@ -824,10 +825,11 @@ export default function App() { editorRef.current?.blur()); - const { shortHeight } = useLayout(); + const { shortHeight, isSplit } = useLayout(); const typingInShortWindow = shortHeight && kbObstruction > 0; // When the keyboard is up it covers the bottom safe area, so we don't // need to add it on top — pad by whichever is larger. - const bottomPad = Math.max(kbObstruction, insets.bottom); + // On a tablet the composer is a centred panel that stops PANEL_MARGIN + // short of the screen bottom; the keyboard covers that much less of it. + const bottomPad = isSplit + ? Math.max(0, kbObstruction - PANEL_MARGIN) + : Math.max(kbObstruction, insets.bottom); const replyTo = route.params?.replyTo; const draft = route.params?.draft; const mode = route.params?.mode ?? 'compose'; @@ -2263,8 +2267,8 @@ export default function ComposeScreen({ route, navigation }: Props) { ); }; - return ( - + const composer = ( + ); + if (!isSplit) return composer; + // Tablet: a centred panel over the dimmed screen it was opened from. + return ( + + {composer} + + ); } +/** Gap between the tablet composer panel and the screen edges. */ +const PANEL_MARGIN = 24; + function makeStyles(c: ThemePalette) { return StyleSheet.create({ container: { flex: 1, backgroundColor: c.background }, flex: { flex: 1 }, + panelBackdrop: { + flex: 1, + backgroundColor: 'rgba(0,0,0,0.5)', + alignItems: 'center', + paddingHorizontal: PANEL_MARGIN, + }, + panel: { + flex: 1, + width: '100%', + maxWidth: 760, + borderRadius: radius.lg, + borderWidth: 1, + borderColor: c.border, + overflow: 'hidden', + backgroundColor: c.background, + }, scrollContent: { flexGrow: 1 }, header: {