From 334fe55a1cc0cb7536205f6bf76c0976cc79973b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 14 Oct 2026 16:26:23 +0000 Subject: [PATCH 1/2] fix(web): apply Tyler-approved account-choice copy Fixes #4461 Rename local-only and add-account labels in welcome, auth, settings, and the anonymous calendar row. Share strings with macOS via AccountChoiceCopy. Co-authored-by: Tyler Dane --- .../CompassKit/Auth/AccountChoiceCopy.swift | 11 ++++++++++ .../AccountChoiceCopyTests.swift | 17 +++++++++++++++ .../Onboarding/WelcomeModalView.swift | 16 +++++++++++++- .../SettingsAccountsSectionView.swift | 6 ++++++ .../src/auth/posthog/signup-funnel.ts | 2 +- .../providers/ConnectProviderChooser.test.tsx | 8 +++++-- .../src/auth/providers/connect.types.ts | 2 +- .../auth/providers/provider-copy.util.test.ts | 15 +++++++++++++ .../src/auth/providers/provider-copy.util.ts | 12 +++++++++++ .../src/components/AuthModal/AuthModal.tsx | 12 +++++++++++ .../components/Settings/AccountsSection.tsx | 11 +++++++--- .../CalendarList/AccountSectionHeader.tsx | 2 +- .../AnonymousCalendarRow.test.tsx | 4 ++-- .../CalendarList/AnonymousCalendarRow.tsx | 9 +++++++- .../CalendarList/CalendarList.test.tsx | 8 +++---- .../WelcomeModal/WelcomeModal.test.tsx | 16 +++++++------- .../components/WelcomeModal/WelcomeModal.tsx | 21 +++++++++++++++++-- docs/frontend/frontend-runtime-flow.md | 6 +++--- docs/frontend/shortcut-commandments.md | 2 +- .../connect-onboarding-a11y.spec.ts | 2 +- .../teaching-surface-a11y.spec.ts | 2 +- e2e/calendars/microsoft-surfaces.spec.ts | 6 ++++-- e2e/onboarding/first-run.spec.ts | 2 +- e2e/onboarding/shortcut-showcase.spec.ts | 2 +- e2e/onboarding/welcome-cta-width.spec.ts | 2 +- .../google/google.auth.service.test.ts | 2 +- .../services/google/google.auth.service.ts | 2 +- .../src/common/errors/auth/auth.errors.ts | 2 +- 28 files changed, 162 insertions(+), 40 deletions(-) create mode 100644 apps/calendar-macos/CompassKit/Sources/CompassKit/Auth/AccountChoiceCopy.swift create mode 100644 apps/calendar-macos/CompassKitTests/AccountChoiceCopyTests.swift diff --git a/apps/calendar-macos/CompassKit/Sources/CompassKit/Auth/AccountChoiceCopy.swift b/apps/calendar-macos/CompassKit/Sources/CompassKit/Auth/AccountChoiceCopy.swift new file mode 100644 index 0000000000..85f7b7f655 --- /dev/null +++ b/apps/calendar-macos/CompassKit/Sources/CompassKit/Auth/AccountChoiceCopy.swift @@ -0,0 +1,11 @@ +import Foundation + +/// Web parity: `apps/calendar-web/src/auth/providers/provider-copy.util.ts`. +enum AccountChoiceCopy { + static let localDeviceOnlyLabel = "On this device only" + static let localDeviceOnlySubtitle = + "Events stay in this browser until you connect an account." + static let connectCalendarAccountLabel = "Connect a calendar account" + static let connectCalendarAccountHelper = + "Pick Google, Microsoft, or Apple. Or keep using this device only from the calendar list." +} diff --git a/apps/calendar-macos/CompassKitTests/AccountChoiceCopyTests.swift b/apps/calendar-macos/CompassKitTests/AccountChoiceCopyTests.swift new file mode 100644 index 0000000000..47868351fc --- /dev/null +++ b/apps/calendar-macos/CompassKitTests/AccountChoiceCopyTests.swift @@ -0,0 +1,17 @@ +import XCTest +@testable import CompassKit + +final class AccountChoiceCopyTests: XCTestCase { + func testAccountChoiceCopyMatchesWeb() { + XCTAssertEqual(AccountChoiceCopy.localDeviceOnlyLabel, "On this device only") + XCTAssertEqual( + AccountChoiceCopy.localDeviceOnlySubtitle, + "Events stay in this browser until you connect an account.") + XCTAssertEqual( + AccountChoiceCopy.connectCalendarAccountLabel, + "Connect a calendar account") + XCTAssertEqual( + AccountChoiceCopy.connectCalendarAccountHelper, + "Pick Google, Microsoft, or Apple. Or keep using this device only from the calendar list.") + } +} diff --git a/apps/calendar-macos/CompassUI/Sources/CompassUI/Onboarding/WelcomeModalView.swift b/apps/calendar-macos/CompassUI/Sources/CompassUI/Onboarding/WelcomeModalView.swift index 3d1473e31f..7a3af21cff 100644 --- a/apps/calendar-macos/CompassUI/Sources/CompassUI/Onboarding/WelcomeModalView.swift +++ b/apps/calendar-macos/CompassUI/Sources/CompassUI/Onboarding/WelcomeModalView.swift @@ -106,7 +106,21 @@ struct WelcomeModalView: View { .foregroundStyle(theme.textMutedColor) } VStack(spacing: 12) { - primaryButton(title: "Explore without an account", hint: "S") { model.welcomeExplore() } + primaryButton(title: AccountChoiceCopy.localDeviceOnlyLabel, hint: "S") { + model.welcomeExplore() + } + Text(AccountChoiceCopy.localDeviceOnlySubtitle) + .font(.rubik(14)) + .foregroundStyle(theme.textMutedColor) + VStack(spacing: 4) { + Text(AccountChoiceCopy.connectCalendarAccountLabel) + .font(.rubik(14, weight: .semibold)) + .foregroundStyle(theme.textColor) + Text(AccountChoiceCopy.connectCalendarAccountHelper) + .font(.rubik(14)) + .foregroundStyle(theme.textMutedColor) + } + .frame(maxWidth: .infinity) Text("Ready to keep it? Start your free 7-day trial.") .font(.rubik(14)) .foregroundStyle(theme.textMutedColor) diff --git a/apps/calendar-macos/CompassUI/Sources/CompassUI/Settings/SettingsAccountsSectionView.swift b/apps/calendar-macos/CompassUI/Sources/CompassUI/Settings/SettingsAccountsSectionView.swift index 4ed5640ca9..27acd52544 100644 --- a/apps/calendar-macos/CompassUI/Sources/CompassUI/Settings/SettingsAccountsSectionView.swift +++ b/apps/calendar-macos/CompassUI/Sources/CompassUI/Settings/SettingsAccountsSectionView.swift @@ -52,6 +52,12 @@ struct SettingsAccountsSectionView: View { private var connectButtons: some View { VStack(alignment: .leading, spacing: 6) { + Text(AccountChoiceCopy.connectCalendarAccountLabel) + .font(.rubik(13, weight: .semibold)) + .foregroundStyle(theme.textColor) + Text(AccountChoiceCopy.connectCalendarAccountHelper) + .font(.rubik(11)) + .foregroundStyle(theme.textMutedColor) Button("Connect Google") { Task { await syncStore.connect(provider: .google) } } diff --git a/apps/calendar-web/src/auth/posthog/signup-funnel.ts b/apps/calendar-web/src/auth/posthog/signup-funnel.ts index f1be6e252d..47e05bfa4d 100644 --- a/apps/calendar-web/src/auth/posthog/signup-funnel.ts +++ b/apps/calendar-web/src/auth/posthog/signup-funnel.ts @@ -152,7 +152,7 @@ export async function trackSignupStartedAtClick( trackSignupStarted(source, anon_events_created); } -/** Anonymous visitor chose local-only mode (e.g. sidebar "This browser"). */ +/** Anonymous visitor chose local-only mode (e.g. sidebar "On this device only"). */ export function trackLocalModeSelected(source: LocalModeSource): void { track("local_mode_selected", { source }); } diff --git a/apps/calendar-web/src/auth/providers/ConnectProviderChooser.test.tsx b/apps/calendar-web/src/auth/providers/ConnectProviderChooser.test.tsx index eaa55a4268..b6b277c17b 100644 --- a/apps/calendar-web/src/auth/providers/ConnectProviderChooser.test.tsx +++ b/apps/calendar-web/src/auth/providers/ConnectProviderChooser.test.tsx @@ -155,9 +155,13 @@ describe("ConnectProviderChooser", () => { const user = userEvent.setup(); available = ["google", "microsoft", "apple"]; - renderChooser(); + renderChooser( + , + ); - await user.click(screen.getByRole("button", { name: /Add account/ })); + await user.click( + screen.getByRole("button", { name: /Connect a calendar account/ }), + ); for (const name of ["Google", "Microsoft"] as const) { const item = screen.getByRole("menuitem", { name }); diff --git a/apps/calendar-web/src/auth/providers/connect.types.ts b/apps/calendar-web/src/auth/providers/connect.types.ts index 58533ed398..2f60993b8e 100644 --- a/apps/calendar-web/src/auth/providers/connect.types.ts +++ b/apps/calendar-web/src/auth/providers/connect.types.ts @@ -26,7 +26,7 @@ export type UseConnectGoogleOptions = { connection?: SyncConnectionSummary | null; /** * Always start a new-account OAuth round-trip (`{}`), even when some other - * account is `RECONNECT_REQUIRED`. Settings "Add account" must never bind + * account is `RECONNECT_REQUIRED`. Settings "Connect a calendar account" must never bind * to a reconnect. */ newAccount?: boolean; diff --git a/apps/calendar-web/src/auth/providers/provider-copy.util.test.ts b/apps/calendar-web/src/auth/providers/provider-copy.util.test.ts index 7ef103dc3f..7e367b4315 100644 --- a/apps/calendar-web/src/auth/providers/provider-copy.util.test.ts +++ b/apps/calendar-web/src/auth/providers/provider-copy.util.test.ts @@ -1,10 +1,14 @@ import { ArrowsClockwiseIcon } from "@phosphor-icons/react/dist/csr/ArrowsClockwise"; import { bookingConnectPromptCopy, + CONNECT_CALENDAR_ACCOUNT_HELPER, + CONNECT_CALENDAR_ACCOUNT_LABEL, CONNECT_CALENDAR_LABEL, calendarProductName, connectionProvider, emptyCalendarsCopy, + LOCAL_DEVICE_ONLY_LABEL, + LOCAL_DEVICE_ONLY_SUBTITLE, openingProviderCopy, RECONNECT_BANNER_MESSAGE, RECONNECT_CALENDAR_LABEL, @@ -112,4 +116,15 @@ describe("provider copy", () => { ); expect(reconnect?.label).toBe("Reconnect Microsoft Calendar"); }); + + it("keeps Tyler-approved account-choice copy byte-identical", () => { + expect(LOCAL_DEVICE_ONLY_LABEL).toBe("On this device only"); + expect(LOCAL_DEVICE_ONLY_SUBTITLE).toBe( + "Events stay in this browser until you connect an account.", + ); + expect(CONNECT_CALENDAR_ACCOUNT_LABEL).toBe("Connect a calendar account"); + expect(CONNECT_CALENDAR_ACCOUNT_HELPER).toBe( + "Pick Google, Microsoft, or Apple. Or keep using this device only from the calendar list.", + ); + }); }); diff --git a/apps/calendar-web/src/auth/providers/provider-copy.util.ts b/apps/calendar-web/src/auth/providers/provider-copy.util.ts index cf92d4b731..c24472303f 100644 --- a/apps/calendar-web/src/auth/providers/provider-copy.util.ts +++ b/apps/calendar-web/src/auth/providers/provider-copy.util.ts @@ -27,6 +27,18 @@ export const CONNECT_CALENDAR_REASSURANCE = export const CALENDAR_HOST_EXPLAINER = "If you view your calendar in Apple Calendar, it may still be hosted by Google or Microsoft."; +/** Anonymous local-only calendar row and onboarding device-only path. */ +export const LOCAL_DEVICE_ONLY_LABEL = "On this device only"; + +export const LOCAL_DEVICE_ONLY_SUBTITLE = + "Events stay in this browser until you connect an account."; + +/** Settings and sign-in add-account chooser trigger. */ +export const CONNECT_CALENDAR_ACCOUNT_LABEL = "Connect a calendar account"; + +export const CONNECT_CALENDAR_ACCOUNT_HELPER = + "Pick Google, Microsoft, or Apple. Or keep using this device only from the calendar list."; + /** Admin-consent required (Microsoft Graph `consentRequired`). */ export const CONSENT_REQUIRED_COPY = "Your organization's admin has to approve Compass before this account can connect."; diff --git a/apps/calendar-web/src/components/AuthModal/AuthModal.tsx b/apps/calendar-web/src/components/AuthModal/AuthModal.tsx index 9692fd5aec..2bcf24b3ef 100644 --- a/apps/calendar-web/src/components/AuthModal/AuthModal.tsx +++ b/apps/calendar-web/src/components/AuthModal/AuthModal.tsx @@ -11,6 +11,10 @@ import { import { type ProviderKind } from "@core/types/sync/identity.contracts"; import { trackSignupStep } from "@web/auth/posthog/signup-funnel"; import { consumeGoogleAuthNeedsConsentRetry } from "@web/auth/providers/authorization/provider-authorization.storage"; +import { + CONNECT_CALENDAR_ACCOUNT_HELPER, + CONNECT_CALENDAR_ACCOUNT_LABEL, +} from "@web/auth/providers/provider-copy.util"; import { signInProviderForShortcutLetter } from "@web/auth/providers/sign-in-provider.util"; import { useSignInProviders } from "@web/auth/providers/useSignInProviders"; import { isEditableKeyboardTarget } from "@web/common/utils/form/form.util"; @@ -311,6 +315,14 @@ export const AuthModal: FC = () => { {/* Google Sign In - at bottom */} {showProviderSignIn ? ( <> +
+

