Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/app/_layout/_components/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,14 @@ const Navigation = ({ items, label, home, className }: NavigationProps) => {
const active = useActiveSection(items.map(({ id }) => id).join(','), home)

return (
<nav aria-label={label} className={className}>
<ul className="flex flex-wrap items-center gap-x-5 gap-y-2 font-mono text-sm sm:gap-x-8">
<nav
aria-label={label}
className={cn(
'overflow-x-auto [scrollbar-width:none] md:overflow-visible [&::-webkit-scrollbar]:hidden',
className
)}
>
<ul className="flex items-center gap-x-4 whitespace-nowrap font-mono text-xs min-[360px]:gap-x-5 min-[360px]:text-sm sm:gap-x-8 md:gap-x-5 lg:gap-x-8">
{items.map(({ id, label, href }) => {
const isActive = id === active

Expand All @@ -69,8 +75,8 @@ const Navigation = ({ items, label, home, className }: NavigationProps) => {
aria-current={isActive ? 'location' : undefined}
{...trackable('nav_click', { section: id })}
className={cn(
'relative block py-1 text-ink-soft transition-colors hover:text-ink',
'after:absolute after:-bottom-[1.1rem] after:left-0 after:h-0.5 after:w-full after:bg-pen after:opacity-0 after:transition-opacity',
'relative block rounded-sm pb-3 pt-1 text-ink-soft transition-colors hover:text-ink focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-pen md:py-1',
'after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-full after:bg-pen after:opacity-0 after:transition-opacity md:after:-bottom-[1.1rem]',
isActive && 'text-ink after:opacity-100'
)}
>
Expand Down
2 changes: 1 addition & 1 deletion src/app/_layout/_components/siteHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const SiteHeader = ({ locale }: { locale: Locale }) => {
>
{ui.skipToContent}
</a>
<Container className="flex flex-wrap items-center justify-between gap-x-6 gap-y-3 py-4 md:h-16 md:flex-nowrap md:py-0">
<Container className="flex flex-wrap items-center justify-between gap-x-6 gap-y-3 pt-4 md:h-16 md:flex-nowrap md:py-0">
<Brand href={homeAnchor(locale, 'top')} />
<div className="flex items-center gap-4 md:order-last">
<LanguageToggle locale={locale} label={ui.language} />
Expand Down
4 changes: 2 additions & 2 deletions src/app/_page/_components/engineeringSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const EngineeringSection = ({ locale }: { locale: Locale }) => {
<h3 className="font-mono text-sm font-medium text-pen">
{ui.toolbox}
</h3>
<ul className="mt-4 grid grid-cols-2 gap-x-6 sm:grid-cols-4">
<ul className="mt-4 grid grid-cols-1 gap-x-6 min-[320px]:grid-cols-2 sm:grid-cols-4">
{toolbox.map(({ id, label, items }) => {
const Icon = icons[id]

Expand All @@ -84,7 +84,7 @@ const EngineeringSection = ({ locale }: { locale: Locale }) => {
<Annotation
lines={engineering.principle}
underline
className="mt-8 -rotate-[4deg] text-[1.6rem]"
className="mt-8 -rotate-[4deg] text-[1.35rem] min-[320px]:text-[1.6rem]"
/>
</div>
</Container>
Expand Down
56 changes: 56 additions & 0 deletions tests/responsive.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { expect, test } from '@playwright/test'

const PAGES = ['/', '/privacy', '/pt', '/pt/privacidade']
const WIDTHS = [320, 360, 414, 768, 1024]

test.describe('Responsive layout', () => {
for (const width of WIDTHS) {
for (const path of PAGES) {
test(`Expected - ${path} to fit ${width}px with a single-row nav`, async ({
page,
}) => {
await page.setViewportSize({ width, height: 800 })
await page.goto(path)
await page.evaluate(() => document.fonts.ready)

const layout = await page.evaluate(() => {
const nav = document.querySelector<HTMLElement>(
'header nav:not(:has([hreflang]))'
)!
const rows = new Set(
Array.from(nav.querySelectorAll('li')).map((li) =>
Math.round(li.getBoundingClientRect().top)
)
)
const header = document.querySelector('header')!
const underline = Array.from(nav.querySelectorAll('a')).map(
(link) => {
const bottom = parseFloat(
getComputedStyle(link, '::after').bottom
)
return link.getBoundingClientRect().bottom - bottom
}
)

return {
pageOverflow:
document.documentElement.scrollWidth -
document.documentElement.clientWidth,
navOverflow: nav.scrollWidth - nav.clientWidth,
navRows: rows.size,
underlineOffsets: underline.map((y) =>
Math.abs(y - header.getBoundingClientRect().bottom)
),
}
})

expect(layout.pageOverflow).toBeLessThanOrEqual(0)
expect(layout.navOverflow).toBeLessThanOrEqual(1)
expect(layout.navRows).toBe(1)
for (const offset of layout.underlineOffsets) {
expect(offset).toBeLessThanOrEqual(3)
}
})
}
}
})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading