I pressed Save. Did it save? · slopware 101

slopware 101 · step 8 of 35

I pressed Save. Did it save?

by · 3 min read

You type a note, press Save, and a green message appears. You close the page. Tomorrow the note is gone.

The button did respond. The important question is what made it show that message. Perhaps the interface declared success as soon as you clicked, before the storage operation had finished. Perhaps it saved in this browser and you came back on another device. Those produce similar disappointments for different reasons. The storage chapter helps you distinguish them; now we need the screen to tell the truth about what it knows.

Follow one note

Take a version of our notes app that saves to a server. While editing, the note is a draft in the page. When Save is pressed, the request starts. Only a successful confirmation from the service can tell this page that the server accepted the change according to its storage contract. The click alone cannot.

Write the journey in ordinary words before deciding how to code it:

What happened What the page knows What the person should see
The text changed There is an unsaved draft The draft, with a Save action
Save was pressed A request is underway Saving, with the draft still visible
The service confirmed the save This version was accepted Saved
The service explicitly rejected it This attempt was not accepted The reason and a way to correct or recover
No answer arrived in time The outcome is unknown Could not confirm the save, with the draft retained

That last row matters. A lost response can hide a successful write. For a notes app, checking the saved record may resolve it. For a payment or a booking, blindly repeating the action can create a second purchase. The later chapter on repeated events explains how to make retries safe.

For this first version, keep the editor unchanged while its save is pending. A more advanced editor can allow further typing, but then it must distinguish the version being saved from the new draft. Otherwise a late response can mark text as saved that was never sent.

These named situations are states. The permitted movements between them form a state machine. We have arrived at that term by following a note; you do not need to start with a diagram full of arrows to see why the distinction matters.

Empty is an answer too

A blank list needs the same care. “You have no notes” means the list was read successfully and came back empty. It does not mean the request failed, is still loading, or requires you to sign in again.

Keep those outcomes separate in the code. A catch block that substitutes an empty list turns a service failure into an apparently valid answer. The person may begin recreating work that never disappeared.

I keep a related distinction in lulumelon: a failed model request is recorded as a failure, rather than as an answer in which a brand was not mentioned. The screened report has a test for a round with no readable answers, so an empty result is explained where the names would otherwise appear. The question is the same even though the product is different: did we observe nothing, or did we fail to observe?

Give the person a way back

If a title is missing, put the explanation beside the title field. If the service is unavailable, say that; changing the title will not repair the service. Preserve the entered text when showing either problem. This distinction between input errors and service problems, and keeping entered answers intact, is also part of the GOV.UK error-message guidance.

A message that vanishes before someone can read it is a poor home for an unresolved problem. Keep the recovery action with the affected note. Ordinary save progress can be announced through an existing role="status" region without moving keyboard focus; MDN describes how that status role works. Visible text is still needed. Making a message available to a screen reader does not replace explaining it on the screen.

Rehearse the awkward versions

In a development copy, arrange for the save operation to answer after a delay, explicitly reject a request, and produce no response before the app's deadline. If an agent is helping, ask it to add a development-only fake service with those three behaviours. Keep that switch out of the production path and use invented notes.

For each version, write down what you typed, what the screen said, and whether the draft remained. Try pressing Save twice. Then try a successful save and reopen the note. Decide which interactions should be allowed while waiting and check that the interface follows that decision.

Finally, show a successfully empty account and a failed list request side by side. They should tell different stories. A reassuring animation is welcome once it accompanies the right story.