English

ナビゲーション

アプリケーションのページの間を移るリンクです。セクションの一覧、パンくずリスト、長い一覧のページ送りがあります。

実行結果

navigation.rs
use hypersig::html::div;
use hypersig::style::Style;
use hypersig::style::pattern::stack;
use hypersig::style::value::{Display, raw, rem};
use hypersig::{Page, Rest, Signals};
use hypersig_ui::{Breadcrumb, NavList, PaginationText, pagination};
use serde::{Deserialize, Serialize};

use crate::doc::{Component, Doc};
use crate::{PAGE, Site};

#[derive(Signals, Serialize, Deserialize)]
pub struct Docs {
    title: String,
}

/// The component pages the pagination steps through.
const PAGES: [Component; 6] = [
    Component::Tabs,
    Component::Accordion,
    Component::Card,
    Component::Separator,
    Component::Navigation,
    Component::DataTable,
];

/// The path of `doc` inside this site, as `PAGE` takes it.
fn at(site: Site, doc: Doc) -> Rest {
    Rest::new(doc.url(site).trim_start_matches('/'))
}

pub fn page() -> Page<Docs> {
    let here = Doc::Components(Component::Navigation);
    let sections = NavList::new(
        "セクション",
        PAGE.url(at(site, here)),
    )
    .item(
        "インストール",
        PAGE,
        at(site, Doc::Components(Component::Installation)),
    )
    .item(
        "ナビゲーション",
        PAGE,
        at(site, here),
    )
    .item(
        "ダイアログ",
        PAGE,
        at(site, Doc::Components(Component::Dialog)),
    );
    let trail = Breadcrumb::new("パンくずリスト")
    .link(
        "コンポーネント",
        PAGE.link_with(&at(site, Doc::ComponentsHome)),
    )
    .current("ナビゲーション");
    let text = PaginationText {
        label: "ページ送り"
            .into(),
        previous: "前へ"
            .into(),
        next: "次へ"
            .into(),
    };
    let pager = pagination(
        5,
        6,
        |page| PAGE.link_with(&at(site, Doc::Components(PAGES[page as usize - 1]))),
        &text,
    );
    let initial = Docs {
        title: here.title(site).into(),
    };
    Page::new(
        "ドキュメント",
        initial,
    )
    .child(
        div()
            .css(
                Style::new()
                    .display(Display::Grid)
                    .grid_template_columns(raw("9rem 1fr"))
                    .gap(rem(1.5)),
            )
            .child(sections)
            .child(div().css(stack(rem(1.5))).child(trail).child(pager)),
    )
}

アクセシビリティ

どれも、受け取ったラベルを名前に持つ <nav> で、中にリンクの一覧を持ちます。そのため、スクリーンリーダーはページのランドマークの 1 つとして一覧に出します。リンクはルートから作った型付きの Link で、訪問者がいるページへのリンクは aria-current="page" を持ちます。

NavList は、Route::url で書いたページ自身の Url をもとに、サーバーで印を決めます。同じパスへのリンクは aria-current="page" を持ち、ページのパスが続きとなるパスへのリンクは aria-current="true" を持ちます。Breadcrumb::current は今のページをテキストとして最後に置き、要素を返すので、そのあとにリンクは続けられません。pagination は最初と最後のページ、今のページの前後のページを表示し、前や次のページがないときはそのリンクを aria-disabled にします。デモのリンクは、このサイトのページにつながります。

API

項目概要
NavList::new<nav> の名前が label で、current のページに置く空の一覧
itemRoute::url と同じ形の引数 args を付けた、route へのリンクを足します。
Breadcrumb::new<nav> の名前が label(たとえば「Breadcrumb」)の空のパンくずリスト
link今のページより上のページへのリンクを、それまでのリンクのあとに足します。
current今のページ text で終わるパンくずリスト
paginationcount ページある一覧の各ページへのリンク。今のページは current
PaginationTextpagination が各部分の名前に使う言葉