From db13a6ab8b51d61e62005e9b9b3ea27b37620024 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 5 Jan 2025 09:23:56 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20[bootsier]=20Nuevos=20componentes?= =?UTF-8?q?=20Navbar=20y=20Offcanvas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/pagetop-bootsier/src/bs.rs | 52 ++++- packages/pagetop-bootsier/src/bs/container.rs | 4 +- packages/pagetop-bootsier/src/bs/grid.rs | 4 +- .../src/bs/grid/{cssgrid.rs => component.rs} | 6 +- packages/pagetop-bootsier/src/bs/grid/item.rs | 6 +- packages/pagetop-bootsier/src/bs/navbar.rs | 11 + .../src/bs/navbar/component.rs | 157 +++++++++++++++ .../pagetop-bootsier/src/bs/navbar/element.rs | 63 ++++++ .../pagetop-bootsier/src/bs/navbar/item.rs | 90 +++++++++ .../pagetop-bootsier/src/bs/navbar/nav.rs | 75 +++++++ packages/pagetop-bootsier/src/bs/offcanvas.rs | 59 ++++++ .../src/bs/offcanvas/component.rs | 188 ++++++++++++++++++ packages/pagetop-bootsier/src/lib.rs | 2 +- .../src/locale/en-US/components.ftl | 5 + .../src/locale/es-ES/components.ftl | 5 + website/config/default.toml | 2 +- website/src/main.rs | 30 +++ 17 files changed, 743 insertions(+), 16 deletions(-) rename packages/pagetop-bootsier/src/bs/grid/{cssgrid.rs => component.rs} (93%) create mode 100644 packages/pagetop-bootsier/src/bs/navbar.rs create mode 100644 packages/pagetop-bootsier/src/bs/navbar/component.rs create mode 100644 packages/pagetop-bootsier/src/bs/navbar/element.rs create mode 100644 packages/pagetop-bootsier/src/bs/navbar/item.rs create mode 100644 packages/pagetop-bootsier/src/bs/navbar/nav.rs create mode 100644 packages/pagetop-bootsier/src/bs/offcanvas.rs create mode 100644 packages/pagetop-bootsier/src/bs/offcanvas/component.rs create mode 100644 packages/pagetop-bootsier/src/locale/en-US/components.ftl create mode 100644 packages/pagetop-bootsier/src/locale/es-ES/components.ftl diff --git a/packages/pagetop-bootsier/src/bs.rs b/packages/pagetop-bootsier/src/bs.rs index f3108edf..1abfc280 100644 --- a/packages/pagetop-bootsier/src/bs.rs +++ b/packages/pagetop-bootsier/src/bs.rs @@ -2,10 +2,23 @@ use pagetop::prelude::*; use std::fmt; -mod container; +// Container. +pub mod container; pub use container::{Container, ContainerType}; +// Grid. pub mod grid; +pub use grid::Grid; + +// Offcanvas. +pub mod offcanvas; +pub use offcanvas::{ + Offcanvas, OffcanvasBackdrop, OffcanvasBodyScroll, OffcanvasPlacement, OffcanvasVisibility, +}; + +// Navbar. +pub mod navbar; +pub use navbar::{Navbar, NavbarType}; /// Define los puntos de interrupción (*breakpoints*) usados por Bootstrap para diseño responsivo. #[rustfmt::skip] @@ -24,15 +37,46 @@ pub enum BreakPoint { } impl BreakPoint { - /// Indica si se trata de un punto de interrupción de Bootstrap. - /// Devuelve `true` si el valor es SM, MD, LG, XL o XXL. - /// Devuelve `false` si es None, Fluid o FluidMax. + /// Indica si el punto de interrupción es efectivo en Bootstrap. + /// + /// Devuelve `true` si el valor es `SM`, `MD`, `LG`, `XL` o `XXL`. + /// Devuelve `false` si es `None`, `Fluid` o `FluidMax`. pub fn is_breakpoint(&self) -> bool { !matches!( self, BreakPoint::None | BreakPoint::Fluid | BreakPoint::FluidMax(_) ) } + + /// Genera un nombre de clase CSS basado en el punto de interrupción. + /// + /// Si es un punto de interrupción efectivo (ver [`is_breakpoint()`] se concatenan el prefijo + /// proporcionado, un guion (`-`) y el texto asociado al punto de interrupción. En otro caso, se + /// devuelve únicamente el prefijo. + /// + /// # Parámetros + /// + /// - `prefix`: Prefijo para concatenar con el punto de interrupción. + /// + /// # Ejemplo + /// + /// ```rust#ignore + /// let breakpoint = BreakPoint::MD; + /// let class = breakpoint.breakpoint_class("col"); + /// assert_eq!(class, "col-md".to_string()); + /// + /// let breakpoint = BreakPoint::Fluid; + /// let class = breakpoint.breakpoint_class("offcanvas"); + /// assert_eq!(class, "offcanvas".to_string()); + /// ``` + pub fn breakpoint_class(&self, prefix: impl Into) -> String { + let prefix: String = prefix.into(); + if self.is_breakpoint() { + join_string!(prefix, "-", self.to_string()) + } else { + prefix + } + } } /// Devuelve el texto asociado al punto de interrupción usado por Bootstrap. diff --git a/packages/pagetop-bootsier/src/bs/container.rs b/packages/pagetop-bootsier/src/bs/container.rs index e645c810..9de58b21 100644 --- a/packages/pagetop-bootsier/src/bs/container.rs +++ b/packages/pagetop-bootsier/src/bs/container.rs @@ -141,7 +141,7 @@ impl Container { self } - pub fn add_child(mut self, child: impl ComponentTrait) -> Self { + pub fn with_child(mut self, child: impl ComponentTrait) -> Self { self.children.add(ChildComponent::with(child)); self } @@ -154,7 +154,7 @@ impl Container { // Container GETTERS. - fn classes(&self) -> &OptionClasses { + pub fn classes(&self) -> &OptionClasses { &self.classes } diff --git a/packages/pagetop-bootsier/src/bs/grid.rs b/packages/pagetop-bootsier/src/bs/grid.rs index 58b99965..a72fd4f4 100644 --- a/packages/pagetop-bootsier/src/bs/grid.rs +++ b/packages/pagetop-bootsier/src/bs/grid.rs @@ -4,8 +4,8 @@ use crate::bs::BreakPoint; use std::fmt; -mod cssgrid; -pub use cssgrid::Grid; +mod component; +pub use component::Grid; mod item; pub use item::Item; diff --git a/packages/pagetop-bootsier/src/bs/grid/cssgrid.rs b/packages/pagetop-bootsier/src/bs/grid/component.rs similarity index 93% rename from packages/pagetop-bootsier/src/bs/grid/cssgrid.rs rename to packages/pagetop-bootsier/src/bs/grid/component.rs index cfb18e7b..4226f911 100644 --- a/packages/pagetop-bootsier/src/bs/grid/cssgrid.rs +++ b/packages/pagetop-bootsier/src/bs/grid/component.rs @@ -43,7 +43,7 @@ impl ComponentTrait for Grid { impl Grid { pub fn with(item: grid::Item) -> Self { - Grid::default().add_item(item) + Grid::default().with_item(item) } // Grid BUILDER. @@ -72,7 +72,7 @@ impl Grid { self } - pub fn add_item(mut self, item: grid::Item) -> Self { + pub fn with_item(mut self, item: grid::Item) -> Self { self.items.add(ChildComponent::with(item)); self } @@ -85,7 +85,7 @@ impl Grid { // Grid GETTERS. - fn classes(&self) -> &OptionClasses { + pub fn classes(&self) -> &OptionClasses { &self.classes } diff --git a/packages/pagetop-bootsier/src/bs/grid/item.rs b/packages/pagetop-bootsier/src/bs/grid/item.rs index e08f01bb..f0ae5d74 100644 --- a/packages/pagetop-bootsier/src/bs/grid/item.rs +++ b/packages/pagetop-bootsier/src/bs/grid/item.rs @@ -49,7 +49,7 @@ impl ComponentTrait for Item { impl Item { pub fn with(child: impl ComponentTrait) -> Self { - Item::default().add_child(child) + Item::default().with_child(child) } // Item BUILDER. @@ -84,7 +84,7 @@ impl Item { self } - pub fn add_child(mut self, child: impl ComponentTrait) -> Self { + pub fn with_child(mut self, child: impl ComponentTrait) -> Self { self.children.add(ChildComponent::with(child)); self } @@ -97,7 +97,7 @@ impl Item { // Item GETTERS. - fn classes(&self) -> &OptionClasses { + pub fn classes(&self) -> &OptionClasses { &self.classes } diff --git a/packages/pagetop-bootsier/src/bs/navbar.rs b/packages/pagetop-bootsier/src/bs/navbar.rs new file mode 100644 index 00000000..d5aab896 --- /dev/null +++ b/packages/pagetop-bootsier/src/bs/navbar.rs @@ -0,0 +1,11 @@ +mod component; +pub use component::{Navbar, NavbarType}; + +mod element; +pub use element::{Element, ElementType}; + +mod nav; +pub use nav::Nav; + +mod item; +pub use item::{Item, ItemType}; diff --git a/packages/pagetop-bootsier/src/bs/navbar/component.rs b/packages/pagetop-bootsier/src/bs/navbar/component.rs new file mode 100644 index 00000000..fc113021 --- /dev/null +++ b/packages/pagetop-bootsier/src/bs/navbar/component.rs @@ -0,0 +1,157 @@ +use pagetop::prelude::*; + +use crate::bs::navbar; +use crate::bs::{BreakPoint, Offcanvas}; +use crate::LOCALES_BOOTSIER; + +#[derive(AutoDefault)] +pub enum NavbarType { + #[default] + Default, + Basic, + Offcanvas(TypedComponent), +} + +#[rustfmt::skip] +#[derive(AutoDefault)] +pub struct Navbar { + id : OptionId, + classes : OptionClasses, + navbar_type: NavbarType, + expand : BreakPoint, + elements : Children, +} + +impl ComponentTrait for Navbar { + fn new() -> Self { + Navbar::default() + } + + fn id(&self) -> Option { + self.id.get() + } + + fn setup_before_prepare(&mut self, _cx: &mut Context) { + self.alter_classes( + ClassesOp::Prepend, + [ + "navbar".to_string(), + self.expand().breakpoint_class("navbar-expand"), + ] + .join(" "), + ); + } + + fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup { + let elements = self.elements().render(cx); + if elements.is_empty() { + return PrepareMarkup::None; + } + + let id = cx.required_id::(self.id()); + let (output, id_content) = if let NavbarType::Offcanvas(oc) = self.navbar_type() { + ( + oc.writable() + .alter_children(ChildOp::Prepend(ChildComponent::with(Html::with(elements)))) + .render(cx), + cx.required_id::(oc.id()), + ) + } else { + (elements, join_string!(id, "-content")) + }; + let id_content_target = join_string!("#", id_content); + + PrepareMarkup::With(html! { + nav id=(id) class=[self.classes().get()] { + div class="container-fluid" { + @match self.navbar_type() { + NavbarType::Default => { + button + type="button" + class="navbar-toggler" + data-bs-toggle="collapse" + data-bs-target=(id_content_target) + aria-controls=(id_content) + aria-expanded="false" + aria-label=[L10n::t("toggle", &LOCALES_BOOTSIER).using(cx.langid())] + { + span class="navbar-toggler-icon" {} + } + div id=(id_content) class="collapse navbar-collapse" { + (output) + } + }, + NavbarType::Basic => { + (output) + }, + NavbarType::Offcanvas(_) => { + button + type="button" + class="navbar-toggler" + data-bs-toggle="offcanvas" + data-bs-target=(id_content_target) + aria-controls=(id_content) + aria-label=[L10n::t("toggle", &LOCALES_BOOTSIER).using(cx.langid())] + { + span class="navbar-toggler-icon" {} + } + (output) + }, + } + } + } + }) + } +} + +impl Navbar { + // Navbar BUILDER. + + #[fn_builder] + pub fn with_id(mut self, id: impl Into) -> Self { + self.id.alter_value(id); + self + } + + #[fn_builder] + pub fn with_classes(mut self, op: ClassesOp, classes: impl Into) -> Self { + self.classes.alter_value(op, classes); + self + } + + #[fn_builder] + pub fn with_type(mut self, navbar_type: NavbarType) -> Self { + self.navbar_type = navbar_type; + self + } + + #[fn_builder] + pub fn with_expand(mut self, bp: BreakPoint) -> Self { + self.expand = bp; + self + } + + #[fn_builder] + pub fn with_nav(mut self, op: TypedOp) -> Self { + self.elements.alter_typed(op); + self + } + + // Navbar GETTERS. + + pub fn classes(&self) -> &OptionClasses { + &self.classes + } + + pub fn navbar_type(&self) -> &NavbarType { + &self.navbar_type + } + + pub fn expand(&self) -> &BreakPoint { + &self.expand + } + + pub fn elements(&self) -> &Children { + &self.elements + } +} diff --git a/packages/pagetop-bootsier/src/bs/navbar/element.rs b/packages/pagetop-bootsier/src/bs/navbar/element.rs new file mode 100644 index 00000000..0b952912 --- /dev/null +++ b/packages/pagetop-bootsier/src/bs/navbar/element.rs @@ -0,0 +1,63 @@ +use pagetop::prelude::*; + +use crate::bs::navbar; + +#[derive(AutoDefault)] +pub enum ElementType { + #[default] + None, + Nav(navbar::Nav), + Text(L10n), +} + +// Element. + +#[rustfmt::skip] +#[derive(AutoDefault)] +pub struct Element { + element_type: ElementType, +} + +impl ComponentTrait for Element { + fn new() -> Self { + Element::default() + } + + fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup { + match self.element_type() { + ElementType::None => PrepareMarkup::None, + ElementType::Nav(_nav) => PrepareMarkup::With(html! { + span class="navbar-text" { + ("Prueba") + } + }), + ElementType::Text(label) => PrepareMarkup::With(html! { + span class="navbar-text" { + (label.escaped(cx.langid())) + } + }), + } + } +} + +impl Element { + pub fn nav(nav: navbar::Nav) -> Self { + Element { + element_type: ElementType::Nav(nav), + ..Default::default() + } + } + + pub fn text(label: L10n) -> Self { + Element { + element_type: ElementType::Text(label), + ..Default::default() + } + } + + // Element GETTERS. + + pub fn element_type(&self) -> &ElementType { + &self.element_type + } +} diff --git a/packages/pagetop-bootsier/src/bs/navbar/item.rs b/packages/pagetop-bootsier/src/bs/navbar/item.rs new file mode 100644 index 00000000..bfee2bcc --- /dev/null +++ b/packages/pagetop-bootsier/src/bs/navbar/item.rs @@ -0,0 +1,90 @@ +use pagetop::prelude::*; + +type Label = L10n; + +#[derive(AutoDefault)] +pub enum ItemType { + #[default] + Void, + Label(Label), + Link(Label, FnContextualPath), + LinkBlank(Label, FnContextualPath), +} + +// Item. + +#[rustfmt::skip] +#[derive(AutoDefault)] +pub struct Item { + item_type: ItemType, +} + +impl ComponentTrait for Item { + fn new() -> Self { + Item::default() + } + + fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup { + let description: Option = None; + + match self.item_type() { + ItemType::Void => PrepareMarkup::None, + ItemType::Label(label) => PrepareMarkup::With(html! { + li class="nav-item" { + span title=[description] { + //(left_icon) + (label.escaped(cx.langid())) + //(right_icon) + } + } + }), + ItemType::Link(label, path) => PrepareMarkup::With(html! { + li class="nav-item" { + a class="nav-link" href=(path(cx)) title=[description] { + //(left_icon) + (label.escaped(cx.langid())) + //(right_icon) + } + } + }), + ItemType::LinkBlank(label, path) => PrepareMarkup::With(html! { + li class="nav-item" { + a class="nav-link" href=(path(cx)) title=[description] target="_blank" { + //(left_icon) + (label.escaped(cx.langid())) + //(right_icon) + } + } + }), + } + } +} + +impl Item { + pub fn label(label: L10n) -> Self { + Item { + item_type: ItemType::Label(label), + ..Default::default() + } + } + + pub fn link(label: L10n, path: FnContextualPath) -> Self { + Item { + item_type: ItemType::Link(label, path), + ..Default::default() + } + } + + pub fn link_blank(label: L10n, path: FnContextualPath) -> Self { + Item { + item_type: ItemType::LinkBlank(label, path), + ..Default::default() + } + } + + // Item GETTERS. + + pub fn item_type(&self) -> &ItemType { + &self.item_type + } +} diff --git a/packages/pagetop-bootsier/src/bs/navbar/nav.rs b/packages/pagetop-bootsier/src/bs/navbar/nav.rs new file mode 100644 index 00000000..3b522d28 --- /dev/null +++ b/packages/pagetop-bootsier/src/bs/navbar/nav.rs @@ -0,0 +1,75 @@ +use pagetop::prelude::*; + +use crate::bs::navbar; + +#[rustfmt::skip] +#[derive(AutoDefault)] +pub struct Nav { + id : OptionId, + classes: OptionClasses, + items : Children, +} + +impl ComponentTrait for Nav { + fn new() -> Self { + Nav::default() + } + + fn id(&self) -> Option { + self.id.get() + } + + fn setup_before_prepare(&mut self, _cx: &mut Context) { + self.alter_classes(ClassesOp::Prepend, "navbar-nav"); + } + + fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup { + let items = self.items().render(cx); + if items.is_empty() { + return PrepareMarkup::None; + } + + PrepareMarkup::With(html! { + ul id=[self.id()] class=[self.classes().get()] { + (items) + } + }) + } +} + +impl Nav { + // Nav BUILDER. + + #[fn_builder] + pub fn with_id(mut self, id: impl Into) -> Self { + self.id.alter_value(id); + self + } + + #[fn_builder] + pub fn with_classes(mut self, op: ClassesOp, classes: impl Into) -> Self { + self.classes.alter_value(op, classes); + self + } + + pub fn with_item(mut self, item: navbar::Item) -> Self { + self.items.add(ChildComponent::with(item)); + self + } + + #[fn_builder] + pub fn with_items(mut self, op: TypedOp) -> Self { + self.items.alter_typed(op); + self + } + + // Nav GETTERS. + + pub fn classes(&self) -> &OptionClasses { + &self.classes + } + + pub fn items(&self) -> &Children { + &self.items + } +} diff --git a/packages/pagetop-bootsier/src/bs/offcanvas.rs b/packages/pagetop-bootsier/src/bs/offcanvas.rs new file mode 100644 index 00000000..5036851a --- /dev/null +++ b/packages/pagetop-bootsier/src/bs/offcanvas.rs @@ -0,0 +1,59 @@ +use pagetop::prelude::*; + +use std::fmt; + +mod component; +pub use component::Offcanvas; + +#[derive(AutoDefault)] +pub enum OffcanvasPlacement { + #[default] + Start, + End, + Top, + Bottom, +} + +#[rustfmt::skip] +impl fmt::Display for OffcanvasPlacement { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + OffcanvasPlacement::Start => write!(f, "offcanvas-start"), + OffcanvasPlacement::End => write!(f, "offcanvas-end"), + OffcanvasPlacement::Top => write!(f, "offcanvas-top"), + OffcanvasPlacement::Bottom => write!(f, "offcanvas-bottom"), + } + } +} + +#[derive(AutoDefault)] +pub enum OffcanvasVisibility { + #[default] + Default, + Show, +} + +#[rustfmt::skip] +impl fmt::Display for OffcanvasVisibility { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + OffcanvasVisibility::Default => write!(f, "show"), + OffcanvasVisibility::Show => write!(f, ""), + } + } +} + +#[derive(AutoDefault)] +pub enum OffcanvasBodyScroll { + #[default] + Disabled, + Enabled, +} + +#[derive(AutoDefault)] +pub enum OffcanvasBackdrop { + Disabled, + #[default] + Enabled, + Static, +} diff --git a/packages/pagetop-bootsier/src/bs/offcanvas/component.rs b/packages/pagetop-bootsier/src/bs/offcanvas/component.rs new file mode 100644 index 00000000..96060f42 --- /dev/null +++ b/packages/pagetop-bootsier/src/bs/offcanvas/component.rs @@ -0,0 +1,188 @@ +use pagetop::prelude::*; + +use crate::bs::{ + BreakPoint, OffcanvasBackdrop, OffcanvasBodyScroll, OffcanvasPlacement, OffcanvasVisibility, +}; +use crate::LOCALES_BOOTSIER; + +#[rustfmt::skip] +#[derive(AutoDefault)] +pub struct Offcanvas { + id : OptionId, + classes : OptionClasses, + title : OptionTranslated, + breakpoint: BreakPoint, + placement : OffcanvasPlacement, + visibility: OffcanvasVisibility, + scrolling : OffcanvasBodyScroll, + backdrop : OffcanvasBackdrop, + children : Children, +} + +impl ComponentTrait for Offcanvas { + fn new() -> Self { + Offcanvas::default() + } + + fn id(&self) -> Option { + self.id.get() + } + + fn setup_before_prepare(&mut self, _cx: &mut Context) { + self.alter_classes( + ClassesOp::Prepend, + [ + self.breakpoint().breakpoint_class("offcanvas"), + self.placement().to_string(), + self.visibility().to_string(), + ] + .join(" "), + ); + } + + fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup { + let body = self.children().render(cx); + if body.is_empty() { + return PrepareMarkup::None; + } + + let id = cx.required_id::(self.id()); + let id_label = join_string!(id, "-label"); + let id_target = join_string!("#", id); + + let body_scroll = match self.body_scroll() { + OffcanvasBodyScroll::Disabled => None, + OffcanvasBodyScroll::Enabled => Some("true".to_string()), + }; + + let backdrop = match self.backdrop() { + OffcanvasBackdrop::Disabled => Some("true".to_string()), + OffcanvasBackdrop::Enabled => None, + OffcanvasBackdrop::Static => Some("static".to_string()), + }; + + PrepareMarkup::With(html! { + div + id=(id) + class=[self.classes().get()] + tabindex="-1" + data-bs-scroll=[body_scroll] + data-bs-backdrop=[backdrop] + aria-labelledby=(id_label) + { + div class="offcanvas-header" { + h5 class="offcanvas-title" id=(id_label) { + (self.title().escaped(cx.langid())) + } + button + type="button" + class="btn-close" + data-bs-dismiss="offcanvas" + data-bs-target=(id_target) + aria-label=[L10n::t("close", &LOCALES_BOOTSIER).using(cx.langid())] + {} + } + div class="offcanvas-body" { + (body) + } + } + }) + } +} + +impl Offcanvas { + // Offcanvas BUILDER. + + #[fn_builder] + pub fn with_id(mut self, id: impl Into) -> Self { + self.id.alter_value(id); + self + } + + #[fn_builder] + pub fn with_classes(mut self, op: ClassesOp, classes: impl Into) -> Self { + self.classes.alter_value(op, classes); + self + } + + #[fn_builder] + pub fn with_title(mut self, title: L10n) -> Self { + self.title.alter_value(title); + self + } + + #[fn_builder] + pub fn with_breakpoint(mut self, bp: BreakPoint) -> Self { + self.breakpoint = bp; + self + } + + #[fn_builder] + pub fn with_placement(mut self, placement: OffcanvasPlacement) -> Self { + self.placement = placement; + self + } + + #[fn_builder] + pub fn with_visibility(mut self, visibility: OffcanvasVisibility) -> Self { + self.visibility = visibility; + self + } + + #[fn_builder] + pub fn with_body_scroll(mut self, scrolling: OffcanvasBodyScroll) -> Self { + self.scrolling = scrolling; + self + } + + #[fn_builder] + pub fn with_backdrop(mut self, backdrop: OffcanvasBackdrop) -> Self { + self.backdrop = backdrop; + self + } + + pub fn with_child(mut self, child: impl ComponentTrait) -> Self { + self.children.add(ChildComponent::with(child)); + self + } + + #[fn_builder] + pub fn with_children(mut self, op: ChildOp) -> Self { + self.children.alter_child(op); + self + } + + // Offcanvas GETTERS. + + pub fn classes(&self) -> &OptionClasses { + &self.classes + } + + pub fn title(&self) -> &OptionTranslated { + &self.title + } + + pub fn breakpoint(&self) -> &BreakPoint { + &self.breakpoint + } + + pub fn placement(&self) -> &OffcanvasPlacement { + &self.placement + } + + pub fn visibility(&self) -> &OffcanvasVisibility { + &self.visibility + } + + pub fn body_scroll(&self) -> &OffcanvasBodyScroll { + &self.scrolling + } + + pub fn backdrop(&self) -> &OffcanvasBackdrop { + &self.backdrop + } + + pub fn children(&self) -> &Children { + &self.children + } +} diff --git a/packages/pagetop-bootsier/src/lib.rs b/packages/pagetop-bootsier/src/lib.rs index 9036c938..323bff94 100644 --- a/packages/pagetop-bootsier/src/lib.rs +++ b/packages/pagetop-bootsier/src/lib.rs @@ -65,7 +65,7 @@ impl ThemeTrait for Bootsier { (bs::Container::new() .with_id("container-wrapper") .with_breakpoint(bs::BreakPoint::FluidMax(config::SETTINGS.bootsier.max_width)) - .add_child(Region::of("region-content")) + .with_child(Region::of("region-content")) .render(page.context())) } } diff --git a/packages/pagetop-bootsier/src/locale/en-US/components.ftl b/packages/pagetop-bootsier/src/locale/en-US/components.ftl new file mode 100644 index 00000000..83dde396 --- /dev/null +++ b/packages/pagetop-bootsier/src/locale/en-US/components.ftl @@ -0,0 +1,5 @@ +# Offcanvas +close = Close + +# Navbar +toggle = Toggle navigation diff --git a/packages/pagetop-bootsier/src/locale/es-ES/components.ftl b/packages/pagetop-bootsier/src/locale/es-ES/components.ftl new file mode 100644 index 00000000..1ae97888 --- /dev/null +++ b/packages/pagetop-bootsier/src/locale/es-ES/components.ftl @@ -0,0 +1,5 @@ +# Offcanvas +close = Cerrar + +# Navbar +toggle = Mostrar/ocultar navegación diff --git a/website/config/default.toml b/website/config/default.toml index ac3f0b74..c9f5c5cd 100644 --- a/website/config/default.toml +++ b/website/config/default.toml @@ -4,7 +4,7 @@ description = "An opinionated web framework to build modular Server-Side Renderi theme = "Bootsier" [bootsier] -max_width = "1600px" +max_width = "1520px" [log] rolling = "Daily" diff --git a/website/src/main.rs b/website/src/main.rs index aaea6178..256a7779 100644 --- a/website/src/main.rs +++ b/website/src/main.rs @@ -1,5 +1,7 @@ use pagetop::prelude::*; +use pagetop_bootsier::bs::*; + include_files!(BUNDLE_DOC => doc); include_locales!(LOCALES_WEBSITE); @@ -25,6 +27,34 @@ impl PackageTrait for PageTopWebSite { } fn init(&self) { + let nav = Navbar::new().with_nav(TypedOp::Add(TypedComponent::with( + navbar::Nav::new() + .with_item(navbar::Item::link( + L10n::t("menu_home", &LOCALES_WEBSITE), + |cx| match cx.langid().language.as_str() { + "es" => "/es", + _ => "/", + }, + )) + .with_item(navbar::Item::link( + L10n::t("menu_documentation", &LOCALES_WEBSITE), + |cx| match cx.langid().language.as_str() { + "es" => "/doc/latest/es", + _ => "/doc/latest/en", + }, + )) + .with_item(navbar::Item::link_blank( + L10n::t("menu_api", &LOCALES_WEBSITE), + |_| "https://docs.rs/pagetop", + )) + .with_item(navbar::Item::link_blank( + L10n::t("menu_code", &LOCALES_WEBSITE), + |_| "https://github.com/manuelcillero/pagetop", + )), + ))); + + InRegion::Content.add(ChildComponent::with(nav)); + /* let branding = Branding::new() .with_logo(Some(Image::pagetop()))