Replace the modal command palette with a nonmodal terminal dock.
Ctrl+K now opens a corner session with a parsed navigate grammar, persistent history, and no page lock. Unknown targets stay on a closed alias table and never become URLs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { pagePath } from './helpers';
|
||||
|
||||
test.describe('keyboard and palette', () => {
|
||||
test.describe('keyboard and terminal dock', () => {
|
||||
test('skip link is first and moves focus to main', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.keyboard.press('Tab');
|
||||
@@ -87,37 +87,32 @@ test.describe('keyboard and palette', () => {
|
||||
const headerBox = await page.locator('.site-header').boundingBox();
|
||||
expect(headerBox, 'header while submenu is open').toBeTruthy();
|
||||
expect(headerBox!.height, 'header height while submenu is open').toBeLessThanOrEqual(200);
|
||||
|
||||
const background = await firstChild.evaluate((element) => {
|
||||
const submenu = element.closest('.submenu');
|
||||
return submenu ? getComputedStyle(submenu).backgroundColor : '';
|
||||
});
|
||||
expect(background, 'submenu background must be fully opaque').toMatch(
|
||||
/^rgb\(\d+,\s*\d+,\s*\d+\)$/,
|
||||
);
|
||||
});
|
||||
|
||||
test('palette opens with Control+K, traps focus, locks scroll and restores on Escape', async ({
|
||||
test('terminal dock opens with Control+K without locking the page and restores on Escape', async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto('/');
|
||||
const trigger = page.locator('.command-palette-trigger');
|
||||
const trigger = page.locator('.terminal-dock-trigger');
|
||||
await trigger.focus();
|
||||
await page.keyboard.press('Control+k');
|
||||
|
||||
const dialog = page.locator('[role="dialog"]');
|
||||
await expect(dialog).toBeVisible();
|
||||
await expect(page.locator('.site')).toHaveAttribute('inert', '');
|
||||
expect(await page.evaluate(() => document.body.style.overflow)).toBe('hidden');
|
||||
|
||||
const focusable = dialog.locator(
|
||||
'a[href], button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled])',
|
||||
);
|
||||
const count = await focusable.count();
|
||||
const first = focusable.first();
|
||||
const last = focusable.nth(count - 1);
|
||||
await last.focus();
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(first).toBeFocused();
|
||||
await page.keyboard.press('Shift+Tab');
|
||||
await expect(last).toBeFocused();
|
||||
const panel = page.locator('.terminal-dock-panel');
|
||||
await expect(panel).toBeVisible();
|
||||
await expect(page.locator('.site')).not.toHaveAttribute('inert');
|
||||
expect(await page.evaluate(() => document.body.style.overflow)).not.toBe('hidden');
|
||||
await expect(page.locator('[role="dialog"]')).toHaveCount(0);
|
||||
|
||||
await page.keyboard.press('Escape');
|
||||
await expect(dialog).toHaveCount(0);
|
||||
await expect(page.locator('.site')).not.toHaveAttribute('inert');
|
||||
expect(await page.evaluate(() => document.body.style.overflow)).toBe('');
|
||||
await expect(panel).toHaveCount(0);
|
||||
await expect(trigger).toBeFocused();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user