From e80554d5277d7586e70144102ff3b9b14d9bfb5b Mon Sep 17 00:00:00 2001 From: Cam Quilici Date: Tue, 18 Aug 2026 15:09:57 -0500 Subject: [PATCH] feat(nav): surface datasets in primary navigation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the localized Datasets destination to the desktop and mobile header, preserve child-route active state, and cover responsive plus route-level navigation behavior. 中文:在桌面端和移动端顶层导航中加入本地化的“数据集”入口,保留子路由高亮状态,并补充响应式布局与实际路由跳转测试。 --- packages/app/cypress/component/header.cy.tsx | 40 +++++++++++++++++-- packages/app/cypress/e2e/navigation.cy.ts | 5 +++ packages/app/cypress/e2e/zh-pages.cy.ts | 6 +++ packages/app/src/components/header/header.tsx | 6 +++ packages/app/src/lib/tab-meta-zh.ts | 1 + 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/packages/app/cypress/component/header.cy.tsx b/packages/app/cypress/component/header.cy.tsx index 208abb9fd..4d0d560e4 100644 --- a/packages/app/cypress/component/header.cy.tsx +++ b/packages/app/cypress/component/header.cy.tsx @@ -105,9 +105,26 @@ describe('Header', () => { cy.get('[data-testid="nav-link-compare"]').should('have.attr', 'href', '/compare'); }); + it('shows Datasets as a top-level nav link and highlights dataset child pages', () => { + cy.get('[data-testid="nav-link-datasets"]') + .should('be.visible') + .and('have.attr', 'href', '/datasets'); + + mountHeader('/datasets/claude-code-traces'); + cy.get('[data-testid="nav-link-datasets"]').should('have.class', 'text-brand'); + }); + + it('keeps Datasets in the Chinese navigation tree', () => { + mountHeader('/zh/datasets'); + cy.get('[data-testid="nav-link-datasets"]') + .should('be.visible') + .and('contain.text', '数据集') + .and('have.attr', 'href', '/zh/datasets') + .and('have.class', 'text-brand'); + }); + it('keeps footer destinations out of the primary nav', () => { cy.get('[data-testid="nav-link-supporters"]').should('not.exist'); - cy.get('[data-testid="nav-link-datasets"]').should('not.exist'); cy.get('[data-testid="nav-link-blog"]').should('not.exist'); }); @@ -134,8 +151,8 @@ describe('Header', () => { cy.contains('a', 'Overview').should('be.visible').and('have.attr', 'href', '/overview'); cy.contains('a', 'Dashboard').should('be.visible').and('have.attr', 'href', '/inference'); cy.contains('a', 'Comparisons').should('be.visible').and('have.attr', 'href', '/compare'); + cy.contains('a', 'Datasets').should('be.visible').and('have.attr', 'href', '/datasets'); cy.contains('a', 'Supporters').should('not.exist'); - cy.contains('a', 'Datasets').should('not.exist'); cy.contains('a', 'Articles').should('not.exist'); }); }); @@ -150,6 +167,21 @@ describe('Header', () => { cy.wrap(mockRouter.push).should('have.been.calledTwice'); }); + it('keeps every primary link inside the header at the desktop breakpoint', () => { + cy.viewport(1024, 720); + cy.get('[data-testid="header"]').then(($header) => { + const header = $header[0]; + const bounds = header.getBoundingClientRect(); + expect(header.scrollWidth, 'header scrollWidth').to.be.at.most(header.clientWidth); + + cy.get('[data-testid^="nav-link-"]:visible').each(($link) => { + const rect = $link[0].getBoundingClientRect(); + expect(rect.left, `${$link.text()} left edge`).to.be.at.least(bounds.left - EPSILON); + expect(rect.right, `${$link.text()} right edge`).to.be.at.most(bounds.right + EPSILON); + }); + }); + }); + describe('at 320x700', () => { beforeEach(() => { cy.viewport(320, 700); @@ -205,10 +237,10 @@ describe('Header', () => { cy.get('[data-testid="mobile-menu-toggle"]').click(); cy.get('[data-testid="mobile-menu"]').should('be.visible'); cy.get('[data-testid="mobile-menu"]').within(() => { - ['Home', 'Overview', 'Dashboard', 'Comparisons', 'About'].forEach((label) => { + ['Home', 'Overview', 'Dashboard', 'Comparisons', 'Datasets', 'About'].forEach((label) => { cy.contains('a', label).should('be.visible'); }); - ['Supporters', 'Datasets', 'Articles'].forEach((label) => { + ['Supporters', 'Articles'].forEach((label) => { cy.contains('a', label).should('not.exist'); }); }); diff --git a/packages/app/cypress/e2e/navigation.cy.ts b/packages/app/cypress/e2e/navigation.cy.ts index 12fc661da..4f31b6e29 100644 --- a/packages/app/cypress/e2e/navigation.cy.ts +++ b/packages/app/cypress/e2e/navigation.cy.ts @@ -77,6 +77,11 @@ describe('First-load navigation', () => { cy.location('pathname').should('eq', '/compare'); }); + it('navigates to datasets from the header with one click', () => { + cy.get('[data-testid="nav-link-datasets"]').should('have.attr', 'href', '/datasets').click(); + cy.location('pathname').should('eq', '/datasets'); + }); + it('navigates to overview and the full dashboard from the landing CTAs', () => { cy.get('[data-testid="landing-overview-link"]') .should('have.attr', 'href', '/overview') diff --git a/packages/app/cypress/e2e/zh-pages.cy.ts b/packages/app/cypress/e2e/zh-pages.cy.ts index 2ae1441db..a189e82ae 100644 --- a/packages/app/cypress/e2e/zh-pages.cy.ts +++ b/packages/app/cypress/e2e/zh-pages.cy.ts @@ -27,6 +27,12 @@ describe('Chinese (/zh) pages', () => { cy.get('[data-testid="language-toggle"]').should('have.attr', 'href', '/'); }); + it('header links to the Chinese datasets page', () => { + cy.get('[data-testid="nav-link-datasets"]') + .should('contain.text', '数据集') + .and('have.attr', 'href', '/zh/datasets'); + }); + it('footer renders in Chinese with zh-internal links', () => { cy.get('[data-testid="footer-brand-description"]').should('contain.text', '开源推理基准测试'); cy.get('[data-testid="footer-link-supporters"]') diff --git a/packages/app/src/components/header/header.tsx b/packages/app/src/components/header/header.tsx index a8c58186e..d2d263868 100644 --- a/packages/app/src/components/header/header.tsx +++ b/packages/app/src/components/header/header.tsx @@ -49,6 +49,12 @@ const NAV_LINKS = [ testId: 'nav-link-compare', event: 'header_compare_clicked', }, + { + href: '/datasets', + label: 'Datasets', + testId: 'nav-link-datasets', + event: 'header_datasets_clicked', + }, { href: '/about', label: 'About', testId: 'nav-link-about', event: 'header_about_clicked' }, ] as const; diff --git a/packages/app/src/lib/tab-meta-zh.ts b/packages/app/src/lib/tab-meta-zh.ts index 55d57ab09..206d5400d 100644 --- a/packages/app/src/lib/tab-meta-zh.ts +++ b/packages/app/src/lib/tab-meta-zh.ts @@ -143,6 +143,7 @@ export const NAV_LABELS_ZH: Record = { '/overview': '总览', '/inference': '仪表板', '/compare': 'Chip 对比', + '/datasets': '数据集', '/about': '关于', };