X-01 · Composites
All elements · OverlaySystem on the Composites page
Last checked 2026-10-22 · Awaiting approval · Accessibility tests
Approve OverlaySystem
Approving as
Dialogs behave like windows in an operating system. A [data-window-area] is the view area
they live in; each dialog.qf-overlay[data-window] inside it drags by its header, snaps to
the edges and corners of that area, resizes from eight grips, raises to the front when it is clicked or
focused, and minimizes to a dock. js/windows.js writes the geometry; the nine
data-snap rects, the grips, the dock and the drop-zone ghost are CSS.
In an app the area is the whole .qf-shell, not its content: windows stack at
--qf-z-window, above the nav and the app bar, and snap over them; minimized windows become
tabs in a dock along the foot of the screen, at --qf-z-dock, and snapped windows stop above
it. Menus, popovers, toasts and the narrow nav drawer stay above both.
The full-screen page is
overlay-system.html,
inside the app shell. The specimen below is copied from overlay-system.html by
bun scripts/design-pages/build-composite-pages.mjs — edit that file, not this one;
--check fails when they drift.
| Axis | Values |
|---|---|
[data-window-area] |
flag — the bounding view area windows are positioned inside; the app's .qf-shell
|
.qf-overlay[data-window] |
flag — make the dialog an OS-style window (drag · snap · resize · raise) |
[data-snap] |
left · right · top · bottom · top-left · top-right · bottom-left · bottom-right · maximized — absent is floating |
[data-state] |
active (front window) · minimized (docked; wins over active) |
[data-window-action] |
minimize · maximize · close — on a button in .qf-window-controls |
[data-ds-open-window] · [data-ds-close-window] |
opens that window id (non-modal show()) · closes the window it is in |
[data-window-title] · [data-window-icon] |
label and sprite id for the dock chip; default to the window's own title and icon |
.qf-overlay__resize[data-edge] |
n · e · s · w · ne · nw · se · sw — resize grips, injected by js/windows.js |
.qf-snap-preview[data-snap] · .qf-dialog-dock |
drop-zone ghost and the dock of minimized windows |
[data-window-minimizable] |
false — a window that must be answered (a confirmation) does not minimize |
qf-window-snap · -minimize · -restore ·
-close
|
bubbling events on the window, so a framework that renders it can follow its state |
--qf-window-dock |
the dock's height on its area, written by js/windows.js; snap rects stop above it
|
Guidance
When to use
- Use it when users need several objects open at once to compare or copy between them, such as a case, its policy and its photos.
- Use it when an object opened from Search, a DataGrid or a list should stay open while the user keeps working in the list.
- Use it to host a QEditor office file, which always opens as its own window.
- Use the dock when users park open work for later in the same session.
When to consider something else
- Use a modal Overlay when the user must finish or cancel one task before doing anything else. See Overlay.
- Use a Confirmation for a short yes or no decision about a destructive action. See Confirmation.
- Use a two-pane view, as in the Inbox, when users step through records one at a time. See Inbox.
- Use a Task pane for a side panel tied to the current document rather than a free-floating object. See TaskPane.
Usability
-
Place every window inside a
[data-window-area], normally the app's.qf-shell, so windows snap over the nav and app bar and minimize to a dock along the foot of the screen. -
Give every window a
.qf-overlay__titlethat names the object, plusdata-window-iconso its dock chip is recognizable. -
Open windows with
data-ds-open-windowon the control that represents the object, so focus can return to it. -
Keep the standard
.qf-window-controls(Minimize, Maximize, Close) in every window header. -
When the window's content draws the whole chrome (QEditor in an iframe), set
data-chrome="editor"and render no header: the window keeps a hairline edge, and the content reports its title-bar drags and control clicks toqfWindows.dragStart/dragMove/dragEnd,toggleMaximize,minimizeandclose, and draws theqf-window-stateevent's active and maximized state. Name it witharia-labeland give itdata-window-titleanddata-window-iconfor its dock chip. Inside the content, its own outer frame is adata-presentation="fullscreen"window, whichjs/windows.jsnever drags, resizes, snaps or maximizes: only the host window moves. - Let new windows cascade from the area's top-left instead of stacking at one position.
- Do not use a window for a blocking decision; windows are non-modal and the page behind stays usable.
- Do not make dragging the only way to move or size a window; snap keys and Maximize must stay available.
- Do not open a second copy of an object that is already open; opening it again raises the existing window.
- Do not place windows outside a window area, where snapping and the dock have no bounds.
Accessibility
Keyboard
| Keys | Action |
|---|---|
| Tab | Moves through the window's controls; focusing any control inside a window raises it to the front. |
| Enter or Space | On an opener, opens or raises its window; on a dock chip, restores the minimized window. |
| Escape | Closes the focused window and returns focus to the control that opened it. |
| Alt+Arrow keys or Cmd+Arrow keys | Snaps the window: Up maximizes, Left and Right snap to halves, Up and Down from a half snap to quarters, and Down from maximized restores floating. |
| Enter on Maximize |
Toggles between maximized and the previous size; the button reports its state with
aria-pressed.
|
Roles and names
-
Each window is a non-modal
<dialog class="qf-overlay" data-window>opened withshow(), notshowModal(). -
The binding must name each window with
aria-labelledbypointing at its.qf-overlay__title; the static markup does not. -
Window controls are icon-only buttons labeled Minimize, Maximize and Close; Maximize carries
aria-pressed. -
Resize grips and the snap preview ghost are
aria-hidden="true"; dock chips are real buttons labeled with the window title. -
data-state="active"marks the front window anddata-state="minimized"a docked one; neither is announced, so state changes must not rely on them alone.
Focus
- Opening a window does not move focus in the reference; the binding must move focus into the new window (its first control or title).
- Closing returns focus to the opener; restoring from the dock focuses the first header button.
- Windows do not trap focus; Tab can leave a window to reach the page and other windows.
- A front window must not fully hide the focused control in another window or the page (2.4.11).
Other requirements
- Header drag and edge resizing are pointer-only; the Alt+Arrow snaps and the Maximize button are the alternatives 2.5.7 Dragging Movements requires.
- Window content must reflow when snapped to a quarter or shown at 320 CSS pixels wide (1.4.10).
-
Window control buttons are
data-size="sm"; confirm they meet 24 by 24 CSS pixels (2.5.8). -
Snapping and raising must not animate for users who set
prefers-reduced-motion(2.3.3).
Test your implementation too. This guidance covers the element as specified here. How a screen composes it (labels, order, announcements) still needs its own keyboard and screen reader check.
Accessibility tests
Passed the gate (run 358b316 on 2026-10-22): no finding in any theme. Awaiting a person’s approval of the checklist below.
| Area | Automated | A person checks |
|---|---|---|
| General | Passed | Color is never the only cue, text alternatives say the same thing as the graphic, and the element reads the same in the light and the dark theme. |
| Zoom | Passed | At 200% zoom, at 320 CSS pixels wide and with the WCAG text-spacing overrides, nothing is lost, clipped or overlapping. |
| Keyboard | Passed | Every row of the Keyboard table works, focus is always visible and never trapped, and the tab order follows the reading order. (5 rows) |
| Screen reader | Passed | With NVDA or JAWS on Windows and VoiceOver on macOS, names, roles and states are announced as Roles and names says, and changes are announced once. (5 items) |
Approving. When the checklist passes on the checked run, record it with
bun run a11y:approve -- overlay-system --by "Your name" and commit
a11y/approvals.json with the rebuilt pages.
All test status
Package
Consumers link one stylesheet, css/classic/index.css, which includes every element. The
files below are where this element is defined.
| Source |
css/classic/components/overlays.csscss/classic/composites/documents.csscss/classic/composites/office-shell.csscss/classic/composites/overlay-system.csscss/classic/composites/windows.css
|
|---|---|
| Specimens also use | Box · Button · Card · Chip · Control · Field · Form · Icon · Overlay · Table · Text · Toolbar |
| Sprites | sprites/icons.svg |
| React | Not yet available: the React binding has not started. |
Latest updates
| Date | Version | Breaking | Description |
|---|---|---|---|
| 2026-10-20 | 0.1 | Yes |
Classic is the only skin: css/modern/ and js/skin.js are removed, so consumers link
css/classic/index.css directly (no data-skin-sheet swap) and keep
data-skin="classic" on <html> for scripts. The skin switch is gone from the
site's app bar, the shell's identity menu and the Office review strip; theme stays. The per-skin
composite pages are single pages: composites/shell.html, inbox.html, overlay-system.html and
search.html replace the *.classic.html and *.modern.html pairs
|
| 2026-10-20 | 0.1 | No | OverlaySystem: the save-search window the search toolbar's bookmark opens, non-modal (Edit saved search: Name, a note when the search on screen differs, Delete… · Cancel · Save as new · Update), classic skin |