From c87c11734bae0af42e231f034a1e05884972f563 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Wed, 4 Nov 2026 15:19:11 +0100 Subject: [PATCH] feat: add a setting to keep the account switcher at the top of the sidebar, on by default --- app/boot-skeleton.css | 3 ++ components/boot-skeleton/mail-skeleton.tsx | 12 +++--- components/email/email-list.tsx | 10 +++-- .../layout/__tests__/sidebar-compose.test.tsx | 39 ++++++++++++++++--- components/layout/sidebar.tsx | 20 ++++++---- .../mail/__tests__/after-send-hook.test.tsx | 13 +++++-- .../mail/__tests__/mobile-tour-end.test.tsx | 26 +++++++++---- components/mail/mail-app.tsx | 9 +++-- components/settings/layout-settings.tsx | 13 +++++-- .../__tests__/boot-script.test.ts | 11 ++++++ lib/boot-skeleton/boot-script.ts | 3 ++ lib/plugin-sandbox/host-api-app.ts | 2 +- lib/settings-schema.ts | 1 + lib/settings-search.ts | 1 + locales/ar/common.json | 4 ++ locales/ca/common.json | 4 ++ locales/cs/common.json | 4 ++ locales/da/common.json | 4 ++ locales/de/common.json | 4 ++ locales/en/common.json | 4 ++ locales/es/common.json | 4 ++ locales/et/common.json | 4 ++ locales/fa/common.json | 4 ++ locales/fr/common.json | 4 ++ locales/he/common.json | 4 ++ locales/hu/common.json | 4 ++ locales/it/common.json | 4 ++ locales/ja/common.json | 4 ++ locales/ko/common.json | 4 ++ locales/lv/common.json | 4 ++ locales/mn/common.json | 4 ++ locales/nb/common.json | 4 ++ locales/nl/common.json | 4 ++ locales/pl/common.json | 4 ++ locales/pt/common.json | 4 ++ locales/ro/common.json | 4 ++ locales/ru/common.json | 4 ++ locales/sk/common.json | 4 ++ locales/th/common.json | 4 ++ locales/tr/common.json | 4 ++ locales/uk/common.json | 4 ++ locales/vi/common.json | 4 ++ locales/zh-TW/common.json | 4 ++ locales/zh/common.json | 4 ++ stores/settings-store.ts | 5 +++ 45 files changed, 247 insertions(+), 41 deletions(-) diff --git a/app/boot-skeleton.css b/app/boot-skeleton.css index dbf7543cf..dc27f65a3 100644 --- a/app/boot-skeleton.css +++ b/app/boot-skeleton.css @@ -30,6 +30,9 @@ } } +/* Compose heads the folder sidebar, in place of the account switcher. */ +@custom-variant boot-sidebar-compose (&:where([data-boot-sidebar-compose="on"] *)); + /* A message, thread, contact, settings page or admin page is open. */ @custom-variant boot-open (&:where([data-boot-pane] *)); @custom-variant boot-thread (&:where([data-boot-pane="thread"] *)); diff --git a/components/boot-skeleton/mail-skeleton.tsx b/components/boot-skeleton/mail-skeleton.tsx index 07c634645..2a3b4a87d 100644 --- a/components/boot-skeleton/mail-skeleton.tsx +++ b/components/boot-skeleton/mail-skeleton.tsx @@ -131,7 +131,7 @@ function SidebarSkeleton({ embedded }: { embedded: boolean }) { {/* A compact desktop folds the sidebar to its icons (sidebarFolded). */} - + @@ -139,9 +139,11 @@ function SidebarSkeleton({ embedded }: { embedded: boolean }) { + {/* Compose in place of the account switcher (sidebarAccountSwitcher off). */} + - {/* The folded sidebar's Compose button. */} -
+ {/* The folded sidebar's Compose button (sidebarAccountSwitcher off). */} +
@@ -665,8 +667,8 @@ export function MailSkeletonBody({ embedded = false }: { embedded?: boolean }) { className={cn( "absolute z-40 shadow-lg bottom-4 end-4 h-12 w-12 max-desk:h-14 max-desk:w-14", "max-desk:mv:w-36 max-desk:mv:rounded-2xl", - // A desktop has Compose in the folder sidebar; a Pro pane keeps the round one. - !embedded && "desk:hidden", + // A desktop can have Compose in the folder sidebar instead; a Pro pane keeps the round one. + !embedded && "desk:mv:hidden desk:boot-sidebar-compose:hidden", )} /> diff --git a/components/email/email-list.tsx b/components/email/email-list.tsx index 4d0b0c496..aa32bf841 100644 --- a/components/email/email-list.tsx +++ b/components/email/email-list.tsx @@ -216,6 +216,7 @@ export function EmailList({ const mountainViewList = useSettingsStore((state) => state.interfaceLayout === 'mountain-view'); const isDesktopPane = useIsDesktop(); const isEmbeddedList = useIsEmbedded(); + const sidebarAccountSwitcher = useSettingsStore((state) => state.sidebarAccountSwitcher); const undo = undoLabels(tNotifications); const tRemove = useTranslations('email_list.confirm_remove'); const { client } = useAuthStore(useShallow((state) => ({ client: state.client }))); @@ -1161,10 +1162,11 @@ export function EmailList({ // Room under the last row for the round Compose button, which would otherwise // sit on that row's actions (Mountain View has no such button, and a desktop - // has Compose in the folder sidebar instead). A spacer and - // not padding on the list: padding is a minimum height the list can't go - // under, and on a short screen it pushed the rows over the tab bar. - const composeButtonRoom = !mountainViewList && (!isDesktopPane || isEmbeddedList) ? - {/* Floating Compose Button - on desktop the folder sidebar has - Compose at its top instead (and Mountain View its rail), so the - button no longer sits on the list's rows. */} - {!mvShell && (isMobile || isEmbedded) &&