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}