From 04ec81c7a271e086b9aaab1abba08f113d68d210 Mon Sep 17 00:00:00 2001
From: Daniel Castro <2968031+odanieldcs@users.noreply.github.com>
Date: Sun, 11 Oct 2026 21:51:56 -0300
Subject: [PATCH 1/2] fix(a11y): landmark posts, skip to content, and mark the
view switch (ENG-155)
Posts sat outside a main landmark, the header took several tabs before the content, and the list/grid links used aria-pressed.
---
app/globals.css | 6 ++
components/layout/site-shell.tsx | 2 +
components/layout/skip-link.test.tsx | 49 ++++++++++++++++
components/layout/skip-link.tsx | 41 +++++++++++++
components/views/blog-view.test.tsx | 17 ++++--
components/views/blog-view.tsx | 2 +-
components/views/post-article.test.tsx | 67 ++++++++++++++++++++++
components/views/post-article.tsx | 6 +-
components/views/view-mode-switch.test.tsx | 52 +++++++++++++++++
components/views/view-mode-switch.tsx | 2 +-
e2e/skip-link.spec.ts | 43 ++++++++++++++
lib/i18n/dictionary.test.ts | 6 ++
lib/i18n/dictionary.ts | 12 ++++
13 files changed, 296 insertions(+), 9 deletions(-)
create mode 100644 components/layout/skip-link.test.tsx
create mode 100644 components/layout/skip-link.tsx
create mode 100644 components/views/post-article.test.tsx
create mode 100644 components/views/view-mode-switch.test.tsx
create mode 100644 e2e/skip-link.spec.ts
diff --git a/app/globals.css b/app/globals.css
index d1f74a0..a1543b6 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -4,6 +4,12 @@
@import "./theme/spacing.css";
@import "./theme/containers.css";
+/* Skip-link focus is programmatic. Beats the preflight :focus-visible outline. */
+main:focus,
+main:focus-visible {
+ outline: none;
+}
+
@custom-variant dark (&:where(.dark, .dark *));
@theme {
diff --git a/components/layout/site-shell.tsx b/components/layout/site-shell.tsx
index 3d99d47..a372bac 100644
--- a/components/layout/site-shell.tsx
+++ b/components/layout/site-shell.tsx
@@ -7,6 +7,7 @@ import { Footer } from '@/components/layout/footer'
import { Header } from '@/components/layout/header'
import { LoadingBar } from '@/components/layout/loading-indicator'
import { NavigationProgress } from '@/components/layout/navigation-progress'
+import { SkipLink } from '@/components/layout/skip-link'
import { ThemeProvider } from '@/components/theme-provider'
import { htmlLang, type InterfaceLanguage } from '@/lib/i18n/types'
import '@/app/globals.css'
@@ -46,6 +47,7 @@ export function SiteShell({
/>
+
{children}
diff --git a/components/layout/skip-link.test.tsx b/components/layout/skip-link.test.tsx
new file mode 100644
index 0000000..195dbb0
--- /dev/null
+++ b/components/layout/skip-link.test.tsx
@@ -0,0 +1,49 @@
+import { cleanup, fireEvent, render, screen } from '@testing-library/react'
+import type { ReactNode } from 'react'
+import { afterEach, expect, test } from 'vitest'
+import { InterfaceLanguageProvider } from '@/components/interface-language-provider'
+import { SkipLink } from './skip-link'
+
+afterEach(() => {
+ cleanup()
+})
+
+function renderSkipLink(language: 'pt' | 'en', children?: ReactNode) {
+ return render(
+
+
+ {children}
+ ,
+ )
+}
+
+test('renders Portuguese and English skip copy', () => {
+ const { unmount } = renderSkipLink('pt')
+
+ const link = screen.getByRole('link', { name: 'Pular para o conteúdo' })
+ expect(link.getAttribute('href')).toBe('#conteudo')
+ expect(
+ screen.getByRole('navigation', { name: 'Atalho' }).contains(link),
+ ).toBe(true)
+
+ unmount()
+ renderSkipLink('en')
+
+ expect(screen.getByRole('link', { name: 'Skip to content' })).toBeTruthy()
+ expect(screen.getByRole('navigation', { name: 'Skip' })).toBeTruthy()
+})
+
+test('click focuses the only main and sets tabIndex to -1', () => {
+ renderSkipLink(
+ 'pt',
+
+ Conteúdo
+ ,
+ )
+
+ fireEvent.click(screen.getByRole('link', { name: 'Pular para o conteúdo' }))
+
+ const main = screen.getByRole('main')
+ expect(document.activeElement).toBe(main)
+ expect(main.tabIndex).toBe(-1)
+})
diff --git a/components/layout/skip-link.tsx b/components/layout/skip-link.tsx
new file mode 100644
index 0000000..f543969
--- /dev/null
+++ b/components/layout/skip-link.tsx
@@ -0,0 +1,41 @@
+'use client'
+
+import type { MouseEvent } from 'react'
+import { useUiDictionary } from '@/components/interface-language-provider'
+
+// not-sr-only sets position: static and fights with fixed. Reset the clip on focus.
+const skipLinkClassName = [
+ 'sr-only fixed z-50 bg-background text-sm font-medium text-foreground',
+ 'outline-hidden focus-visible:ring-2 focus-visible:ring-foreground/35',
+ 'focus-visible:ring-offset-2 focus-visible:ring-offset-background',
+ 'focus-visible:fixed focus-visible:top-4 focus-visible:left-4',
+ 'focus-visible:m-0 focus-visible:h-auto focus-visible:w-auto',
+ 'focus-visible:overflow-visible focus-visible:px-4 focus-visible:py-2',
+ 'focus-visible:whitespace-normal focus-visible:rounded-md',
+ 'focus-visible:[clip-path:none]',
+].join(' ')
+
+export function SkipLink() {
+ const { skipLink } = useUiDictionary()
+
+ function onClick(event: MouseEvent) {
+ const mains = document.querySelectorAll('main')
+ const main = mains.length === 1 ? mains[0] : undefined
+ if (!main) {
+ return
+ }
+
+ event.preventDefault()
+ main.tabIndex = -1
+ main.focus()
+ }
+
+ return (
+
+ )
+}
diff --git a/components/views/blog-view.test.tsx b/components/views/blog-view.test.tsx
index 4e7a1b3..6bbe1c9 100644
--- a/components/views/blog-view.test.tsx
+++ b/components/views/blog-view.test.tsx
@@ -89,14 +89,23 @@ test('list view formats month and year in English', () => {
expect(within(articleLink).getByRole('time').textContent).toBe('Sep 2026')
})
-test('grid view hides descriptions and shows cover images', () => {
- renderBlog('pt', { view: 'grid' })
+test('grid view hides descriptions and treats covers as decorative', () => {
+ const { container } = renderBlog('pt', { view: 'grid' })
expect(
screen.queryByText('Um passeio pelo pipeline de ponta a ponta.'),
).toBeNull()
- expect(screen.getAllByRole('img')).toHaveLength(3)
- expect(screen.getByRole('img', { name: 'Hello World' })).toBeTruthy()
+ const covers = container.querySelectorAll('img')
+ expect(covers).toHaveLength(3)
+ for (const cover of covers) {
+ expect(cover.getAttribute('alt')).toBe('')
+ }
+ expect(
+ screen.getByRole('link', {
+ name: (accessibleName) =>
+ accessibleName.split('Hello World').length - 1 === 1,
+ }),
+ ).toBeTruthy()
})
test('view switch links preserve the current page', () => {
diff --git a/components/views/blog-view.tsx b/components/views/blog-view.tsx
index b250876..7993e31 100644
--- a/components/views/blog-view.tsx
+++ b/components/views/blog-view.tsx
@@ -116,7 +116,7 @@ function GridCard({
{coverSrc ? (
({
+ default: function MockImage({ alt, src }: { alt: string; src: string }) {
+ return
+ },
+}))
+
+vi.mock('@/lib/content/mdx', () => ({
+ MdxContent: ({ source }: { source: string }) => {source}
,
+}))
+
+vi.mock('next/link', () => ({
+ default: function MockLink({
+ children,
+ href,
+ className,
+ }: {
+ children: ReactNode
+ href: string
+ className?: string
+ }) {
+ return (
+
+ {children}
+
+ )
+ },
+}))
+
+const post: Post = {
+ slug: 'hello-world',
+ content: 'Body',
+ frontmatter: {
+ title: 'Hello World',
+ description: 'A post',
+ date: new Date('2026-09-21T00:00:00.000Z'),
+ tags: [],
+ cover: 'hello-world.png',
+ language: 'pt',
+ },
+}
+
+afterEach(() => {
+ cleanup()
+})
+
+test('wraps the article frame in main and keeps the top button outside the frame', () => {
+ const { container } = render()
+
+ const main = screen.getByRole('main')
+ const frame = container.querySelector('.article-frame')
+ const article = container.querySelector('article')
+ expect(frame).toBeTruthy()
+ expect(main.contains(frame)).toBe(true)
+ expect(frame?.contains(article)).toBe(true)
+ expect(article?.getAttribute('data-analytics-source')).toBe('post')
+
+ const backToTop = screen.getByRole('button', { name: 'Voltar ao topo' })
+ expect(main.contains(backToTop)).toBe(true)
+ expect(frame?.contains(backToTop)).toBe(false)
+ expect(container.querySelector('img')?.getAttribute('alt')).toBe('')
+})
diff --git a/components/views/post-article.tsx b/components/views/post-article.tsx
index 96c4f35..fa454d2 100644
--- a/components/views/post-article.tsx
+++ b/components/views/post-article.tsx
@@ -69,7 +69,7 @@ export function PostArticle({
: undefined
return (
- <>
+
- >
+
)
}
diff --git a/components/views/view-mode-switch.test.tsx b/components/views/view-mode-switch.test.tsx
new file mode 100644
index 0000000..48502e8
--- /dev/null
+++ b/components/views/view-mode-switch.test.tsx
@@ -0,0 +1,52 @@
+import { cleanup, render, screen } from '@testing-library/react'
+import { afterEach, expect, test } from 'vitest'
+import { ViewModeSwitch } from './view-mode-switch'
+
+const options = [
+ { id: 'list' as const, label: 'Lista', icon: list },
+ { id: 'grid' as const, label: 'Grade', icon: grid },
+]
+
+afterEach(() => {
+ cleanup()
+})
+
+test('link mode marks the committed view with aria-current', () => {
+ render(
+ (id === 'list' ? '/blog' : '/blog?view=grid')}
+ options={options}
+ />,
+ )
+
+ const list = screen.getByRole('link', { name: 'Lista' })
+ const grid = screen.getByRole('link', { name: 'Grade' })
+
+ expect(list.getAttribute('aria-current')).toBe('page')
+ expect(grid.hasAttribute('aria-current')).toBe(false)
+ expect(list.hasAttribute('aria-pressed')).toBe(false)
+ expect(grid.hasAttribute('aria-pressed')).toBe(false)
+ expect(list.className.split(/\s+/)).toContain('text-foreground')
+})
+
+test('button mode keeps aria-pressed and omits aria-current', () => {
+ render(
+ ,
+ )
+
+ const list = screen.getByRole('button', { name: 'Lista' })
+ const grid = screen.getByRole('button', { name: 'Grade' })
+
+ expect(grid.getAttribute('aria-pressed')).toBe('true')
+ expect(list.getAttribute('aria-pressed')).toBe('false')
+ expect(list.hasAttribute('aria-current')).toBe(false)
+ expect(grid.hasAttribute('aria-current')).toBe(false)
+})
diff --git a/components/views/view-mode-switch.tsx b/components/views/view-mode-switch.tsx
index 3ee1df1..6cf5d32 100644
--- a/components/views/view-mode-switch.tsx
+++ b/components/views/view-mode-switch.tsx
@@ -90,7 +90,7 @@ export function ViewModeSwitch({
{
+ await skipToMain(page, '/')
+})
+
+test('first Tab skips to main on a post', async ({ page }) => {
+ await skipToMain(page, '/blog/meu-blog-profissional')
+})
+
+test('open mobile menu makes the skip link inert', async ({ page }) => {
+ await page.setViewportSize({ width: 390, height: 844 })
+ await page.goto('/')
+ await page.getByRole('button', { name: 'Menu' }).click()
+
+ const skipNav = page.locator('nav[aria-label="Atalho"]')
+ const skip = skipNav.locator('a')
+ await expect(skipNav).toHaveAttribute('inert')
+
+ for (let step = 0; step < 8; step += 1) {
+ await page.keyboard.press('Tab')
+ await expect(skip).not.toBeFocused()
+ }
+})
diff --git a/lib/i18n/dictionary.test.ts b/lib/i18n/dictionary.test.ts
index 8648a9b..8b52ac6 100644
--- a/lib/i18n/dictionary.test.ts
+++ b/lib/i18n/dictionary.test.ts
@@ -23,6 +23,8 @@ test('pt and en dictionaries share the same key shape', () => {
expect(Object.keys(en.language)).toEqual(Object.keys(pt.language))
expect(Object.keys(pt.mobileMenu)).toEqual(['trigger', 'navAriaLabel'])
expect(Object.keys(en.mobileMenu)).toEqual(Object.keys(pt.mobileMenu))
+ expect(Object.keys(pt.skipLink)).toEqual(['label', 'navAriaLabel'])
+ expect(Object.keys(en.skipLink)).toEqual(Object.keys(pt.skipLink))
expect(Object.keys(pt.navigation)).toEqual(['loading'])
expect(Object.keys(en.navigation)).toEqual(Object.keys(pt.navigation))
})
@@ -71,6 +73,10 @@ test('includes theme, language switch, and mobile menu copy in both languages',
expect(en.language.switchToPt).toBe('Switch to Portuguese')
expect(pt.mobileMenu.trigger).toBe('Menu')
expect(en.mobileMenu.navAriaLabel).toBe('Main navigation')
+ expect(pt.skipLink.label).toBe('Pular para o conteúdo')
+ expect(en.skipLink.label).toBe('Skip to content')
+ expect(pt.skipLink.navAriaLabel).toBe('Atalho')
+ expect(en.skipLink.navAriaLabel).toBe('Skip')
expect(pt.navigation.loading).toBe('O conteúdo está sendo carregado')
expect(en.navigation.loading).toBe('The content is loading')
})
diff --git a/lib/i18n/dictionary.ts b/lib/i18n/dictionary.ts
index d7d4069..0b2dee8 100644
--- a/lib/i18n/dictionary.ts
+++ b/lib/i18n/dictionary.ts
@@ -21,6 +21,10 @@ export type UiDictionary = {
trigger: string
navAriaLabel: string
}
+ skipLink: {
+ label: string
+ navAriaLabel: string
+ }
navigation: {
loading: string
}
@@ -42,6 +46,10 @@ const uiCopy: Record> = {
trigger: 'Menu',
navAriaLabel: 'Navegação principal',
},
+ skipLink: {
+ label: 'Pular para o conteúdo',
+ navAriaLabel: 'Atalho',
+ },
navigation: {
loading: 'O conteúdo está sendo carregado',
},
@@ -61,6 +69,10 @@ const uiCopy: Record> = {
trigger: 'Menu',
navAriaLabel: 'Main navigation',
},
+ skipLink: {
+ label: 'Skip to content',
+ navAriaLabel: 'Skip',
+ },
navigation: {
loading: 'The content is loading',
},
From eb35e165e6d37f67c3b70b11a9212fe403d28555 Mon Sep 17 00:00:00 2001
From: Daniel Castro <2968031+odanieldcs@users.noreply.github.com>
Date: Sun, 11 Oct 2026 22:38:11 -0300
Subject: [PATCH 2/2] fix(a11y): point the skip link at a real target (ENG-155)
The hash had no element, so Enter did nothing before hydration and axe flagged skip-link on every page.
---
app/globals.css | 6 ++--
components/layout/site-shell.tsx | 9 +++--
components/layout/skip-link.test.tsx | 43 +++++------------------
components/layout/skip-link.tsx | 30 +++-------------
e2e/skip-link.spec.ts | 51 ++++++++++++++++++++++------
lib/i18n/dictionary.test.ts | 4 +--
lib/i18n/dictionary.ts | 3 --
7 files changed, 63 insertions(+), 83 deletions(-)
diff --git a/app/globals.css b/app/globals.css
index a1543b6..c49a048 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -4,9 +4,9 @@
@import "./theme/spacing.css";
@import "./theme/containers.css";
-/* Skip-link focus is programmatic. Beats the preflight :focus-visible outline. */
-main:focus,
-main:focus-visible {
+/* Hash focus from the skip link. Beats the preflight :focus-visible outline. */
+#conteudo:focus,
+#conteudo:focus-visible {
outline: none;
}
diff --git a/components/layout/site-shell.tsx b/components/layout/site-shell.tsx
index a372bac..14a2bab 100644
--- a/components/layout/site-shell.tsx
+++ b/components/layout/site-shell.tsx
@@ -9,6 +9,7 @@ import { LoadingBar } from '@/components/layout/loading-indicator'
import { NavigationProgress } from '@/components/layout/navigation-progress'
import { SkipLink } from '@/components/layout/skip-link'
import { ThemeProvider } from '@/components/theme-provider'
+import { getDictionary } from '@/lib/i18n/dictionary'
import { htmlLang, type InterfaceLanguage } from '@/lib/i18n/types'
import '@/app/globals.css'
@@ -32,6 +33,8 @@ export function SiteShell({
language: InterfaceLanguage
children: ReactNode
}) {
+ const skipLabel = getDictionary(language).skipLink.label
+
return (
-
+
- {children}
+
+ {children}
+
diff --git a/components/layout/skip-link.test.tsx b/components/layout/skip-link.test.tsx
index 195dbb0..71f6bdb 100644
--- a/components/layout/skip-link.test.tsx
+++ b/components/layout/skip-link.test.tsx
@@ -1,49 +1,22 @@
-import { cleanup, fireEvent, render, screen } from '@testing-library/react'
-import type { ReactNode } from 'react'
+import { cleanup, render, screen } from '@testing-library/react'
import { afterEach, expect, test } from 'vitest'
-import { InterfaceLanguageProvider } from '@/components/interface-language-provider'
import { SkipLink } from './skip-link'
afterEach(() => {
cleanup()
})
-function renderSkipLink(language: 'pt' | 'en', children?: ReactNode) {
- return render(
-
-
- {children}
- ,
- )
-}
-
-test('renders Portuguese and English skip copy', () => {
- const { unmount } = renderSkipLink('pt')
+test('points at #conteudo in Portuguese and English', () => {
+ const { unmount } = render()
const link = screen.getByRole('link', { name: 'Pular para o conteúdo' })
expect(link.getAttribute('href')).toBe('#conteudo')
- expect(
- screen.getByRole('navigation', { name: 'Atalho' }).contains(link),
- ).toBe(true)
+ expect(link.closest('nav')).toBeNull()
unmount()
- renderSkipLink('en')
-
- expect(screen.getByRole('link', { name: 'Skip to content' })).toBeTruthy()
- expect(screen.getByRole('navigation', { name: 'Skip' })).toBeTruthy()
-})
+ render()
-test('click focuses the only main and sets tabIndex to -1', () => {
- renderSkipLink(
- 'pt',
-
- Conteúdo
- ,
- )
-
- fireEvent.click(screen.getByRole('link', { name: 'Pular para o conteúdo' }))
-
- const main = screen.getByRole('main')
- expect(document.activeElement).toBe(main)
- expect(main.tabIndex).toBe(-1)
+ expect(
+ screen.getByRole('link', { name: 'Skip to content' }).getAttribute('href'),
+ ).toBe('#conteudo')
})
diff --git a/components/layout/skip-link.tsx b/components/layout/skip-link.tsx
index f543969..5e563ae 100644
--- a/components/layout/skip-link.tsx
+++ b/components/layout/skip-link.tsx
@@ -1,8 +1,3 @@
-'use client'
-
-import type { MouseEvent } from 'react'
-import { useUiDictionary } from '@/components/interface-language-provider'
-
// not-sr-only sets position: static and fights with fixed. Reset the clip on focus.
const skipLinkClassName = [
'sr-only fixed z-50 bg-background text-sm font-medium text-foreground',
@@ -15,27 +10,10 @@ const skipLinkClassName = [
'focus-visible:[clip-path:none]',
].join(' ')
-export function SkipLink() {
- const { skipLink } = useUiDictionary()
-
- function onClick(event: MouseEvent) {
- const mains = document.querySelectorAll('main')
- const main = mains.length === 1 ? mains[0] : undefined
- if (!main) {
- return
- }
-
- event.preventDefault()
- main.tabIndex = -1
- main.focus()
- }
-
+export function SkipLink({ label }: { label: string }) {
return (
-
+
+ {label}
+
)
}
diff --git a/e2e/skip-link.spec.ts b/e2e/skip-link.spec.ts
index 5b30864..7924bff 100644
--- a/e2e/skip-link.spec.ts
+++ b/e2e/skip-link.spec.ts
@@ -1,6 +1,6 @@
import { expect, type Page, test } from '@playwright/test'
-async function skipToMain(page: Page, path: string) {
+async function skipToContent(page: Page, path: string) {
await page.goto(path)
await page.keyboard.press('Tab')
@@ -14,17 +14,17 @@ async function skipToMain(page: Page, path: string) {
await page.keyboard.press('Enter')
- const main = page.locator('main')
- await expect(main).toBeFocused()
- await expect(main).toHaveCSS('outline-style', 'none')
+ const target = page.locator('#conteudo')
+ await expect(target).toBeFocused()
+ await expect(target).toHaveCSS('outline-style', 'none')
}
-test('first Tab skips to main on the home page', async ({ page }) => {
- await skipToMain(page, '/')
+test('first Tab skips to content on the home page', async ({ page }) => {
+ await skipToContent(page, '/')
})
-test('first Tab skips to main on a post', async ({ page }) => {
- await skipToMain(page, '/blog/meu-blog-profissional')
+test('first Tab skips to content on a post', async ({ page }) => {
+ await skipToContent(page, '/blog/meu-blog-profissional')
})
test('open mobile menu makes the skip link inert', async ({ page }) => {
@@ -32,12 +32,41 @@ test('open mobile menu makes the skip link inert', async ({ page }) => {
await page.goto('/')
await page.getByRole('button', { name: 'Menu' }).click()
- const skipNav = page.locator('nav[aria-label="Atalho"]')
- const skip = skipNav.locator('a')
- await expect(skipNav).toHaveAttribute('inert')
+ const skip = page.locator('a[href="#conteudo"]')
+ await expect(skip).toHaveAttribute('inert')
for (let step = 0; step < 8; step += 1) {
await page.keyboard.press('Tab')
await expect(skip).not.toBeFocused()
}
})
+
+test.describe('without JavaScript', () => {
+ test.use({ javaScriptEnabled: false })
+
+ test('Enter then Tab reaches the first content link on the home page', async ({
+ page,
+ }) => {
+ await skipWithoutJavaScript(page, '/')
+ })
+
+ test('Enter then Tab reaches the first content link on a post', async ({
+ page,
+ }) => {
+ await skipWithoutJavaScript(page, '/blog/meu-blog-profissional')
+ })
+})
+
+async function skipWithoutJavaScript(page: Page, path: string) {
+ await page.goto(path)
+ await page.keyboard.press('Tab')
+ await expect(
+ page.getByRole('link', { name: 'Pular para o conteúdo' }),
+ ).toBeFocused()
+
+ await page.keyboard.press('Enter')
+ await expect(page.locator('#conteudo')).toBeFocused()
+
+ await page.keyboard.press('Tab')
+ await expect(page.locator('#conteudo a').first()).toBeFocused()
+}
diff --git a/lib/i18n/dictionary.test.ts b/lib/i18n/dictionary.test.ts
index 8b52ac6..42fe83d 100644
--- a/lib/i18n/dictionary.test.ts
+++ b/lib/i18n/dictionary.test.ts
@@ -23,7 +23,7 @@ test('pt and en dictionaries share the same key shape', () => {
expect(Object.keys(en.language)).toEqual(Object.keys(pt.language))
expect(Object.keys(pt.mobileMenu)).toEqual(['trigger', 'navAriaLabel'])
expect(Object.keys(en.mobileMenu)).toEqual(Object.keys(pt.mobileMenu))
- expect(Object.keys(pt.skipLink)).toEqual(['label', 'navAriaLabel'])
+ expect(Object.keys(pt.skipLink)).toEqual(['label'])
expect(Object.keys(en.skipLink)).toEqual(Object.keys(pt.skipLink))
expect(Object.keys(pt.navigation)).toEqual(['loading'])
expect(Object.keys(en.navigation)).toEqual(Object.keys(pt.navigation))
@@ -75,8 +75,6 @@ test('includes theme, language switch, and mobile menu copy in both languages',
expect(en.mobileMenu.navAriaLabel).toBe('Main navigation')
expect(pt.skipLink.label).toBe('Pular para o conteúdo')
expect(en.skipLink.label).toBe('Skip to content')
- expect(pt.skipLink.navAriaLabel).toBe('Atalho')
- expect(en.skipLink.navAriaLabel).toBe('Skip')
expect(pt.navigation.loading).toBe('O conteúdo está sendo carregado')
expect(en.navigation.loading).toBe('The content is loading')
})
diff --git a/lib/i18n/dictionary.ts b/lib/i18n/dictionary.ts
index 0b2dee8..0742c90 100644
--- a/lib/i18n/dictionary.ts
+++ b/lib/i18n/dictionary.ts
@@ -23,7 +23,6 @@ export type UiDictionary = {
}
skipLink: {
label: string
- navAriaLabel: string
}
navigation: {
loading: string
@@ -48,7 +47,6 @@ const uiCopy: Record> = {
},
skipLink: {
label: 'Pular para o conteúdo',
- navAriaLabel: 'Atalho',
},
navigation: {
loading: 'O conteúdo está sendo carregado',
@@ -71,7 +69,6 @@ const uiCopy: Record> = {
},
skipLink: {
label: 'Skip to content',
- navAriaLabel: 'Skip',
},
navigation: {
loading: 'The content is loading',