Skip to content
Back to skills

Layout Interaction Design

ASecurity

The BEHAVIORAL layer companion to `design-system` — how a UI is spaced, where actions go, how users move through it, and how it responds. Load alongside `design-system` for any non-trivial interactive or multi-screen build (Next.js + Tailwind v4 + shadcn/ui on Vercel). Covers: spacing & layout mechanics (8pt grid, padding vs margin vs gap, Every-Layout primitives, measure), button & action hierarchy + placement/ordering (with the cross-platform disagreement flagged), navigation & routing (top...

  • 2 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 19, 2026
ai-agentsgonextjsawsapi

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 19, 2026

npx -y skills add SirCharan/second-brain --skill layout-interaction-design --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Layout Interaction Design?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Layout Interaction Design
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/sircharan-layout-interaction-design/badge)](https://www.skillsdirectory.com/skills/sircharan-layout-interaction-design)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: layout-interaction-design
description: >
  The BEHAVIORAL layer companion to `design-system` — how a UI is spaced, where actions go, how users
  move through it, and how it responds. Load alongside `design-system` for any non-trivial interactive or
  multi-screen build (Next.js + Tailwind v4 + shadcn/ui on Vercel). Covers: spacing & layout mechanics
  (8pt grid, padding vs margin vs gap, Every-Layout primitives, measure), button & action hierarchy +
  placement/ordering (with the cross-platform disagreement flagged), navigation & routing (top-nav vs
  sidebar vs tabs vs breadcrumbs, multi-step flows, Next.js App Router: Link/prefetch, layouts,
  loading.tsx, parallel & intercepting modal routes, active-link, View Transitions), and interaction
  states + UX heuristics (feedback latency, skeletons vs spinners, validation/error/empty states, focus
  management, Fitts/Hick/Doherty, Nielsen's 10). Trigger on: "where do I put", "button placement",
  "padding/margin/spacing/gap", "navigation", "sidebar vs tabs", "page transition", "multi-step form /
  wizard", "modal route", "loading/empty/error state", "user flow", "how should this behave".
---

# Layout & Interaction Design

The "how it behaves & connects" half of the design family (`design-system` owns "how it looks"). Rules
first, then the Next.js/shadcn implementation. ✅ = from a primary source (cited) · ◐ = well-sourced
judgment. Note: the deep-research verify pass was rate-limited, so claims rest on **primary sources +
corroboration**, not a formal vote — treat ◐ as strong defaults.

---

## 1. Spacing & layout mechanics

**8pt grid** ✅ — size and space everything in multiples of 8 (4 allowed for tight icon/text gaps). Maps to
Tailwind's default scale (`1`=4px, `2`=8px, `4`=16px, `6`=24px, `8`=32px…). One scale, used everywhere.

**The load-bearing rule — "internal ≤ external"** ✅ (Cieden): the space *inside/around* a grouped element
must be **≤** the space *separating* it from other groups. Proximity = grouping; if padding inside a card
≥ the gap between cards, the grouping reads wrong. Concretely: card padding 16–24px → gap between cards
24–32px → section gap 48–64px. Tighten *within*, loosen *between*.

**padding vs margin vs gap** ✅◐ — decision rule:
- **`gap`** = rhythm between siblings in a flex/grid. **Default choice.** No collapsing, no leftover edge
  margin, survives wrapping (margins don't). `flex flex-col gap-4`, `grid gap-6`.
- **`padding`** = breathing room *inside* a container (card, button, section). Always padding for inner space.
- **`margin`** = sparingly, for outer separation a parent can't own (e.g. one-off `mt` on a heading).
  Prefer a `gap` on the parent over per-child margins. Avoid margin for list/stack rhythm.

**Layout primitives** ✅ (Every Layout) — compose pages from a few reusable primitives instead of bespoke
flex per screen. Paste-ready Tailwind:
- **Stack** (vertical rhythm): `<div className="flex flex-col gap-4">`
- **Cluster** (wrapping row, e.g. tags/toolbar): `<div className="flex flex-wrap items-center gap-2">`
- **Sidebar** (sidebar + fluid main, wraps when narrow): `<div className="flex flex-wrap gap-6">` + main `flex-1 basis-[60%]`
- **Center** (constrained reading column): `<div className="mx-auto w-full max-w-prose px-4">`
- **Grid** (responsive auto-fit cards): `<div className="grid gap-6 [grid-template-columns:repeat(auto-fit,minmax(16rem,1fr))]">`
- **Switcher** (N-up that drops to stacked under a threshold): auto-fit grid as above with a min width.

**Measure / content width** ✅ — body text `max-w-prose` (~65ch); app content `max-w-7xl` (1280px) typical;
full-bleed only for dashboards/hero. Never let prose run the full viewport.

**Responsive composition** ✅ — viewport breakpoints for *page* layout (`md: lg:`), Tailwind v4 **container
queries** (`@container` + `@md:`) for *components* that live in variable-width slots (a card in a sidebar
vs a wide grid). Primitives above already wrap without breakpoints — prefer them.

---

## 2. Buttons & action hierarchy

**One primary action per view** ✅ (GOV.UK) — exactly one filled/default button; everything else is
secondary/tertiary. More than one primary dilutes both.

**Hierarchy** ✅ — three+ tiers: **primary** (filled accent, the main CTA) → **secondary** (outline/tonal) →
**tertiary** (ghost/link) → **destructive** (a distinct *warning* style, not just red text). shadcn maps
these to `variant="default" | "secondary" | "outline" | "ghost" | "destructive"`.

**Placement & ordering — ⚠️ platforms disagree (flag, don't assume):** ✅
- **Apple HIG:** primary/affirmative button **far right**, Cancel to its immediate left.
- **Windows / older Android:** affirmative (OK) on the **left**.
- **GOV.UK:** one primary button **left-aligned** to the form edge; no separate Cancel — destructive is a
  warning button or a confirmation page.
- **NN/g's overriding rule:** follow the convention of *your users' dominant platform* and stay consistent;
  a standard order beats a marginally-optimal novel one.
- **House default (pick one & be consistent):** **dialogs/modals → primary RIGHT, Cancel left** (web/Mac
  norm; matches shadcn AlertDialog). **Forms/pages → primary LEFT** at the start of the action row
  (GOV.UK; it's where the eye lands after the last field).

**Form actions get missed in top bars** ✅ (UX Movement) — users finish a form at the *bottom*, so a submit
button in a top action bar is overlooked. Put the primary submit at the **bottom of the form**, left or
left-of-row; on long/mobile forms add a **sticky bottom action bar**.

**Sticky bars** ✅ (Smashing) — sticky nav/action bars hold **≤5 items**; overflow → menu. Hide-on-scroll-down
/ show-on-scroll-up headers should slide in fast (~150–300ms).

**Sizing & hit area** ✅ — min target **44×44px** (touch) / 24px (WCAG floor). Comfortable padding ratio
≈ vertical:horizontal of `1 : 2–2.5` (e.g. `px-4 py-2`, `px-6 py-3` for large). Don't make buttons full-bleed
unless mobile-primary.

**Icon-only buttons** ✅ — always an `aria-label` (and ideally a tooltip). Never ship an icon button a screen
reader announces as "button".

**Destructive actions** ✅ (Adam Silver) — don't *hide* the trigger; gate it behind a **confirmation step**
(AlertDialog or a confirm page) with the destructive verb on the confirm button ("Delete 3 signals").

---

## 3. Navigation & routing

**Pick the nav pattern by IA shape** ◐:
- **Top nav** — ≤~7 flat destinations; marketing & simple apps.
- **Sidebar** — many destinations / app with persistent context (dashboards, docs). Collapsible; group by section.
- **Tabs** — switching *views of the same object* (not navigating away). Keep ≤~5; don't use tabs as primary site nav.
- **Breadcrumbs** — deep hierarchies (≥3 levels) to show location + enable up-navigation. Secondary, not the only nav.

**Multi-step flows / wizards** ◐ — show progress (step N of M), allow back without data loss, validate per
step (§4), one primary action per step ("Continue"), persist state to URL/query so refresh and back work.

**Back & deep-linking** ✅ — every meaningful state should be a URL (filters, tabs, open modal) so back,
refresh, and share work. Don't trap state in component memory.

### Next.js App Router specifics ✅ (nextjs.org)
- **`<Link>` prefetch:** auto-prefetches routes entering the viewport (and on hover), **production only**;
  a plain `<a>` does not. Static routes prefetch fully; dynamic routes prefetch only to the nearest
  **`loading.tsx`** boundary. `prefetch={false}` to opt out; `prefetch={null}`-on-hover to limit to intent.
- **Nested `layout.tsx`** — shared chrome (sidebar/nav) that **persists without unmounting** across
  navigation. Put a dashboard sidebar in `app/(dashboard)/layout.tsx` (route group) so it stays mounted.
- **`loading.tsx`** — drop one in a route folder → Next wraps the page in `<Suspense>`, giving instant
  navigation + a streamed skeleton. Recommended for any dynamic/slow route.
- **Route groups** `(group)` — organize/segment layouts without affecting the URL.
- **Active link** — `const p = usePathname()`; mark active with **prefix match**
  `p === href || p.startsWith(href + '/')`, **special-casing `'/'`** to exact (else it matches everything).
- **Modal routes (deep-linkable)** — **intercepting** `(.)`/`(..)` routes + **parallel** `@slot` routes:
  a `@modal` slot with `default.tsx` returning `null`, an intercepting `(.)photo/[id]` rendering in a
  Modal over the current page on *soft* navigation; a **hard** load/refresh/share hits the real full page.
  Matchers: `(.)` same level, `(..)` one up, `(..)(..)` two up, `(...)` from app root.
- **Page transitions** — **View Transitions API** (Baseline Oct 2025) for route/shared-element morphs;
  gate with `prefers-reduced-motion`; graceful fallback on old browsers.

---

## 4. Interaction states & UX heuristics

**State set per interactive element** ✅ (NN/g) — design **all 7**: default, hover, focus(-visible),
active/pressed, disabled, **loading**, selected. Missing states (esp. focus + loading) is the #1 "templated"
tell. shadcn ships most; verify focus-visible + a loading variant.

**Feedback latency** ✅◐ — Doherty Threshold: respond in **≤400ms** to keep flow. Rules of thumb (Nielsen):
**<0.1s** = feels instant (no indicator) · **<1s** = keep attention, a subtle spinner ok · **>1s** show a
determinate indicator · **>10s** show progress + allow other work. Prefer **optimistic UI** (update
immediately, reconcile on response) for high-confidence mutations.

**Skeletons vs spinners** ✅ (NN/g) — **skeletons** for full-page/section loads roughly **>500ms and <10s**
that have a known layout (they imply structure + progress); **omit for <1s** loads (the flash annoys); a
**determinate progress bar** for **>10s**. Spinners for small inline/indeterminate waits only.

**Feedback channels** ✅◐ — **inline, next to the field/control** for validation and contextual results
(not a top banner); **toast** for transient async confirmations ("Saved") — auto-dismiss ~4–6s, never for
errors that need action; **inline error region** (`role="alert"`) for form/submit errors; **empty states**
are instructional — say what's missing + the next action, never a blank panel.

**Forms** ✅◐ — validate **on blur / per field**, not only on submit; specific in-context messages ("Leverage
must be 1–200×"); show the error at the field with `aria-invalid` + `aria-describedby`; don't disable the
submit button silently (explain what's required); allow paste/autofill (WCAG 2.2).

**Accessible focus on navigation** ✅ — on client-side route change, move focus to the new page's `<h1>`/main
(or an `aria-live` route announcer) so keyboard/SR users aren't stranded; keep a visible `:focus-visible`
ring (see `design-system` §5). Don't trap focus except inside modals (where you *must* trap + restore).

**UX laws to apply** ◐ —
- **Fitts's Law:** make frequent/important targets bigger and closer (or screen-edge "infinite" targets);
  primary actions large, destructive small/guarded.
- **Hick's Law:** fewer choices = faster decisions; reduce options per screen, use progressive disclosure.
- **Jakob's Law:** match platform/competitor conventions (ties back to button order).
- **Nielsen's 10 heuristics** as a review checklist: visibility of system status, match real world, user
  control/undo, consistency, error prevention, recognition over recall, flexibility, minimal aesthetic,
  help users recover from errors, help/docs.

---

## Sources
✅ primary: nextjs.org App Router docs (linking/prefetch, intercepting & parallel routes), every-layout.dev
(Stack/primitives, gap-vs-margin), nngroup.com (OK-Cancel order, skeleton screens, button states,
heuristics), design-system.service.gov.uk (button hierarchy/placement), developer.apple.com HIG (button
order), uxmovement.com (form-button placement), smashingmagazine.com (sticky menus), adamsilver.io
(destructive actions), w3.org WCAG 2.2 (focus-visible), aurorascharff.no (active NavLink). Verify pass was
rate-limited (false-negative votes) — claims rest on these primary sources + corroboration. See
`design-system` for the visual layer this composes with.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.