English

メニュー

ボタンで開く、操作のメニューです。

実行結果

menu.rs
use hypersig::html::{div, p};
use hypersig::style::pattern::stack;
use hypersig::style::value::rem;
use hypersig::{Page, Signals};
use hypersig_ui::{ButtonSize, ButtonVariant, Menu, MenuItem};
use serde::{Deserialize, Serialize};

#[derive(Signals, Serialize, Deserialize)]
pub struct Project {
    archived: bool,
    status: String,
}

const ACTIONS: Menu<Project> = Menu::new("actions");

pub fn page() -> Page<Project> {
    let archived = Project::archived();
    let status = Project::status();
    let initial = Project {
        archived: false,
        status: String::new(),
    };
    Page::new(
        "プロジェクト",
        initial,
    )
    .child(
        div()
            .css(stack(rem(1)))
            .child(
                div()
                    .child(
                        ACTIONS
                            .trigger(ButtonVariant::Outline, ButtonSize::Default)
                            .text("プロジェクトの操作"),
                    )
                    .child(
                        ACTIONS.menu([
                            MenuItem::new(
                                "名前を変更",
                                status.set("プロジェクトの名前を変更しました。"),
                            ),
                            MenuItem::new(
                                "複製",
                                status.set("プロジェクトを複製しました。"),
                            ),
                            MenuItem::new(
                                "アーカイブ",
                                archived.set(true).then(status.set("プロジェクトをアーカイブしました。")),
                            )
                            .disabled(archived),
                            MenuItem::new(
                                "削除",
                                status.set("プロジェクトを削除しました。"),
                            )
                            .destructive(),
                        ]),
                    ),
            )
            .child(p().attr("role", "status").bind_text(status)),
    )
}

アクセシビリティ

WAI-ARIA menu button パターンに従います。ボタンは aria-haspopup="menu" を、メニューは role="menu" を、各操作は role="menuitem" を持ちます。メニューは popover なので、ブラウザがページの上に重ねて表示し、Escape か外側のクリックで閉じます。メニューは CSS の anchor positioning でボタンの下に置かれ、下に場所がなければボタンの上に移ります。

無効な操作はその位置に残り、矢印キーでは飛ばされます。

キー動作
Enter、Spaceボタンにフォーカスがあるときに押すと、メニューを開いて最初の操作にフォーカスを移します。操作にフォーカスがあるときに押すと、その操作を実行してメニューを閉じます。
上矢印、下矢印前か次の操作に移ります。
Home、End最初か最後の操作に移ります。
Escapeメニューを閉じ、ボタンにフォーカスを戻します。
Tabメニューを閉じます。

API

項目概要
Menu::newid が name のメニュー
triggerメニューを開閉するボタン
menuitems を順に並べたメニュー
MenuItem::newlabel をラベルに持ち、選ばれると run を実行する操作
destructive操作を token::destructive の色で描きます。削除する操作に使います。
disabledwhen が true の間、操作を無効にします。無効な操作は矢印キーで飛ばされます。