[Render Preview] [Feature] Toast (sonner port, Hotwire-native)
Merged
DJ
6mo ago+1895+1895+0123456789012345678901234567890123456789-1-1-0123456789
Summary
https://github.com/user-attachments/assets/299856b7-f1b6-44e0-80dc-947176c8b8ab
Preview
https://web-1-pr-389.onrender.com/ (might not be available all the time)
Description
Hotwire-native port of shadcn/ui's sonner (originally backed by emilkowalski/sonner) implemented as a single Toast component family in RubyUI.
- Two trigger paths. Server-pushed via Turbo Stream
appendinto<turbo-frame id="ruby-ui-toaster">, or client-side viawindow.RubyUI.toast.{success,error,warning,info,loading,dismiss,promise}(registered by the Toaster Stimulus controller on connect). - Full sonner parity: variants (
default/success/error/warning/info/loading), action + cancel buttons, auto-dismiss with hover-pause, stack with expand-on-hover, swipe-to-dismiss (pointer events), promise toasts, configurable position (6), theme/rich-colors hooks, hotkey to focus region,Escapeto dismiss focused, ARIA roles (statusvsalert). - Pure Tailwind utilities — no custom CSS file. Reuses RubyUI design tokens and
tailwindcss-animate. Per-toast offsets via inline CSS variables only. - Rails
flashbridge viaturbo_frame_tag refresh: :morph(jetrockets pattern). - Tests follow the existing
ComponentTestrendering pattern only — no new test category. 175/175 green; standardrb clean.
Files
Gem:
gem/lib/ruby_ui/toast/— Region, Item, Title, Description, Icon, Action, Cancel, Close + 2 Stimulus controllers (toaster_controller.js,toast_controller.js).gem/test/ruby_ui/toast{,_item,_region}_test.rb.gem/lib/generators/ruby_ui/dependencies.yml—toast:entry.
Docs site:
- Mount
RubyUI::ToastRegion.newinapplication_layout.rb. app/views/docs/toast.rb— full docs page (mount, variants, server-pushed, JS API, position, flash bridge).app/controllers/docs/toast_demo_controller.rb— turbo_stream.append endpoints for live demos.app/javascript/controllers/toast_demo_controller.js— Stimulus controller for JS-API buttons (Phlex blocksonclick).- Stimulus index: register
ruby-ui--toastandruby-ui--toaster. - Sidebar entry under "Toast".
Spec & plan
specs/2026-05-08-toast-hotwire-design.mdspecs/2026-05-08-toast-hotwire-plan.md
(These specs are not committed; they're working docs.)
Test plan
-
cd gem && bundle exec rake— 175 runs, 749 assertions, 0 failures, 0 errors. StandardRB clean. - Brought up
docs/.devcontainer(compose updated for monorepo layout: mounts repo at/workspaces/ruby_ui, working_dirdocs, ports3001:3000). -
GET /docs/toast→ 200, region mounted, 6 variant skeletons present. -
POST /docs/toast_demo/success→ 200, returns<turbo-stream action="append" target="ruby-ui-toaster">with valid Toast::Item HTML. - Reviewer — open
http://localhost:3001/docs/toastaftercd docs/.devcontainer && docker compose up -dand verify visually:- Variants buttons spawn correct toast (icon + role).
- Auto-dismiss after ~4s; hover pauses; leave resumes.
- Stack of 3+ collapses; hover expands; leave collapses.
- Swipe (drag) horizontally on a toast > 45px → dismisses; small drag → snaps back.
- Action button click dismisses + emits
ruby-ui:toast:dismiss. - Close X visible on hover.
-
RubyUI.toast.promise(...)from console → loading → success transition. -
Alt+Tfocuses first toast;Escapedismisses focused. - Position prop variants (
:top_right,:top_center, etc.) place region correctly. - Dark mode flips colors via existing tokens.
Notes for reviewer
- The docs site mounts the Region globally; toasts are universal across the docs.
docs/.devcontainer/compose.yamlwas rewired for the monorepo layout (was pointing at the legacy siblingweb/repo). If you use VSCode "Reopen in Container" this should still work.- The gem ships zero new npm dependencies.