Form-first UI components for Phoenix LiveView (1.1+) on Phoenix 1.8+: rich select, date picker, OTP input, dialogs, menus, tables, toasts and top-layer panels — server-authoritative, viewport-aware, themeable from 12 CSS tokens, with zero third-party JavaScript (one JS import, ~9 KB min+gzip).

A daisyUI replacement you install and manage through mix tasks built on Igniter — including --strip-daisy to remove Phoenix 1.8's bundled daisyUI.

Install

One command — Igniter adds the dep and wires everything (CSS, JS hooks, component imports, flash → Skua toasts, strips the default Phoenix navbar, and scaffolds an editable starter home at /):

mix igniter.install skua                                # existing app
mix igniter.new my_app --with phx.new --install skua    # brand-new app

Skua replaces daisyUI, so the installer removes Phoenix 1.8's bundled daisyUI by default — it deletes the vendored files and bridges daisy's color utilities (bg-base-100, text-error, …) to Skua tokens so existing markup keeps resolving. Keep daisyUI instead with --no-strip-daisy:

mix igniter.install skua --no-strip-daisy

(If your daisyUI config was customized with nested rules, the installer leaves it alone and prints a manual step rather than risk mangling it.)

Without Igniter — add the dep and run the plain Mix task (Igniter is optional; the task still works):

# mix.exs
{:skua, "~> 0.3.0"}
mix deps.get
mix skua.install            # --strip-daisy optional
mix phx.server              # open /

Every step is idempotent — re-run any time after mix deps.update skua. The installer degrades to printed manual steps if your app diverges from the default layout. Local-testing notes in guides/local-testing.md.

Authentication

mix skua.gen.auth runs mix phx.gen.auth and then applies a flow on top. The generated code is yours to edit.

mix skua.gen.auth --auth magic_link    # default — Phoenix's passwordless flow
mix skua.gen.auth --auth otp           # one-time-code login (no passwords)
mix skua.gen.auth --auth password_otp  # password + OTP on one login screen
mix skua.gen.auth --auth custom        # stock phx.gen.auth, nothing added

The otp and password_otp flows ship a production-grade one-time-code login: CSPRNG codes (unique every time, never :rand), SHA-256-hashed storage, single-use under concurrency (FOR UPDATE + transaction), constant-time compare, a session-fixation guard, enumeration-safe responses, and built-in Hammer rate limiting on both the request and verify steps — all tunable in the generated config/config.exs. Code length and expiry are flags:

mix skua.gen.auth --auth otp --otp-length 8 --otp-expiry 5

The magic_link flow adds a Resend production mailer (dev/test keep Swoosh's local mailbox; prod reads RESEND_API_KEY at runtime — see the generated .env.example). Run mix deps.get && mix ecto.migrate afterwards.

Repository layout

  • PLAN.md — the full project plan (architecture decisions, installer spec, strip-daisy design, release pipeline, roadmap).
  • assets/css/skua.css — the token + component CSS layer (the stable artifact).
  • lib/ — components, the install mix tasks (Skua.Install.Patches holds the shared install logic), and supporting modules.
  • _component_defaults/ — reference prototypes the library is being built from (styled-layer HTML demo, LiveView hook/component prototypes, and the skua.sh brand system). Not shipped in the hex package.

License

MIT — see LICENSE.md.