Pin local widget stylesheets + adopt styled_module!/merge_attributes

Pin local widget stylesheets + adopt styled_module!/merge_attributes

#26 in Riparion/riparion-cms — merged 2026-06-01

Summary

Companion to Riparion/arium#23. Fixes the downstream symptom of locally-installed catalog widgets (dx components add) silently rendering unstyled on SSR and after client-side remounts.

  • Bump arium-dioxus pin to the merged catalog-styling overhaul.
  • For every local widget that uses #[css_module] (alert_dialog, avatar, button, dropdown_menu, input, navbar, select, textarea), declare the Asset explicitly and emit document::Stylesheet { href: X_CSS } inside the widget. Bypasses the css_module macro's OnceLock-based emit (which fires once per process and silently no-ops thereafter, dropping the <link> from <head> on SSR + client remount).
  • New src/components/stylesheets.rs::LocalStylesheets re-declares every local widget's asset and is mounted permanently in App. Mirrors arium_dioxus::ui::AuthStylesheets; keeps the link tags in <head> for the whole session across navigation/auth churn.
  • Adopt the new upstream arium_dioxus::styled_module! macro to collapse the const-asset + struct-css_module pair into one statement.
  • Fix the duplicate-class= bug in navbar (Navbar/NavbarNav/NavbarTrigger/NavbarContent/NavbarItem) and alert_dialog (Root/Title/Description/Actions/Cancel/Action): both forwarded class: AND attributes to their underlying primitives, producing two class= attributes that the HTML parser silently de-duped. Now use merge_attributes to compose into one.
  • Pre-mount Card {} / Button {} in the hidden preload block alongside the existing Input {} / Label {} so every catalog widget the auth screens render has its link tag warm on first paint.

Test plan

  • dx serve (restart, not hot reload — main.rs structural change), hit /login and /account and /admin/posts/new: confirm the LoginPanel form fields, navbar account dropdown, and admin form inputs all render with their catalog chrome (borders, backgrounds, button styling, vertical spacing).
  • Sign in, navigate away, sign out, hit /login again: form should still render styled (the remount path that used to fail).
  • curl -s http://localhost:8080/login | grep -E 'class="[^"]+"[^>]+class=' returns nothing (no duplicate class= attributes).
  • cargo clippy --no-default-features --features server,sqlite -- -D warnings -A clippy::too_many_arguments (passes locally).
  • cargo clippy --no-default-features --features server,postgres -- -D warnings -A clippy::too_many_arguments (passes locally).
  • cargo clippy --no-default-features --features web --target wasm32-unknown-unknown -- -D warnings -A clippy::too_many_arguments -A dead_code (passes locally).

🤖 Generated with Claude Code

Last updated 2026-06-02