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///
76/// # Embedded in a host that already loads Bootstrap
77///
78/// When your app renders inside a host page that already includes Bootstrap
79/// (for example an outer shell), set both to `None` so it is not loaded twice:
80/// ```rust,ignore
81/// rsx! { BootstrapHead { css: BootstrapCss::None, icons: BootstrapIcons::None } }
82/// ```
83#[derive(Clone, PartialEq, Props)]
84pub struct BootstrapHeadProps {
85    /// How to load Bootstrap CSS. Default: bundled v5.3.3.
86    #[props(default)]
87    pub css: BootstrapCss,
88    /// How to load Bootstrap Icons CSS. Default: bundled.
89    #[props(default)]
90    pub icons: BootstrapIcons,
91}
92
93#[component]
94pub fn BootstrapHead(props: BootstrapHeadProps) -> Element {
95    let css_element = match &props.css {
96        BootstrapCss::Bundled => rsx! {
97            document::Link { rel: "stylesheet", href: BOOTSTRAP_CSS }
98        },
99        BootstrapCss::Url(url) => {
100            let url = url.clone();
101            rsx! { link { rel: "stylesheet", href: "{url}" } }
102        }
103        BootstrapCss::Cdn(version) => {
104            let href = format!(
105                "https://cdn.jsdelivr.net/npm/bootstrap@{version}/dist/css/bootstrap.min.css"
106            );
107            rsx! { link { rel: "stylesheet", href: "{href}" } }
108        }
109        BootstrapCss::None => rsx! {},
110    };
111
112    let icons_element = match &props.icons {
113        BootstrapIcons::Bundled => rsx! {
114            document::Link { rel: "stylesheet", href: BOOTSTRAP_ICONS_CSS }
115        },
116        BootstrapIcons::Url(url) => {
117            let url = url.clone();
118            rsx! { link { rel: "stylesheet", href: "{url}" } }
119        }
120        BootstrapIcons::None => rsx! {},
121    };
122
123    rsx! {
124        {css_element}
125        {icons_element}
126    }
127}