Settings

Press Ctrl+K to preview the palette.
Sidebar
Display
Profile Panel
👤

John Doe

Administrator
  • 📊 Dashboard
  • 📝 Forms
  • 📋 Tables
Commands
🚀
Go to Page
Navigate to a page
AltG
🌓
Toggle Theme
Switch between light and dark mode
AltT
📐
Toggle Sidebar
Show or hide the sidebar
AltB
⚙️
Open Settings
Open the settings panel
AltS
Search In
📄
Pages
Search pages
:p
🧩
Components
Search component pages
:c

Responsivity — how it works

Two small JavaScript engines let a component react to the space it is actually given — not the size of the window. That is the difference between a media query (asks the viewport) and a container query (asks the box). Pure Admin ships both a CSS-native path and a JS path, because some responsive moves (mounting a chart, moving a block into a menu) can't be done in CSS alone.

The big idea. A sidebar, a split pane, or a card in a grid can be narrow while the window is wide. Viewport media queries can't see that. Everything on this page keys off an element's own width, so a component adapts correctly wherever you drop it.

The two engines

 Fit fit.jsContainer Breakpoint container-breakpoint.js
Decides byMeasuring content — "does the row still fit?"Declared width thresholds — "which named band am I in?"
OutputDegrades slots one at a time (hide / step-down / relocate)One named mode reflected to [data-mode]
Best forA row of things competing for one line (toolbars, the navbar)A component that restyles wholesale at set sizes (grid → tabs → icons)
Eventpc:fit-relocate (on a relocated slot)pc:breakpoint (on mode flip)

1 · Fit — degrade a row to fit

Fit watches a horizontal container and, when the content can't fit, degrades the lowest-priority slot first, restoring as space returns. The navbar auto-inits; wrap any other flex row in a FitContainer and mark participants with attributes (or wrap them in a FitSlot):

  • data-pc-fit="hide" — remove the slot when it must yield.
  • data-pc-fit="steps" — show the largest ranked variant that fits (logo → wordmark → monogram).
  • data-pc-fit="relocate" — move the slot somewhere else entirely (next section).
  • data-pc-fit-priority — lower degrades first; data-pc-fit-auto folds in every child of a container; data-pc-fit-ignore pins one out.

2 · Relocation — fit decides, a sink places

A relocate slot doesn't just hide — it moves out of the row into a named destination and comes back on widen. Crucially, the Fit engine only decides a slot must yield; where it goes is a pluggable sink named by target. Two sinks ship built-in:

  • target="floating-menu" — folds into a "•••" flyout panel. Self-contained; needs no sidebar.
  • target="sidebar" — rebuilds the slot as a sidebar list item.
  • your ownpureAdmin.components.fit.registerSink('name', { out, in }).

Live — drag to narrow the bar. The badge cluster is one relocate slot targeting floating-menu; when the bar runs out of room it folds into the "•••" panel, and returns when you widen. "New" is pinned with data-pc-fit-ignore.

Bar width 720px
Acme Console Users 123 Rooms 23 Subs 45
Why a sink registry? The engine used to hard-code "move into the sidebar." Extracting the destination means one generic detector serves many placements — sidebar, flyout, or anything you register — and it's the seam that lets the navbar live in the foundation layer while the sidebar-specific sink stays in the admin layer.

3 · The event & hands-off mode (Svelte / Phoenix)

Before it moves anything, Fit fires a cancelable pc:fit-relocate event on the slot (detail = { action: 'out' | 'in', target, container }). A plain HTML page lets the built-in sink do the DOM move. A reactive framework does the opposite: it owns placement itself.

Set managed (the data-pc-fit-managed attribute — or call preventDefault()) and Fit performs no DOM surgery; it only hides the slot in-row and hands you the flip through onrelocate. The framework then re-renders the block in its new home from state. That solves the staleness trap: a moved DOM node keeps its old Users: 123; a re-render is bound to the live store, so the relocated copy is always fresh.

Same contract in Phoenix LiveView: the hook forwards pc:fit-relocate with pushEvent, the server assigns the mode, and only the branch for the current placement is rendered — never a stale off-screen copy.

4 · Container Breakpoint — named modes at set widths

When a component restyles wholesale at set sizes — not a row shedding pieces, but a card that becomes a grid, then tabs, then icons — declare width thresholds and let the engine name the band. It's the JS counterpart to a CSS @container query, for the cases CSS can't reach (mount a chart, push to the server).

  • Thresholds are rem by default (root font is 10px, so 34 = 340px, 64 = 640px); add unit="px" for pixels.
  • The engine reflects the band to [data-mode] (CSS can key off it) and mounts only the branch for the current mode.
  • It fires pc:breakpoint only on a flip — the hook for "mount on demand" (build the chart in grid, destroy it otherwise).
  • A small hysteresis dead-band stops flip-flopping right at a threshold — important, because a flip mounts/unmounts, not just a CSS toggle.
See it live on the Fit to Size page — Example 4 builds a chart instance only once the card reaches grid mode and destroys it below, logging every flip.

Which one do I reach for?

Row of items fighting for one line? Fit — it measures and sheds by priority.
One component that reshapes at set widths? Container Breakpoint — it names the band and you style/mount per mode.
Purely cosmetic swap with no mount/DOM move? A plain CSS @container query — no JS at all. Reach for an engine only when a move needs JavaScript: relocating a node, or mounting/destroying on demand.

Ready to see Fit degrade real cards and toolbars across several strategies? Head to Fit to Size for the worked, slider-driven examples.

Keyboard Shortcuts

No shortcuts registered.