Feedback
Seven components answer one question — where does the message go. Choosing wrong is why interfaces feel unresponsive rather than look wrong.
What it solves
Every message an interface shows is an answer to «what just happened, and does it concern me?». The hard part is not writing the text — it is putting it where the person is already looking, at the moment they are asking.
Seven components cover this, and they are not interchangeable. Each one answers a different question, and the library states the condition for each:
- The message belongs to a place on the page —
GrAlert. It stays until the situation changes, because the situation is still there. - An action has finished —
GrToaster. It appears, is read, and leaves; nothing on the page has changed shape. - A request failed —
GrResponseErrorBanner. It takes the raw error and turns statuses, validation payloads and network failures into a title, a message and a retry — without the page knowing what kind of request it was. - The list is empty from the start —
GrEmptyState. Not an error: a place that has not been filled yet, and a suggestion of what to do about it. - The content is not there yet —
GrSkeleton. The shape arrives before the data, so the page does not jump when the data does. - The content is there and updating —
GrLoading. Different from the skeleton: there is something to look at, and it must not disappear. - The share done is known —
GrProgressBar. Only when it really is known; a bar that guesses is a lie with a number in it.
Anatomy
Feedback has three properties, and every message has all three whether you chose them or not.
Place. Attached to the thing it is about, or floating above the page. The
first is GrAlert and the error inside a field; the second is GrToaster.
A message about a specific field that floats is a message the person has to
match up themselves.
Lifetime. Until dismissed, until the situation changes, or a few seconds. The rule is simple: a message that requires action lives until the action happens. A toast that carries the only way to undo something is a trap with a timer.
Weight. Colour, icon and wording say how bad it is. Three levels are enough — neutral, warning, error. A fourth one is invented by teams who used «error» for everything and then needed something louder.
Example
Do and don’t
Do — Toast for what has finished, alert for what is still true
«Saved» is over the moment it is read — a toast. «This project is read-only» is true until something changes — an alert on the page. The question is not importance but duration.
Don’t — Toast for anything that needs a decision
A message that disappears on a timer cannot carry the only «undo». The person who looked away has lost the option and does not know it existed. If a decision is needed, the message stays until it is made.
Do — Skeleton when there is nothing, spinner when there is
GrSkeleton reserves the shape before the data arrives, so nothing jumps when it
does. GrLoading says an existing block is refreshing — the content stays
readable while it happens.
Don’t — A spinner in place of the whole page
Replacing content with a spinner throws away what the person was reading and tells them nothing about what is coming. They cannot tell a slow page from a broken one, because both look like a circle.
Do — Say what to do next, especially when empty
An empty list is a question, not a failure: «no invoices yet» plus the button
that creates one. GrEmptyState exists because the first screen of a new account
is the most common screen in any product and the least designed.
Don’t — «Something went wrong»
It says nothing and offers nothing. The server sent a status, and often a reason;
GrResponseErrorBanner reads them. If the reason truly is unknown, say what the
person can do — retry, or reach support — and leave the honest sentence short.
Accessibility
A message that appears must be announced. A toast that fades in and out without a live region is invisible to a screen reader: the action completed and nothing said so.
Urgency is a property of the message, not of the colour. Assertive announcements interrupt whatever is being read — right for an error that blocks work, wrong for «saved». Interrupting a person mid-sentence to tell them things are fine is worse than staying quiet.
Loading has to be perceivable without motion. An animated spinner is nothing
to a person with animation disabled, and prefers-reduced-motion is not rare.
The text and the reserved space carry the meaning; the animation repeats it.
Timing is the part no component decides for you. A toast that lives four seconds is unreadable for someone who reads slowly, and there is no correct number — which is why anything that matters must not depend on one.
Components in this pattern
The list is built from frontmatter, not from links in the prose: renaming a slug does not lose it.
GrAlertfeedbackGrToasterfeedbackGrEmptyStatefeedbackGrSkeletonfeedbackGrLoadingfeedbackGrProgressBarfeedbackGrResponseErrorBannerfeedback
Keyboard
Contracts come from the library. The pattern does not restate them — it points at them.
GrToasterComponent contract