Window
A generic window frame around whatever the slot holds.
Code
The three render the same class names, the same ARIA and the same data attributes. That is checked when this site builds: a class in any of these samples that neither the markup contract nor the shipped stylesheet defines fails the build.
<div class="wsu-window" style="max-inline-size:26rem">
<div class="wsu-window__bar">
<span class="wsu-window__dots" aria-hidden="true"></span>
<span class="wsu-window__title">Exam prep</span>
</div>
<div class="wsu-window__content">
<div style="inline-size:100%;box-sizing:border-box;padding:var(--wsu-space-6) var(--wsu-space-4)">
<p style="margin:0 0 var(--wsu-space-3);font-weight:var(--wsu-font-weight-bold)">Before the exam</p>
<div style="display:grid;gap:var(--wsu-space-1);margin-block-end:var(--wsu-space-3)">
<label class="wsu-checkbox">
<input type="checkbox" id="wd-task-1" name="task-1" checked>
<span>Review lecture notes</span>
</label>
<label class="wsu-checkbox">
<input type="checkbox" id="wd-task-2" name="task-2">
<span>Print the formula sheet</span>
</label>
<label class="wsu-checkbox">
<input type="checkbox" id="wd-task-3" name="task-3">
<span>Confirm the room number</span>
</label>
</div>
<div class="wsu-field">
<label class="wsu-field__label" for="wd-new-task">New task</label>
<input class="wsu-input" id="wd-new-task" name="new-task" placeholder="Add a task">
</div>
<button class="wsu-btn wsu-btn--primary wsu-btn--sm" type="button" style="margin-block-start:var(--wsu-space-2)">Add task</button>
</div>
</div>
</div><x-wsu::window title="Exam prep">
<div style="inline-size:100%;box-sizing:border-box;padding:var(--wsu-space-6) var(--wsu-space-4)">
<p style="margin:0 0 var(--wsu-space-3);font-weight:var(--wsu-font-weight-bold)">Before the exam</p>
<div style="display:grid;gap:var(--wsu-space-1);margin-block-end:var(--wsu-space-3)">
<x-wsu::form.checkbox name="task-1" label="Review lecture notes" checked />
<x-wsu::form.checkbox name="task-2" label="Print the formula sheet" />
<x-wsu::form.checkbox name="task-3" label="Confirm the room number" />
</div>
<x-wsu::form.input name="new-task" label="New task" placeholder="Add a task" />
<x-wsu::button variant="primary" size="sm" style="margin-block-start:var(--wsu-space-2)">Add task</x-wsu::button>
</div>
</x-wsu::window>
<x-wsu::window title="bordered and accent" bordered variant="accent">
<p class="wsu-prose" style="padding:var(--wsu-space-6) var(--wsu-space-4);text-align:center">Content stays exactly as legible either way.</p>
</x-wsu::window><Window title="Exam prep">
<div style="inline-size: 100%; box-sizing: border-box; padding: var(--wsu-space-6) var(--wsu-space-4)">
<p style="margin: 0 0 var(--wsu-space-3); font-weight: var(--wsu-font-weight-bold)">Before the exam</p>
<div style="display: grid; gap: var(--wsu-space-1); margin-block-end: var(--wsu-space-3)">
<Checkbox id="wd-task-1" name="task-1" label="Review lecture notes" :model-value="true" />
<Checkbox id="wd-task-2" name="task-2" label="Print the formula sheet" />
<Checkbox id="wd-task-3" name="task-3" label="Confirm the room number" />
</div>
<Input id="wd-new-task" name="new-task" label="New task" placeholder="Add a task" />
<Button variant="primary" size="sm" style="margin-block-start: var(--wsu-space-2)">Add task</Button>
</div>
</Window>
<Window title="bordered and accent" bordered variant="accent">
<p class="wsu-prose" style="padding: var(--wsu-space-6) var(--wsu-space-4); text-align: center">Content stays exactly as legible either way.</p>
</Window>Why it works this way
- The dots are decoration for the same reason a Browser's toolbar is, and carry aria-hidden. The title is the exception: unlike an address bar, a window's title can genuinely say what is inside, a filename, a session name, so it renders as real, visible text and stays in reading order rather than being hidden with the dots beside it.
- Give it a title when the window is showing something with a name of its own. Leave it off for a bare frame, the same decision Browser makes about its address bar.
- Unlike Browser, this frame has no toolbar strip: a browser has a filled, bordered bar because a real one does, and a plain window is not a browser. The dots and the title sit directly on the frame's own background instead, with padding around them rather than a second surface under them, and the border that used to sit under the bar now sits above the content, which is what still reads as chrome above a body without needing a strip to draw it with.
- The example below is a small application, not a caption, on purpose: a heading, a checklist with one item already done, and a way to add another, built from Checkbox, Input and Button rather than hand-rolled markup, so it doubles as a composition example. Its own layout (the grid the checklist sits in, the spacing around the button) is on its own elements, never on a wsu- class, the boundary ADR-0012 draws.
- `bordered` swaps the frame's own edge for a single accent color, border.brand, proven at 3:1 (WCAG 1.4.11) against the page in both themes. `variant` recolors the toolbar strip only, its fill, its dots and its title text: never the content slot, which is a caller's own markup this component cannot see the foreground color of. Both are the fixed set drawn from the semantic layer that wsu-badge and wsu-alert already use (brand, accent, success, danger), each already proven at 7:1 against its own text in both themes.
Accessibility
- The dots are aria-hidden; the title, when given, is not, so a screen reader user reaches it in the same order a sighted reader sees it (1.3.1).
- Track the title in the markup contract rather than only the frame: a path that dropped it would still look like a window and would have quietly stopped saying what the window is.
Success criteria in brackets refer to WCAG 2.2. Every one of them is checked by axe-core in both themes at three viewport widths before this page can be published. See Accessibility for what the gates are.
Props
Blade
| Attribute | Default | What it does |
|---|---|---|
title | '' | What the window is showing, e.g. a filename. Omit for a bare bar. |
bordered | false | Swaps the frame's own edge for the accent border color. |
variant | '' | '' | 'brand' | 'accent' | 'success' | 'danger'. Recolors the toolbar strip only, never the content slot. |
Vue
| Prop | Type and default | What it does |
|---|---|---|
title | String, '' | What the window is showing, e.g. a filename. Omit for a bare bar. |
bordered | Boolean, false | Swaps the frame's own edge for the accent border color. |
variant | String, '' | '' | 'brand' | 'accent' | 'success' | 'danger'. Recolors the toolbar strip only, never the content slot. |
In the markup contract
contract/markup-contract.json is extracted from the two static templates and every package tests against it. This is what it records for .wsu-window.
| Template | Elements | Accessibility attributes | Uses |
|---|---|---|---|
| internal apps/examples/static-html/index.html | div | none recorded | 1 |
| public apps/examples/static-html/public-app.html | div | none recorded | 1 |