Proa UI

Interactivity

Native controls, data-attribute behavior, action bindings, and rsjs controlled components.

Open Markdown

proa_ui starts with server-rendered markup. Components add interactivity in three layers: native browser behavior, stable data attributes for small client controllers, and rsjs controlled components when the UI needs reactive state.

Native First

Prefer native semantics when they solve the problem:

Native behavior keeps the baseline HTML useful before any client script runs.

Data Attribute Controllers

Interactive primitives expose data hooks for client behavior:

<button data-dialog-trigger>Open</button>
<div data-dialog-content>...</div>
<div data-dropdown-content data-side="bottom" data-align="start">...</div>

Those attributes let small controllers attach behavior without requiring a runtime virtual DOM. Keep selectors stable and component-specific. Do not rely on Tailwind classes as JavaScript selectors.

Action Bindings

Some components accept ActionDataStatic handlers and emit data attributes for the action runtime. Button supports onclick, onblur, and onfocus.

ActionDataStatic comes from proa_actions, which Proa UI does not re-export. Add it alongside the installed crate:

proa_actions = { git = "https://github.com/Proa-Labs/proa.git" }
use proa_actions::ActionDataStatic;
use crate::components::{Button, ButtonType};

const SAVE_ACTION: ActionDataStatic = ActionDataStatic::new("save");

Button {
    button_type: ButtonType::Submit,
    children: Some("Submit"),
    onclick: Some(SAVE_ACTION),
    ..Button::default()
}

The rendered element carries the action identifier in a data-* attribute, which keeps the server-rendered HTML explicit and inspectable.

Reactive Attributes

Components can accept ReactiveAttr<T> when a value may be static or bound to client state. Button uses this for disabled and loading:

use crate::components::Button;

Button {
    disabled: true.into(),
    loading: false.into(),
    children: Some("Processing"),
    ..Button::default()
}

Static values render directly. Bound values also emit binding attributes so client code can update the element.

Controlled Components

The rsjs feature, enabled by default, exposes controlled wrappers such as:

Use controlled components when the browser needs to update state without a full page round trip. Use the plain server-rendered components when static HTML or normal form submission is enough.

Hydration Boundary

Keep client behavior close to the component that needs it:

Search

Type at least 2 characters