portfolio_leptos/src/app/components/timeline.rs

123 lines
2.8 KiB
Rust

use leptos::*;
use leptos_icons::FaIcon::FaCaretDownSolid;
use leptos_icons::*;
#[component]
pub fn Timeline(
#[prop(default = vec![])] elements: Vec<TimelineElement>,
) -> impl IntoView {
view! {
<div class="timeline">
<ul>
{ elements.collect_view() }
</ul>
</div>
}
}
#[slot]
pub struct TimelineLabel {
children: ChildrenFn,
}
impl IntoView for TimelineLabel {
fn into_view(self) -> View {
let view = view! { <>{ (self.children)() }</> };
view.into_view()
}
}
#[slot]
pub struct TimelineElement {
#[prop(default = vec![])] labels: Vec<TimelineLabel>,
#[prop(default = vec![])] cards: Vec<TimelineCard>,
}
impl IntoView for TimelineElement {
fn into_view(self) -> View {
let view = view! {
<li class="timeline-element">
<div class="timeline-element__category">
{ self.labels.collect_view() }
</div>
<div class="timeline-element__info">
{ self.cards.collect_view() }
</div>
</li>
};
view.into_view()
}
}
#[slot]
pub struct TimelineCardContent {
children: ChildrenFn,
}
impl IntoView for TimelineCardContent {
fn into_view(self) -> View {
let view = view! { <>{ (self.children)() }</> };
view.into_view()
}
}
#[slot]
pub struct TimelineCardTag {
children: ChildrenFn,
}
impl IntoView for TimelineCardTag {
fn into_view(self) -> View {
let view = view! {
<>
{ (self.children)() }
</>
};
view.into_view()
}
}
#[slot]
pub struct TimelineCardSummary {
#[prop(default = vec![])] tags: Vec<TimelineCardTag>,
children: ChildrenFn,
}
impl IntoView for TimelineCardSummary {
fn into_view(self) -> View {
let view = view! {
<>
{ (self.children)() }
{
view! {
<div class="flex flex-wrap gap-2 mt-2">
{ self.tags.collect_view() }
</div>
}
}
</>
};
view.into_view()
}
}
#[slot]
pub struct TimelineCard {
#[prop(default = vec![])] titles: Vec<TimelineCardSummary>,
#[prop(default = vec![])] cards: Vec<TimelineCardContent>,
}
impl IntoView for TimelineCard {
fn into_view(self) -> View {
let view = view! {
<details>
<summary>
{ self.titles.collect_view() }
<i><Icon icon=Icon::from(FaCaretDownSolid) /></i>
</summary>
<div>{ self.cards.collect_view() }</div>
</details>
};
view.into_view()
}
}