pagetop/extensions/pagetop-bootsier/src/theme/class/button.rs

221 lines
6.4 KiB
Rust

use pagetop::prelude::*;
use crate::theme::ThemeColor;
// **< ButtonColor >********************************************************************************
/// Estilo visual aplicado al color de un botón ([`ButtonColor`]).
#[derive(AutoDefault, Clone, Copy, Debug, PartialEq)]
pub enum ButtonColorStyle {
/// Sin clase de color (estilo por defecto del tema).
#[default]
None,
/// Botón sólido: genera la clase `btn-{color}`.
Solid,
/// Botón con contorno: genera la clase `btn-outline-{color}`.
Outline,
/// Botón tipo enlace: genera la clase `btn-link`.
Link,
}
/// Clases para establecer el **color y estilo** de los botones.
///
/// # Ejemplos
///
/// ```rust,no_run
/// use pagetop::prelude::*;
/// use pagetop_bootsier::theme::*;
///
/// // Botón sólido.
/// let save = bs::Button::submit(L10n::n("Save"))
/// .with_prop(PropsOp::add_classes(class::ButtonColor::solid(ThemeColor::Primary)));
///
/// // Botón con contorno.
/// let cancel = bs::Button::plain(L10n::n("Cancel"))
/// .with_prop(PropsOp::add_classes(class::ButtonColor::outline(ThemeColor::Secondary)));
///
/// // Botón tipo enlace.
/// let back = bs::Button::plain(L10n::n("Back"))
/// .with_prop(PropsOp::add_classes(class::ButtonColor::link()));
/// ```
#[derive(AutoDefault, Clone, Copy, Debug, PartialEq)]
pub struct ButtonColor {
style: ButtonColorStyle,
color: ThemeColor,
}
impl ButtonColor {
/// Sin clase de color (estilo por defecto del tema).
pub fn new() -> Self {
Self::default()
}
/// Botón sólido: genera la clase `btn-{color}`.
pub fn solid(color: ThemeColor) -> Self {
Self {
style: ButtonColorStyle::Solid,
color,
..Default::default()
}
}
/// Botón con contorno: genera la clase `btn-outline-{color}`.
pub fn outline(color: ThemeColor) -> Self {
Self {
style: ButtonColorStyle::Outline,
color,
..Default::default()
}
}
/// Botón tipo enlace: genera la clase `btn-link`.
pub fn link() -> Self {
Self {
style: ButtonColorStyle::Link,
..Default::default()
}
}
// **< ButtonColor BUILDER >********************************************************************
/// Cambia el color aplicado al botón (`btn-*` o `btn-outline-*`).
pub fn with_color(mut self, color: ThemeColor) -> Self {
self.color = color;
self
}
/// Cambia el estilo aplicado al botón (sólido, contorno o enlace).
pub fn with_style(mut self, style: ButtonColorStyle) -> Self {
self.style = style;
self
}
// **< ButtonColor HELPERS >********************************************************************
/// Añade la clase `btn-*` a la cadena de clases.
#[rustfmt::skip]
#[inline]
pub fn push_to(self, classes: &mut String) {
let (prefix, suffix) = match self.style {
ButtonColorStyle::None => return,
ButtonColorStyle::Solid => ("btn-", self.color.as_str()),
ButtonColorStyle::Outline => ("btn-outline-", self.color.as_str()),
ButtonColorStyle::Link => ("btn-link", ""),
};
if !classes.is_empty() {
classes.push(' ');
}
classes.push_str(prefix);
classes.push_str(suffix);
}
/// Devuelve la clase `btn-*` correspondiente al color del botón.
///
/// Si no se ha definido ningún estilo, devuelve `""`.
pub fn to_class(self) -> String {
let mut class = String::new();
self.push_to(&mut class);
class
}
}
impl Into<CowStr> for ButtonColor {
/// Permite pasar [`ButtonColor`] directamente a [`PropsOp`](pagetop::prelude::PropsOp).
fn into(self) -> CowStr {
self.to_class().into()
}
}
// **< ButtonSize >*********************************************************************************
/// Tamaño aplicado a un botón ([`ButtonSize`]).
#[derive(AutoDefault, Clone, Copy, Debug, PartialEq)]
pub enum ButtonSizeKind {
/// Sin clase de tamaño (tamaño por defecto del tema).
#[default]
None,
/// Botón compacto: genera la clase `btn-sm`.
Small,
/// Botón grande: genera la clase `btn-lg`.
Large,
}
/// Clases para establecer el **tamaño** de los botones.
///
/// # Ejemplos
///
/// ```rust,no_run
/// use pagetop::prelude::*;
/// use pagetop_bootsier::theme::*;
///
/// let small = bs::Button::submit(L10n::n("Save"))
/// .with_prop(PropsOp::add_classes(class::ButtonSize::small()));
///
/// let large = bs::Button::submit(L10n::n("Save"))
/// .with_prop(PropsOp::add_classes(class::ButtonSize::large()));
/// ```
#[derive(AutoDefault, Clone, Copy, Debug, PartialEq)]
pub struct ButtonSize {
size: ButtonSizeKind,
}
impl ButtonSize {
/// Sin clase de tamaño (tamaño por defecto del tema).
pub fn new() -> Self {
Self::default()
}
/// Botón compacto: genera la clase `btn-sm`.
pub fn small() -> Self {
Self {
size: ButtonSizeKind::Small,
}
}
/// Botón grande: genera la clase `btn-lg`.
pub fn large() -> Self {
Self {
size: ButtonSizeKind::Large,
}
}
// **< ButtonSize BUILDER >*********************************************************************
/// Cambia el tamaño aplicado al botón.
pub fn with_size(mut self, size: ButtonSizeKind) -> Self {
self.size = size;
self
}
// **< ButtonSize HELPERS >*********************************************************************
/// Añade la clase `btn-sm` o `btn-lg` a la cadena de clases.
#[inline]
pub fn push_to(self, classes: &mut String) {
let class = match self.size {
ButtonSizeKind::None => return,
ButtonSizeKind::Small => "btn-sm",
ButtonSizeKind::Large => "btn-lg",
};
if !classes.is_empty() {
classes.push(' ');
}
classes.push_str(class);
}
/// Devuelve la clase `btn-sm` o `btn-lg` correspondiente al tamaño del botón.
///
/// Si no se ha definido ningún tamaño, devuelve `""`.
pub fn to_class(self) -> String {
let mut class = String::new();
self.push_to(&mut class);
class
}
}
impl Into<CowStr> for ButtonSize {
/// Permite pasar [`ButtonSize`] directamente a [`PropsOp`](pagetop::prelude::PropsOp).
fn into(self) -> CowStr {
self.to_class().into()
}
}