+ {CONNECT_CALENDAR_ACCOUNT_LABEL} +

+

+ {CONNECT_CALENDAR_ACCOUNT_HELPER} +

+
or diff --git a/apps/calendar-web/src/components/Settings/AccountsSection.tsx b/apps/calendar-web/src/components/Settings/AccountsSection.tsx index 5bdf062dcc..4d9a561659 100644 --- a/apps/calendar-web/src/components/Settings/AccountsSection.tsx +++ b/apps/calendar-web/src/components/Settings/AccountsSection.tsx @@ -2,7 +2,10 @@ import { type FC } from "react"; import { type Calendar } from "@core/types/calendar.contracts"; import { type SyncConnectionSummary } from "@core/types/user.types"; import { ConnectProviderChooser } from "@web/auth/providers/ConnectProviderChooser"; -import { CALENDAR_HOST_EXPLAINER } from "@web/auth/providers/provider-copy.util"; +import { + CONNECT_CALENDAR_ACCOUNT_HELPER, + CONNECT_CALENDAR_ACCOUNT_LABEL, +} from "@web/auth/providers/provider-copy.util"; import { useDisconnectGoogleAccount } from "@web/auth/providers/useDisconnectAccount"; import { accountKey, @@ -61,7 +64,7 @@ export const AccountsSection: FC = ({ = ({ variant="overlay-primary" /> -

{CALENDAR_HOST_EXPLAINER}

+

+ {CONNECT_CALENDAR_ACCOUNT_HELPER} +

); }; diff --git a/apps/calendar-web/src/components/Sidebar/CalendarList/AccountSectionHeader.tsx b/apps/calendar-web/src/components/Sidebar/CalendarList/AccountSectionHeader.tsx index 838e496bfa..0e90687885 100644 --- a/apps/calendar-web/src/components/Sidebar/CalendarList/AccountSectionHeader.tsx +++ b/apps/calendar-web/src/components/Sidebar/CalendarList/AccountSectionHeader.tsx @@ -20,7 +20,7 @@ import { useAccountHeaderStatus } from "./useAccountHeaderStatus"; * and five accounts render the same shape, so the two can't drift apart the * way a separate single-account header did. * - * Adding/disconnecting accounts lives in the command palette's "Add account" / + * Adding/disconnecting accounts lives in the command palette's "Connect a calendar account" / * "Show accounts" items - not a permanent row or icon here, which stayed noisy * for accounts with many subcalendars. */ diff --git a/apps/calendar-web/src/components/Sidebar/CalendarList/AnonymousCalendarRow.test.tsx b/apps/calendar-web/src/components/Sidebar/CalendarList/AnonymousCalendarRow.test.tsx index 1a45ae1068..b8f4782f5e 100644 --- a/apps/calendar-web/src/components/Sidebar/CalendarList/AnonymousCalendarRow.test.tsx +++ b/apps/calendar-web/src/components/Sidebar/CalendarList/AnonymousCalendarRow.test.tsx @@ -71,10 +71,10 @@ describe("AnonymousCalendarRow", () => { isActive: true, }; - it("renders the row with 'This browser' label and trial sync copy", () => { + it("renders the row with the local device label and trial sync copy", () => { render(); - expect(screen.getByText("This browser")).toBeInTheDocument(); + expect(screen.getByText("On this device only")).toBeInTheDocument(); expect(ANONYMOUS_CALENDAR_ROW_TRIAL_MESSAGE).toBe( "Start your free trial to sync", ); diff --git a/apps/calendar-web/src/components/Sidebar/CalendarList/AnonymousCalendarRow.tsx b/apps/calendar-web/src/components/Sidebar/CalendarList/AnonymousCalendarRow.tsx index 79274424a3..9f194fd7ff 100644 --- a/apps/calendar-web/src/components/Sidebar/CalendarList/AnonymousCalendarRow.tsx +++ b/apps/calendar-web/src/components/Sidebar/CalendarList/AnonymousCalendarRow.tsx @@ -9,6 +9,10 @@ import { trackLocalModeSelected, trackSignupStartedAtClick, } from "@web/auth/posthog/signup-funnel"; +import { + LOCAL_DEVICE_ONLY_LABEL, + LOCAL_DEVICE_ONLY_SUBTITLE, +} from "@web/auth/providers/provider-copy.util"; import { useAuthModal } from "@web/components/AuthModal/hooks/useAuthModal"; import { Tooltip, @@ -69,10 +73,13 @@ export const AnonymousCalendarRow: FC = ({ borderColor: calendar.backgroundColor, }} /> - This browser + + {LOCAL_DEVICE_ONLY_LABEL} + + {LOCAL_DEVICE_ONLY_SUBTITLE} {ANONYMOUS_CALENDAR_ROW_TRIAL_MESSAGE} +

+ {LOCAL_DEVICE_ONLY_SUBTITLE} +

+
+

+ {CONNECT_CALENDAR_ACCOUNT_LABEL} +

+

+ {CONNECT_CALENDAR_ACCOUNT_HELPER} +

+

Ready to keep it? Start your free 7-day trial.

diff --git a/docs/frontend/frontend-runtime-flow.md b/docs/frontend/frontend-runtime-flow.md index 258adfdd91..a4990f7eaf 100644 --- a/docs/frontend/frontend-runtime-flow.md +++ b/docs/frontend/frontend-runtime-flow.md @@ -90,13 +90,13 @@ Welcome → signup → first-event contract: - the last screen is titled **Let's get started** with the subtitle **Connect a calendar or start fresh**. Its CTA order is **Continue with Google** (`G`, when Google is available), **Sign up with email** (`U`), then - **Explore without an account** (`S`), all the same full-width height. + **On this device only** (`S`), all the same full-width height. Explore is a quieter secondary pill so signup stays the stronger choice. Social and legal links (`6`–`0`) sit below. Google leads because the scopes Compass requests include the calendar, so that one round trip signs the user up *and* connects it, the moment the product starts being worth keeping -- **Explore without an account** closes the welcome dialog and leaves the +- **On this device only** closes the welcome dialog and leaves the Shortcut Showcase closed until the visitor opts in - **Log in** opens the auth modal and leaves the showcase flags alone, so a returning user is not handed the practice or the first-event prompt @@ -222,7 +222,7 @@ lands on the grid. Rageclicks on public booking pages are still dropped by the booking filter. `local_mode_selected` fires when an anonymous visitor chooses the sidebar -**This browser** row (local IndexedDB mode). It must not be confused with +**On this device only** row (local IndexedDB mode). It must not be confused with `signup_started`, which is reserved for explicit login or trial CTAs (OAuth, email sign-up modal, command palette, and similar). diff --git a/docs/frontend/shortcut-commandments.md b/docs/frontend/shortcut-commandments.md index 4fe6b2c335..ad3ea41e0b 100644 --- a/docs/frontend/shortcut-commandments.md +++ b/docs/frontend/shortcut-commandments.md @@ -95,7 +95,7 @@ Settings is an OverlayPanel with its own letter map while it holds app-lock (`apps/calendar-web/src/settings/useSettingsShortcuts.ts`). Those letters are not page-jump digits; they activate controls already on the Settings overlay. Billing: `U` Update card, -`C` Cancel subscription, `R` Resume subscription. Accounts: `A` Add account, +`C` Cancel subscription, `R` Resume subscription. Accounts: `A` Connect a calendar account, `E` Export, `D` Delete account, `O` Log out. `B` (trial badge / Start Premium) is registered by `UpgradeConfirmationProvider` and keeps working while Settings is open. Meeting settings reveal only sidebar digits diff --git a/e2e/accessibility/connect-onboarding-a11y.spec.ts b/e2e/accessibility/connect-onboarding-a11y.spec.ts index f653e13805..ec41f849a5 100644 --- a/e2e/accessibility/connect-onboarding-a11y.spec.ts +++ b/e2e/accessibility/connect-onboarding-a11y.spec.ts @@ -140,7 +140,7 @@ test("the add-account chooser with Google, Microsoft, and Other / iCloud has no const settingsDialog = page.getByRole("dialog", { name: "Settings" }); await settingsDialog.getByRole("button", { name: "Accounts" }).click(); const addAccount = settingsDialog.getByRole("button", { - name: "Add account", + name: "Connect a calendar account", }); await expect(addAccount).toBeVisible(); await addAccount.click(); diff --git a/e2e/accessibility/teaching-surface-a11y.spec.ts b/e2e/accessibility/teaching-surface-a11y.spec.ts index 2733766dbe..898b6840a7 100644 --- a/e2e/accessibility/teaching-surface-a11y.spec.ts +++ b/e2e/accessibility/teaching-surface-a11y.spec.ts @@ -40,7 +40,7 @@ test("exploring without an account returns focus to the week view without trappi .click(); await welcomeDialog.getByRole("button", { name: "Next" }).click(); await welcomeDialog - .getByRole("button", { name: "Explore without an account" }) + .getByRole("button", { name: "On this device only" }) .click(); await expect(welcomeDialog).toBeHidden(); diff --git a/e2e/calendars/microsoft-surfaces.spec.ts b/e2e/calendars/microsoft-surfaces.spec.ts index 11197c8be0..32eda530c6 100644 --- a/e2e/calendars/microsoft-surfaces.spec.ts +++ b/e2e/calendars/microsoft-surfaces.spec.ts @@ -117,7 +117,7 @@ test("Add account starts Microsoft OAuth from the chooser", async ({ const settingsDialog = page.getByRole("dialog", { name: "Settings" }); await settingsDialog.getByRole("button", { name: "Accounts" }).click(); const addAccount = settingsDialog.getByRole("button", { - name: "Add account", + name: "Connect a calendar account", }); await expect(addAccount).toBeVisible(); await addAccount.click(); @@ -151,7 +151,9 @@ test("Add account menu shows a logo for Google and Microsoft plus Other / iCloud const settingsDialog = page.getByRole("dialog", { name: "Settings" }); await settingsDialog.getByRole("button", { name: "Accounts" }).click(); - await settingsDialog.getByRole("button", { name: "Add account" }).click(); + await settingsDialog + .getByRole("button", { name: "Connect a calendar account" }) + .click(); const menu = settingsDialog.getByRole("menu"); await expect(menu).toBeVisible(); diff --git a/e2e/onboarding/first-run.spec.ts b/e2e/onboarding/first-run.spec.ts index ebec09be8a..ccb09f754a 100644 --- a/e2e/onboarding/first-run.spec.ts +++ b/e2e/onboarding/first-run.spec.ts @@ -46,7 +46,7 @@ test("welcomes a first-time user and seeds sample events", async ({ // The welcome modal advertises S for this action; prove the shortcut. await expect( - welcomeDialog.getByRole("button", { name: "Explore without an account" }), + welcomeDialog.getByRole("button", { name: "On this device only" }), ).toBeVisible(); await page.keyboard.press("s"); await expect(welcomeDialog).toBeHidden(); diff --git a/e2e/onboarding/shortcut-showcase.spec.ts b/e2e/onboarding/shortcut-showcase.spec.ts index e2b26f25c9..1c29e775ec 100644 --- a/e2e/onboarding/shortcut-showcase.spec.ts +++ b/e2e/onboarding/shortcut-showcase.spec.ts @@ -19,7 +19,7 @@ const dismissWelcomeWithExplore = async (page: Page) => { ).toBeVisible(); await page.keyboard.press("Enter"); await expect( - welcomeDialog.getByRole("button", { name: "Explore without an account" }), + welcomeDialog.getByRole("button", { name: "On this device only" }), ).toBeVisible(); await page.keyboard.press("s"); await expect(welcomeDialog).toBeHidden(); diff --git a/e2e/onboarding/welcome-cta-width.spec.ts b/e2e/onboarding/welcome-cta-width.spec.ts index 3cf7f9332f..11e3ca013f 100644 --- a/e2e/onboarding/welcome-cta-width.spec.ts +++ b/e2e/onboarding/welcome-cta-width.spec.ts @@ -40,7 +40,7 @@ test("keeps Google, email signup, and explore buttons the same width", async ({ name: "Sign up with email", }); const explore = welcomeDialog.getByRole("button", { - name: "Explore without an account", + name: "On this device only", }); await expect(google).toBeVisible(); await expect(email).toBeVisible(); diff --git a/packages/backend/src/auth/services/google/google.auth.service.test.ts b/packages/backend/src/auth/services/google/google.auth.service.test.ts index 6f597d011a..9da0087614 100644 --- a/packages/backend/src/auth/services/google/google.auth.service.test.ts +++ b/packages/backend/src/auth/services/google/google.auth.service.test.ts @@ -244,7 +244,7 @@ describe("handleGoogleAuth", () => { }), ).rejects.toMatchObject({ result: - "You're already signed in. Use Settings → Add account to connect this Google account.", + "You're already signed in. Use Settings → Connect a calendar account to connect this Google account.", code: "GOOGLE_SIGNIN_WHILE_AUTHENTICATED", }); diff --git a/packages/backend/src/auth/services/google/google.auth.service.ts b/packages/backend/src/auth/services/google/google.auth.service.ts index a62b69ff3d..815e13feed 100644 --- a/packages/backend/src/auth/services/google/google.auth.service.ts +++ b/packages/backend/src/auth/services/google/google.auth.service.ts @@ -244,7 +244,7 @@ async function handleGoogleAuth( if (options?.hasExistingSession) { throw error( AuthError.GoogleSignInWhileAuthenticated, - "You're already signed in. Use Settings → Add account to connect this Google account.", + "You're already signed in. Use Settings → Connect a calendar account to connect this Google account.", ); } const isNewUser = createdNewRecipeUser && loginMethodsLength === 1; diff --git a/packages/backend/src/common/errors/auth/auth.errors.ts b/packages/backend/src/common/errors/auth/auth.errors.ts index b5bb34a255..83eecf595c 100644 --- a/packages/backend/src/common/errors/auth/auth.errors.ts +++ b/packages/backend/src/common/errors/auth/auth.errors.ts @@ -34,7 +34,7 @@ export const authErrorCopy = { refreshTokenMissing: (provider?: ProviderKind) => `${calendarHostLabel(provider)} did not grant a fresh authorization. Please try again.`, signInWhileAuthenticated: (provider?: ProviderKind) => - `You're already signed in. Use Settings → Add account to connect this ${calendarHostLabel(provider)} account.`, + `You're already signed in. Use Settings → Connect a calendar account to connect this ${calendarHostLabel(provider)} account.`, }; export const AuthError: AuthErrors = { From 5f4faf9beff66e41296e35b72d13cb9695905c36 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 14 Oct 2026 17:00:08 +0000 Subject: [PATCH 2/2] fix(macos): export AccountChoiceCopy for CompassUI Co-authored-by: Tyler Dane --- .../Sources/CompassKit/Auth/AccountChoiceCopy.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/calendar-macos/CompassKit/Sources/CompassKit/Auth/AccountChoiceCopy.swift b/apps/calendar-macos/CompassKit/Sources/CompassKit/Auth/AccountChoiceCopy.swift index 85f7b7f655..c7d1e097f3 100644 --- a/apps/calendar-macos/CompassKit/Sources/CompassKit/Auth/AccountChoiceCopy.swift +++ b/apps/calendar-macos/CompassKit/Sources/CompassKit/Auth/AccountChoiceCopy.swift @@ -1,11 +1,11 @@ import Foundation /// Web parity: `apps/calendar-web/src/auth/providers/provider-copy.util.ts`. -enum AccountChoiceCopy { - static let localDeviceOnlyLabel = "On this device only" - static let localDeviceOnlySubtitle = +public enum AccountChoiceCopy { + public static let localDeviceOnlyLabel = "On this device only" + public static let localDeviceOnlySubtitle = "Events stay in this browser until you connect an account." - static let connectCalendarAccountLabel = "Connect a calendar account" - static let connectCalendarAccountHelper = + public static let connectCalendarAccountLabel = "Connect a calendar account" + public static let connectCalendarAccountHelper = "Pick Google, Microsoft, or Apple. Or keep using this device only from the calendar list." }