From 4b282e7064ccb827e44ee9fee3b108a9bd4ff0b9 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Sun, 11 Oct 2026 20:09:31 +0200 Subject: [PATCH] fix: give touch tips in the welcome banner on a phone --- .../ui/__tests__/welcome-banner.test.tsx | 37 +++++++++++++++++++ components/ui/welcome-banner.tsx | 9 +++-- locales/en/common.json | 2 + 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 components/ui/__tests__/welcome-banner.test.tsx diff --git a/components/ui/__tests__/welcome-banner.test.tsx b/components/ui/__tests__/welcome-banner.test.tsx new file mode 100644 index 000000000..f91c9b069 --- /dev/null +++ b/components/ui/__tests__/welcome-banner.test.tsx @@ -0,0 +1,37 @@ +import { render, screen } from '@testing-library/react'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import React from 'react'; + +// On a phone the banner said "Press c to compose" and pointed at a sidebar +// that the phone layout does not have. + +const device = vi.hoisted(() => ({ isMobile: false })); +vi.mock('@/hooks/use-media-query', () => ({ + useDeviceDetection: () => ({ isMobile: device.isMobile, isTablet: false, isDesktop: !device.isMobile }), +})); +vi.mock('@/components/tour/tour-provider', () => ({ useTour: () => ({ startTour: vi.fn() }) })); +vi.mock('@/i18n/navigation', () => ({ useRouter: () => ({ push: vi.fn() }) })); + +const { WelcomeBanner } = await import('../welcome-banner'); +const { useSettingsStore } = await import('@/stores/settings-store'); + +describe('WelcomeBanner tips', () => { + beforeEach(() => { + useSettingsStore.setState({ onboardingCompleted: false }); + }); + + it('gives keyboard tips on a desktop', () => { + device.isMobile = false; + render(); + expect(screen.getByText('tip_compose')).toBeInTheDocument(); + expect(screen.getByText('tip_shortcuts')).toBeInTheDocument(); + }); + + it('gives touch tips on a phone', () => { + device.isMobile = true; + render(); + expect(screen.getByText('tip_compose_touch')).toBeInTheDocument(); + expect(screen.getByText('tip_sidebar_touch')).toBeInTheDocument(); + expect(screen.queryByText('tip_shortcuts')).toBeNull(); + }); +}); diff --git a/components/ui/welcome-banner.tsx b/components/ui/welcome-banner.tsx index a2082b7f3..736418b37 100644 --- a/components/ui/welcome-banner.tsx +++ b/components/ui/welcome-banner.tsx @@ -7,6 +7,7 @@ import { Button } from "@/components/ui/button"; import { useRouter } from "@/i18n/navigation"; import { useTour } from "@/components/tour/tour-provider"; import { useSettingsStore } from "@/stores/settings-store"; +import { useDeviceDetection } from "@/hooks/use-media-query"; const ONBOARDING_KEY = "onboarding_completed"; @@ -19,6 +20,8 @@ export function WelcomeBanner() { const updateSetting = useSettingsStore((s) => s.updateSetting); const [visible, setVisible] = useState(false); const [dismissed, setDismissed] = useState(false); + // A phone has no keyboard shortcuts and keeps the apps in the bottom bar. + const { isMobile } = useDeviceDetection(); useEffect(() => { // One-time migration: if the legacy per-device flag is set but the synced @@ -89,9 +92,9 @@ export function WelcomeBanner() { {t("title")} diff --git a/locales/en/common.json b/locales/en/common.json index 95fe437da..b3aab598e 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -3600,6 +3600,8 @@ "tip_shortcuts": "Press ? to see all keyboard shortcuts", "tip_sidebar": "Find Calendar, Contacts and Settings in the sidebar menu", "tip_settings": "Customize your experience in Settings", + "tip_compose_touch": "Tap the pencil button to write a new email", + "tip_sidebar_touch": "Find Calendar, Contacts and Settings in the bar at the bottom", "got_it": "Got it", "settings": "Settings", "dismiss": "Dismiss",