Patterns
The one rule worth designing around. Across breakpoints, keep the same elements in the same containers. Change size, direction, order and visibility as freely as you like — all four are nearly free. Re-parenting an element, or splitting one group into two, is not: it means the same control is built twice, and the two copies drift.
Index-page toolbar
One flex row at desktop: search, the filters in order, a spacer, then the view switch. Below md exactly four things change — the row becomes a column, search goes full width, the filters become an edge-to-edge scrolling track, and the switch disappears because there is no list view on a phone.
Nothing moves between containers, which is why this cost an afternoon rather than a week. The two wrappers around the filters become display: contents at md+, so their children rejoin the desktop row as ordinary flex items and there is one copy of every control.
Note what the track needs from a design: it bleeds through the page gutter to the screen edge, so a design has to say whether a row scrolls, wraps, or truncates. All three are buildable; guessing between them is not.
Card grid
Specify a grid as a rule, not a track: four across at desktop, one on a phone, gutters 22 and 30. A fixed pixel column only works on the canvas it was drawn against — a 290px track from a 1340px canvas silently becomes three across inside our 1240px content width, and the fix is arithmetic nobody can do from the design file alone.
The floor here is minmax(17rem, 1fr) with auto-fill, chosen as the largest value that still yields four across in our container. Cards land near 275px rather than the design's 305px, and that is the right trade rather than a defect.
Sidebar layout — nav and breadcrumb
The chrome around a reading view: a vertical section nav down the left, a breadcrumb above the content. The nav here is live — click a section and the highlight and the breadcrumb follow, because the active treatment comes from the route rather than from a flag.
A profile and the settings page are the same composition, not two designs. They differ in their data: settings puts a separator node between groups and gates some groups by role, which is why the fixture below carries a separator. A group heading, an icon per item, and an optional separator is the whole vocabulary — anything else in a nav design is new work.
Below md the nav is not a narrower nav, it is a different thing: a fixed drawer over the content, opened by a hamburger that shares a row with the breadcrumb, and closed again by any navigation. Worth designing explicitly — the closed state is the one people forget, and it is what a phone shows first.
Preview modal shell
The real component, not a reproduction — this one lives in a library. Desktop is two columns, each scrolling its own content, with the header inside the left one so the rail runs the full height. Below md the design linearises it into a single scroll with the header and the action bar pinned.
That linearisation is the expensive kind of change, and it is worth seeing why. Two scroll regions cannot become one while they are siblings, so both wrappers go display: contents, their four parts become children of the panel, and the panel itself scrolls with the header and bar held by position: sticky. It works, and it took a rebuild rather than a restyle. A design that kept one scroll region at both breakpoints would have cost nothing.
The other regrouping here was genuinely unavoidable: the desktop rail's five actions become a three-button bar plus a kebab on mobile. Because content cannot cross containers, those controls exist twice in the markup, with one copy hidden at each breakpoint. That is the price of the split, and it is worth paying knowingly.