fix: reorder welcome onboarding actions
This commit is contained in:
@@ -41,16 +41,18 @@ describe('WelcomeScreen', () => {
|
||||
expect(brandIcon).toHaveAttribute('src', tolariaIcon)
|
||||
})
|
||||
|
||||
it('shows all three option buttons', () => {
|
||||
it('shows the onboarding actions in the guided-first order', () => {
|
||||
render(<WelcomeScreen {...defaultProps} />)
|
||||
expect(screen.getByTestId('welcome-create-new')).toHaveTextContent('Create empty vault')
|
||||
expect(screen.getByTestId('welcome-open-folder')).toHaveTextContent('Open existing vault')
|
||||
expect(screen.getByTestId('welcome-create-vault')).toHaveTextContent('Get started with a template')
|
||||
|
||||
const optionButtons = screen.getAllByRole('button')
|
||||
expect(optionButtons[0]).toBe(screen.getByTestId('welcome-create-vault'))
|
||||
expect(optionButtons[1]).toBe(screen.getByTestId('welcome-create-new'))
|
||||
expect(optionButtons[2]).toBe(screen.getByTestId('welcome-open-folder'))
|
||||
})
|
||||
|
||||
it('focuses the first action for keyboard users', () => {
|
||||
render(<WelcomeScreen {...defaultProps} />)
|
||||
expect(screen.getByTestId('welcome-create-new')).toHaveFocus()
|
||||
expect(screen.getByTestId('welcome-create-vault')).toHaveFocus()
|
||||
})
|
||||
|
||||
it('shows the simplified template option description', () => {
|
||||
@@ -109,13 +111,13 @@ describe('WelcomeScreen', () => {
|
||||
})
|
||||
|
||||
it('cycles onboarding actions with Tab and activates the selected action with Enter', () => {
|
||||
const onOpenFolder = vi.fn()
|
||||
render(<WelcomeScreen {...defaultProps} onOpenFolder={onOpenFolder} />)
|
||||
const onCreateEmptyVault = vi.fn()
|
||||
render(<WelcomeScreen {...defaultProps} onCreateEmptyVault={onCreateEmptyVault} />)
|
||||
|
||||
fireEvent.keyDown(window, { key: 'Tab' })
|
||||
fireEvent.keyDown(window, { key: 'Enter' })
|
||||
|
||||
expect(onOpenFolder).toHaveBeenCalledOnce()
|
||||
expect(onCreateEmptyVault).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('disables all buttons while creating', () => {
|
||||
|
||||
@@ -310,18 +310,18 @@ function useWelcomeActionButtons({
|
||||
> & {
|
||||
busy: boolean
|
||||
}) {
|
||||
const primaryActionRef = useRef<HTMLButtonElement>(null)
|
||||
const openFolderActionRef = useRef<HTMLButtonElement>(null)
|
||||
const templateActionRef = useRef<HTMLButtonElement>(null)
|
||||
const createEmptyActionRef = useRef<HTMLButtonElement>(null)
|
||||
const openFolderActionRef = useRef<HTMLButtonElement>(null)
|
||||
const actionButtonRefs = useMemo(
|
||||
() => [primaryActionRef, openFolderActionRef, templateActionRef],
|
||||
() => [templateActionRef, createEmptyActionRef, openFolderActionRef],
|
||||
[],
|
||||
)
|
||||
const actions = useMemo<WelcomeAction[]>(
|
||||
() => ([
|
||||
{ disabled: isOffline, run: onCreateVault },
|
||||
{ disabled: false, run: onCreateEmptyVault },
|
||||
{ disabled: false, run: onOpenFolder },
|
||||
{ disabled: isOffline, run: onCreateVault },
|
||||
]),
|
||||
[isOffline, onCreateEmptyVault, onCreateVault, onOpenFolder],
|
||||
)
|
||||
@@ -330,7 +330,7 @@ function useWelcomeActionButtons({
|
||||
if (busy) return
|
||||
|
||||
// WKWebView can ignore `autoFocus`; move focus explicitly so keyboard-only
|
||||
// onboarding always starts on "Create empty vault".
|
||||
// onboarding always starts on the guided template flow.
|
||||
focusWelcomeAction(actionButtonRefs, 0)
|
||||
}, [actionButtonRefs, busy, mode])
|
||||
|
||||
@@ -362,9 +362,9 @@ function useWelcomeActionButtons({
|
||||
}, [actionButtonRefs, actions, busy])
|
||||
|
||||
return {
|
||||
primaryActionRef,
|
||||
openFolderActionRef,
|
||||
templateActionRef,
|
||||
createEmptyActionRef,
|
||||
openFolderActionRef,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,7 +382,7 @@ export function WelcomeScreen({
|
||||
}: WelcomeScreenProps) {
|
||||
const busy = creatingAction !== null
|
||||
const presentation = getWelcomeScreenPresentation(mode, defaultVaultPath, isOffline)
|
||||
const { primaryActionRef, openFolderActionRef, templateActionRef } = useWelcomeActionButtons({
|
||||
const { templateActionRef, createEmptyActionRef, openFolderActionRef } = useWelcomeActionButtons({
|
||||
mode,
|
||||
busy,
|
||||
isOffline,
|
||||
@@ -417,6 +417,21 @@ export function WelcomeScreen({
|
||||
<div style={DIVIDER_STYLE} />
|
||||
|
||||
<div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 10 }}>
|
||||
<OptionButton
|
||||
icon={<Rocket size={18} style={{ color: 'var(--accent-purple)' }} />}
|
||||
iconBg="var(--accent-purple-light, #F3E8FF)"
|
||||
label="Get started with a template"
|
||||
description={presentation.templateDescription}
|
||||
loadingLabel="Downloading template…"
|
||||
loadingDescription="Cloning the Getting Started vault template"
|
||||
onClick={onCreateVault}
|
||||
disabled={busy || isOffline}
|
||||
loading={creatingAction === 'template'}
|
||||
testId="welcome-create-vault"
|
||||
autoFocus
|
||||
buttonRef={templateActionRef}
|
||||
/>
|
||||
|
||||
<OptionButton
|
||||
icon={<Plus size={18} style={{ color: 'var(--accent-blue)' }} />}
|
||||
iconBg="var(--accent-blue-light, #EBF4FF)"
|
||||
@@ -428,8 +443,7 @@ export function WelcomeScreen({
|
||||
disabled={busy}
|
||||
loading={creatingAction === 'empty'}
|
||||
testId="welcome-create-new"
|
||||
autoFocus
|
||||
buttonRef={primaryActionRef}
|
||||
buttonRef={createEmptyActionRef}
|
||||
/>
|
||||
|
||||
<OptionButton
|
||||
@@ -442,20 +456,6 @@ export function WelcomeScreen({
|
||||
testId="welcome-open-folder"
|
||||
buttonRef={openFolderActionRef}
|
||||
/>
|
||||
|
||||
<OptionButton
|
||||
icon={<Rocket size={18} style={{ color: 'var(--accent-purple)' }} />}
|
||||
iconBg="var(--accent-purple-light, #F3E8FF)"
|
||||
label="Get started with a template"
|
||||
description={presentation.templateDescription}
|
||||
loadingLabel="Downloading template…"
|
||||
loadingDescription="Cloning the Getting Started vault template"
|
||||
onClick={onCreateVault}
|
||||
disabled={busy || isOffline}
|
||||
loading={creatingAction === 'template'}
|
||||
testId="welcome-create-vault"
|
||||
buttonRef={templateActionRef}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{creatingAction === 'template' && (
|
||||
|
||||
@@ -181,8 +181,10 @@ test('keyboard onboarding can create an empty vault and the first note', async (
|
||||
|
||||
await expect(page.getByTestId('welcome-screen')).toBeVisible()
|
||||
await expect(page.getByTestId('welcome-create-new')).toContainText('Create empty vault')
|
||||
await expect(page.getByTestId('welcome-create-new')).toBeFocused()
|
||||
await expect(page.getByTestId('welcome-create-vault')).toBeFocused()
|
||||
|
||||
await page.keyboard.press('Tab')
|
||||
await expect(page.getByTestId('welcome-create-new')).toBeFocused()
|
||||
await page.keyboard.press('Enter')
|
||||
|
||||
await expect(page.getByTestId('note-list-container')).toBeVisible({ timeout: 5_000 })
|
||||
|
||||
@@ -59,7 +59,7 @@ test('accepting telemetry consent on a fresh start opens the vault choice wizard
|
||||
|
||||
await expect(page.getByTestId('welcome-screen')).toBeVisible()
|
||||
await expect(page.getByTestId('welcome-open-folder')).toBeVisible()
|
||||
await expect(page.getByTestId('welcome-create-new')).toBeFocused()
|
||||
await expect(page.getByTestId('welcome-create-vault')).toBeFocused()
|
||||
})
|
||||
|
||||
test('telemetry consent still leaves the welcome wizard fully keyboard navigable @smoke', async ({ page }) => {
|
||||
@@ -76,6 +76,9 @@ test('telemetry consent still leaves the welcome wizard fully keyboard navigable
|
||||
await page.keyboard.press('Enter')
|
||||
|
||||
await expect(page.getByTestId('welcome-screen')).toBeVisible()
|
||||
await expect(page.getByTestId('welcome-create-vault')).toBeFocused()
|
||||
|
||||
await page.keyboard.press('Tab')
|
||||
await expect(page.getByTestId('welcome-create-new')).toBeFocused()
|
||||
|
||||
await page.keyboard.press('Tab')
|
||||
@@ -92,10 +95,10 @@ test('telemetry consent still leaves the welcome wizard fully keyboard navigable
|
||||
|
||||
await expect(page.getByTestId('welcome-screen')).toBeVisible()
|
||||
|
||||
await page.keyboard.press('Tab')
|
||||
await expect(page.getByTestId('welcome-create-vault')).toBeFocused()
|
||||
await page.keyboard.press('Shift+Tab')
|
||||
await expect(page.getByTestId('welcome-open-folder')).toBeFocused()
|
||||
await expect(page.getByTestId('welcome-create-new')).toBeFocused()
|
||||
await page.keyboard.press('Shift+Tab')
|
||||
await expect(page.getByTestId('welcome-create-vault')).toBeFocused()
|
||||
})
|
||||
|
||||
for (const action of ['accept', 'decline'] as const) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { test, expect, type Page } from '@playwright/test'
|
||||
async function installOnboardingMocks(page: Page, offline: boolean) {
|
||||
await page.addInitScript((isOffline: boolean) => {
|
||||
localStorage.clear()
|
||||
let createdVaultPath: string | null = null
|
||||
|
||||
let ref: Record<string, unknown> | null = null
|
||||
|
||||
@@ -16,11 +17,12 @@ async function installOnboardingMocks(page: Page, offline: boolean) {
|
||||
hidden_defaults: [],
|
||||
})
|
||||
ref.get_default_vault_path = () => '/Users/mock/Documents/Getting Started'
|
||||
ref.check_vault_exists = () => false
|
||||
ref.check_vault_exists = (args: { path?: string }) => args.path === createdVaultPath
|
||||
ref.create_getting_started_vault = (args: { targetPath?: string | null }) => {
|
||||
if (args.targetPath !== '/Users/mock/Documents/Getting Started') {
|
||||
throw new Error(`Unexpected Getting Started target: ${args.targetPath}`)
|
||||
}
|
||||
createdVaultPath = args.targetPath
|
||||
return args.targetPath
|
||||
}
|
||||
},
|
||||
@@ -65,6 +67,6 @@ test('status bar keeps a Getting Started clone entry available after onboarding'
|
||||
await expect(page.getByTestId('claude-onboarding-screen')).toBeVisible()
|
||||
await page.getByTestId('claude-onboarding-continue').click()
|
||||
await expect(page.locator('[data-testid="note-list-container"]')).toBeVisible()
|
||||
await page.getByTitle('Switch vault').click()
|
||||
await page.getByTestId('status-vault-trigger').click()
|
||||
await expect(page.getByTestId('vault-menu-clone-getting-started')).toBeVisible()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user