Skip to main content

fc_dioxus/components/
reasoning.rs

1//! A collapsible reasoning trace, from reasoning.css.
2use crate::{
3    core::{
4        assets,
5        attrs::{component_attributes, FcData, Kind},
6    },
7    prelude::*,
8    theme::use_stylesheets,
9};
10const BEM: Bem = Bem::new("fc-reasoning");
11
12/// A model's reasoning, collapsed behind a summary line. The summary says "Thinking"
13/// while the work is live and "Thought" once it has settled, unless `label` says
14/// otherwise.
15#[component]
16pub fn Reasoning(
17    state: Lifecycle,
18    #[props(default)] label: Option<Element>,
19    /// How long it took or has taken so far.
20    #[props(default)]
21    duration: Option<Element>,
22    #[props(default)] open: bool,
23    #[props(default)] class: Option<String>,
24    #[props(extends = GlobalAttributes)] attributes: Vec<Attribute>,
25    children: Element,
26) -> Element {
27    let mut attributes = component_attributes(
28        attributes,
29        ClassList::new(BEM.block()).extend(class.as_deref()),
30        &["open"],
31    );
32    attributes.extend(
33        FcData {
34            kind: Some(Kind::Reasoning),
35            state: Some(state),
36            ..FcData::default()
37        }
38        .attributes(),
39    );
40    let label = label.unwrap_or_else(|| {
41        if state.is_settled() {
42            rsx! { "Thought" }
43        } else {
44            rsx! { "Thinking" }
45        }
46    });
47    rsx! {
48        if use_stylesheets() { document::Stylesheet { href: assets::COMPONENTS_REASONING_CSS } }
49        details { open, ..attributes,
50            summary { class: BEM.element("summary"),
51                span { class: BEM.element("label"), {label} }
52                if let Some(duration) = duration { span { class: BEM.element("duration"), {duration} } }
53            }
54            div { class: BEM.element("body"), {children} }
55        }
56    }
57}