Skip to content
fandhe-frontendcore v0.4.3
GitHub

cta-signup-celebrate

fandhe-frontend-pre-styled-ui の card / field / input / button 部品を合成した、Motion+ sections/cta-sections の signup celebrate に相当する合成例です。Blocks セクションは新規部品を追加するものではなく、既存の Themes/Primitives 部品を組み合わせた実例集であることに注意してください。

本 Demo は静的な表示例であり、<form> 要素を持たず、送信ボタンは type="button" のまま送信先を持ちません。メールアドレスの入力値・完了メッセージはいずれも架空のものであり、実企業名・実クレデンシャル・PII を含みません。送信ボタンに付与している data-fandhe-confetti-trigger と canvas に付与している data-fandhe-confetti-canvas は、fandhe-frontend- wasm-full の confetti feature(既定 on、イシュー #2533 で実装済み)がそのまま消費する既存の opt-in 属性の組であり、本 block では confetti 自体を新規実装せず既存機構を「使う側」として合成しています。本 docs サイトは JS ハイドレーションを一切行わないため、本 Demo ではクリック委譲・confetti の発火は発生しません。代わりに「送信前」カードと「送信完了(celebrate)」カードを静的に併記し、実アプリで両属性が付与されたときの見た目を示します。実際の送信処理・バリデーションは利用者自身の Rust コードで書いてください(docs/policy/intentional-non-adoption.md §3.25 の責務境界: UI コンポーネント層はアプリケーションロジックを内包しません)。

Demo

使用部品

Rust コード

Rust
use fandhe_frontend_core::{div, el, text, Node};
use fandhe_frontend_pre_styled_ui::button::{self, ButtonProps};
use fandhe_frontend_pre_styled_ui::card::{self, CardProps};
use fandhe_frontend_pre_styled_ui::field::{self, FieldOrientation, FieldRootProps};
use fandhe_frontend_pre_styled_ui::icon::{icon, IconProps};
use fandhe_frontend_pre_styled_ui::input::{self, FieldIds, FieldProps, InputProps};
use fandhe_frontend_pre_styled_ui::Size;

/// confetti 発火対象 canvas の `id`(`data-fandhe-confetti-trigger` の値と
/// 一致させる、モジュール doc「confetti の使用」節参照)。
const CANVAS_ID: &str = "cta-signup-celebrate-canvas";

/// 自作のチェックマークアイコン(著作物を複製しない、`signup_05`/
/// `sidebar_03` の `geo_icon` と同型)。
fn checkmark_icon() -> Node {
    icon(
        &IconProps {
            size: Size::Lg,
            ..IconProps::default()
        },
        vec![("data-blocks-cta-signup-celebrate-check", "")],
        vec![el(
            "path",
            vec![
                ("d", "M20 6L9 17l-5-5"),
                ("fill", "none"),
                ("stroke", "currentColor"),
                ("stroke-width", "2"),
                ("stroke-linecap", "round"),
                ("stroke-linejoin", "round"),
            ],
            vec![],
        )],
    )
}

/// 「送信前」カード(email 入力 + confetti トリガー付き送信ボタン +
/// canvas)。
fn before_submit_card() -> Node {
    let email_field = FieldProps {
        id: "blocks-cta-signup-celebrate-email",
        ids: FieldIds::default(),
        disabled: false,
        invalid: false,
        required: true,
        readonly: false,
        has_helper_text: false,
    };
    let orientation = FieldRootProps {
        orientation: FieldOrientation::Vertical,
    };

    card::root(
        CardProps::default(),
        vec![("data-blocks-cta-signup-celebrate-card", "")],
        vec![
            card::header(
                vec![],
                vec![
                    card::title(vec![], vec![text("Get notified at launch")]),
                    card::description(
                        vec![],
                        vec![text("We will only email you once, when we ship.")],
                    ),
                ],
            ),
            card::body(
                vec![],
                vec![
                    field::root(
                        &orientation,
                        &email_field,
                        vec![("data-blocks-cta-signup-celebrate-field", "")],
                        vec![
                            field::label(&email_field, vec![], vec![text("Email")]),
                            input::input(
                                &InputProps::default(),
                                &email_field,
                                vec![("type", "email"), ("placeholder", "m@example.com")],
                            ),
                        ],
                    ),
                    button::button(
                        &ButtonProps::default(),
                        vec![
                            ("data-blocks-cta-signup-celebrate-submit", ""),
                            ("data-fandhe-confetti-trigger", CANVAS_ID),
                        ],
                        vec![text("Notify me")],
                    ),
                    el(
                        "canvas",
                        vec![
                            ("id", CANVAS_ID),
                            ("data-fandhe-confetti-canvas", ""),
                            ("data-blocks-cta-signup-celebrate-canvas", ""),
                            ("aria-hidden", "true"),
                        ],
                        vec![],
                    ),
                ],
            ),
        ],
    )
}

/// 「送信完了(celebrate)」カード(チェックマーク + 完了メッセージ)。
fn after_submit_card() -> Node {
    card::root(
        CardProps::default(),
        vec![("data-blocks-cta-signup-celebrate-card", "")],
        vec![card::body(
            vec![("data-blocks-cta-signup-celebrate-celebrate", "")],
            vec![
                checkmark_icon(),
                card::title(vec![], vec![text("You're all set!")]),
                card::description(vec![], vec![text("We'll email you the moment we launch.")]),
            ],
        )],
    )
}

/// `cta-signup-celebrate` の Demo 本体。呼び出しごとに同一の `Node` を
/// 返す純関数。
pub fn demo() -> Node {
    div(
        vec![("data-blocks-cta-signup-celebrate-stack", "")],
        vec![
            div(
                vec![("data-blocks-cta-signup-celebrate-caption", "")],
                vec![text("Before submission")],
            ),
            before_submit_card(),
            div(
                vec![("data-blocks-cta-signup-celebrate-caption", "")],
                vec![text("After submission (celebrate)")],
            ),
            after_submit_card(),
        ],
    )
}