Skip to main content

dioxus_bootstrap_css/
head.rs

1use dioxus::prelude::*;
2
3const BOOTSTRAP_CSS: Asset = asset!("/assets/bootstrap.min.css");
4const BOOTSTRAP_ICONS_CSS: Asset = asset!("/assets/bootstrap-icons.min.css");
5
6/// How to load Bootstrap CSS.
7///
8/// Default: `Bundled` — uses the crate's embedded Bootstrap 5.3.3.
9#[derive(Clone, PartialEq, Default)]
10pub enum BootstrapCss {
11    /// Use the crate's bundled Bootstrap 5.3.3 CSS (default, zero config).
12    #[default]
13    Bundled,
14    /// Load from a custom URL (self-hosted, proxy to SSR backend, etc.).
15    ///
16    /// ```rust,ignore
17    /// BootstrapHead { css: BootstrapCss::Url("/static/vendor/bootstrap.min.css".into()) }
18    /// ```
19    Url(String),
20    /// Load from jsDelivr CDN with a specific version.
21    ///
22    /// ```rust,ignore
23    /// BootstrapHead { css: BootstrapCss::Cdn("5.3.3".into()) }
24    /// ```
25    Cdn(String),
26    /// Don't load any CSS — user handles it themselves.
27    None,
28}
29
30/// How to load Bootstrap Icons CSS.
31///
32/// Default: `Bundled` — uses the crate's embedded Bootstrap Icons.
33#[derive(Clone, PartialEq, Default)]
34pub enum BootstrapIcons {
35    /// Use the crate's bundled Bootstrap Icons CSS (default).
36    #[default]
37    Bundled,
38    /// Load from a custom URL.
39    Url(String),
40    /// Don't load icons CSS — user handles it.
41    None,
42}
43
44/// Loads Bootstrap CSS and Bootstrap Icons for your Dioxus app.
45///
46/// Place this at the top of your app, before any Bootstrap components.
47///
48/// # Zero config (default — bundled Bootstrap 5.3.3)
49/// ```rust,ignore
50/// rsx! { BootstrapHead {} }
51/// ```
52///
53/// # Custom CSS URL (migrating from SSR with its own Bootstrap)
54/// ```rust,ignore
55/// rsx! {
56///     BootstrapHead {
57///         css: BootstrapCss::Url("/static/vendor/bootstrap.min.css".into()),
58///         icons: BootstrapIcons::Url("/static/vendor/bootstrap-icons/font/bootstrap-icons.css".into()),
59///     }
60/// }
61/// ```
62///
63/// # CDN with specific version
64/// ```rust,ignore
65/// rsx! { BootstrapHead { css: BootstrapCss::Cdn("5.3.3".into()) } }
66/// ```
67///
68/// # Full control (load CSS yourself)
69/// ```rust,ignore
70/// rsx! {
71///     BootstrapHead { css: BootstrapCss::None, icons: BootstrapIcons::None }
72///     link { rel: "stylesheet", href: "my-custom-bootstrap.css" }
73/// }
74/// ```
75#[derive(Clone, PartialEq, Props)]
76pub struct BootstrapHeadProps {
77    /// How to load Bootstrap CSS. Default: bundled v5.3.3.
78    #[props(default)]
79    pub css: BootstrapCss,
80    /// How to load Bootstrap Icons CSS. Default: bundled.
81    #[props(default)]
82    pub icons: BootstrapIcons,
83}
84
85#[component]
86pub fn BootstrapHead(props: BootstrapHeadProps) -> Element {
87    let css_element = match &props.css {
88        BootstrapCss::Bundled => rsx! {
89            document::Link { rel: "stylesheet", href: BOOTSTRAP_CSS }
90        },
91        BootstrapCss::Url(url) => {
92            let url = url.clone();
93            rsx! { link { rel: "stylesheet", href: "{url}" } }
94        }
95        BootstrapCss::Cdn(version) => {
96            let href = format!(
97                "https://cdn.jsdelivr.net/npm/bootstrap@{version}/dist/css/bootstrap.min.css"
98            );
99            rsx! { link { rel: "stylesheet", href: "{href}" } }
100        }
101        BootstrapCss::None => rsx! {},
102    };
103
104    let icons_element = match &props.icons {
105        BootstrapIcons::Bundled => rsx! {
106            document::Link { rel: "stylesheet", href: BOOTSTRAP_ICONS_CSS }
107        },
108        BootstrapIcons::Url(url) => {
109            let url = url.clone();
110            rsx! { link { rel: "stylesheet", href: "{url}" } }
111        }
112        BootstrapIcons::None => rsx! {},
113    };
114
115    rsx! {
116        {css_element}
117        {icons_element}
118    }
119}