日本語

Installation

hypersig_ui is a set of components that look like shadcn/ui and take their behavior from the browser's native elements and the WAI-ARIA Authoring Practices.

Add the crate

Add it next to hypersig:

Cargo.toml
[dependencies]
hypersig = "0.2"
hypersig_ui = "0.2"

Add the theme to the page

Add hypersig_ui::global() and hypersig_ui::theme() to the page once. global is a small reset with the font and the page colors, and theme switches the color tokens to their dark values for a visitor whose system prefers dark.

use hypersig::{Page, Signals};
use hypersig_ui::{ButtonSize, ButtonVariant, TextField, button, card, card_content};
use serde::{Deserialize, Serialize};

#[derive(Signals, Serialize, Deserialize)]
struct Signup {
    name: String,
}

let html = Page::new("Sign up", Signup { name: String::new() })
    .global(hypersig_ui::global())
    .theme(hypersig_ui::theme())
    .child(
        card().child(
            card_content()
                .child(TextField::new("Name", Signup::name()))
                .child(button(ButtonVariant::Default, ButtonSize::Default).text("Continue")),
        ),
    )
    .render();
assert!(html.contains(r#"for="ui-name-input""#));

How the components are built

  • Each component is a function or a small builder that returns an El<S>, so it takes handlers, styles, and children like any other element.
  • The behavior a screen reader and a keyboard depend on comes from the browser where the browser has it: a native <button>, <input>, <select>, <details>, <dialog>, or popover. Where it does not, the component follows the WAI-ARIA Authoring Practices, with keyboard handling from El::roving_focus and El::active_descendant.
  • The ids that tie a label to its control, or a tab to its panel, are derived from the signal the component is bound to. A dialog, a menu, a tooltip, and a combobox keep their names in a const handle that their parts share. A name that cannot be used in an id is a compile error.
  • The colors follow shadcn/ui's zinc theme. Three values differ, to meet WCAG 2.2 AA: a control's border has 3:1 contrast or more, secondary text keeps 4.5:1 on the muted background, and focus is a solid outline, which forced-colors mode still draws.

The demos on these pages run in frames on this static site, so they use signals alone. The ui example in the repository puts every component on one page with a server, and its end-to-end test drives them with the keyboard.