From b87a1be8fc5dea9c3ec7a131f0a16f640bcdd16b Mon Sep 17 00:00:00 2001 From: Amirhossein Khalili Date: Wed, 9 Sep 2026 23:17:39 +0330 Subject: [PATCH] fix: restore case study drawer interactions --- e2e/project-case-study.spec.ts | 9 ++++----- src/components/CaseStudyContent.tsx | 2 +- src/components/CaseStudyDrawer.module.css | 10 ---------- src/components/CaseStudyDrawer.tsx | 13 ++++++++++--- src/components/ProjectsSection.tsx | 4 ++++ tests/project-case-studies.test.mjs | 3 +++ 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/e2e/project-case-study.spec.ts b/e2e/project-case-study.spec.ts index 60e930e..49dd8a4 100644 --- a/e2e/project-case-study.spec.ts +++ b/e2e/project-case-study.spec.ts @@ -9,20 +9,19 @@ async function expectDrawerOpen(page: import('@playwright/test').Page) { return dialog; } -test('a card CTA opens a route-backed drawer and restores the portfolio', async ({ page }) => { +test('a pointer click on the card CTA opens a route-backed drawer and restores the portfolio', async ({ page }) => { await page.goto('/', { waitUntil: 'domcontentloaded' }); await page.evaluate(() => { window.scrollTo({ top: document.body.scrollHeight * 0.35, behavior: 'instant' }); }); const card = page.getByRole('article', { name: 'Qlockify' }); const cta = card.getByRole('link', { name: 'View case study' }); - await cta.focus(); const portfolioScroll = await page.evaluate(() => window.scrollY); - await cta.press('Enter'); + await cta.click(); await expect(page).toHaveURL(new RegExp(`${caseStudyPath}$`)); const dialog = await expectDrawerOpen(page); - await expect(dialog.getByRole('heading', { name: 'Qlockify', level: 1 })).toBeFocused(); + await expect(dialog.getByRole('button', { name: 'Close case study' })).toBeFocused(); await expect(card.getByRole('link', { name: /Open the live Qlockify/ })).toHaveAttribute('target', '_blank'); await expect(card.getByRole('link', { name: /Open the live Qlockify/ })).toHaveAttribute('rel', 'noopener noreferrer'); @@ -53,7 +52,7 @@ test('copy feedback, focus containment, and the localized RTL route work', async await page.goto('/fa/projects/qlockify', { waitUntil: 'domcontentloaded' }); const dialog = await expectDrawerOpen(page); await expect(page.locator('html')).toHaveAttribute('dir', 'rtl'); - await expect(dialog.getByRole('heading', { name: 'Qlockify', level: 1 })).toBeFocused(); + await expect(dialog.getByRole('button', { name: 'بستن مطالعه موردی' })).toBeFocused(); await dialog.getByRole('button', { name: 'کپی پیوند' }).click(); await expect(dialog.getByText('پیوند کپی شد', { exact: true }).first()).toBeVisible(); diff --git a/src/components/CaseStudyContent.tsx b/src/components/CaseStudyContent.tsx index f4aad6e..eb9f13a 100644 --- a/src/components/CaseStudyContent.tsx +++ b/src/components/CaseStudyContent.tsx @@ -24,7 +24,7 @@ export function CaseStudyContent({

{project.date}

-

+

{project.title}

{caseStudy.introduction}

diff --git a/src/components/CaseStudyDrawer.module.css b/src/components/CaseStudyDrawer.module.css index 4e5b373..6a96433 100644 --- a/src/components/CaseStudyDrawer.module.css +++ b/src/components/CaseStudyDrawer.module.css @@ -204,16 +204,6 @@ letter-spacing: 0; } -.title:focus { - outline: none; -} - -.title:focus-visible { - border-radius: var(--radius-sm); - outline: 3px solid var(--focus-ring); - outline-offset: var(--space-2); -} - .introduction { max-width: 46rem; color: var(--text-secondary); diff --git a/src/components/CaseStudyDrawer.tsx b/src/components/CaseStudyDrawer.tsx index 27cf6d8..9d6fb3c 100644 --- a/src/components/CaseStudyDrawer.tsx +++ b/src/components/CaseStudyDrawer.tsx @@ -74,7 +74,7 @@ export function CaseStudyDrawer({ children, locale }: { children: ReactNode; loc root.style.overflow = 'hidden'; requestAnimationFrame(() => { dialog.dataset.state = 'open'; - dialog.querySelector('[data-case-study-heading]')?.focus(); + dialog.querySelector('[data-case-study-initial-focus]')?.focus(); }); return () => { @@ -96,7 +96,7 @@ export function CaseStudyDrawer({ children, locale }: { children: ReactNode; loc scrollRef.current?.scrollTo({ top: 0, behavior: 'auto' }); requestAnimationFrame(() => { setCopyState('idle'); - dialogRef.current?.querySelector('[data-case-study-heading]')?.focus(); + dialogRef.current?.querySelector('[data-case-study-initial-focus]')?.focus(); }); }, [pathname]); @@ -145,7 +145,14 @@ export function CaseStudyDrawer({ children, locale }: { children: ReactNode; loc {copyState === 'copied' ?