# Yew‑Bootstrap Component Library – Unoffical & Impure
---
## Table of Contents
| 1 | **Getting Started** | [getting‑started](#getting-started) |
| 2 | **Layout & Grid** | [layout‑grid](#layout‑grid) |
| 3 | **Navigation & Breadcrumbs** | [navigation‑breadcrumbs](#navigation‑breadcrumbs) |
| 4 | **Content & Display Components** | [content‑display](#content‑display) |
| 5 | **Interaction & Overlays** | [interaction‑overlays](#interaction‑overlays) |
| 6 | **Utilities (Spacing, Sizing, Visibility, …)** | [utilities](#utilities) |
| 7 | **Accessibility Guidelines** | [accessibility‑guidelines](#accessibility-guidelines) |
| 8 | **Performance & Best Practices** | [performance‑best‑practices](#performance‑best‑practices) |
| 9 | **Running the Example Apps** | [running‑examples](#running-the-example-apps) |
|10| **Full Component Reference** | [full‑reference](#full‑component‑reference) |
|11| **License** | [license](#license) |
---
## 1️⃣ Getting Started <a name="getting-started"></a>
### 1.1 Prerequisites
| **Rust** | `1.73+` (stable) |
| **cargo** | bundled with Rust |
| **Yew-BS** | `cargo add yew-bs` |
| **trunk** (for running the demo apps) | `0.19+` – `cargo install trunk` |
### 1.2 Adding the crate
**cargo add yew-bs**
```toml
# Cargo.toml
[dependencies]
yew = "0.21"
yew-bs = "0.1.0"
```
All components are re‑exported from `yew_bs::prelude::*`, so import once in each file:
```rust
use yew::prelude::*;
use yew_bs::prelude::*;
```
### 1.3 Minimal “Hello World”
```rust
#[function_component(App)]
fn app() -> Html {
html! {
<Container class="my-5">
<Heading level={HeadingLevel::H1}>{"Yew‑Bootstrap Demo"}</Heading>
<Badge variant={Variant::Primary}>{"Primary badge"}</Badge>
</Container>
}
}
#[wasm_bindgen(start)]
pub fn init_web_app() {
// Initialize logging if you want to
wasm_logger::init(wasm_logger::Config::default());
// Initialize Yew-BS (Bootstrap)
yew_bs::init();
// Mount the app
yew::Renderer::<App>::new().render();
}
```
Compile & serve with **trunk**:
```bash
trunk serve
# open http://localhost:8080
```
### 1.4 Project Structure
The Yew-Bootstrap library is organized into three main directories that serve different purposes in development and documentation:
#### `docs/` Directory
Contains comprehensive markdown documentation for each component, providing:
- Detailed API reference with all props, types, and variants
- Usage examples and code snippets
- Component-specific implementation notes
- Accessibility guidelines per component
Each component has its own `.md` file (e.g., `badge.md`, `navbar.md`, `carousel.md`) for easy reference and maintenance.
#### `examples/` Directory
Houses interactive examples demonstrating component usage:
- Each component gets its own subdirectory with a complete Trunk-based project
- `Cargo.toml` and `Trunk.toml` for build configuration
- `index.html` with Bootstrap CSS/JS and the compiled Wasm bundle
- Minimal Rust source code in `src/lib.rs` showing practical implementation
- Run any example with `cd examples/<component> && trunk serve`
#### `src/` Directory
The core library implementation:
- `components/` – Individual Rust modules for each Bootstrap component
- `assets/` – Bundled Bootstrap 5.3 CSS and JavaScript files
- `lib.rs` – Main library entry point with component exports
- `interop.rs` – JavaScript interop utilities for interactive components
---
## 2️⃣ Layout & Grid <a name="layout-grid"></a>
Bootstrap’s responsive grid is the backbone of any UI. Yew‑Bootstrap offers two parallel approaches:
| **Classic** (`Container` / `Row` / `Col`) | Simple tables, forms, or when you need direct control over the column break‑points. | `Container`, `Row`, `Col` |
| **High‑level** (`Grid` / `GridItem`) | Automatic gutter handling, fluid containers, ordering, offsetting, and a cleaner syntax for complex responsive layouts. | `Grid`, `GridItem` |
### 2.1 Classic Grid
```rust
html! {
<Container>
<Row>
<Col xs={12} md={8}>
<div class="p-3 bg-light border">{"Main area"}</div>
</Col>
<Col xs={12} md={4}>
<div class="p-3 bg-light border">{"Sidebar"}</div>
</Col>
</Row>
</Container>
}
```
| `xs, sm, md, lg, xl, xxl` | `Option<u8>` (1‑12) | `None` | Column width per breakpoint |
| `class` | `Option<AttrValue>` | `None` | Extra CSS classes |
| `node_ref` | `NodeRef` | – | Direct DOM reference (rarely needed) |
### 2.2 High‑Level Grid
```rust
html! {
<Grid fluid={true} gutter={Some(3)}>
<GridItem size={GridSize::Fixed(4)} order={Some(GridOrder::First)} offset={Some(2)}>
<div class="p-3 bg-primary text-white">{"First (ordered)"}</div>
</GridItem>
<GridItem size={GridSize::Auto}>
<div class="p-3 bg-secondary text-white">{"Auto‑sized column"}</div>
</GridItem>
</Grid>
}
```
| `fluid` | `bool` | Full‑width container |
| `breakpoint` | `Option<Breakpoint>` | Becomes fluid at the given breakpoint |
| `gutter / gutter_x / gutter_y` | `Option<u8>` | Global spacing (0‑5) |
| `container_class / row_class` | `Option<AttrValue>` | Additional classes |
| **GridItem props** | | |
| `size` | `Option<GridSize>` | `Auto` or `Fixed(1..12)` for all break‑points |
| `xs … xxl` | `Option<GridSize>` | Override per breakpoint |
| `offset` | `Option<u8>` | Space left of the column (1‑11) |
| `order` | `Option<GridOrder>` | `First`, `Last`, or `Number(0..5)` |
| `class` | `Option<AttrValue>` | Extra CSS classes |
#### 2.2.1 When to Prefer `Grid` over `Col`
* You need **automatic gutter handling** (`g-3`, `gx-2`, …).
* You want **ordering/offset** without extra wrapper classes.
* You’re building **complex responsive layouts** (e.g., 6‑column layout on xl, 4‑column on md).
### 2.3 Aspect Ratio (`Ratio`)
Useful for video embeds, cards, or any media that must keep a fixed aspect ratio.
```rust
html! {
<Ratio ratio={AspectRatio::Ratio16x9}>
<iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ"
title="Demo video"
allowfullscreen={true} />
</Ratio>
}
```
| `ratio` | `AspectRatio` | One of `Ratio1x1`, `Ratio4x3`, `Ratio16x9`, `Ratio21x9` |
| `class` | `Option<AttrValue>` | Extra CSS classes |
| `children` | `Children` | Usually an `<img>` or `<iframe>` |
---
## 3️⃣ Navigation & Breadcrumbs <a name="navigation-breadcrumbs"></a>
### 3.1 Navbar
A fully responsive navigation header with optional dark/light theming, background colours, and sticky/fixed positioning.
```rust
html! {
<Navbar expand={Some(NavbarExpand::Lg)}
bg={Some(NavbarBg::Primary)}
dark={true}
placement={Some(NavbarPlacement::StickyTop)}>
<Container>
<NavbarBrand href="#">{"MyApp"}</NavbarBrand>
<NavbarToggler target="#mainNav"
expanded={!*collapsed}
onclick={toggle_collapse} />
<NavbarCollapse id="mainNav" show={!*collapsed}>
<NavbarNav>
<NavItem>
<NavLink href="#" active={true}>{"Home"}</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">{"Features"}</NavLink>
</NavItem>
<NavItem>
<NavLink href="#" disabled={true}>{"Disabled"}</NavLink>
</NavItem>
</NavbarNav>
</NavbarCollapse>
</Container>
</Navbar>
}
```
| `expand` | `Option<NavbarExpand>` | `None` (always collapsed) | Break‑point where the navbar expands horizontally (`Sm`, `Md`, `Lg`, `Xl`, `Xxl`) |
| `bg` | `Option<NavbarBg>` | `None` | Background colour (`Light`, `Dark`, `Primary`, …) |
| `light / dark` | `bool` | `false` | Switch text colour for contrast |
| `placement` | `Option<NavbarPlacement>` | `None` | `FixedTop`, `FixedBottom`, `StickyTop`, `StickyBottom` |
| `class` | `Option<AttrValue>` | `None` | Extra classes |
#### Sub‑components
| `NavbarBrand` | `href`, `onclick`, `class` | Logo or text that links to home |
| `NavbarNav` | `class` | Wrapper for `NavItem`s |
| `NavbarToggler` | `target`, `expanded`, `onclick` | Hamburger button for mobile |
| `NavbarCollapse` | `id`, `show` | Collapsible menu container |
### 3.2 Nav / Tabs / Pills
`Nav` can be styled as **pills**, **tabs**, **vertical**, **filled**, or **justified**.
```rust
html! {
<Nav pills={true} fill={Some(NavFill::Fill)} class="mb-3">
<NavItem><NavLink href="#" active={true}>{"Active"}</NavLink></NavItem>
<NavItem><NavLink href="#">{"Link"}</NavLink></NavItem>
<NavItem><NavLink href="#" disabled={true}>{"Disabled"}</NavLink></NavItem>
</Nav>
}
```
| `pills` | `bool` | Pill‑style navigation |
| `tabs` | `bool` | Tab‑style navigation |
| `fill` | `Option<NavFill>` | `Fill` – equal width, `Justified` – equal width + justified text |
| `align` | `Option<NavAlign>` | `Start`, `Center`, `End` |
| `orientation` | `Option<NavOrientation>` | `Horizontal` (default) or `Vertical` |
### 3.3 Breadcrumb
Shows the user’s location within a hierarchy.
```rust
let crumbs = vec![
BreadcrumbItem { text: "Home".into(), href: Some("/".into()), active: false },
BreadcrumbItem { text: "Library".into(), href: Some("/library".into()), active: false },
BreadcrumbItem { text: "Data".into(), href: None, active: true }
];
html! { <Breadcrumb items={crumbs} /> }
```
| `items` | `Vec<BreadcrumbItem>` | Ordered list of breadcrumb entries |
| `class` | `Option<AttrValue>` | Extra classes |
| `aria_label` | `Option<AttrValue>` | Defaults to `"breadcrumb"` |
### 3.4 ScrollSpy
Automatically highlights nav items based on scroll position.
```rust
html! {
<Row>
<Col xs={4}>
<ScrollSpyNav variant={Some(ScrollSpyNavVariant::Pills)} class="flex-column">
<ScrollSpyNavItem href="section1">{"Section 1"}</ScrollSpyNavItem>
<ScrollSpyNavItem href="section2">{"Section 2"}</ScrollSpyNavItem>
</ScrollSpyNav>
</Col>
<Col xs={8}>
<ScrollSpyContent>
<ScrollSpySection id="section1"><h4>{"Section 1"}</h4><p>{"Lorem…"}</p></ScrollSpySection>
<ScrollSpySection id="section2"><h4>{"Section 2"}</h4><p>{"Dolor…"}</p></ScrollSpySection>
</ScrollSpyContent>
</Col>
</Row>
}
```
| `variant` | `Option<ScrollSpyNavVariant>` | `Pills`, `Tabs`, or `Underline` |
| `class` | `Option<AttrValue>` | Extra classes (e.g., `position-sticky`) |
| `offset` | `i32` | Pixel offset for when a section is considered “active” |
| `method` | `ScrollMethod` | `Auto`, `Offset`, `Position` – how the active element is calculated |
---
## 4️⃣ Content & Display Components <a name="content-display"></a>
### 4.1 Badges
Small status labels, counters, or “new” tags.
```rust
html! {
<Badge variant={Variant::Success} pill={true}>{"Success Pill"}</Badge>
<Badge variant={Variant::Danger}>{"Error"}</Badge>
}
```
| `variant` | `Variant` | `Primary` |
| `pill` | `bool` | `false` |
| `class` | `Option<AttrValue>` | `None` |
| `children` | `Children` | – |
### 4.2 Buttons & Button Groups
`Button` (not reproduced here) works like Bootstrap’s `<button>` with colour `variant`, size `size`, and optional outline / loading states.
#### 4.2.1 ButtonGroup
```rust
html! {
<ButtonGroup aria_label={"Basic group"}>
<Button variant={Variant::Primary}>{"Left"}</Button>
<Button variant={Variant::Primary}>{"Middle"}</Button>
<Button variant={Variant::Primary}>{"Right"}</Button>
</ButtonGroup>
}
```
| `vertical` | `bool` | `false` |
| `size` | `Option<ButtonGroupSize>` | `None` (`default`) |
| `aria_label` | `Option<AttrValue>` | `None` |
| `class` | `Option<AttrValue>` | `None` |
#### 4.2.2 ButtonToolbar
Wraps several `ButtonGroup`s and adds automatic spacing.
```rust
html! {
<ButtonToolbar aria_label={"Toolbar"}>
<ButtonGroup><Button variant={Variant::Primary}>{"1"}</Button></ButtonGroup>
<ButtonGroup><Button variant={Variant::Secondary}>{"2"}</Button></ButtonGroup>
</ButtonToolbar>
}
```
### 4.3 Images
Boostrap‑styled `<img>` with fluid, thumbnail, rounding, floating, and lazy‑loading support.
```rust
html! {
<Image src="https://picsum.photos/500/300"
alt="Random"
fluid={true}
rounded={Some(ImageRounded::Rounded)}
class="my-3" />
}
```
| `src` | `AttrValue` | URL |
| `alt` | `Option<AttrValue>` | Alt text |
| `fluid` | `bool` | `img-fluid` – scales with parent |
| `thumbnail` | `bool` | `img-thumbnail` |
| `rounded` | `Option<ImageRounded>` | `Circle`, `Rounded`, etc. |
| `float_*` | `bool` | `float-start`, `float-end`, responsive variants (`float_sm_start`, …) |
| `loading` | `Option<ImageLoading>` | `Lazy` or `Eager` |
| `decoding` | `Option<ImageDecoding>` | `Auto`, `Sync`, `Async` |
| `class` | `Option<AttrValue>` | Extra classes |
#### Figure & Figcaption
```rust
html! {
<Figure class="my-4">
<Image src="photo.jpg" alt="A photo" fluid={true} />
<Figcaption>{"This is the caption."}</Figcaption>
</Figure>
}
```
### 4.4 Carousel
A slideshow with optional indicators, controls, captions, auto‑play, pause‑on‑hover, touch support, and programmatic control.
```rust
html! {
<Carousel interval={Some(4000)} ride={true}>
<img src="slide1.jpg" class="d-block w-100" alt="First" />
<img src="slide2.jpg" class="d-block w-100" alt="Second" />
<img src="slide3.jpg" class="d-block w-100" alt="Third" />
</Carousel>
}
```
| `indicators` | `bool` | `true` |
| `controls` | `bool` | `true` |
| `captions` | `bool` | `false` |
| `ride` | `bool` | `true` (auto‑start) |
| `pause` | `bool` | `true` (pause on hover) |
| `wrap` | `bool` | `true` |
| `touch` | `bool` | `true` |
| `interval` | `Option<u32>` | `None` (default 5000 ms) |
| `keyboard` | `bool` | `true` |
| `active_index` | `usize` | `0` |
| `on_slide_change` | `Option<Callback<usize>>` | `None` |
**Advanced usage** – control via state: update `active_index` and set `ride={false}`.
### 4.5 Collapse (Accordions)
Show/hide content with smooth animation.
```rust
html! {
<Button onclick={toggle}>{"Toggle"}</Button>
<Collapse id="demo-collapse" expanded={*is_open}>
<Card><CardBody>{"Hidden content"}</CardBody></Card>
</Collapse>
}
```
| `id` | `AttrValue` | **required** – used for `aria-controls` |
| `expanded` | `bool` | `false` |
| `class` | `Option<AttrValue>` | `None` |
| `node_ref` | `NodeRef` | – |
### 4.6 Offcanvas
Sliding panels that appear from any edge – great for mobile menus, filters, carts, etc.
```rust
html! {
<Button onclick={show_offcanvas}>{"Open Sidebar"}</Button>
<Offcanvas show={*open}
placement={OffcanvasPlacement::End}
backdrop={true}
backdrop_close={true}
on_hidden={hide_offcanvas}>
<OffcanvasHeader>
<OffcanvasTitle>{"Menu"}</OffcanvasTitle>
<CloseButton data_bs_dismiss="offcanvas" aria_label="Close" />
</OffcanvasHeader>
<OffcanvasBody>
<Nav>{/* navigation items */}</Nav>
</OffcanvasBody>
</Offcanvas>
}
```
| `show` | `bool` | `false` |
| `placement` | `OffcanvasPlacement` | `End` |
| `backdrop` | `bool` | `true` |
| `backdrop_close` | `bool` | `true` |
| `keyboard` | `bool` | `true` |
| `scroll` | `bool` | `false` |
| Event callbacks (`on_show`, `on_shown`, `on_hide`, `on_hidden`) | `Option<Callback<()>>` | `None` |
### 4.7 Progress
Indicates completion of a task (single bar or stacked bars).
```rust
html! {
<Progress value={70} variant={Some(Variant::Success)} animation={Some(ProgressAnimation::Both)} />
}
```
| `value` | `Option<u8>` | `None` (use child `ProgressBar`s for stacked) |
| `variant` | `Option<Variant>` | `None` |
| `animation` | `Option<ProgressAnimation>` | `None` |
| `striped` | `bool` | `false` |
| `animated` | `bool` | `false` |
| `height` | `Option<AttrValue>` | `None` (default 1 rem) |
| `children` | `Children` | – (for stacked bars) |
**Stacked example**
```rust
html! {
<Progress>
<ProgressBar value={30} variant={Some(Variant::Success)} />
<ProgressBar value={20} variant={Some(Variant::Warning)} />
<ProgressBar value={50} variant={Some(Variant::Danger)} />
</Progress>
}
```
### 4.8 Pagination
Navigate through large data sets.
```rust
html! {
<Pagination active_page={*page}
total_pages={42}
on_page_change={set_page}
size={Some(Size::Large)}
alignment={Some(PaginationAlignment::Center)}
show_first_last={true}
prev_text={"← Prev".into()}
next_text={"Next →".into()} />
}
```
| `active_page` | `usize` | **required** |
| `total_pages` | `usize` | **required** |
| `on_page_change` | `Callback<usize>` | **required** |
| `size` | `Option<Size>` | `None` |
| `alignment` | `Option<PaginationAlignment>` | `None` |
| `max_page_buttons` | `usize` | `7` |
| `show_first_last` | `bool` | `false` |
| `prev_text / next_text / first_text / last_text` | `AttrValue` | `"Previous"`, `"Next"`, `"First"`, `"Last"` |
| `aria_label` | `AttrValue` | `"Page navigation"` |
### 4.9 Placeholders (Skeleton UI)
Show loading skeletons while data is fetched.
```rust
html! {
<PlaceholderWrapper animation={Some(PlaceholderAnimation::Glow)}>
<Placeholder width={"80%".into()} height={"1rem".into()} variant={"primary".into()} />
<Placeholder width={"60%".into()} height={"1rem".into()} variant={"secondary".into()} />
</PlaceholderWrapper>
}
```
| `size` | `PlaceholderSize` | `ExtraSmall`, `Small`, `Medium` (default), `Large`, `ExtraLarge` |
| `width` / `height` | `Option<AttrValue>` | Custom dimensions (`"200px"`, `"75%"`) |
| `variant` | `Option<AttrValue>` | Background colour (e.g., `"primary"`) |
| `animation` (via `PlaceholderWrapper`) | `Option<PlaceholderAnimation>` | `Glow`, `Wave`, or `None` |
**Pre‑built skeletons**
* `PlaceholderCard` – card layout with avatar, title, content, and actions.
* `PlaceholderTable` – table skeleton with configurable rows/columns.
### 4.10 Toasts
Lightweight, auto‑dismissable notifications.
```rust
html! {
<ToastContainer placement={ToastPlacement::BottomEnd}>
<Toast show={true}
variant={Some(Variant::Success)}
delay={4000}
on_hide={hide_toast}>
<strong class="me-auto">{"Success!"}</strong>
{"Your operation completed."}
</Toast>
</ToastContainer>
}
```
| `show` | `bool` | `true` |
| `variant` | `Option<Variant>` | `None` |
| `delay` | `u32` (ms) | `5000` (0 = no auto‑hide) |
| `dismissible` | `bool` | `true` |
| `on_hide` | `Option<Callback<()>>` | `None` |
| `class` | `Option<AttrValue>` | `None` |
| `placement` | `ToastPlacement` | `TopEnd` |
| `children` | `Children` | – |
| `class` | `Option<AttrValue>` | `None` |
### 4.11 Popovers
Rich overlay with optional HTML content, triggered by click, hover, focus or manually.
```rust
html! {
<Popover title={"User Info".into()}
content={r#"<div class="text-center"><img src="avatar.jpg" class="rounded-circle mb-2" width="64"/><p>John Doe</p></div>"#.into()}
allow_html={true}
placement={PopoverPlacement::Right}
trigger={PopoverTrigger::Hover}>
<img src="avatar-thumb.jpg" class="rounded-circle" alt="User" />
</Popover>
}
```
| `title` | `Option<AttrValue>` | `None` |
| `content` | `Option<AttrValue>` | `None` |
| `placement` | `PopoverPlacement` | `Top` |
| `trigger` | `PopoverTrigger` | `Click` |
| `show` | `bool` | `false` (used only for `Manual`) |
| `allow_html` | `bool` | `false` |
| `animation` | `bool` | `true` |
| `delay` | `Option<u32>` | `None` |
| `class` | `Option<AttrValue>` | `None` |
### 4.12 Tooltips
Simple text‑only overlays, typically on hover or focus.
```rust
html! {
<Tooltip title={"Save changes"} placement={TooltipPlacement::Top}>
<Button variant={Variant::Success}>{"Save"}</Button>
</Tooltip>
}
```
| `title` | `AttrValue` | **required** |
| `placement` | `TooltipPlacement` | `Top` |
| `trigger` | `TooltipTrigger` | `Hover` |
| `show` | `bool` | `false` (only for `Manual`) |
| `class` | `Option<AttrValue>` | `None` |
### 4.13 Text‑Related Components
#### 4.13.1 Heading
Semantic `<h1>`‑`<h6>` with optional display size, colour, alignment, and all text utilities.
```rust
html! {
<Heading level={HeadingLevel::H2}
display={Some(DisplayHeading::D2)}
color={Some(Variant::Info)}
text_align={Some(TextAlign::Center)}
weight={Some(FontWeight::Bold)}>
{"Big Section Title"}
</Heading>
}
```
| `level` | `HeadingLevel` | **required** |
| `display` | `Option<DisplayHeading>` | `None` |
| `lead` | `bool` | `false` |
| `color` | `Option<Variant>` | `None` |
| `text_align` | `Option<TextAlign>` | `None` |
| `weight` | `Option<FontWeight>` | `None` |
| `style` | `Option<FontStyle>` | `None` |
| `transform` | `Option<TextTransform>` | `None` |
| `decoration` | `Option<TextDecoration>` | `None` |
| `wrap` | `Option<TextWrap>` | `None` |
| `truncate` | `bool` | `false` |
| `break_text` | `bool` | `false` |
#### 4.13.2 Paragraph
Same utilities as `Heading` but renders a `<p>`.
```rust
html! {
<Paragraph color={Some(Variant::Dark)} weight={Some(FontWeight::Light)} text_align={Some(TextAlign::Justify)}>
{"Long paragraph with justified alignment and light weight."}
</Paragraph>
}
```
#### 4.13.3 Blockquote
Optional citation footer.
```rust
html! {
<Blockquote footer={html!{<>{"— ", <cite>{"Author"}</cite>}</>}>
{"The only limit to our realization of tomorrow is our doubts of today."}
</Blockquote>
}
```
#### 4.13.4 Text (inline utilities)
Wrap any inline element (`span`, `strong`, `code`, …) and apply colour, weight, transform, decoration, wrapping, truncation, etc.
```rust
html! {
<p>
{"Press "}<Text element={TextElement::Kbd}>{"Ctrl+S"}</Text>{" to save."}
</p>
}
```
| `Span` | default | `<span>` |
| `Strong` | → `<strong>` |
| `Em` | → `<em>` |
| `Code` | → `<code>` |
| `Kbd` | → `<kbd>` |
| `Mark` | → `<mark>` |
| `Del` | → `<del>` |
| `Ins` | → `<ins>` |
| `Sub` / `Sup` | → `<sub>` / `<sup>` |
| `Pre` | → `<pre>` |
---
## 5️⃣ Interaction & Overlays <a name="interaction-overlays"></a>
This section groups components that require user interaction or appear above the main UI.
| **Popover** | Contextual rich overlay (profile card, action menu) | `title`, `content`, `placement`, `trigger`, `allow_html` |
| **Tooltip** | Small hint text (form help, icon description) | `title`, `placement`, `trigger` |
| **Collapse** | Accordion sections, show/hide panels | `id`, `expanded`, `class` |
| **Offcanvas** | Mobile side‑menu, settings panel, cart drawer | `show`, `placement`, `backdrop`, `keyboard` |
| **Toast** | Brief notifications (success, error, info) | `show`, `variant`, `delay`, `placement` (via container) |
| **Spinner** | Loading indicator (inline, centered, small) | `spinner_type`, `variant`, `size`, `centered` |
| **ButtonGroup / Toolbar** | Grouped actions (text editor toolbar, media controls) | `vertical`, `size` |
| **Progress** | Upload/processing status (single or stacked) | `value`, `variant`, `animation` |
| **Carousel** | Slideshows, hero banners, product showcases | `interval`, `ride`, `controls`, `indicators` |
| **Pagination** | Page navigation for tables/lists | `active_page`, `total_pages`, `on_page_change` |
| **Placeholder** | Skeleton UI while loading data | `size`, `width`, `height`, `variant`, `animation` |
**Accessibility Checklist** (applies to all interactive components)
* Ensure a clear **focus state** (`FocusRing` or native outline).
* Provide **ARIA labels** (`aria-label`, `aria-labelledby`) when icons have no text.
* For components that appear/disappear (`Popover`, `Tooltip`, `Offcanvas`, `Toast`), manage **focus trapping** if they become modal‑like (e.g., Offcanvas).
* Use **keyboard triggers** (`Enter`, `Space`, `Esc`) where appropriate (e.g., `PopoverTrigger::Focus`, `Offcanvas` ESC to close).
---
## 6️⃣ Utilities (Spacing, Sizing, Visibility, …) <a name="utilities"></a>
Bootstrap’s utility‑first approach is mirrored in Yew‑Bootstrap with dedicated components that accept enums instead of manual class strings.
### 6.1 Spacing
```rust
html! {
<Spacing margin={Some(MarginSpacing::MY(SpacingSize::Size3))}
padding={Some(PaddingSpacing::PX(SpacingSize::Size2))} />
}
```
| `MarginSpacing::M(size)` | `m-3` |
| `MarginSpacing::MT(size)` | `mt-4` |
| `MarginSpacing::MB(size)` | `mb-2` |
| `MarginSpacing::MS(size)` | `ms-1` |
| `MarginSpacing::ME(size)` | `me-5` |
| `MarginSpacing::MX(size)` | `mx-auto` |
| `MarginSpacing::MY(size)` | `my-3` |
| `PaddingSpacing::P(size)` | `p-3` |
| `PaddingSpacing::PT(size)` | `pt-4` |
| `PaddingSpacing::PX(size)` | `px-2` |
| `PaddingSpacing::PY(size)` | `py-5` |
`SpacingSize` values: `Size0` (0), `Size1` (0.25rem), `Size2` (0.5rem), `Size3` (1rem), `Size4` (1.5rem), `Size5` (3rem), `Auto` (`auto`).
### 6.2 Sizing
```rust
html! {
<Sizing width={Some(Width::W50)} height={Some(Height::H25)} class="bg-light" />
}
```
| `width` | `Width::W25`, `W50`, `W75`, `W100`, `Auto` | `w-25`, `w-50`, … |
| `height` | `Height::H25`, `H50`, `H75`, `H100`, `Auto` | `h-25`, `h-50`, … |
| `max_width` | `MaxWidth::MW100` | `mw-100` |
| `max_height` | `MaxHeight::MH100` | `mh-100` |
| `viewport` | `ViewportSize::VW100`, `VH100` | `vw-100`, `vh-100` |
### 6.3 Visibility
```rust
html! {
<Visibility visibility={Visibility::Invisible}>{"Hidden but takes space"}</Visibility>
}
```
| `Visible` | `visibility: visible` |
| `Invisible` | `visibility: hidden` (space preserved) |
### 6.4 Vertical Align
```rust
html! {
<VerticalAlign align={VerticalAlign::Middle}>
<i class="bi bi-star"></i>
{"Starred"}
</VerticalAlign>
}
```
| `Baseline` | `align-baseline` |
| `Top` | `align-top` |
| `Middle` | `align-middle` |
| `Bottom` | `align-bottom` |
| `TextTop` | `align-text-top` |
| `TextBottom` | `align-text-bottom` |
### 6.5 Focus Ring
```rust
html! {
<FocusRing color={Some(FocusRingColor::Success)}>
<button class="btn btn-outline-success">{"Focus me"}</button>
</FocusRing>
}
```
| `Primary` | `focus-ring-primary` |
| `Success` | `focus-ring-success` |
| `Danger` | `focus-ring-danger` |
| `Info` | `focus-ring-info` |
| `None` (default) | `focus-ring` |
### 6.6 Clearfix
```rust
html! {
<Clearfix>
<div class="float-start">{"Left"}</div>
<div class="float-end">{"Right"}</div>
</Clearfix>
}
```
Adds `clearfix` class (`::after { content:""; display:block; clear:both; }`).
---
## 7️⃣ Accessibility Guidelines <a name="accessibility-guidelines"></a>
| **Badge** | Decorative only – may be ignored by screen readers. | Add `aria-label` if the badge conveys meaning (e.g., `"4 new messages"`). |
| **Button / ButtonGroup** | Must have discernible text or `aria-label`. | Use `<Button aria_label="Close">` when icon‑only. |
| **Navbar / Nav** | Proper landmark roles and ARIA current on active items. | `role="navigation"` added automatically; add `aria-current="page"` manually if needed. |
| **Carousel** | Slides should have `aria-label`/`aria-roledescription="carousel"` and each slide should be reachable via keyboard. | Yew‑Bootstrap adds appropriate attributes; you can override with `aria-label`. |
| **Collapse / Accordion** | Need `aria-controls` on toggler and `aria-expanded` reflecting state. | Example in `Collapse` docs. |
| **Offcanvas** | Should trap focus while open and restore focus on close. | Handled by the component; ensure you don’t nest interactive elements that break focus. |
| **Popover / Tooltip** | Must be attached via `aria-describedby` on the trigger; should disappear on `Esc`. | The library attaches IDs automatically. |
| **Toast** | Should have `role="alert"` and `aria-live="assertive"` for urgent messages. | Default implementation includes these. |
| **Modal (if you use a separate Modal component)** | Needs `role="dialog"` and `aria-modal="true"`. | Follow the Modal documentation (not included in this merged file). |
| **Placeholder** | Content is decorative – hide from screen readers. | `aria-hidden="true"` applied automatically. |
| **Visibility** | `visibility:hidden` still exposed to AT. Use `aria-hidden="true"` when you truly want it hidden. | Add attribute manually if needed. |
| **FocusRing** | Visual focus indicator for custom controls. | Ensure you include `tabindex` on non‑native focusable elements. |
---
## 8️⃣ Performance & Best Practices <a name="performance-best-practices"></a>
| **State Management** | Keep component state as small as possible. Use `use_state` for simple booleans, `use_reducer` for complex UI (e.g., pagination + filters). |
| **Lazy Loading** | Use `ImageLoading::Lazy` for off‑screen images, `Placeholder` while fetching data, and `Carousel` with `ride={false}` for manual control. |
| **Avoid Over‑Rendering** | When showing/hiding large sections, prefer conditional rendering (`if show { … }`) rather than merely toggling `Visibility` unless you need the layout to stay stable. |
| **Throttle ScrollSpy / Scroll Events** | `ScrollSpy` uses `IntersectionObserver` by default (efficient). If you resort to `ScrollMethod::Offset`, debounce updates. |
| **Z‑Index Management** | Stick to Bootstrap’s predefined values (`z-0` … `z-3`, `z-n1`) to avoid unexpected stacking conflicts. |
| **Animations** | Use CSS‑only animations (`animate` props) – they are cheap. Avoid heavy JavaScript timers for UI animation unless necessary. |
| **Component Size** | If you only need a subset of components, enable Cargo features (`default-features = false`, then `features = ["badge","navbar",...]`). |
| **Responsive Images** | Combine `fluid` with explicit `width`/`height` attributes to prevent CLS (Cumulative Layout Shift). |
| **Testing for Reduced Motion** | Respect `prefers-reduced-motion` when using `animation` flags (`Glow`, `Wave`). |
| **Server‑Side Rendering (SSR)** | All components render to static HTML; avoid using browser‑only APIs (e.g., `window`) during the first render. |
---
## 9️⃣ Running the Example Apps <a name="running-examples"></a>
Each component ships with a minimal example under `examples/<component_name>`. To explore them:
```bash
# Clone the repo
git clone https://github.com/cyber-boost/yew-bs.git
cd yew-bs
# Install trunk (if not already)
cargo install trunk
# Run a specific example (e.g., badge)
cd examples/badge
trunk serve
# Open http://localhost:8080 in your browser
```
Replace `badge` with any of:
```
accordion button-group breadcrumb carousel clearfix close-button
col collapse color-background colored-links focus-ring
grid icon-link image nav navbar
offcanvas pagination placeholders popovers position
progress ratio scrollspy sizing spacing
spinners table text toasts tooltips
typography vertical-align visibility z-index
```
All examples share a common `index.html` that loads the compiled Wasm bundle; you can edit the source file to experiment.
---
## 🔟 Full Component Reference <a name="full-reference"></a>
> **The tables below summarize the *most frequently used* props.**
> For the **exhaustive list** (including less‑common attributes and callbacks), see each component’s individual markdown file (`badge.md`, `navbar.md`, …) located in the repository root.
### 10.1 Layout
| `Container` | `fluid: bool` | – |
| `Row` | `class`, `gutter` (via `Spacing`) | – |
| `Col` | `xs, sm, md, lg, xl, xxl: Option<u8>` | – |
| `Grid` | `fluid`, `breakpoint`, `gutter`, `gutter_x`, `gutter_y`, `container_class`, `row_class` | `Breakpoint` |
| `GridItem` | `size`, `xs…xxl`, `offset`, `order` | `GridSize`, `GridOrder` |
| `Ratio` | `ratio: AspectRatio` | `Ratio1x1`, `Ratio4x3`, `Ratio16x9`, `Ratio21x9` |
| `Position` | `position: Position`, `coordinates: Vec<PositionCoordinate>` | `Position`, `PositionCoordinate` |
| `ZIndex` | `z_index: ZIndex` | `Z0`, `Z1`, `Z2`, `Z3`, `ZN1` |
| `Clearfix` | `class` | – |
| `Sizing` | `width`, `height`, `max_width`, `max_height`, `viewport` | `Width`, `Height`, `MaxWidth`, `MaxHeight`, `ViewportSize` |
| `Spacing` | `margin`, `padding` | `MarginSpacing`, `PaddingSpacing` |
| `VerticalAlign` | `align: VerticalAlign` | `Baseline`, `Top`, `Middle`, `Bottom`, `TextTop`, `TextBottom` |
| `Visibility` | `visibility: Visibility` | `Visible`, `Invisible` |
| `FocusRing` | `color: Option<FocusRingColor>`, `tabindex` | `Primary`, `Success`, `Danger`, `Info` |
### 10.2 Navigation
| `Navbar` | `expand`, `bg`, `placement`, `light`, `dark` | `NavbarExpand`, `NavbarBg`, `NavbarPlacement` |
| `NavbarBrand` | `href`, `onclick` | – |
| `NavbarNav` | `class` | – |
| `NavbarToggler` | `target`, `expanded`, `onclick` | – |
| `NavbarCollapse` | `id`, `show` | – |
| `Nav` | `pills`, `tabs`, `fill`, `align`, `orientation` | `NavFill`, `NavAlign`, `NavOrientation` |
| `NavItem` | `class` | – |
| `NavLink` | `href`, `active`, `disabled` | – |
| `TabTrigger` | `active`, `target`, `onclick` | – |
| `TabContent` / `TabPane` | `active`, `fade`, `id` | – |
| `Breadcrumb` | `items: Vec<BreadcrumbItem>` | – |
| `ScrollSpyNav` | `variant`, `class` | `ScrollSpyNavVariant` |
| `ScrollSpyNavItem` | `href`, `active`, `disabled` | – |
| `ScrollSpyContent` / `ScrollSpySection` | `id` | – |
### 10.3 Content
| `Badge` | `variant`, `pill` | `Variant` |
| `ButtonGroup` / `ButtonToolbar` | `vertical`, `size`, `aria_label` | `ButtonGroupSize` |
| `Image` | `src`, `alt`, `fluid`, `thumbnail`, `rounded`, `float_*`, `loading`, `decoding` | `ImageRounded`, `ImageLoading`, `ImageDecoding` |
| `Figure` / `Figcaption` | `class` | – |
| `Progress` / `ProgressBar` | `value`, `variant`, `animation`, `striped`, `animated`, `height` | `ProgressAnimation` |
| `Pagination` | `active_page`, `total_pages`, `on_page_change`, `size`, `alignment`, `show_first_last` | `PaginationAlignment`, `Size` |
| `Placeholder` / `PlaceholderButton` / `PlaceholderCard` / `PlaceholderTable` | `size`, `width`, `height`, `variant`, `animation` | `PlaceholderSize`, `PlaceholderAnimation` |
| `Carousel` | `indicators`, `controls`, `ride`, `pause`, `wrap`, `touch`, `interval`, `keyboard`, `active_index`, `on_slide_change` | – |
| `Collapse` | `id`, `expanded` | – |
| `Offcanvas` | `show`, `placement`, `backdrop`, `backdrop_close`, `keyboard`, `scroll` | `OffcanvasPlacement` |
| `Spinner` | `spinner_type`, `variant`, `size`, `centered` | `SpinnerType`, `Size` |
| `Toast` / `ToastContainer` | `show`, `variant`, `delay`, `dismissible`, `placement` (via container) | `ToastPlacement` |
| `Popover` | `title`, `content`, `placement`, `trigger`, `show`, `allow_html`, `animation`, `delay` | `PopoverPlacement`, `PopoverTrigger` |
| `Tooltip` | `title`, `placement`, `trigger`, `show` | `TooltipPlacement`, `TooltipTrigger` |
| `Table` | `striped`, `bordered`, `borderless`, `hover`, `size`, `variant`, `responsive`, `responsive_breakpoint`, `caption` | `TableSize`, `ResponsiveBreakpoint` |
| `Heading` | `level`, `display`, `lead`, `color`, `text_align`, `weight`, `style`, `transform`, `decoration`, `wrap`, `truncate`, `break_text` | `HeadingLevel`, `DisplayHeading`, `TextAlign`, `FontWeight`, `FontStyle`, `TextTransform`, `TextDecoration`, `TextWrap` |
| `Paragraph` | Same as `Heading` minus `level/display` | – |
| `Blockquote` | `footer` | – |
| `Text` | `element`, `color`, `align`, `weight`, `style`, `transform`, `decoration`, `wrap`, `truncate`, `break_text` | `TextElement`, `TextAlign`, `FontWeight`, `FontStyle`, `TextTransform`, `TextDecoration`, `TextWrap` |
| `Typography` (collection of `Heading`, `Paragraph`, `Blockquote`, `Text`) | – | – |
---
## 11️⃣ License <a name="license"></a>
This project is released under the **BBL License**. See `LICENSE` for the full text.
---
### What does unofficially impure mean?
**unofficial** = not endorsed by yew or bootstrap.
**impure** = just a wrapper around bootstrap 5.
### Final Note
All components are thin wrappers around Bootstrap’s CSS classes backed by the **Bootstrap JavaScript plugins** where interaction is required (e.g., `Carousel`, `Popover`, `Tooltip`, `Offcanvas`, `Collapse`).
The library intentionally mirrors the **Bootstrap API** so that developers familiar with Bootstrap can transition to Yew with minimal friction, while still enjoying **type‑safety** and **Rust‑centric ergonomics**.# yew-bs