📝 Repasa doc de Dropdown, Nav y Offcanvas
This commit is contained in:
parent
749e182619
commit
93804721e1
8 changed files with 124 additions and 108 deletions
|
|
@ -6,6 +6,23 @@
|
|||
//!
|
||||
//! Los ítems pueden estar activos, deshabilitados o abrirse en nueva ventana según su contexto y
|
||||
//! configuración, y permiten incluir etiquetas localizables usando [`L10n`](pagetop::locale::L10n).
|
||||
//!
|
||||
//! # Ejemplo
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use pagetop::prelude::*;
|
||||
//! # use pagetop_bootsier::prelude::*;
|
||||
//! let dd = Dropdown::new()
|
||||
//! .with_title(L10n::n("Menu"))
|
||||
//! .with_button_color(ButtonColor::Background(Color::Secondary))
|
||||
//! .with_auto_close(dropdown::AutoClose::ClickableInside)
|
||||
//! .with_direction(dropdown::Direction::Dropend)
|
||||
//! .add_item(dropdown::Item::link(L10n::n("Home"), |_| "/"))
|
||||
//! .add_item(dropdown::Item::link_blank(L10n::n("External"), |_| "https://www.google.es"))
|
||||
//! .add_item(dropdown::Item::divider())
|
||||
//! .add_item(dropdown::Item::header(L10n::n("User session")))
|
||||
//! .add_item(dropdown::Item::button(L10n::n("Sign out")));
|
||||
//! ```
|
||||
|
||||
mod props;
|
||||
pub use props::{AutoClose, Direction, MenuAlign, MenuPosition};
|
||||
|
|
|
|||
|
|
@ -17,22 +17,8 @@ use crate::LOCALES_BOOTSIER;
|
|||
/// cuenta **el título** (si no existe le asigna uno por defecto) y **la lista de elementos**; el
|
||||
/// resto de propiedades no afectarán a su representación en [`Nav`].
|
||||
///
|
||||
/// # Ejemplo
|
||||
///
|
||||
/// ```rust
|
||||
/// # use pagetop::prelude::*;
|
||||
/// # use pagetop_bootsier::prelude::*;
|
||||
/// let dd = Dropdown::new()
|
||||
/// .with_title(L10n::n("Menu"))
|
||||
/// .with_button_color(ButtonColor::Background(Color::Secondary))
|
||||
/// .with_auto_close(dropdown::AutoClose::ClickableInside)
|
||||
/// .with_direction(dropdown::Direction::Dropend)
|
||||
/// .add_item(dropdown::Item::link(L10n::n("Home"), |_| "/"))
|
||||
/// .add_item(dropdown::Item::link_blank(L10n::n("External"), |_| "https://www.google.es"))
|
||||
/// .add_item(dropdown::Item::divider())
|
||||
/// .add_item(dropdown::Item::header(L10n::n("User session")))
|
||||
/// .add_item(dropdown::Item::button(L10n::n("Sign out")));
|
||||
/// ```
|
||||
/// Ver ejemplo en el módulo [`dropdown`].
|
||||
/// Si no contiene elementos, el componente **no se renderiza**.
|
||||
#[rustfmt::skip]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Dropdown {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ impl Component for Item {
|
|||
} => {
|
||||
let path = path(cx);
|
||||
let current_path = cx.request().map(|request| request.path());
|
||||
let is_current = !*disabled && current_path.map_or(false, |p| p == path);
|
||||
let is_current = !*disabled && (current_path == Some(path));
|
||||
|
||||
let mut classes = "dropdown-item".to_string();
|
||||
if is_current {
|
||||
|
|
@ -274,7 +274,7 @@ impl Item {
|
|||
&self.classes
|
||||
}
|
||||
|
||||
/// Devuelve el tipo de elemento representado por este elemento.
|
||||
/// Devuelve el tipo de elemento representado.
|
||||
pub fn item_kind(&self) -> &ItemKind {
|
||||
&self.item_kind
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,26 @@
|
|||
//!
|
||||
//! Los ítems pueden estar activos, deshabilitados o abrirse en nueva ventana según su contexto y
|
||||
//! configuración, y permiten incluir etiquetas localizables usando [`L10n`](pagetop::locale::L10n).
|
||||
//!
|
||||
//! # Ejemplo
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use pagetop::prelude::*;
|
||||
//! # use pagetop_bootsier::prelude::*;
|
||||
//! let nav = Nav::tabs()
|
||||
//! .with_layout(nav::Layout::End)
|
||||
//! .add_item(nav::Item::link(L10n::n("Home"), |_| "/"))
|
||||
//! .add_item(nav::Item::link_blank(L10n::n("External"), |_| "https://www.google.es"))
|
||||
//! .add_item(nav::Item::dropdown(
|
||||
//! Dropdown::new()
|
||||
//! .with_title(L10n::n("Options"))
|
||||
//! .with_items(TypedOp::AddMany(vec![
|
||||
//! Typed::with(dropdown::Item::link(L10n::n("Action"), |_| "/action")),
|
||||
//! Typed::with(dropdown::Item::link(L10n::n("Another action"), |_| "/another")),
|
||||
//! ])),
|
||||
//! ))
|
||||
//! .add_item(nav::Item::link_disabled(L10n::n("Disabled"), |_| "#"));
|
||||
//! ```
|
||||
|
||||
mod props;
|
||||
pub use props::{Kind, Layout};
|
||||
|
|
|
|||
|
|
@ -8,25 +8,8 @@ use crate::prelude::*;
|
|||
/// como *pestañas* (`Tabs`), *botones* (`Pills`) o *subrayado* (`Underline`). También permite
|
||||
/// controlar su distribución y orientación ([`nav::Layout`](crate::theme::nav::Layout)).
|
||||
///
|
||||
/// # Ejemplo
|
||||
///
|
||||
/// ```rust
|
||||
/// # use pagetop::prelude::*;
|
||||
/// # use pagetop_bootsier::prelude::*;
|
||||
/// let nav = Nav::tabs()
|
||||
/// .with_layout(nav::Layout::End)
|
||||
/// .add_item(nav::Item::link(L10n::n("Home"), |_| "/"))
|
||||
/// .add_item(nav::Item::link_blank(L10n::n("External"), |_| "https://www.google.es"))
|
||||
/// .add_item(nav::Item::dropdown(
|
||||
/// Dropdown::new()
|
||||
/// .with_title(L10n::n("Options"))
|
||||
/// .with_items(TypedOp::AddMany(vec![
|
||||
/// Typed::with(dropdown::Item::link(L10n::n("Action"), |_| "/action")),
|
||||
/// Typed::with(dropdown::Item::link(L10n::n("Another action"), |_| "/another")),
|
||||
/// ])),
|
||||
/// ))
|
||||
/// .add_item(nav::Item::link_disabled(L10n::n("Disabled"), |_| "#"));
|
||||
/// ```
|
||||
/// Ver ejemplo en el módulo [`nav`].
|
||||
/// Si no contiene elementos, el componente **no se renderiza**.
|
||||
#[rustfmt::skip]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Nav {
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ impl Component for Item {
|
|||
|
||||
ItemKind::Label(label) => PrepareMarkup::With(html! {
|
||||
li id=[self.id()] class=[self.classes().get()] {
|
||||
span {
|
||||
span class="nav-link disabled" aria-disabled="true" {
|
||||
(label.using(cx))
|
||||
}
|
||||
}
|
||||
|
|
@ -86,7 +86,7 @@ impl Component for Item {
|
|||
} => {
|
||||
let path = path(cx);
|
||||
let current_path = cx.request().map(|request| request.path());
|
||||
let is_current = !*disabled && current_path.map_or(false, |p| p == path);
|
||||
let is_current = !*disabled && (current_path == Some(path));
|
||||
|
||||
let mut classes = "nav-link".to_string();
|
||||
if is_current {
|
||||
|
|
@ -250,7 +250,7 @@ impl Item {
|
|||
&self.classes
|
||||
}
|
||||
|
||||
/// Devuelve el tipo de elemento representado por este elemento.
|
||||
/// Devuelve el tipo de elemento representado.
|
||||
pub fn item_kind(&self) -> &ItemKind {
|
||||
&self.item_kind
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,24 @@
|
|||
//! Definiciones para crear paneles laterales deslizantes [`Offcanvas`].
|
||||
//!
|
||||
//! # Ejemplo
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use pagetop::prelude::*;
|
||||
//! # use pagetop_bootsier::prelude::*;
|
||||
//! let panel = Offcanvas::new()
|
||||
//! .with_id("offcanvas_example")
|
||||
//! .with_title(L10n::n("Offcanvas title"))
|
||||
//! .with_placement(offcanvas::Placement::End)
|
||||
//! .with_backdrop(offcanvas::Backdrop::Enabled)
|
||||
//! .with_body_scroll(offcanvas::BodyScroll::Enabled)
|
||||
//! .with_visibility(offcanvas::Visibility::Default)
|
||||
//! .add_child(Dropdown::new()
|
||||
//! .with_button_title(L10n::n("Menu"))
|
||||
//! .add_item(dropdown::Item::label(L10n::n("Label")))
|
||||
//! .add_item(dropdown::Item::link_blank(L10n::n("Google"), |_| "https://www.google.es"))
|
||||
//! .add_item(dropdown::Item::link(L10n::n("Sign out"), |_| "/signout"))
|
||||
//! );
|
||||
//! ```
|
||||
|
||||
mod props;
|
||||
pub use props::{Backdrop, BodyScroll, Placement, Visibility};
|
||||
|
|
|
|||
|
|
@ -18,27 +18,9 @@ use crate::LOCALES_BOOTSIER;
|
|||
/// ([`with_breakpoint()`](Self::with_breakpoint)).
|
||||
/// - Asocia título y controles de accesibilidad a un identificador único y expone atributos
|
||||
/// adecuados para lectores de pantalla y navegación por teclado.
|
||||
/// - **No se renderiza** si no tiene contenido.
|
||||
///
|
||||
/// # Ejemplo
|
||||
///
|
||||
/// ```rust
|
||||
/// # use pagetop::prelude::*;
|
||||
/// # use pagetop_bootsier::prelude::*;
|
||||
/// let panel = Offcanvas::new()
|
||||
/// .with_id("offcanvas_example")
|
||||
/// .with_title(L10n::n("Offcanvas title"))
|
||||
/// .with_placement(offcanvas::Placement::End)
|
||||
/// .with_backdrop(offcanvas::Backdrop::Enabled)
|
||||
/// .with_body_scroll(offcanvas::BodyScroll::Enabled)
|
||||
/// .with_visibility(offcanvas::Visibility::Default)
|
||||
/// .add_child(Dropdown::new()
|
||||
/// .with_button_title(L10n::n("Menu"))
|
||||
/// .add_item(dropdown::Item::label(L10n::n("Label")))
|
||||
/// .add_item(dropdown::Item::link_blank(L10n::n("Google"), |_| "https://www.google.es"))
|
||||
/// .add_item(dropdown::Item::link(L10n::n("Sign out"), |_| "/signout"))
|
||||
/// );
|
||||
/// ```
|
||||
/// Ver ejemplo en el módulo [`offcanvas`].
|
||||
/// Si no contiene elementos, el componente **no se renderiza**.
|
||||
#[rustfmt::skip]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Offcanvas {
|
||||
|
|
@ -84,54 +66,7 @@ impl Component for Offcanvas {
|
|||
}
|
||||
|
||||
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>(self.id());
|
||||
let id_label = join!(id, "-label");
|
||||
let id_target = join!("#", id);
|
||||
|
||||
let body_scroll = match self.body_scroll() {
|
||||
offcanvas::BodyScroll::Disabled => None,
|
||||
offcanvas::BodyScroll::Enabled => Some("true"),
|
||||
};
|
||||
|
||||
let backdrop = match self.backdrop() {
|
||||
offcanvas::Backdrop::Disabled => Some("false"),
|
||||
offcanvas::Backdrop::Enabled => None,
|
||||
offcanvas::Backdrop::Static => Some("static"),
|
||||
};
|
||||
|
||||
let title = self.title().using(cx);
|
||||
|
||||
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" {
|
||||
@if !title.is_empty() {
|
||||
h5 class="offcanvas-title" id=(id_label) { (title) }
|
||||
}
|
||||
button
|
||||
type="button"
|
||||
class="btn-close"
|
||||
data-bs-dismiss="offcanvas"
|
||||
data-bs-target=(id_target)
|
||||
aria-label=[L10n::t("offcanvas_close", &LOCALES_BOOTSIER).lookup(cx)]
|
||||
{}
|
||||
}
|
||||
div class="offcanvas-body" {
|
||||
(body)
|
||||
}
|
||||
}
|
||||
})
|
||||
PrepareMarkup::With(self.render_offcanvas(cx, None))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -258,4 +193,59 @@ impl Offcanvas {
|
|||
pub fn children(&self) -> &Children {
|
||||
&self.children
|
||||
}
|
||||
|
||||
// **< Offcanvas HELPERS >**********************************************************************
|
||||
|
||||
pub(crate) fn render_offcanvas(&self, cx: &mut Context, extra: Option<&Children>) -> Markup {
|
||||
let body = self.children().render(cx);
|
||||
let body_extra = extra.map(|c| c.render(cx)).unwrap_or_else(|| html! {});
|
||||
if body.is_empty() && body_extra.is_empty() {
|
||||
return html! {};
|
||||
}
|
||||
|
||||
let id = cx.required_id::<Self>(self.id());
|
||||
let id_label = join!(id, "-label");
|
||||
let id_target = join!("#", id);
|
||||
|
||||
let body_scroll = match self.body_scroll() {
|
||||
offcanvas::BodyScroll::Disabled => None,
|
||||
offcanvas::BodyScroll::Enabled => Some("true"),
|
||||
};
|
||||
|
||||
let backdrop = match self.backdrop() {
|
||||
offcanvas::Backdrop::Disabled => Some("false"),
|
||||
offcanvas::Backdrop::Enabled => None,
|
||||
offcanvas::Backdrop::Static => Some("static"),
|
||||
};
|
||||
|
||||
let title = self.title().using(cx);
|
||||
|
||||
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" {
|
||||
@if !title.is_empty() {
|
||||
h5 class="offcanvas-title" id=(id_label) { (title) }
|
||||
}
|
||||
button
|
||||
type="button"
|
||||
class="btn-close"
|
||||
data-bs-dismiss="offcanvas"
|
||||
data-bs-target=(id_target)
|
||||
aria-label=[L10n::t("offcanvas_close", &LOCALES_BOOTSIER).lookup(cx)]
|
||||
{}
|
||||
}
|
||||
div class="offcanvas-body" {
|
||||
(body)
|
||||
(body_extra)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue