notify & shake

Feedback in motion: the g.notify toasts + the g.shake attention shake

Toasts — g.notify and the four shorthands (live)

  • A toast answers "did my action work?": g.success after a save/delete, g.error for system failures, g.warning for business refusals (res.error.code ≥ 1000), g.info for neutral progress news. When to use a toast vs a page alert: UI elements.
  • Errors are sticky by default — they stay until closed; the other types auto-hide after 5s. Per-type defaults in g.notify.defaults.durations, per-call override via duration (0 = sticky).
  • Identical toasts never stack: press g.error twice — the visible one bumps (re-flash; a running countdown restarts) instead of a twin appearing.
  • All four are sugar over g.notify(message, opts)opts takes title, icon (any ri-*), duration, position, dismissible, html, shake (the card below).
  • Around a redirect/reload, pass { nextPage: true } — the toast is queued and shows on the page you land on (try the button above; a shake target only survives as a selector).
  • Hover pauses the auto-hide; errors announce as role="alert".

Attention shake — g.shake(el, opts) (live)

The target panel
Every button below shakes me (or my parts) — watch the glow color follow the type.
  • g.shake pulls the eye to where something happened — the refused card, the blocking panel, the field that failed. It says nothing by itself: pair it with the toast that says what (usually via the toast's shake option, next card).
  • Off-screen targets scroll into view first (smooth, centered) and the shake starts when the scroll lands — try "Far target": it points at the sign-in card below the fold. Opt out per call with scroll: false.
  • el is an element or a CSS selector; opts: type (glow color, error default), duration (1000 ms), shakes (5 cycles), scroll. Defaults mutable via g.shake.defaults.
  • Cleans up completely — classes and inline variables are removed when the effect ends; a re-shake mid-shake restarts fresh.
  • prefers-reduced-motion: no movement (the glow carries the cue), no smooth scroll (instant jump).

One call — the toast says what, the shake says where (live)

Sign in

  • The STANDARD failure pattern is ONE call — the toast's shake option; the framework login page does exactly this:
    g.error(res.error.message, { shake: '.auth-card' });
  • Sign in (fails) = g.error(msg, { shake: card }); Save (refused) = g.warning(msg, { shake: card }) — the glow follows the toast type automatically.
  • The toast is linked: while it is on screen, clicking its body re-scrolls and re-shakes the target. With sticky errors that link stays useful — scroll away, click the toast, and the page takes you back to the problem.
  • The g.outcome buttons run the whole three-outcome envelope check in one line against the live demo endpoints (ping / demo/error / demo/crash):
    const res = await g.fetch('/examples-demo/ping', { hello: 'genus' });
    if (!g.outcome(res, { shake: '#comboCard', success: 'Data received.' })) return;
    !res.successg.error + shake, res.error.codeg.warning + shake, clean data → g.success (no shake) and true back. For forms, former/validator already do all of this.
  • Docs: templates/app/docs/libs/genus.md "Notifications" + "The outcome check" + "Attention shake".