Skip to main content

orbital_base_components/navigation/carousel/
base.rs

1use leptos::html;
2use leptos::prelude::*;
3
4#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
5pub enum CarouselStepperLayout {
6    #[default]
7    Inline,
8    Bottom,
9}
10
11#[component]
12pub fn BaseCarousel(
13    #[prop(optional, into)] class: MaybeProp<String>,
14    children: Children,
15) -> impl IntoView {
16    view! {
17        <div
18            class=move || {
19                let mut parts = vec!["orbital-carousel".to_string()];
20                if let Some(extra) = class.get() {
21                    if !extra.is_empty() {
22                        parts.push(extra);
23                    }
24                }
25                parts.join(" ")
26            }
27            role="region"
28            aria-roledescription="carousel"
29        >
30            {children()}
31        </div>
32    }
33}
34
35#[component]
36pub fn BaseCarouselViewport(
37    #[prop(optional, into)] class: MaybeProp<String>,
38    node_ref: NodeRef<html::Div>,
39    children: Children,
40) -> impl IntoView {
41    view! {
42        <div
43            node_ref=node_ref
44            class=move || {
45                let mut parts = vec!["orbital-carousel__viewport".to_string()];
46                if let Some(extra) = class.get() {
47                    if !extra.is_empty() {
48                        parts.push(extra);
49                    }
50                }
51                parts.join(" ")
52            }
53            role="group"
54            aria-live="polite"
55        >
56            {children()}
57        </div>
58    }
59}
60
61#[component]
62pub fn BaseCarouselSlide(
63    #[prop(optional, into)] class: MaybeProp<String>,
64    index: i32,
65    #[prop(optional, into)] active: Signal<bool>,
66    children: Children,
67) -> impl IntoView {
68    view! {
69        <div
70            class=move || {
71                let mut parts = vec!["orbital-carousel__slide".to_string()];
72                if active.get() {
73                    parts.push("orbital-carousel__slide--active".to_string());
74                }
75                if let Some(extra) = class.get() {
76                    if !extra.is_empty() {
77                        parts.push(extra);
78                    }
79                }
80                parts.join(" ")
81            }
82            role="group"
83            aria-roledescription="slide"
84            aria-label=move || format!("Slide {}", index + 1)
85            aria-hidden=move || (!active.get()).to_string()
86            tabindex=move || if active.get() { "0" } else { "-1" }
87            data-slide-index=index
88        >
89            {children()}
90        </div>
91    }
92}
93
94#[component]
95pub fn BaseCarouselStepper(
96    #[prop(optional, into)] class: MaybeProp<String>,
97    #[prop(optional, into)] layout: Signal<CarouselStepperLayout>,
98    children: Children,
99) -> impl IntoView {
100    view! {
101        <nav
102            class=move || {
103                let mut parts = vec!["orbital-carousel__stepper".to_string()];
104                parts.push(match layout.get() {
105                    CarouselStepperLayout::Inline => "orbital-carousel__stepper--inline",
106                    CarouselStepperLayout::Bottom => "orbital-carousel__stepper--bottom",
107                }.to_string());
108                if let Some(extra) = class.get() {
109                    if !extra.is_empty() {
110                        parts.push(extra);
111                    }
112                }
113                parts.join(" ")
114            }
115            aria-label="Carousel stepper"
116        >
117            {children()}
118        </nav>
119    }
120}