Expandable
A component that allows you to expand and collapse content.
Mikael Ainalem
This is a dummy content
use leptos::prelude::*; use leptos_meta::Stylesheet; use crate::components::ui::expandable::{ExpandableContent, ExpandableTransition, ExpandableTrigger}; #[component] pub fn DemoExpandable() -> impl IntoView { view! { <Stylesheet href="/components/expandable.css" /> <ExpandableTrigger class="mx-auto"> <ExpandableTransition> <p>Mikael Ainalem</p> </ExpandableTransition> <ExpandableContent class="bg-pink-200"> <p>"This is a dummy content"</p> </ExpandableContent> </ExpandableTrigger> } }
Installation
You can run either of the following commands:
# cargo install ui-cli --forceui add demo_expandableui add expandable
Update the imports to match your project setup.
Copy and paste the following code into your project:
components/ui/expandable.rs
use icons::X; use leptos::prelude::*; use tw_merge::*; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ✨ FUNCTIONS ✨ */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ #[component] pub fn ExpandableTrigger( #[prop(into, optional)] class: Signal<String>, children: Children, ) -> impl IntoView { let class = Memo::new(move |_| { tw_merge!( "overflow-hidden relative rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 h-[32px] w-[162px] expandableMainWrapper ", class() ) }); view! { <div class=class onclick="this.classList.add('expand')"> {children()} </div> } } #[component] pub fn ExpandableTransition( #[prop(into, optional)] class: Signal<String>, children: Children, ) -> impl IntoView { let class = Memo::new(move |_| { tw_merge!( "absolute transition-opacity duration-200 delay-100 from", class() ) }); view! { <div class=class style="transition-timing-function: cubic-bezier(0.0, 0.0, 0.2, 1);"> <div class="flex flex-row transition-transform duration-300 origin-top-left ease-[cubic-bezier(0.4,0.0,0.2,1)] from-contents"> {children()} </div> </div> } } #[component] pub fn ExpandableContent( #[prop(into, optional)] class: Signal<String>, children: Children, ) -> impl IntoView { let class = Memo::new(move |_| { tw_merge!( "relative w-full bg-muted h-full scale-[0.55] origin-top-left transition-transform duration-300 ease-[cubic-bezier(0.4,0.0,0.2,1)] to-contents", class() ) }); view! { <div class="absolute w-full h-full opacity-0 transition-opacity duration-100 ease-[cubic-bezier(0.4,0.0,1,1)] to"> // * 💁 "to" 👆 <div class=class> <button class="flex absolute top-1 right-1 justify-center items-center" onclick="document.querySelector('.expandableMainWrapper').classList.remove('expand');event.stopPropagation();" > <X class="size-6" /> </button> {children()} </div> </div> } }
Update the imports to match your project setup.
Usage
// Coming soon 🦀