use maud::{html, Markup, PreEscaped};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Orientation {
Horizontal,
Vertical,
}
impl Orientation {
fn class_name(self) -> &'static str {
match self {
Orientation::Horizontal => "mui-button-group--horizontal",
Orientation::Vertical => "mui-button-group--vertical",
}
}
fn aria_value(self) -> &'static str {
match self {
Orientation::Horizontal => "horizontal",
Orientation::Vertical => "vertical",
}
}
fn opposite(self) -> Self {
match self {
Orientation::Horizontal => Orientation::Vertical,
Orientation::Vertical => Orientation::Horizontal,
}
}
}
pub fn separator(orientation: Orientation) -> Markup {
html! {
div class="mui-button-group__separator" role="separator"
aria-orientation=(orientation.aria_value()) {}
}
}
pub fn separator_for_group(group_orientation: Orientation) -> Markup {
separator(group_orientation.opposite())
}
pub fn text(children: Markup) -> Markup {
html! {
div class="mui-button-group__text" {
(children)
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Mode {
Exclusive,
Multiple,
}
impl Mode {
fn attr(self) -> &'static str {
match self {
Mode::Exclusive => "exclusive",
Mode::Multiple => "multiple",
}
}
}
#[derive(Clone, Debug)]
pub struct Props {
pub children: Markup,
pub orientation: Orientation,
pub size: Option<String>,
pub mode: Option<Mode>,
}
impl Default for Props {
fn default() -> Self {
Self {
children: html! {},
orientation: Orientation::Horizontal,
size: None,
mode: None,
}
}
}
pub fn render(props: Props) -> Markup {
let mut class = "mui-button-group".to_string();
class.push(' ');
class.push_str(props.orientation.class_name());
if let Some(size) = props.size {
class.push(' ');
class.push_str(&size);
}
let data_mui = props
.mode
.map(|_| r#" data-mui="button-group""#)
.unwrap_or("");
let data_mode = props
.mode
.map(|m| format!(r#" data-mode="{}""#, m.attr()))
.unwrap_or_default();
let aria_orientation = if props.orientation == Orientation::Vertical {
r#" aria-orientation="vertical""#
} else {
""
};
html! {
(PreEscaped(format!(
r#"<div class="{}" role="group"{}{}{}>"#,
class, aria_orientation, data_mui, data_mode,
)))
(props.children)
(PreEscaped("</div>"))
}
}
pub fn showcase() -> Markup {
let buttons_align = html! {
button type="button" class="mui-btn mui-btn--outline mui-btn--md" aria-pressed="true" aria-label="Align left" {
span aria-hidden="true" { "\u{2630}" }
" Left"
}
button type="button" class="mui-btn mui-btn--outline mui-btn--md" aria-label="Align center" {
span aria-hidden="true" { "\u{2261}" }
" Center"
}
button type="button" class="mui-btn mui-btn--outline mui-btn--md" aria-label="Align right" {
span aria-hidden="true" { "\u{268c}" }
" Right"
}
};
let buttons_format = html! {
button type="button" class="mui-btn mui-btn--outline mui-btn--md" aria-pressed="true" aria-label="Bold" {
strong { "B" }
}
button type="button" class="mui-btn mui-btn--outline mui-btn--md" aria-label="Italic" {
em { "I" }
}
button type="button" class="mui-btn mui-btn--outline mui-btn--md" aria-label="Underline" {
span style="text-decoration:underline;" { "U" }
}
};
let buttons_view = html! {
button type="button" class="mui-btn mui-btn--outline mui-btn--md" aria-pressed="true" {
span aria-hidden="true" { "\u{25a6}" }
" Grid"
}
button type="button" class="mui-btn mui-btn--outline mui-btn--md" {
span aria-hidden="true" { "\u{2630}" }
" List"
}
button type="button" class="mui-btn mui-btn--outline mui-btn--md" {
span aria-hidden="true" { "\u{25a7}" }
" Board"
}
};
let buttons_pager_separator = html! {
button type="button" class="mui-btn mui-btn--outline mui-btn--sm" {
span aria-hidden="true" { "\u{2039}" }
" Prev"
}
(separator_for_group(Orientation::Horizontal))
button type="button" class="mui-btn mui-btn--outline mui-btn--sm" {
"Next "
span aria-hidden="true" { "\u{203a}" }
}
};
let buttons_pager_text = html! {
(text(html! { "Page 1 of 10" }))
button type="button" class="mui-btn mui-btn--outline mui-btn--md" {
span aria-hidden="true" { "\u{2039}" }
" Prev"
}
button type="button" class="mui-btn mui-btn--outline mui-btn--md" {
"Next "
span aria-hidden="true" { "\u{203a}" }
}
};
html! {
div.mui-showcase__grid {
section {
h2 { "Text alignment toolbar" }
p.mui-showcase__caption { "Editor toolbar — exactly one alignment active at a time. Click or use ← / → to switch." }
div.mui-showcase__row {
(render(Props {
children: buttons_align,
orientation: Orientation::Horizontal,
size: None,
mode: Some(Mode::Exclusive),
}))
}
}
section {
h2 { "Text formatting" }
p.mui-showcase__caption { "Rich-text controls — each toggle independent (Bold currently on). Click any to flip." }
div.mui-showcase__row {
(render(Props {
children: buttons_format,
orientation: Orientation::Horizontal,
size: None,
mode: Some(Mode::Multiple),
}))
}
}
section {
h2 { "View switcher" }
p.mui-showcase__caption { "Project listing view — Grid / List / Board (Grid active)." }
div.mui-showcase__row {
(render(Props {
children: buttons_view,
orientation: Orientation::Horizontal,
size: None,
mode: Some(Mode::Exclusive),
}))
}
}
section {
h2 { "Pager with separator" }
p.mui-showcase__caption { "Sm-size pager — [Prev] [separator] [Next]. The separator is a vertical rule between buttons in a horizontal group." }
div.mui-showcase__row {
(render(Props {
children: buttons_pager_separator,
orientation: Orientation::Horizontal,
size: None,
mode: None,
}))
}
}
section {
h2 { "Pager with text indicator" }
p.mui-showcase__caption { "Non-interactive text cell — [Page 1 of 10] [Prev] [Next]. Useful for status read-outs inside toolbars." }
div.mui-showcase__row {
(render(Props {
children: buttons_pager_text,
orientation: Orientation::Horizontal,
size: None,
mode: None,
}))
}
}
}
}
}