Split view

The one two-pane layout of the application: an aside next to the main content — record rail | detail, config | preview, list | reader, work | discussion. Every two-column screen uses it; nobody writes a new two-column grid. React SplitView in apps/web/src/components/SplitView.tsx (app-side); CSS apps/web/src/ds/split-view.css (.sv, .sv-aside, .sv-main, .sv-pad, modifiers .sv-r, .sv-div-line, .sv-div-gap, .sv-fill, .sv-collapse); the phone stack lives in apps/web/src/ds/responsive.css. Recipes and migration history: docs/DS-SPLITVIEW.md in the app repo.

When to use

  • A screen whose body is two columns that live side by side: a record (rail | detail), a calculator or builder (config | preview), a list with a reader (Aktivity, DPH, Deník), a project (work | discussion).
  • The body under a bar — PageHeader or Section top bar sits above the split across the full width; the split is only what is under it.

When not to use

  • Settings (navigation | feed), the guide (filters stacked above results), single-column screens (Pokladna, Tým), mail (list + modal) — they are not aside | main.
  • A layout inside a card or a dialog; the split is a page body.
  • Anything that needs the user to drag the divider — the split is not resizable, by decision.

Anatomy

  • Root div.sv: a grid var(--sv-aside) minmax(0, 1fr). Default aside width clamp(356px, 31%, 452px) (minmax(320px, 0.82fr) when the aside is on the right). asideWidth sets --sv-aside — a number is px, a string any grid track.
  • Panes .sv-aside and .sv-main: flex columns that may shrink below their content (min-width/min-height: 0).
  • Divider: divider="line" (default) = a --border hairline on the aside's inner edge; divider="gap" = a gap --sv-gap (default --sp-6) instead of the line.
  • asidePosition="right" (.sv-r): the aside sits on the right and the main pane comes FIRST in the DOM.
  • fill (default on, .sv-fill): the split fills the height under the bar and each pane scrolls on its own. It needs a flex-column parent with a height (.pr on a page). fill={false}: both panes hug their content and scroll together in the parent.
  • collapse (.sv-collapse): one column below 1080px on desktop (Projekt). Independent of the phone stack.
  • Gutter .sv-pad on a pane without its own gutter (rail, form): padding --sp-5 --sp-5 --sp-6, flex column with --sp-5 gap, and --il-gutter: var(--sp-5) for embedded item lists.
  • Phone (≤720px, automatic): the panes stack — aside on top for .sv, main on top for .sv-r; the line becomes a horizontal hairline, the gap a row gap; with fill the whole page scrolls once.

Best practices

Do

  • Use the default width unless the screen is one of the recipes (Schůzka clamp(320px, 27%, 396px), list | reader 372, narrow filter list 280, discussion on the right clamp(300px, 24%, 360px)).
  • Wrap a bare pane in .sv-pad; leave panes that bring their own gutter alone.
  • Use fill={false} when the split sits inside something that already scrolls.
  • Keep the bar above the split, full width.

Don't

  • Write a new two-column grid or a new class next to .sv.
  • Invent widths or breakpoints, or add a resize handle.
  • Put inline padding on .sv-aside — that is what .sv-pad is for.
  • Use fill inside a region that already scrolls (two scrollbars, cut-off panes).
  • Pass gap without divider="gap" — with the line divider it has no effect.
  • Nest a split inside a split.

Content

  • The aside is the context (who, what, settings, list); the main pane is where the work happens. The aside never repeats the title shown in the bar.
  • An empty main pane says what to do in one short line ("Vyberte záznam vlevo"), no illustration and no explanation.
  • While loading, both panes keep their place and show skeletons, so nothing jumps when the data arrive.
  • record-rail — the usual content of the aside on a record.
  • section-top-bar, page-header — the bar above the split.
  • command-palette — built on the same .sv-* panes (.gsp2).
  • Stories: components--split-view--default, --variants, --sizes, --states, --composition.

Source: docs/app-shell/split-view.usage.md · GitLab