fix(responsive): make every section usable on phones, tablets and 1024-1279 laptops - #7
Merged
Conversation
The responsive fixes that follow need a few things in place first so each area can be worked on independently: the i18n keys for the new navigation, carousel, timeline and language-switcher labels (previously hard-coded in English), pause/play icons for the featured card, the sidebar offset as a single set of constants, two small hooks (media query, element width), an `xs` breakpoint at 420px, `scroll-padding-top` so hash links clear the fixed header, a `viewport` export with `viewport-fit=cover` so safe-area insets work on notched phones, and a `className` prop on the footer so the home page can offset it next to the sidebar. - en.json/es.json: nav.*, hero.featuredProject.goTo/pauseRotation/resumeRotation, language.selection/switchTo/current, journey.back/start/yearDetails/ closeDetails/legend*, new top-level `carousel`; shorter OBT subtitle so it fits the featured card without truncation - icons: PauseIcon, PlayIcon - morphNav/layout.ts: SIDEBAR_* constants - lib/hooks: useMediaQuery, useElementWidth - globals.css: @theme --breakpoint-xs, scroll-padding-top - app/layout.tsx: viewport export (replaces the manual theme-color meta) - Footer: optional className Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`DevelopmentModal`, `useScrollGuard` and the generic `Modal` were only referenced by each other and by nothing in the app. The modal also carried a latent mobile bug (no max-height or inner scroll while it locked body scroll with `overflow: unset`), so removing it is safer than fixing code nobody renders. The `development` i18n block that only it consumed goes with it, in both locales, so the translation check stays balanced. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Between 768px and 1279px the header showed only the brand: the desktop nav was gated at xl while the mobile language switcher disappeared at md, and the floating menu button only mounted after 450px of scroll. At 1024px the fixed 17rem sidebar also squeezed every section into 664px. The drawer clipped its own content (no scroll, language switcher cut off on every phone) and the desktop sidebar overflowed 720px-tall viewports. - Sidebar and content offset move from lg to xl; the offset lives in one set of constants shared by the home content, the footer and the scroll cue - Header below xl: language switcher + 44px hamburger that opens the drawer from any scroll position (drawer state lives in MorphNavProvider) - SidebarPanel is a real module-level component (was recreated every render) and is the scroll region for both the aside and the drawer, with safe-area padding; drawer items no longer depend on isMorphed to become visible - MorphDrawer: body scroll lock that restores the previous value, focus to the close button and back to the opener, Tab trap, Escape, auto-close when the xl sidebar takes over - FAB and browser-translate hint respect the safe area and no longer share a corner; language switcher buttons are 44px; labels localized - Footer receives the sidebar offset on the home pages so it no longer sits under the aside Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The hero used a 12-column grid with 48px gaps, so 11 gutters ate 528px and the card column measured 192px at 1024px. The featured card had a hard 252px height with fixed slots; the Code-XR link row overflowed by 77px at 320px (a shrink-0 group that could not wrap) and the OBT subtitle was always truncated by line-clamp-2. - Two-track grid (5fr/7fr) with a single gap; 100svh instead of 100vh - Featured card: both projects render stacked in one grid cell so the card takes the taller one's height and never jumps; links wrap; subtitle gets 3-4 lines; 44px dot buttons and a pause/resume toggle (touch and keyboard users could not pause before); labels localized - ProfileBio aside floor lowered so the main column stays wider - Badge used colour names that do not exist in the Tailwind v4 build (the legacy config is not loaded), so it rendered without background; now uses the CSS variables like the rest of the site Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Arrows were revealed on hover only, which Tailwind v4 wraps in @media (hover: hover), so phones and tablets never saw them; the dots were 8px targets; there was no swipe; and the lightbox kept auto-rotating and overflowed landscape phones. - Arrows visible on coarse pointers and on keyboard focus, larger on touch - Dots have 24px hit areas and a 7-dot sliding window (Code-XR has 14 images) - Pointer swipe with axis lock; a swipe never opens the lightbox or bubbles a click to the parent card; manual interaction holds autoplay - Lightbox: 44px controls, safe-area padding, height that fits landscape phones, swipe-down to close on touch, Tab trap - All labels through the new `carousel` i18n namespace Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ablets - Sticky project nav: 44px back button, previous/next always available (they were hidden below md), safe-area top padding - Detail hero: monotonic heading sizes, 4:3 preview on phones, DOI chip that can break, 44px links on touch (compact only for fine pointers at lg+) - Detail layout: no nested <main>; on phones the release notes follow the narrative instead of trailing the sidebar column - Release cards and footer: 40-44px controls - Landing cards: secondary grid goes 1 -> 2 -> 3 columns (was 1 -> 3 at 768px with 203-222px cards), equal card heights, clamped summaries on phones, 40px link buttons - /uses: dvh height, 44px back link with a language switcher, block anchors so cards align, 3 columns from lg Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… at small widths - Skills modal: header and 44px close button stay fixed while the body scrolls (the close button used to scroll away); distribution tiles no longer overflow at 320-419px; category card header wraps - References: two columns from md instead of lg (tablet portrait was one 720px-wide column) - Certifications: the inner card grid follows the panel width with a container query instead of the viewport (124px cards at 1024px before); min-heights only from md so phones lose the empty bands; tags can break - Contact: the availability pill wraps instead of overflowing its card in Spanish at 320-360px - Footer: one column of links below 420px, 36px link rows, 44px social icons Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The vertical layout forced an 800px map, hid its detail card in a 156-240px column with truncated titles, used 8-14px touch targets, showed the "today" label on hover only and had year buttons that did nothing on mobile. The horizontal layout centred markers 2-4px off, let achievement dots overlap, and drew the "Start" label over January entries. - VerticalTimeline extracted; map height follows the number of years (512-848px), lanes keep a right gutter, lane dots label each stream - Detail card becomes an in-flow sheet that sticks to the bottom while an entry is selected, full width, with a close button; the section uses overflow-clip so sticky works - 44px hit areas via pseudo-elements while dots and bars stay thin; hover handlers ignore touch pointers - Horizontal: markers centred with translate, achievements staggered into two rows when they would overlap, drill-down padding fixed, coarse-pointer hit areas - Glow animation only runs while the horizontal layout is on screen (it was re-rendering the section at 60fps on phones that never show it) - Legend and drill-down labels localized Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The header row used the 1200px `.container` while the eight nav labels, the brand and the language switcher need about 1240px, so on every desktop width (1280 through 1920, live site included) five nav labels and the brand wrapped onto two lines inside the 64px bar. The row now uses the same max-w-7xl container as the sections, so it lines up with the content and gains 16px; nav labels no longer wrap and use slightly tighter padding; the brand keeps the short "Adrián Montes" form (the full name is the hero h1). Measured slack at 1280-1920: 48px in Spanish, 97px in English. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
At 320px the featured card has ~30 characters per line, so the OBT subtitle still hit the four-line clamp. Five lines below the xs breakpoint (420px), four up to sm, three from sm as before. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
After #6 the site looked wrong on phones, tablets and 1024–1279px laptops. This PR is the result of a full responsive audit (measured on the live site with emulated viewports) plus the fixes, area by area. Desktop at 1280px and wider keeps its look; everything below changes on purpose.
Measured before → after
Navigation shell — sidebar and content offset move from
lgtoxl(one set of constants shared by home, footer and scroll cue); header belowxlgets the language switcher and a 44px hamburger that opens the drawer from any scroll position (drawer state inMorphNavProvider);SidebarPanelis a real component and the scroll region for aside and drawer; drawer has body-scroll lock, focus management, Tab trap and Escape; FAB and browser-translate hint respect the safe area and no longer collide. The desktop header now uses the samemax-w-7xlcontainer as the sections and keeps its eight nav labels on one line (on the live site five of them and the brand wrapped onto two lines at every width from 1280 to 1920).Hero — two-track grid instead of a 12-column grid with 11 gaps; featured card renders both projects stacked in one grid cell so it takes the taller height and never jumps; links wrap; 44px dots and a pause/resume toggle;
Badgeused colour names that do not exist in the Tailwind v4 build.Carousel — arrows visible on coarse pointers and keyboard focus; 7-dot window with 24px hit areas; pointer swipe with axis lock that never opens the lightbox or bubbles to the card; lightbox with 44px controls, safe-area padding and a height that fits landscape phones; all labels in a new
carouseli18n namespace.Projects and /uses — sticky project nav with 44px back and always-available previous/next; detail hero with monotonic heading sizes and a DOI chip that can break; release notes follow the narrative on phones; no nested
<main>; secondary grid 1 → 2 → 3 columns; equal card heights; /uses gets a 44px back link, a language switcher and block anchors.Sections — skills modal with a fixed header and 44px close; distribution tiles readable at 320px; references two columns from
md; certifications inner grid driven by a container query; contact pill wraps; footer links one column below 420px with 36px rows and 44px icons.Journey timeline — vertical layout extracted to
VerticalTimeline; map height follows the number of years (512–848px instead of a fixed 800px); detail card becomes a sticky bottom sheet with a close button; 44px hit areas while dots and bars stay thin; horizontal markers centred withtranslate, achievements staggered into two rows when they would overlap, drill-down padding fixed; glow loop only runs while the horizontal layout is on screen; legend and drill-down labels localized.Foundation / cleanup —
xsbreakpoint (420px),scroll-padding-topfor hash links under the fixed header,viewport-fit=coverso safe-area insets work, pause/play icons,useMediaQuery/useElementWidthhooks; the deadconstructionNotice/Modalcode (with its latent scroll bug) and itsdevelopmenti18n block are removed.Verification
npm run check(lint, typecheck, translations, journey timeline): greennpm run build: 17 static pages exported/es/at 320×568, 360×740, 390×844, 768×1024, 844×390, 1024×768, 1280×720, 1440×900 and 1920×1080, plus/es/projects/code-xr/,/projects/obt/and/es/uses/at 360/768/1024/1440; no horizontal overflow, no console errorsAfter merging
en.jsonchanged. Close it without merging: the Spanish copy in this PR is already curated.tailwind.config.tsand the two fluid plugins are not loaded by Tailwind v4 (either wire them with@configor delete them);Header.tsx,Nav.tsx,Chip.tsx,test-fluid.cssand the unused helpers intimelineConfig.ts/journey.tsare dead code; the vertical timeline could get a per-year zoom.🤖 Generated with Claude Code