diff --git a/extensions/pagetop-bootsier/README.md b/extensions/pagetop-bootsier/README.md index 69440ec6..041701f9 100644 --- a/extensions/pagetop-bootsier/README.md +++ b/extensions/pagetop-bootsier/README.md @@ -34,6 +34,7 @@ use pagetop::prelude::*; struct MyApp; +#[async_trait] impl Extension for MyApp { fn dependencies(&self) -> Vec { vec![ @@ -63,15 +64,90 @@ async fn homepage(request: HttpRequest) -> Result { .with_theme(&Bootsier) .with_child( Block::new() - .with_title(L10n::l("sample_title")) + .with_title(Lc::l("sample_title")) .with_child(Html::with(|cx| html! { - p { (L10n::l("sample_content").using(cx)) } + p { (Lc::l("sample_content").using(cx)) } })), ) + .render().await +} +``` + +## Plantillas + +Bootsier ofrece dos plantillas (`BootsierTemplates`): `Standard`, con cabecera, contenido y pie, +que es la plantilla por defecto de cualquier página; y `Admin`, con la shell completa de +AdminLTE 4 (barra superior + barra lateral + área de contenido), que se activa creando la página +con `Page::admin()` en lugar de `Page::new()`. + +```rust,no_run +use pagetop::prelude::*; + +async fn about(request: HttpRequest) -> Result { + Page::new(request) + .with_child(Html::with(|_| html! { + h1 { "Sobre nosotros" } + p { "Texto de presentación." } + })) .render() } ``` +## Barra lateral + +Registra elementos en `BootsierRegion::Sidebar` para poblar la barra lateral de la shell. Los +elementos esperados son `theme::sidebar::Item` y `theme::sidebar::Section`. + +De forma **global** (visibles en todas las páginas de administración): + +```rust,no_run +use pagetop::prelude::*; +use pagetop_bootsier::theme::{BootsierRegion, sidebar}; + +fn register_navigation() { + InRegion::Global(&BootsierRegion::Sidebar) + .add(sidebar::Section::titled(Lc::n("Administración"))) + .add(sidebar::Item::link(Lc::n("Usuarios"), "/users", "people")) + .add(sidebar::Item::link(Lc::n("Roles"), "/roles", "shield-check")); +} +``` + +O de forma **por página**: + +```rust,no_run +use pagetop::prelude::*; +use pagetop_bootsier::theme::{BootsierRegion, sidebar}; + +async fn settings(request: HttpRequest) -> Result { + Page::admin(request) + .with_child_in( + &BootsierRegion::Sidebar, + sidebar::Item::link(Lc::n("Ajustes"), "/settings", "gear"), + ) + .with_child(Html::with(|_| html! { h3 { "Ajustes" } })) + .render() +} +``` + +## Barra de navegación superior + +La barra superior incluye por defecto los controles de pantalla completa y selector +de tema. Para añadir elementos adicionales en el lado derecho (por ejemplo, el +dropdown de usuario de `pagetop-user`), registra componentes en +`BootsierRegion::Navbar`: + +```rust,no_run +use pagetop::prelude::*; +use pagetop_bootsier::theme::BootsierRegion; + +InRegion::Global(&BootsierRegion::Navbar) + .add(Html::with(|_| html! { + li class="nav-item" { + a class="nav-link" href="/logout" { "Cerrar sesión" } + } + })); +``` + ## Créditos Este *crate* integra la biblioteca de estilos [Bootstrap 5.3.8](https://getbootstrap.com/) para diff --git a/extensions/pagetop-bootsier/assets/_bootsier-custom.scss b/extensions/pagetop-bootsier/assets/_bootsier-custom.scss index f4c6d5d0..fb77c8b9 100644 --- a/extensions/pagetop-bootsier/assets/_bootsier-custom.scss +++ b/extensions/pagetop-bootsier/assets/_bootsier-custom.scss @@ -1,4 +1,4 @@ -// Bootsier CSS rules: self-hosted fonts, form components, and regions. +// Bootsier CSS rules: self-hosted fonts, form elements, regions and components. // Self-hosted Source Sans 3 (SIL OFL 1.1), served from /bootsier/fonts. // Required by AdminLTE 4, which declares it as the primary font family in $font-family-sans-serif. @@ -39,6 +39,15 @@ } } +// Button set (button::ButtonSet): spaces its buttons with a gap instead of relying on Bootstrap's +// .btn-group, which merges adjacent buttons into a single joined control. +.button-set { + display: flex; + flex-wrap: wrap; + gap: $spacer * .5; + margin: 1rem 0; +} + // Fieldset with border and floating legend. fieldset { position: relative; @@ -83,3 +92,153 @@ fieldset > legend { padding: 0.75rem 0 3rem; text-align: center; } + +// Messages component. Classes are fixed by pagetop core (`.message`, `.message-info`, +// `.message-warning`, `.message-error`); reusing Bootstrap's own `.alert`/`.alert-*` styles keeps +// the palette in sync with the active Bootstrap theme instead of duplicating it here. +.message { + @extend .alert; +} +.message-info { + @extend .alert-info; +} +.message-warning { + @extend .alert-warning; +} +.message-error { + @extend .alert-danger; +} + +// Sort indicator on sortable table headers (`table::SortLink`), using Bootstrap Icons' +// sort-up/sort-down glyphs instead of the plain triangle from basic.css. +.table-sort::after { + font-family: $bootstrap-icons-font; + content: "\f575"; // sort-down + margin-left: 0.25rem; + font-size: 0.8em; + opacity: 0.35; +} +.table-sort-asc::after { + content: "\f57b"; // sort-up + opacity: 1; +} +.table-sort-desc::after { + content: "\f575"; // sort-down + opacity: 1; +} + +// Pager component. +// `.pagination`, `.page-item`, `.page-link`, `.active` and `.disabled` already come styled by +// Bootstrap, since Pager reuses that same markup (the ellipsis is a disabled `.page-link` span, +// same as any other cell). Only what Pager adds on top needs rules here: the