fix: a link inside the split pane just goes
"Beside what you are reading, or in a tab?" is a question with one real answer
for somebody who is already beside what they were reading. Inside the pane the
card offered Split view — which replaced the pane they were in — and the click
that would have simply followed the link opened a card instead.
So inside the pane the link goes: the pane follows it, the trail records it,
and Back returns to the reference that sent you. The hover card is still what
happens everywhere else, where the question is real.
One of the tests covering this was passing without testing anything. It held ⌘
with `userEvent.keyboard('{Meta>}')` and then clicked with a *different*
`userEvent` session, and modifier state lives on the session — so the
"modified click" it asserted about was an ordinary one. It holds the key now.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqXevQJhxFrM7jJg82cgZN
This commit is contained in:
parent
febb14490c
commit
93a3b74011
3 changed files with 41 additions and 11 deletions
|
|
@ -114,6 +114,15 @@ export default function ArticleLink({ slug, sectionId = null, children, classNam
|
|||
setOpen(false)
|
||||
return
|
||||
}
|
||||
// Already reading in the pane? Then the pane is where this goes, and the
|
||||
// click says so. There is no second pane to offer, and asking "beside what
|
||||
// you are reading, or in a tab?" of somebody who is already beside what
|
||||
// they were reading is a question with one real answer.
|
||||
if (split?.inPane) {
|
||||
setOpen(false)
|
||||
split.open(slug)
|
||||
return
|
||||
}
|
||||
reveal()
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +143,7 @@ export default function ArticleLink({ slug, sectionId = null, children, classNam
|
|||
{preview.status !== 'published' && ' · draft'}
|
||||
</span>
|
||||
<span className="al-card-actions">
|
||||
{split && (
|
||||
{split && !split.inPane && (
|
||||
<button type="button" className="al-card-action"
|
||||
aria-label={`Open ${preview.title} in split view`}
|
||||
onClick={() => { hideNow(); split.open(slug) }}>
|
||||
|
|
|
|||
|
|
@ -175,22 +175,29 @@ describe('reading a cross-reference without leaving the article', () => {
|
|||
mountBeside({ open, inPane: true }, 'deeper-topic')
|
||||
// ⌘-click, ctrl-click and "open in new tab" are the browser's to handle;
|
||||
// this component does not intercept them.
|
||||
await userEvent.keyboard('{Meta>}')
|
||||
await userEvent.click(linkNamed())
|
||||
await userEvent.keyboard('{/Meta}')
|
||||
//
|
||||
// One `userEvent` session, not three calls on the default one: modifier
|
||||
// state lives on the session, so `userEvent.keyboard('{Meta>}')` followed
|
||||
// by `userEvent.click(...)` is an unmodified click, and this test was
|
||||
// passing without ever holding the key.
|
||||
const session = userEvent.setup()
|
||||
await session.keyboard('{Meta>}')
|
||||
await session.click(linkNamed())
|
||||
await session.keyboard('{/Meta}')
|
||||
// Not intercepted: the split view is not opened and the page is not
|
||||
// changed, leaving the browser to do what it does with a modified click.
|
||||
expect(open).not.toHaveBeenCalled()
|
||||
expect(screen.queryByText('Whole article')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('goes to the pane from the card, even inside a pane', async () => {
|
||||
it('goes straight to the pane when the reader is already in one', async () => {
|
||||
// No card, no question. Somebody reading in the pane who follows a
|
||||
// reference means "in here" — there is no second pane to offer them, and
|
||||
// the card would only stand between them and the article.
|
||||
const open = vi.fn()
|
||||
mountBeside({ open, inPane: true }, 'deeper-topic')
|
||||
await userEvent.click(linkNamed())
|
||||
const card = await screen.findByRole('tooltip')
|
||||
await userEvent.click(within(card).getByRole('button', { name: /split view/i }))
|
||||
expect(open).toHaveBeenCalledWith('deeper-topic')
|
||||
expect(screen.queryByText('Whole article')).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -101,16 +101,30 @@ describe('reading a cross-reference beside the article', () => {
|
|||
expect(screen.getByText(/Fever alone rarely explains it/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('offers no split view to somebody already reading in one', async () => {
|
||||
mount()
|
||||
await screen.findByText(/Fever alone rarely explains it/)
|
||||
await openSplit('meningitis')
|
||||
const pane = await screen.findByRole('region', { name: 'Split view: Meningitis' })
|
||||
await userEvent.hover(within(pane).getByRole('link', { name: 'sepsis' }))
|
||||
const card = await screen.findByRole('tooltip')
|
||||
// A tab, and nothing else: "beside what you are reading" is a question with
|
||||
// one answer for somebody who is already beside what they were reading.
|
||||
expect(within(card).getByRole('link', { name: /new tab/i })).toBeInTheDocument()
|
||||
expect(within(card).queryByRole('button', { name: /split view/i })).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('follows a link inside the pane in the pane, not into a third column', async () => {
|
||||
mount()
|
||||
await screen.findByText(/Fever alone rarely explains it/)
|
||||
await openSplit('meningitis')
|
||||
const pane = await screen.findByRole('region', { name: 'Split view: Meningitis' })
|
||||
|
||||
// Clicking the words opens the card; the card's control is what goes.
|
||||
// Inside the pane the click simply goes. There is no second pane to offer
|
||||
// and no question worth asking: somebody reading in the pane who follows a
|
||||
// reference means "in here". Outside the pane the card still asks, which
|
||||
// the test above covers.
|
||||
await userEvent.click(within(pane).getByRole('link', { name: 'sepsis' }))
|
||||
const card = await screen.findByRole('tooltip')
|
||||
await userEvent.click(within(card).getByRole('button', { name: /split view/i }))
|
||||
await waitFor(() => expect(api.get).toHaveBeenCalledWith('/articles/9'))
|
||||
const deeper = await screen.findByRole('region', { name: 'Split view: Sepsis' })
|
||||
expect(document.querySelectorAll('.article-split-pane')).toHaveLength(1)
|
||||
|
|
|
|||
Loading…
Reference in a new issue