feat(web): reusable flash/notification banner (PRG)
Add a one-shot flash component used across the app — connect success, disconnect, account delete, and registration — instead of per-page ad-hoc markup. setFlash queues a short-lived HttpOnly+SameSite cookie carrying an opaque code; takeFlash consumes it on the next full-page render (not on HTMX fragments). flashBanner maps the code to a styled, role=status banner; the message text lives server-side in flashMessages so the cookie never carries free text and a forged/unknown code renders nothing. Wire it into the list page (the PRG landing spot for connect/registration) and set it on registration and connect-callback success. Styled with the existing design-system tokens; header gains an Account nav link. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,10 @@ templ Layout(title string) {
|
||||
@templ.Raw(styleTag)
|
||||
</head>
|
||||
<body>
|
||||
<header><a href="/" class="brand">Tapir</a></header>
|
||||
<header>
|
||||
<a href="/" class="brand">Tapir</a>
|
||||
<nav class="nav"><a href="/account">Account</a></nav>
|
||||
</header>
|
||||
<main>
|
||||
{ children... }
|
||||
</main>
|
||||
@@ -28,10 +31,23 @@ templ Layout(title string) {
|
||||
</html>
|
||||
}
|
||||
|
||||
// flashBanner renders a one-shot notification for a flash code (connect success/
|
||||
// failure, disconnect, delete, registration). An empty or unknown code renders
|
||||
// nothing, so it is safe to drop into any page unconditionally. Reused across the
|
||||
// app — not per-page ad-hoc markup.
|
||||
templ flashBanner(code string) {
|
||||
if f, ok := flashFor(code); ok {
|
||||
<div class={ "flash", "flash-" + f.Kind } role="status" aria-live="polite">{ f.Message }</div>
|
||||
}
|
||||
}
|
||||
|
||||
// ListPage is the full summary list with the filter form. HTMX swaps only the
|
||||
// #summary-list region; a non-HTMX request renders the whole page.
|
||||
templ ListPage(rows []store.SummaryRow, f Filter) {
|
||||
// #summary-list region; a non-HTMX request renders the whole page. flash carries
|
||||
// a one-shot notification (e.g. "connected", "registered") surfaced on arrival
|
||||
// after a POST→redirect.
|
||||
templ ListPage(rows []store.SummaryRow, f Filter, flash string) {
|
||||
@Layout("Tapir — Summaries") {
|
||||
@flashBanner(flash)
|
||||
@filterForm(f)
|
||||
<div id="summary-list">
|
||||
@summaryList(rows)
|
||||
|
||||
Reference in New Issue
Block a user