Both routes render the same MessageStream; the layout wrapper used to inset /category by px-4 / sm:px-6 on mobile while /browse stayed edge-to-edge, shrinking bubble width and making the category waterfall feel narrower than the all-resources page.
2.4 KiB
title, type, date
| title | type | date |
|---|---|---|
| Category page stream layout mismatch — Quick Fix | quick-fix | 2026-06-03 |
Category page stream layout mismatch — Quick Fix
Bug
After clicking a card on 资料分类 (/categories) and landing on /category/:slug, the resource bubbles render with narrower bubbles / different waterfall spacing than the 全部资料 page (/browse). Both pages use the same MessageStream component, but the page-level wrapper applies extra horizontal padding only to the category route.
Root Cause
src/layouts/PublicLayout.tsx chooses the <main> padding using a flag named footerInContentFlow, defined as:
const footerInContentFlow = stripLangPrefix(pathname) === "/browse";
That flag selects the px-0 ... md:px-9 xl:px-0 zero-mobile-padding branch — which is the layout MessageStream is designed for (it manages its own inner max-w and centers bubbles). All other routes fall through to the default px-4 min-[440px]:px-5 sm:px-6 md:px-9 ..., which on mobile inset the stream by 16–24 px and shrunk each bubble's max-w proportionally. Because /category/:slug rendered the same MessageStream, that extra inset is exactly what made the category waterfall look "off" vs /browse.
Fix
Extend the same zero-padding branch to also match /category/<slug>, so both routes share the wrapper that MessageStream was designed to live in.
Files Modified
src/layouts/PublicLayout.tsx— renamed the flag's derivation to also include/category/*. Kept the existingBackToTopand footer-in-content checks (stripLangPrefix(pathname) === "/browse") untouched, since those are separate features the user did not ask to share with category pages.
Verification
npx tsc --noEmit— clean.npm run format:check— clean.npm test— 49/49 passing.- Visual: opening
/categories→ tapping a category card now lands on a/category/:slugview whose<main>matches/browse(no extra mobile horizontal inset), so bubbles render with the samemax-w-[358px]width.
Notes
- The flag is still called
footerInContentFlowfor now even though it only controls padding, matching prior code; renaming would expand the change footprint beyond this fix. - BackToTop and the
footerInContentFlowfooter slot remain/browse-only — those are independent of layout width and the user didn't ask to enable them on category pages.