use dioxus::prelude::*;
use dioxus_free_icons::{Icon, icons::ld_icons::*};
use crate::components::{DocNodeRenderer, MdxIcon};
use crate::parser::{AccordionGroupNode, DocNode};
#[derive(Props, Clone, PartialEq)]
pub struct DocAccordionGroupProps {
pub group: AccordionGroupNode,
}
#[component]
pub fn DocAccordionGroup(props: DocAccordionGroupProps) -> Element {
rsx! {
div { class: "my-6 space-y-3",
for (i, item) in props.group.items.iter().enumerate() {
DocAccordionItem {
key: "{i}",
title: item.title.clone(),
icon: item.icon.clone(),
content: item.content.clone(),
}
}
}
}
}
#[derive(Props, Clone, PartialEq)]
pub struct DocAccordionItemProps {
title: String,
icon: Option<String>,
content: Vec<DocNode>,
}
#[component]
pub fn DocAccordionItem(props: DocAccordionItemProps) -> Element {
let mut expanded = use_signal(|| false);
rsx! {
div {
class: if expanded() {
"border border-base-content/15 rounded-lg overflow-hidden shadow-sm"
} else {
"border border-base-content/10 rounded-lg overflow-hidden hover:border-base-content/20 transition-colors"
},
button {
class: if expanded() {
"w-full flex items-center gap-3 px-4 py-3.5 text-left bg-base-200/50 transition-colors"
} else {
"w-full flex items-center gap-3 px-4 py-3.5 text-left hover:bg-base-200/30 transition-colors"
},
onclick: move |_| expanded.set(!expanded()),
if let Some(icon) = &props.icon {
div { class: "text-primary shrink-0",
MdxIcon { name: icon.clone(), class: "size-5".to_string() }
}
}
span { class: "flex-1 font-medium text-base-content",
"{props.title}"
}
Icon {
class: if expanded() {
"size-5 text-base-content/50 transform rotate-180 transition-transform duration-200"
} else {
"size-5 text-base-content/50 transition-transform duration-200"
},
icon: LdChevronDown
}
}
if expanded() {
div { class: "px-4 pb-4 border-t border-base-content/10 bg-base-200/30 accordion-content-enter",
AccordionContent { content: props.content.clone() }
}
}
}
}
}
#[derive(Props, Clone, PartialEq)]
struct AccordionContentProps {
content: Vec<DocNode>,
}
#[component]
fn AccordionContent(props: AccordionContentProps) -> Element {
rsx! {
div { class: "prose prose-sm max-w-none pt-4",
for (i, node) in props.content.iter().enumerate() {
DocNodeRenderer { key: "{i}", node: node.clone() }
}
}
}
}