Skip to main content
Gelium UI
Blog View source 0.6.5 Theme Gallery
Recipe

Native behavior · Alden · Gelium defaults · Native baseline

Appearance
Menu

· v0.6.5 · MIT License · Source: newsletter.md

Newsletter

Newsletter is a zero-JavaScript subscription form for audience conversion. Use it when a page invites people to subscribe to a newsletter and the whole contract must work without client-side scripting — the server owns the submit, the validation, and the success view. The form is an <aside> styled with the ui-newsletter classes; HTMX is an optional enhancement that swaps only the aside fragment.

Examples

The initial subscribe state, ready for a no-JS POST.

An invalid email re-renders the aside with an inline error, the submitted value preserved, and the input flagged.

A valid address replaces the form entirely with a persistent confirmation.

The specimens above follow the contract the template newsletter.html defines and the data the server example in internal/app/newsletter.go renders.

Guidance

When to use

Use the newsletter when a page invites subscription and the signup must work without JavaScript — a footer aside, a blog sidebar, a landing block. It earns its place when the server can own the whole round-trip: validate, re-render, and confirm.

When not to use

Do not use it for anything beyond a single email subscription: it has one field and one action. Do not rely on client-side validation alone — the 422 contract is the real gate. If the surface is a general contact form, use the Text field and form patterns instead.

Usability

  • The form is a real <form method="post"> with the action URL, so it submits without any script.
  • HTMX is optional and additive: the same POST targets the same URL and swaps only the closest .ui-newsletter fragment.
  • The email input is type="email" with autocomplete="email" and required, so the browser and the server validate together.

Accessibility

  • The aside is labelled by its title via aria-labelledby.
  • The error reuses the inline-alert primitive with role="alert", and the input carries aria-invalid plus aria-describedby pointing at it.
  • The success view is a role="status" paragraph that replaces the form, so the confirmation is announced politely and never vanishes.

See Choose the right control for the cross-component decision.

Anatomy

  • ui-newsletter — the aside: the surface-container background, the theme radius, the border, and a flex column with --ui-newsletter-* tokens.
  • ui-newsletter-title / ui-newsletter-description — the heading and the one-line pitch, using the headline-sm and body-sm typescales.
  • ui-newsletter-form — the POST form with the email field row and the submit button.
  • ui-newsletter-alert — the wrapper for the inline error, rendered only when validation fails.
  • ui-newsletter-field / ui-newsletter-row / ui-newsletter-label / ui-newsletter-input — the field structure: label, flexible input (min 14rem), and the primary submit button in one row.
  • ui-newsletter-success — the persistent confirmation paragraph (role="status") that replaces the form.

Server contract

  • POST + 422 — an invalid email is rejected with status 422 and the X-Gelium-Validation: true header, re-rendering the aside with the inline error and the submitted value preserved.
  • POST → 200 success — a valid email replaces the form with the persistent confirmation.
  • In production the success landing is a POST + 303 redirect to a GET page that re-renders the success view; the example route demonstrates the direct 200 form.

Anti-patterns

  • Do not auto-submit on keystroke: the submit button is always visible and the round-trip is explicit.
  • Do not hide the email field behind a consent checkbox or extra steps — the pattern is one field, one action.
  • Do not dismiss the success view after a timeout: it is persistent until the person navigates.

Checklist

  • The aside is labelled and the form posts to a real action URL.
  • The email input is type="email", autocomplete="email", and required.
  • The 422 path preserves the submitted value and flags the input with aria-invalid and aria-describedby.
  • The success view replaces the form and carries role="status".
  • Nothing requires JavaScript to subscribe.

Accessibility

The whole flow works with no script: the native form submits, the server re-renders the aside with an alert or a confirmation, and every state is announced through the right role (alert for the error, status for the success). The input keeps its label, its autocomplete hint, and its error association, so assistive technology users get the same path as everyone else.