Skip to main content

fc_dioxus/components/
suggestion.rs

1//! Suggested prompts and follow-ups, from suggestion.css.
2use crate::{
3    core::{
4        assets,
5        attrs::{availability_attributes, component_attributes},
6    },
7    prelude::*,
8    theme::use_stylesheets,
9};
10const LIST: Bem = Bem::new("fc-suggestions");
11const ITEM: Bem = Bem::new("fc-suggestion");
12fc_modifier! { enum ListLayout for LIST { Row => None, Grid => "grid" } }
13fc_modifier! { enum ItemShape for ITEM { Card => None, Pill => "pill" } }
14
15/// A named list of [`Suggestion`]s: cards in a grid, or a row of pills.
16#[component]
17pub fn Suggestions(
18    label: AccessibleName,
19    #[props(default)] grid: bool,
20    #[props(default)] class: Option<String>,
21    #[props(extends = GlobalAttributes)] attributes: Vec<Attribute>,
22    children: Element,
23) -> Element {
24    let attributes = component_attributes(
25        attributes,
26        ClassList::new(LIST.block())
27            .with_modifier(
28                LIST,
29                if grid {
30                    ListLayout::Grid
31                } else {
32                    ListLayout::Row
33                },
34            )
35            .extend(class.as_deref()),
36        &["aria-label"],
37    );
38    rsx! {
39        if use_stylesheets() { document::Stylesheet { href: assets::COMPONENTS_SUGGESTION_CSS } }
40        ul { aria_label: label.to_string(), ..attributes, {children} }
41    }
42}
43
44/// One suggestion: a title and optional hint as a card, or plain text as a pill.
45#[component]
46pub fn Suggestion(
47    #[props(default)] pill: bool,
48    #[props(default)] hint: Option<Element>,
49    #[props(default)] availability: Availability,
50    #[props(default)] onclick: Option<EventHandler<MouseEvent>>,
51    children: Element,
52) -> Element {
53    let class = ClassList::new(ITEM.block())
54        .with_modifier(
55            ITEM,
56            if pill {
57                ItemShape::Pill
58            } else {
59                ItemShape::Card
60            },
61        )
62        .to_string();
63    let onclick = availability.guard(onclick);
64    let state = availability_attributes(&availability);
65    rsx! {
66        li {
67            button { r#type: "button", class,
68                onclick: move |event| if let Some(onclick) = onclick { onclick.call(event); },
69                ..state,
70                if pill { {children} } else {
71                    span { class: ITEM.element("title"), {children} }
72                    if let Some(hint) = hint { span { class: ITEM.element("hint"), {hint} } }
73                }
74            }
75        }
76    }
77}