HabSavingFrame
A region whose whole subject is being written. It wraps the content in the saving wave: a sweep you can see, a veil, aria-busy and inert.
<HabSavingFrame :saving="saving">
<HabInput
v-model="name"
label="Name"
/>
<HabButton @click="save">Save</HabButton>
</HabSavingFrame>HabPanel, HabCard, HabListRow and HabInspectorPanel each take saving and blocking and draw the same wave from the same source. Reach for the frame when the region is one you draw — part of a page, a form section, the body of something that has no saving prop of its own.
The wave is four things
Only one of them is visible, and only that one does nothing on its own:
| Part | What it does |
|---|---|
| The sweep | An accent band moving across. A still tint under reduced motion. |
| The veil | Washes the content out. Only while blocking. |
aria-busy | Tells a screen reader the region is changing. Without it, it's decoration. |
inert | Stops pointer and keyboard input. The veil only says so; this does it. |
The frame applies all four together so none can be half-applied. There is no public class to put the sweep on an element yourself, on purpose: the sweep alone is exactly the half that does not work.
One subject, the whole of it
The wave means a write against everything this region shows. Renaming the thing the region is about, saving the form it holds.
A write against one part of it reports itself on that part. Covering a whole region for one checkbox reads as though the region had gone away — and the row just touched is exactly what the reader still needs to see. A list of rows wants HabListRow's saving, not a frame round the list.
It is writing out. A region waiting for data to arrive is a HabSkeleton, or HabCard's loading bar.
Blocking
On by default. The write is against everything the frame shows, and editing that while it is being written is the race the wave exists to prevent.
What stays usable is decided by what is outside the frame, not by turning blocking off. HabInspectorPanel wraps its header, body and footer and leaves its resize handle out, because resizing is not a write. Do the same with a close button or anything else that is not part of the save.
Stacking
The wave and the veil sit above anything sticky inside the frame — a form action bar, a toolbar pinned in a scrolling HabTabs panel — so the button just pressed does not look live through it. While saving the frame is its own stacking context, so the wave cannot climb past anything outside it.
Nested frames show one wave: the outermost wins. A saving card in a saving panel is one write to wait on, and two veils stacked are nearly opaque. The inner frame keeps its aria-busy and inert. Its veil goes only when the outer frame draws one: inside a non-blocking save, a blocking frame keeps its veil, so a locked region never looks touchable.
The frame is always relative, to anchor the wave. Position it with a parent rather than an absolute or sticky class on the frame itself.
Accessibility
A saving frame is aria-busy, and a blocking one is inert — the attribute, not a pointer-events trick, so the keyboard is stopped too.
Under forced colors (Windows high contrast) the sweep is replaced by an outline in the system highlight colour, since forced colors drops the gradient.
What you are still responsible for: focus. A focused control inside a frame that goes inert loses focus to <body> — typically the Save button you just pressed. Move focus somewhere deliberate before the save starts, or back when it ends.
Not verified here. The stacking order, the outermost-wins rule, the forced-colors outline and the focus loss all need a real browser, which the test suite does not have yet.
API
Props
| Prop | Type | Default | Description |
|---|---|---|---|
as | string | "div" | Element to render as. The frame is always relative, to anchor the wave. |
blocking | boolean | true | Whether a saving wave also swallows input: a veil washes the content out and the frame goes inert, which stops the keyboard as well as the pointer. On by default, because a frame is for a write against the whole of what it shows, and editing that while it is being written is the race the wave exists to prevent. Leave controls that are not part of the write — a resize handle, a close button — outside the frame rather than turning this off. |
saving | boolean | false | A write against everything this frame shows is in flight: a wave sweeps the frame and it is marked aria-busy. Not for a write against one part of it. A row reports itself on the row; covering a whole region for one checkbox reads as though the region had gone away, and the thing just touched is exactly what the reader still needs to see. Writing OUT, not reading in. A region waiting on data to arrive is loading where a component offers it (HabCard's bar), or a HabSkeleton. |
Slots
| Slot | Bindings | Description |
|---|---|---|
default | any | The region the write is against. |