Skip to content

Sonner: replace the JS runtime with a pure Rust/Leptos toast system#33

Open
krishpranav wants to merge 4 commits intorust-ui:mainfrom
krishpranav:feat/issue-29-sonner-rust-port
Open

Sonner: replace the JS runtime with a pure Rust/Leptos toast system#33
krishpranav wants to merge 4 commits intorust-ui:mainfrom
krishpranav:feat/issue-29-sonner-rust-port

Conversation

@krishpranav
Copy link
Copy Markdown
Contributor

Description:

The Sonner docs were still hanging off a bundled JS runtime and lazy loader.
This patch moves the toast state machine, rendering, timers, stacking, and interaction flow into Rust/Leptos and cleans up the demo wiring around it.

What changed:

  • Replaced the Sonner JS runtime with a Rust/Leptos implementation in app_crates/registry/src/ui/sonner.rs
  • Removed Sonner asset loading from app/src/shell.rs
  • Deleted public/components/sonner.js, sonner.min.js, sonner.css, and lazy_load_sonner.js
  • Added reactive toast context, Rust click handlers, auto-dismiss timers, swipe dismissal, stacking, and variant handling
  • Updated the Sonner demos so the default, positions, and variants previews render against the Rust implementation directly
  • Added stable demo preview selectors and tightened the Sonner Playwright page objects around those demos
  • Refreshed the Sonner registry markdown snapshots

Validation:

cargo build
cargo clippy -- -D warnings
cd e2e && PORT=3000 npx playwright test tests/components/sonner.spec.ts --workers=1 --grep "Loading variant should NOT have duration track"
cd e2e && PORT=3000 npx playwright test tests/components/sonner.spec.ts --workers=1 --grep "BOTTOM position: stacked toasts should expand UPWARD on hover|all toasts should have scale\\(1\\) when expanded|progress bar should resume after mouse leave"
cd e2e && PORT=3000 npx playwright test tests/components/sonner.spec.ts --workers=1 --grep "Sonner Positions Page"

The long full-file Playwright run against tests/components/sonner.spec.ts is still unstable in this local runner after extended sequential execution, but the Rust implementation, demo wiring, and the targeted Sonner slices above pass cleanly.

Fixes #29

max-wells and others added 4 commits April 22, 2026 19:02
…ions to bust poisoned cache

add_cache_headers was applying long cache headers to SSR HTML fallback responses
when static files were temporarily missing during rebuild, causing browsers to cache
HTML as JS for up to 7 days. Guard added to skip caching on text/html responses.
Remove sonner.js, sonner.min.js, sonner.css, and lazy_load_sonner.js
entirely. Toast state, auto-dismiss timers, stacking, and position
logic now live in a RwSignal<Vec<ToastData>> provided via Leptos
context.

SonnerTrigger no longer reads data-* attributes on click — it calls
show_toast() directly. SonnerToaster renders toasts as Leptos
components with CSS-only enter/exit animations. No JS runtime
dependency remains in this component.

Fixes rust-ui#29
@krishpranav krishpranav force-pushed the feat/issue-29-sonner-rust-port branch from a27dbde to d35d843 Compare April 22, 2026 13:33
Copy link
Copy Markdown
Contributor

@max-wells max-wells left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@krishpranav Thanks for the effort here — removing the JS files and lazy loader is exactly the right direction. That said, there are several issues that need to be fixed before this can be merged.

Comment thread app/src/app.rs

provide_toaster();
provide_sonner();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two separate toast systems now coexist. The issue explicitly asked to use toast_custom as the foundation rather than starting from scratch. Instead, this PR adds a brand-new SonnerContext / provide_sonner() running in parallel with the existing provide_toaster(). The goal was to consolidate — not duplicate. Please audit app_crates/registry/src/ui/toast_custom/ and build on top of it rather than introducing a second context.

@@ -1,19 +1,415 @@
use icons::{FileText, Lock, TriangleAlert, X};
use leptos::prelude::*;
Copy link
Copy Markdown
Contributor

@max-wells max-wells Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong PR, but the work itself is welcome. This Dialog/Drawer content for page_to_fix was requested separately — please extract it into its own dedicated PR so it can be reviewed and merged independently from the Sonner changes.

@@ -1,2 +1,3 @@
pub mod drawer_tofix;
pub mod page_test;
Copy link
Copy Markdown
Contributor

@max-wells max-wells Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong PR. drawer_tofix belongs in the same dedicated PR as the page_to_fix Dialog/Drawer work — not here.

Comment thread e2e/tests/components/_base_page.ts Outdated

/** The demo preview container - all component tests should scope within this */
readonly preview: Locator;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaking change to shared test infrastructure. Removing the preview field from BasePage and converting it to a computed getter changes behavior for every test that inherits from BasePage. This is a non-trivial refactor that should be validated across all component tests — not bundled silently into a Sonner PR. If this change is needed for the Sonner tests, please scope it to a separate PR with a proper audit of the impact on other test files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace sonner.js + lazy loader with a pure Rust toast system

2 participants