Skip to content

Separator · Scroll area · Resizable handle · Aspect ratio

Aspect ratio — a box that keeps its proportion whatever fills it: a card’s media, an image slot, a video.

Beta · Navigation and overlay · packages/css/src/components/layout-utilities.css

.pui-separator (--vertical --strong) · .pui-scroll-area · .pui-resizable-handle (--horizontal, __grip) · .pui-aspect-ratio (--4-3 --1-1). No decorative separators — only where a line has to be.

Separator · Scroll area · Resizable handle · Aspect ratio — every size and every stateOpen in the workshop

Sizes across, states down.

  • Ratio: 16:9 · 4:3 · 1:1; 320 wide in the specimen — resize keeping the ratio (a 16:9 at 368 is 207)
  • No states; a loading media box is Skeleton’s block

Use when an image or a video sits in a layout that must not jump when it loads — a Card’s media, a gallery, a hero’s figure.

Do not use when the image has its own natural size and the layout can wait (an inline illustration); for an avatar (Avatar); for a logo (Logo/*).

Relates to Card, Skeleton, Avatar, Image card (site), Carousel.

Anti-patterns an image squeezed into the wrong ratio · a ratio per screen for the same media · a fill changed on the instance.

Keywords: aspect ratio, media box, image placeholder, 16:9, thumbnail

Figma — page Layout utilities: Aspect ratio (3 variants)

shadcn: aspect-ratio

Resizable handle — the seam between two panes the user can drag.

  • Orientation: vertical (the seam between side-by-side panes) · horizontal; Has grip
  • 240 long in the specimen; stretches with its panes (constraints)
  • No states drawn: the line takes border/strong while dragged, in code

Use when two panes share a screen and the user’s balance between them matters — a chat and its context, a list and its detail, an editor and its preview.

Do not use when the panes have one right width (a fixed layout); on a phone; for a sidebar (Sidebar has its own width).

Relates to Chat pattern, Sheet, Scroll area, Separator, Sidebar.

Anti-patterns a handle with no minimum pane width behind it (code) · a grip on every handle (only where the seam is hard to find) · three panes with two handles on a laptop · a fill changed on the instance.

Keywords: resizable, split pane, handle, drag, panel group

Figma — page Layout utilities: Resizable handle (4 variants)

shadcn: resizable

Scroll area — a region that scrolls inside the page with a bar the system draws: a long list in a panel, a menu that outgrows its height, a table’s horizontal overflow.

  • Content (swap — default Slot); Orientation: vertical · horizontal; 320 × 240 in the specimen — stretch it, the viewport and the track follow (constraints)
  • No states drawn: the thumb darkens on hover in code (border/strong)

Use when a panel, a sheet, a menu or a card holds more than its height and must not grow — Command’s list, a Sheet’s content, a long Select menu.

Do not use when the page itself scrolls (the browser’s bar, with its gutter reserved); a table wider than its column (Data table’s own overflow); to hide content that should be shorter.

Relates to Slot, Sheet, Command, Select menu, Data table, Resizable.

Anti-patterns a scroll area inside a scroll area · a bar drawn where the browser’s would do · a thumb thinner than 6 · a fill changed on the instance.

Keywords: scroll area, scrollbar, viewport, overflow, scrollable

Figma — page Layout utilities: Scroll area (2 variants)

shadcn: scroll-area

Separator — a line between two things, only where a line has to be.

  • Orientation: horizontal (240 in the specimen — stretch it) · vertical (120); Weight: default · strong; 1px
  • No states, no text; a labelled divider (‘or’) is a row of Separator + text + Separator in the consumer’s layout

Use when two regions touch and spacing alone does not separate them — a menu’s groups (Dropdown menu’s separator is this), a toolbar’s clusters (vertical), a footer above its content.

Do not use when the eye already sees two things (a card on a page, a heading over a list); under every list row (that is the Table’s own rule); as decoration between sections (spacing does it).

Relates to Dropdown menu, Toolbar (Topbar), Table, Card, Accordion item.

Anti-patterns a separator between every section of a page · a separator plus a background change (one is enough) · a 2px separator outside the Accordion item · a fill changed on the instance.

Keywords: separator, divider, rule, hr, line

Figma — page Layout utilities: Separator (4 variants)

shadcn: separator

The class, the parts, and nothing that is not in the package. The same block opens layout-utilities.css.

<hr class="pui-separator"> <div class="pui-separator pui-separator--vertical pui-separator--strong" role="separator"></div>
<div class="pui-scroll-area" tabindex="0" role="region" aria-label="…" style="height: 240px"> …content… </div> (a scrollable region is keyboard-reachable)
<div class="pui-resizable-handle pui-resizable-handle--grip" role="separator" aria-orientation="vertical"><span class="pui-resizable-handle__grip"><span class="pui-icon">…</span></span></div>
<div class="pui-aspect-ratio pui-aspect-ratio--4-3"><img src="…" alt=""></div>

Every number here is measured on the rendered component: contrast (npm run contrast:render), the focus ring (npm run focus) and the keyboard (npm run keyboard). The floors are principle 12’s.

ink on ground reads floor the matrix calls it
#0b0202 on #ffffff 20.51 4.5 text.default on surface.page (promised) ok

1 distinct pair(s) rendered, 0 that axe calls a violation.

primitive on the indicator over the change
Resizable handle surface/page fill #6a66e4 0 px #dad9d9 3.22 ok
Resizable handle surface/card fill #6a66e4 0 px #dad9d9 3.22 ok
Resizable handle surface/sunken fill #6a66e4 0 px #dad9d9 3.22 ok
Scroll area surface/page outline #6a66e4 2 px #ffffff 4.53 ok
Scroll area surface/card outline #6a66e4 2 px #f2f2f7 4.06 ok
Scroll area surface/sunken outline #6a66e4 2 px #f2f2f2 4.05 ok

1 of 1 focus stop(s) in this block meet WCAG 2.4.13 on screen — the same crop screenshotted focused and unfocused, and the difference measured.

Nothing in this component claims an ARIA role with a keyboard contract; its controls are ordinary ones and the browser already gives them their keys.

Tab order across the whole library is document order over 344 stops, and Shift+Tab is its exact reverse — no keyboard trap anywhere (WCAG 2.1.2).

Pepper UI v1.5.0

The Mobupps design system. 386 tokens, 88 components, 65 pages in the workshop — every page of this site generated from the repository, so nothing here is typed twice.