Skip to content

feat(components): add ol-toast and ol-banner web components#12868

Open
lokesh wants to merge 2 commits into
internetarchive:masterfrom
lokesh:banner
Open

feat(components): add ol-toast and ol-banner web components#12868
lokesh wants to merge 2 commits into
internetarchive:masterfrom
lokesh:banner

Conversation

@lokesh
Copy link
Copy Markdown
Collaborator

@lokesh lokesh commented Jun 6, 2026

Part of the notification UI consolidation effort.

Feature: two new Lit web components, demoed on /developers/design only — no production call sites yet.

  • ol-toast + ol-toast-region — Sonner-style stacked toasts. Bottom-center fixed stack; new toasts slide up while older ones scale back behind; hover/focus expands the stack and pauses dismiss timers. showToast() accepts a string, a <template> element, or nodes.
  • ol-banner — callout-style announcement banner with variant (neutral/success/warning/danger) and appearance (outlined/plain), built-in icons matching the toast treatment.

Technical

  • Toast = shadow DOM (JS-instantiated, can't FOUC). Banner = light DOM (server-rendered chrome; styled at first paint via static/css/components/ol-banner.cssol-components.css, with pre-hydration placeholders to avoid layout shift). This decision rule is now documented in docs/ai/web-components.md.
  • Motion is transition-driven (transform/opacity only, prefers-reduced-motion supported). Banners intentionally have no entrance animation.
  • ol-banner is persistence-agnostic: it only fires ol-banner-dismiss. OL-specific plumbing: templates guard rendering on the dismissal cookie, and a site-level listener (js/banner/index.js) POSTs to /hide_banner (also migrated from jQuery to fetch).
  • No runtime string is ever parsed as HTML; toast/banner content comes from attributes (text) or server-rendered markup.
  • i18n: components own no copy except label-close (attribute override pattern); all content arrives translated.

Testing

  1. make lit-components css (or docker compose exec web make lit-components css), restart web.
  2. /developers/design#toast — add toasts; hover the stack to expand (timers stay paused while expanded, even when moving between toasts); check prefers-reduced-motion.
  3. /developers/design#banner — variants/appearances/custom icon; dismiss the cookie-persisted demo, reload (server no longer renders it), reset to restore.

Screenshot

toast-banner.mp4
image image

Stakeholders

@cdrini @mekarpeles

@lokesh lokesh requested a review from Sadashii June 6, 2026 06:49
New Lit components for the notification UI consolidation effort:

- ol-toast + ol-toast-region: Sonner-style stacked toasts (shadow DOM).
  Bottom-center stack, slide-up enter via data-mounted, hover/focus
  expands the stack and pauses dismiss timers, aria-live announcements,
  prefers-reduced-motion support. showToast() helper accepts a string,
  template element, or nodes - never parses runtime strings as HTML.
- ol-banner: callout-style announcement banner (light DOM, ol-button
  pattern) with neutral/success/warning/danger variants and
  outlined/plain appearances. Persistence-agnostic: fires
  ol-banner-dismiss; site glue in js/banner/index.js POSTs /hide_banner;
  templates guard rendering on the dismissal cookie.
- Document shadow-vs-light DOM decision rule in web-components.md.
@lokesh lokesh marked this pull request as ready for review June 6, 2026 07:02
…e; default timeout 4000ms

- resumeTimer() now no-ops while the parent ol-toast-region is expanded,
  so moving the pointer between toasts (mouseleave on the one being left)
  can't restart its timer mid-hover. Region exposes a public 'expanded'
  getter for this.
- Remove the document-level Escape handler: it closed every open toast at
  once and hijacked Escape presses meant for dropdowns/inputs/dialogs.
- Raise the default auto-dismiss timeout from 2500ms to 4000ms.
@Sadashii
Copy link
Copy Markdown
Collaborator

Sadashii commented Jun 6, 2026

Looks beautiful! Definitely a great step in the modernization efforts.

A few observations / suggestions to polish this first-version even more.

From a patron's view:

Stacking of toats with different sizes causes weird overlap:

  • Case 1 (Smaller toast in front, larger toast behind): The larger toast behind extends past the top, which can look a bit awkward:
    image
    image
  • Case 2 (Larger toast in front, smaller toast behind): The larger toast in front completely overlaps and hides the smaller/older toast behind it:
    image
  • Suggestion: We might want to adjust the stack positioning logic so that older notifications are offset appropriately based on height differences, ensuring they are never fully obscured.

Split-second collapse of hovered toasts when dismissing one

  • When hovering over a stack of multiple toasts, clicking "close" on one of them causes the entire list to briefly collapse and then snap back open. The stack should probably stay expanded as long as the user's mouse is still hovering over the notification area.

Font size feels too small

  • For banner, the font size and the colored icons (especially info/warning, while the colors do a great job, icon is difficult) feel too small to see clearly. Same thing with the dismission cross (especially on toast) - it's bounding box is a little too small making dismissing a small task of it's own. Might want to increase it to make the texts/icons/dismiss more prominent and easy.

From a contributor's view:

1. Rename dismiss event reason

  • The ol-toast-close event currently fires with the reasons close-button and dismiss. Having both is slightly confusing since a user click also "dismisses" the toast. Probably rename dismiss to programmatic (or api) to clearly indicate that this was a code-based dismissal.

Side note, Love the icon-custom-slot option for the banner.

@github-actions github-actions Bot added the Needs: Response Issues which require feedback from lead label Jun 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs: Response Issues which require feedback from lead

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants