🐛(frontend) open search results in a new tab with ctrl/cmd+click

Search results were cmdk items navigating with router.push on select,
so the browser had no link to open elsewhere. Each result is now a real
link to the document: a plain click still goes through the quick search
onSelect, while ctrl, cmd, shift or middle click let the browser open it
in a new tab or window and keep the search modal open.

Signed-off-by: Armand <schneideretcollier.innovation@gmail.com>
This commit is contained in:
Armand
2026-09-24 12:28:14 +02:00
committed by Ovgodd
parent 9c8d7f30be
commit 139dd17ca0
3 changed files with 65 additions and 4 deletions
@@ -68,6 +68,52 @@ test.describe('Document search', () => {
).toBeHidden();
});
test('it opens a search result in a new tab with ctrl+click', async ({
page,
browserName,
}) => {
const [docTitle] = await createDoc(
page,
'My doc search new tab',
browserName,
1,
);
await verifyDocName(page, docTitle);
await page.goto('/');
await page.getByTestId('search-docs-button').click();
const inputSearch = page.getByPlaceholder('Type the name of a document');
await inputSearch.fill(docTitle);
const result = page
.getByRole('listbox')
.getByRole('group')
.getByRole('option')
.getByText(docTitle);
await expect(result).toBeVisible();
const [newPage] = await Promise.all([
page.context().waitForEvent('page'),
result.click({ modifiers: ['ControlOrMeta'] }),
]);
await verifyDocName(newPage, docTitle);
// The search stays open in the first tab
await expect(
page.getByRole('heading', { name: 'Search for a document' }),
).toBeVisible();
await expect(result).toBeVisible();
await newPage.close();
// A plain click still opens the document in the current tab
await result.click();
await verifyDocName(page, docTitle);
await expect(
page.getByRole('heading', { name: 'Search for a document' }),
).toBeHidden();
});
test('it checks cmd+k modal search interaction', async ({
page,
browserName,
@@ -1,5 +1,7 @@
import { css } from 'styled-components';
import ArrowIcon from '@/assets/icons/ui-kit/enter.svg';
import { Box, Icon } from '@/components';
import { Box, Icon, StyledLink } from '@/components';
import { QuickSearchItemContent } from '@/components/quick-search/';
import { SimpleDocItem } from '@/docs/doc-management';
import { useResponsiveStore } from '@/stores';
@@ -16,10 +18,22 @@ export const DocSearchItem = ({ doc }: DocSearchItemProps) => {
const { filter } = useDocSearchFilterStore();
return (
<Box
<StyledLink
data-testid={`doc-search-item-${doc.id}`}
$width="100%"
className="--docs--doc-search-item"
href={`/docs/${doc.id}`}
tabIndex={-1}
$css={css`
width: 100%;
color: inherit;
`}
onClick={(e) => {
if (e.metaKey || e.ctrlKey || e.shiftKey) {
e.stopPropagation();
return;
}
e.preventDefault();
}}
>
<QuickSearchItemContent
left={
@@ -42,6 +56,6 @@ export const DocSearchItem = ({ doc }: DocSearchItemProps) => {
/>
}
/>
</Box>
</StyledLink>
);
};