stats-timeline
fandhe-frontend-pre-styled-ui の heading / text / separator の 3 部品のみを合成した、日付付きの出来事(沿革)を横一列に並べる合成例です。Blocks セクションは新規部品を追加するものではなく、既存の Themes/ Primitives 部品を組み合わせた実例集であることに注意してください。
出来事は本リポジトリの架空の沿革として 4 件並べます。日付・題・説明はすべて説明用の架空の内容であり、実企業名・PII・実データは含みません。<form> は使いません(本 block は非対話・静的表示です)。
timeline 部品は縦向きの沿革表示にしか対応していないため、本 block では timeline を使わず、配置は block 固有の CSS と separator の組み合わせで横向きに構成しています。詳細は「原案差分メモ」を参照してください。
Demo
プロジェクトの歩み
日付と出来事はすべて説明用の架空の内容です。
プロジェクト発足
説明用の架空のキックオフです。最小構成の設計をまとめました。
最初の公開版
説明用の架空の初回リリースです。中核機能を公開しました。
利用チームの拡大
説明用の架空の拡大期です。導入チーム数が大きく伸びました。
大型刷新
説明用の架空の刷新です。既定エスケープの製品化を完了しました。
使用部品
Rust コード
Rust
use fandhe_frontend_core::{div, el, text, Node};
use fandhe_frontend_pre_styled_ui::heading::{
heading, HeadingLevel, HeadingProps, HeadingSize, HeadingWeight,
};
use fandhe_frontend_pre_styled_ui::separator::{separator, SeparatorProps};
use fandhe_frontend_pre_styled_ui::text::{self as styled_text, TextProps, TextSize, TextVariant};
/// 出来事 1 件分のダミーデータ(架空、実企業名・PII とは無関係)。
struct EventItem {
/// `<time datetime>` へそのまま使う ISO 8601 表記(年月)。
date_attr: &'static str,
/// 表示用の日付文言。
date_label: &'static str,
title: &'static str,
body: &'static str,
}
/// 出来事一覧(架空、4 件、日付・題とも相異なる)。
const EVENTS: [EventItem; 4] = [
EventItem {
date_attr: "2023-04",
date_label: "2023 年 4 月",
title: "プロジェクト発足",
body: "説明用の架空のキックオフです。最小構成の設計をまとめました。",
},
EventItem {
date_attr: "2023-11",
date_label: "2023 年 11 月",
title: "最初の公開版",
body: "説明用の架空の初回リリースです。中核機能を公開しました。",
},
EventItem {
date_attr: "2024-07",
date_label: "2024 年 7 月",
title: "利用チームの拡大",
body: "説明用の架空の拡大期です。導入チーム数が大きく伸びました。",
},
EventItem {
date_attr: "2025-05",
date_label: "2025 年 5 月",
title: "大型刷新",
body: "説明用の架空の刷新です。既定エスケープの製品化を完了しました。",
},
];
/// 出来事 1 件(`<time>` + ドット/罫線 + 題 + 説明)。
fn event_item(item: &EventItem) -> Node {
el(
"li",
vec![("class", "blocks-stats-timeline-item")],
vec![
el(
"time",
vec![
("datetime", item.date_attr),
("class", "blocks-stats-timeline-date"),
],
vec![text(item.date_label)],
),
div(
vec![("class", "blocks-stats-timeline-marker")],
vec![
el(
"span",
vec![
("aria-hidden", "true"),
("class", "blocks-stats-timeline-dot"),
],
vec![],
),
separator(
&SeparatorProps::default(),
vec![
("aria-hidden", "true"),
("data-blocks-stats-timeline-rule", ""),
],
),
],
),
heading(
HeadingLevel::H4,
&HeadingProps {
size: HeadingSize::Lg,
weight: HeadingWeight::Semibold,
},
vec![],
vec![text(item.title)],
),
styled_text::text(
&TextProps {
size: TextSize::Sm,
variant: TextVariant::Muted,
..TextProps::default()
},
vec![],
vec![text(item.body)],
),
],
)
}
/// `stats-timeline` の Demo 本体(大見出し + リード文 + 出来事 4 件)。
/// 呼び出しごとに同一の `Node` を返す純関数。
pub fn demo() -> Node {
let intro = div(
vec![("class", "blocks-stats-timeline-intro")],
vec![
heading(
HeadingLevel::H3,
&HeadingProps {
size: HeadingSize::Xl3,
weight: HeadingWeight::Bold,
},
vec![],
vec![text("プロジェクトの歩み")],
),
styled_text::text(
&TextProps {
size: TextSize::Lg,
variant: TextVariant::Muted,
..TextProps::default()
},
vec![],
vec![text("日付と出来事はすべて説明用の架空の内容です。")],
),
],
);
let list = el(
"ol",
vec![("class", "blocks-stats-timeline-list"), ("role", "list")],
EVENTS.iter().map(event_item).collect(),
);
div(
vec![("class", "blocks-stats-timeline-layout")],
vec![intro, list],
)
}原案差分メモ
- R1303(日付付きの沿革を横一列に並べる): 参照元は縦向きのタイムラインでしたが、
fandhe-frontend-pre-styled-ui::timelineは縦向きにしか対応していません。本 block ではtimelineを使わず、ol(時系列のためリスト意味論にolを使用)と block 固有の配置 CSS +separatorの組み合わせで、要求どおりの横向き配置(lg以上で 4 列)を独自に構成しました。 - ドット・罫線の実現手段: ドットは装飾のみのため
aria-hidden="true"を付けた<span>を CSS の円(border-radius: var(--fandhe-radius-full))として描いています。罫線はseparatorの既定(Horizontal/Solid)をそのまま使い、flex: 1 1 autoで残り幅いっぱいへ伸ばしています。 - 狭幅時の畳み方:
lg(64rem)以上は横 1 列(4 列)、sm(40rem)以上lg未満は 2 列、sm未満は縦 1 列(1 列)に畳みます。 - 参照元の文言・配色・装飾・アイコンは持ち込んでいません。日付・出来事はすべて架空のものです。