Skip to main content

orbital_date_pickers/guides/
custom_components.rs

1//! Custom day and month renderers (DP-29).
2
3use chrono::Datelike;
4use leptos::prelude::*;
5use orbital_core_components::{
6    default_calendar_day, default_calendar_month_button, CalendarDayProps, CalendarMonthButtonProps,
7};
8use orbital_macros::component_doc;
9
10pub fn weekend_day(props: CalendarDayProps) -> AnyView {
11    let is_weekend = matches!(
12        props.date.weekday(),
13        chrono::Weekday::Sat | chrono::Weekday::Sun
14    );
15    if is_weekend {
16        view! {
17            <div class="orb-picker-custom-day orb-picker-custom-day--weekend">
18                {default_calendar_day(props)}
19            </div>
20        }
21        .into_any()
22    } else {
23        default_calendar_day(props).into_any()
24    }
25}
26
27fn short_month_button(props: CalendarMonthButtonProps) -> impl IntoView {
28    view! {
29        <div class="orb-picker-custom-month">
30            {default_calendar_month_button(CalendarMonthButtonProps {
31                label: props.label.chars().next().unwrap_or('?').to_string(),
32                ..props
33            })}
34        </div>
35    }
36}
37
38/// Customize calendar day cells and month navigation buttons with renderer callbacks.
39///
40/// Pass an [`Arc`] renderer to `appearance.day` on [`DateCalendar`](crate::DateCalendar) or
41/// popover [`DatePicker`](orbital_core_components::DatePicker) surfaces. Start from
42/// [`default_calendar_day`] and [`default_calendar_month_button`] to preserve keyboard
43/// behavior and selection styling, then wrap or extend the default output.
44///
45/// # When to use
46///
47/// - Highlighting weekends, holidays, or blackout dates in the grid
48/// - Compact month/year pickers with abbreviated labels
49/// - Product-specific day badges (dots, counts) on calendar cells
50///
51/// # Usage
52///
53/// 1. Define a function matching [`CalendarDayRenderer`](orbital_core_components::CalendarDayRenderer) (or month button equivalent).
54/// 2. Delegate to the default renderer for baseline interaction, then wrap with extra markup or classes.
55/// 3. Assign `Some(Arc::new(your_renderer))` to `appearance.day` on the calendar or date picker.
56///
57/// # Best Practices
58///
59/// ## Do's
60///
61/// * Call [`default_calendar_day`] inside custom renderers so click and aria behavior stays intact
62/// * Keep custom markup inside the cell boundary — avoid overlapping adjacent days
63/// * Use CSS classes on wrappers rather than inline styles for theme compatibility
64///
65/// ## Don'ts
66///
67/// * Do not replace grid cells with non-interactive elements that block day selection
68/// * Do not fork keyboard navigation — extend defaults instead of reimplementing cells
69///
70/// # Renderer reference
71///
72/// | Hook | Description |
73/// |------|-------------|
74/// | `appearance.day` | Custom day cell renderer on [`DateCalendar`](crate::DateCalendar) |
75/// | [`default_calendar_day`] | Baseline day button with selection and disabled states |
76/// | [`default_calendar_month_button`] | Baseline month/year navigation control |
77///
78/// # Examples
79///
80/// ## Custom day cell
81/// Highlight weekend days with a custom day renderer on [`DateCalendar`].
82/// <!-- preview -->
83/// ```rust
84/// use std::sync::Arc;
85/// use orbital_core_components::CalendarDayRenderer;
86/// use crate::preview::{PickerPreviewExample, PickerPreviewKnobs};
87/// use crate::{DateCalendar, DateCalendarAppearance, DateCalendarBind};
88/// use orbital_base_components::OrbitalDateTime;
89/// let value = RwSignal::new(None::<OrbitalDateTime>);
90/// let day: CalendarDayRenderer = Arc::new(crate::weekend_day);
91/// view! {
92///     <PickerPreviewExample data_testid="date-pickers-custom-components-preview">
93///         <PickerPreviewKnobs />
94///         <DateCalendar
95///             bind=value
96///             appearance=DateCalendarAppearance { day: Some(day), ..Default::default() }
97///         />
98///     </PickerPreviewExample>
99/// }
100/// ```
101#[component_doc(
102    category = "Calendar & Time",
103    preview_slug = "date-pickers-custom-components",
104    preview_label = "Custom Components",
105    preview_icon = icondata::AiCalendarOutlined,
106)]
107#[component]
108pub fn DatePickersCustomComponentsGuide() -> impl IntoView {
109    view! { () }
110}