Responsive design
Index of the responsive corpus, with per-task load recipes and the four rules that decide most questions.
Canonical, versioned guidance for building responsive interfaces with Tessina UI. Written for two readers at once: an AI agent assembling a screen, and a human reviewing one.
This corpus is normative. Where it and a component's own docs page disagree,
this corpus wins and the docs page is a bug. Where it and CONVENTIONS.md
disagree, CONVENTIONS.md wins — the corpus is the long-form expansion of it,
not a competing authority. The one exception is §5b, whose canonical full text is
02-mobile-first-doctrine.md; CONVENTIONS.md §5b carries only the summary.
Load recipes — read only what the task needs
Each file is small enough to load whole. Nobody, human or agent, should read all nine. Pick by what you are doing:
| Task | Load |
|---|---|
| Building a screen, page or app flow | 02 + 05 + 07 |
| Hardening or authoring a component | 03 + 04 |
| Wiring layout (Grid / Stack / Flex / Container) | 01 + 06 |
| Reviewing or QA-ing responsive behaviour | 08 |
| "Which query do I even use here?" | 07 alone — it routes you |
| Something broke at one width and you don't know why | 04 first (emission order eats most of these), then 03 |
| A screenshot shows a break you cannot reproduce | 09 — the incident procedure |
Always read this index first; it is the only file that assumes no context.
The files
| # | File | What it settles |
|---|---|---|
| 01 | 01-foundations.md | The breakpoint ladder, why every rung needs an upper bound, the type ladder, the 16px input floor |
| 02 | 02-mobile-first-doctrine.md | §5b canonical. Design order, thumb zone, no hover-only, sheets below md, safe area, keyboard avoidance, dvh, no trapped scroll |
| 03 | 03-container-queries.md | Container vs viewport; named containers; the bands; what container-type costs you |
| 04 | 04-pointer-and-touch.md | touch: / no-touch:, the 44px floor, tap-pad arithmetic, and the emission-order rules that decide whether any of it works |
| 05 | 05-adaptive-patterns.md | The pattern catalogue: nav transforms, list→detail, modal→sheet, action bars, tables, reading measure |
| 06 | 06-layout-primitives.md | Responsive<T> on Grid / Stack / Flex, Container's gutter bands, and what the primitives will not do |
| 07 | 07-decision-guide.md | The axis picker: content vs container vs viewport vs pointer, as a decision tree with precedent |
| 08 | 08-qa-checklist.md | What to measure, at which widths, and what counts as passing |
| 09 | 09-rendered-reality.md | The procedure for a reported break the gates missed — and the detectors that police rendered reality |
The four rules that survive losing everything else
If you read nothing else in this corpus, carry these:
-
Never pair a bare utility with a variant of the same property.
grid-cols-1 sm:grid-cols-2is one column at every width. Write disjoint bands:max-sm:grid-cols-1 sm:grid-cols-2. This is the single most common responsive defect in this library's history. →04 -
The touch floor is keyed to the pointer, not the width. Write
touch:, nevermax-md:, for anything a finger operates. An iPad Mini is 768px wide and is unambiguously a touch device. →04 -
Ask what is actually changing before you pick a query. If a component reflows because its own column got narrow, that is a container query. If the page is reorganising, that is a viewport query. If the input device changed, that is a pointer query. Picking the wrong axis produces code that is green in every test and wrong on real hardware. →
07 -
Never solve a narrow width by making meaning unreachable. Reflow it, stack it, or move it behind a disclosure, overflow menu or link — all of those conform, and WCAG names the hamburger as a passing example. What fails is content that is simply gone with no equivalent path to it (WCAG F102, a failure of 1.4.10 Reflow). →
02
Conventions used throughout this corpus
- Code fences are verified copies. Every fence carries a source comment
(
// ui/src/components/button/core.tsx:152) and is checked against that range in CI. If a fence has no source comment, it is illustrative pseudo-code and says so. - Numbers are measured, not inferred. Any px value here traces to a
measurement recorded in
CONVENTIONS.md§9, a ledger row, or a gate baseline. Where a number is a convention borrowed from outside the library, its source is in the research ledger,ui/knowledge/responsive/_research-ledger.md(in the source repo; it does not ship in the package). - "Convention" vs "identity". In the pattern catalogue, a behaviour seen in three or more independent products is a convention and we follow it; a behaviour unique to one product is that product's identity and we do not copy it. Evidence is in the research ledger.
Provenance
The research ledger holds the source-tagged evidence behind 05 and the
external claims in 01–03: which products were examined, which design systems
were surveyed, and which claims are unverified. Read it when you want to know
why a rule is a rule, or when you are about to argue with one.