impulse_thaw/accordion/
accordion_item.rs1use crate::AccordionInjection;
2use leptos::prelude::*;
3use thaw_components::CSSTransition;
4use thaw_utils::{class_list, mount_style, update, with};
5
6#[component]
7pub fn AccordionItem(
8 #[prop(optional, into)] class: MaybeProp<String>,
9 #[prop(into)]
11 value: Signal<String>,
12 accordion_header: AccordionHeader,
13 children: Children,
14) -> impl IntoView {
15 mount_style("accordion-item", include_str!("./accordion-item.css"));
16 let AccordionInjection {
17 open_items,
18 multiple,
19 collapsible,
20 } = AccordionInjection::expect_context();
21 let is_show_panel = Memo::new(move |_| with!(|open_items, value| open_items.contains(value)));
22
23 let on_click = move |_| {
24 let is_show_panel = is_show_panel.get_untracked();
25 update!(move |open_items| {
26 if is_show_panel {
27 if collapsible {
28 with!(|value| open_items.remove(value));
29 } else if multiple {
30 with!(|value| open_items.remove(value));
31 }
32 } else {
33 if !multiple {
34 open_items.clear();
35 }
36 open_items.insert(value.get_untracked());
37 }
38 });
39 };
40
41 view! {
42 <div class=class_list!["thaw-accordion-item", class]>
43 <div class="thaw-accordion-header">
44 <button
45 class="thaw-accordion-header__button"
46 aria-expanded=move || is_show_panel.get().to_string()
47 type="button"
48 on:click=on_click
49 >
50 <span class="thaw-accordion-header__expand-icon" aria-hidden="true">
51 <svg
52 fill="currentColor"
53 aria-hidden="true"
54 width="1em"
55 height="1em"
56 viewBox="0 0 20 20"
57 style=move || {
58 if is_show_panel.get() {
59 "transform: rotate(90deg)"
60 } else {
61 "transform: rotate(0deg)"
62 }
63 }
64 >
65 <path
66 d="M7.65 4.15c.2-.2.5-.2.7 0l5.49 5.46c.21.22.21.57 0 .78l-5.49 5.46a.5.5 0 0 1-.7-.7L12.8 10 7.65 4.85a.5.5 0 0 1 0-.7Z"
67 fill="currentColor"
68 ></path>
69 </svg>
70 </span>
71 {(accordion_header.children)()}
72 </button>
73 </div>
74 <CSSTransition show=is_show_panel name="thaw-accordion-panel">
75 <div class="thaw-accordion-panel">
76 {children()}
77 </div>
78 </CSSTransition>
79 </div>
80 }
81}
82
83#[slot]
84pub struct AccordionHeader {
85 children: Children,
86}
87
88