From a79da3d7970aaef3c978b09acdd6f6f89516d563 Mon Sep 17 00:00:00 2001 From: JMARyA Date: Sun, 23 Feb 2025 00:53:33 +0100 Subject: [PATCH] update --- src/asset.rs | 17 +++++------ src/ui/components/appbar.rs | 2 -- src/ui/components/indicator.rs | 4 +++ src/ui/components/mod.rs | 17 +++++++++-- src/ui/components/modal.rs | 54 ++++++++++++++++----------------- src/ui/components/shell.rs | 11 +++---- src/ui/mod.rs | 10 +++--- src/ui/primitives/grid.rs | 34 +++++++++------------ src/ui/primitives/input/form.rs | 4 +-- src/ui/primitives/input/mod.rs | 3 +- src/ui/primitives/list.rs | 4 +++ 11 files changed, 84 insertions(+), 76 deletions(-) diff --git a/src/asset.rs b/src/asset.rs index 2a929f9..0239eda 100644 --- a/src/asset.rs +++ b/src/asset.rs @@ -52,15 +52,12 @@ pub trait AssetRoutes { impl AssetRoutes for rocket::Rocket { fn mount_assets(self) -> Self { - self.mount( - "/", - routes![ - crate::asset::htmx_script_route, - crate::asset::flowbite_css, - crate::asset::flowbite_js, - crate::asset::material_css, - crate::asset::material_font - ], - ) + self.mount("/", routes![ + crate::asset::htmx_script_route, + crate::asset::flowbite_css, + crate::asset::flowbite_js, + crate::asset::material_css, + crate::asset::material_font + ]) } } diff --git a/src/ui/components/appbar.rs b/src/ui/components/appbar.rs index aaaf378..263bf15 100644 --- a/src/ui/components/appbar.rs +++ b/src/ui/components/appbar.rs @@ -1,5 +1,3 @@ -use maud::{Markup, Render}; - use crate::auth::User; use crate::ui::primitives::Optional; diff --git a/src/ui/components/indicator.rs b/src/ui/components/indicator.rs index bb22beb..cfff2ea 100644 --- a/src/ui/components/indicator.rs +++ b/src/ui/components/indicator.rs @@ -4,12 +4,14 @@ use crate::ui::{UIWidget, color::UIColor}; use super::ColorCircle; +#[allow(non_snake_case)] pub fn Indicator(color: C) -> PreEscaped { html! { span class=(format!("flex w-3 h-3 me-3 bg-{} rounded-full", color.color_class())) {}; } } +#[allow(non_snake_case)] pub fn IndicatorLegend(color: C, legend: &str) -> PreEscaped { html! { span class="flex items-center text-sm font-medium text-gray-900 dark:text-white me-3" { @@ -19,6 +21,7 @@ pub fn IndicatorLegend(color: C, legend: &str) -> PreEscap } } +#[allow(non_snake_case)] pub fn NumberIndicator(on: T, amount: u32) -> PreEscaped { html! { div class="relative items-center max-w-fit" { @@ -28,6 +31,7 @@ pub fn NumberIndicator(on: T, amount: u32) -> PreEscaped< } } +#[allow(non_snake_case)] pub fn BadgeIndicator( color: C, dark_color: C, diff --git a/src/ui/components/mod.rs b/src/ui/components/mod.rs index d3e5219..817e002 100644 --- a/src/ui/components/mod.rs +++ b/src/ui/components/mod.rs @@ -15,7 +15,7 @@ pub mod prelude { pub use super::appbar::AppBar; pub use super::avatar::{Avatar, AvatarStack}; pub use super::htmx::{ClickToLoad, InfinityScroll, LazyLoad}; - pub use super::icon::MaterialIcon; + pub use super::icon::{ColoredMaterialIcon, MaterialIcon}; pub use super::indicator::{BadgeIndicator, Indicator, IndicatorLegend, NumberIndicator}; pub use super::modal::{Modal, ModalCloseButton, ModalOpenButton}; pub use super::overlay::{ @@ -31,6 +31,7 @@ pub mod prelude { Alignment, BottomNavigation, BottomNavigationTile, Classic, ClassicWidget, FetchToast, NavBar, Position, Shell, Toast, }; + pub use super::timeline::{ActivityLog, ActivityLogElement, Timeline, TimelineElement}; pub use super::{ Accordion, Alert, Banner, Breadcrumb, Card, Carousel, CarouselMode, ColoredAlert, ColoredSpinner, CopyText, FetchAlert, FnKey, HelpIcon, HorizontalLine, IconStepper, @@ -56,12 +57,14 @@ pub fn HorizontalLine() -> PreEscaped { } } +#[allow(non_snake_case)] pub fn FnKey(key: &str) -> PreEscaped { html! { kbd class="px-2 py-1.5 text-xs font-semibold text-gray-800 bg-gray-100 border border-gray-200 rounded-lg dark:bg-gray-600 dark:text-gray-100 dark:border-gray-500" { (key) }; } } +#[allow(non_snake_case)] pub fn ColoredSpinner(color: T) -> PreEscaped { let col = color.color_class(); html! { @@ -80,6 +83,7 @@ pub fn Spinner() -> PreEscaped { ColoredSpinner(super::color::Blue::_600) } +#[allow(non_snake_case)] pub fn CopyText(txt: &str) -> PreEscaped { let id = uuid::Uuid::new_v4().to_string(); @@ -739,12 +743,14 @@ impl UIWidget for StepperWidget { pub struct TabWidget { pub content: Vec<(PreEscaped, String, Box)>, + pub active: String, } #[allow(non_snake_case)] pub fn Tabs() -> TabWidget { TabWidget { content: Vec::new(), + active: String::new(), } } @@ -759,6 +765,11 @@ impl TabWidget { .push((tab.render(), id.to_string(), Box::new(body))); self } + + pub fn active(mut self, id: &str) -> Self { + self.active = id.to_string(); + self + } } impl Render for TabWidget { @@ -789,11 +800,11 @@ impl UIWidget for TabWidget { @for (i, (head, id, _)) in self.content.iter().enumerate() { li class=(if i == self.content.len() { "" } else { "me-2" }) role="presentation" { button class="inline-block p-4 border-b-2 rounded-t-lg" - data-tabs-target=(format!("#{id}")) + data-tabs-target=(format!("#{id}"))x type="button" role="tab" aria-controls=(id) - aria-selected="false" { (head) }; + aria-selected=(if *id == self.active { "true" } else { "false" }) { (head) }; } }; } diff --git a/src/ui/components/modal.rs b/src/ui/components/modal.rs index 17f80a8..a248df5 100644 --- a/src/ui/components/modal.rs +++ b/src/ui/components/modal.rs @@ -1,7 +1,8 @@ -use maud::{PreEscaped, Render, html}; +use maud::{PreEscaped, html}; use crate::ui::UIWidget; +#[allow(non_snake_case)] pub fn ModalCloseButton(modal: &str, inner: T) -> PreEscaped { html! { button @@ -10,6 +11,7 @@ pub fn ModalCloseButton(modal: &str, inner: T) -> PreEsca } } +#[allow(non_snake_case)] pub fn ModalOpenButton(modal: &str, inner: T) -> PreEscaped { html! { button @@ -19,6 +21,7 @@ pub fn ModalOpenButton(modal: &str, inner: T) -> PreEscap } } +#[allow(non_snake_case)] pub fn Modal E>( title: &str, body: T, @@ -26,32 +29,29 @@ pub fn Modal ) -> (String, PreEscaped) { let id = uuid::Uuid::new_v4().to_string(); - ( - format!("modal-{id}"), - html! { - div id=(format!("modal-{id}")) tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full" { - div class="relative p-4 w-full max-w-2xl max-h-full" { + (format!("modal-{id}"), html! { + div id=(format!("modal-{id}")) tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full" { + div class="relative p-4 w-full max-w-2xl max-h-full" { - div class="relative bg-white rounded-lg shadow dark:bg-gray-700" { - div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600" { - h3 class="text-xl font-semibold text-gray-900 dark:text-white" { (title) } - button type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white" data-modal-hide=(format!("modal-{id}")) { - svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14" { - path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" {}; - }; - span class="sr-only" { "Close modal" }; - } - }; - - div class="p-4 md:p-5 space-y-4" { - (body) - }; - - div class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600" { - (footer(format!("modal-{id}"))) - }; + div class="relative bg-white rounded-lg shadow dark:bg-gray-700" { + div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600" { + h3 class="text-xl font-semibold text-gray-900 dark:text-white" { (title) } + button type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white" data-modal-hide=(format!("modal-{id}")) { + svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14" { + path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" {}; + }; + span class="sr-only" { "Close modal" }; + } }; - }}; - }, - ) + + div class="p-4 md:p-5 space-y-4" { + (body) + }; + + div class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600" { + (footer(format!("modal-{id}"))) + }; + }; + }}; + }) } diff --git a/src/ui/components/shell.rs b/src/ui/components/shell.rs index 85e3b79..ed5fd23 100644 --- a/src/ui/components/shell.rs +++ b/src/ui/components/shell.rs @@ -278,13 +278,10 @@ pub fn BottomNavigationTile( ) -> ClassicWidget { Classic( "inline-flex flex-col items-center justify-center px-5 hover:bg-gray-50 dark:hover:bg-gray-800 group", - Link( - reference, - html! { - (icon.map(|x| x.render()).unwrap_or_default()); - span class="text-sm text-gray-500 dark:text-gray-400 group-hover:text-blue-600 dark:group-hover:text-blue-500" { (text) }; - }, - ), + Link(reference, html! { + (icon.map(|x| x.render()).unwrap_or_default()); + span class="text-sm text-gray-500 dark:text-gray-400 group-hover:text-blue-600 dark:group-hover:text-blue-500" { (text) }; + }), ) } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 34d59cd..a5308dc 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -38,8 +38,8 @@ pub mod prelude { MixBlendMode, Opacity, Saturate, Sepia, }; pub use super::primitives::flex::{ - AlignContent, AlignItems, Direction, DivideStyle, DivideWidth, Flex, FlexBasis, FlexGrow, - Justify, JustifyItems, Order, Strategy, Wrap, + AlignContent, AlignItems, Column, Direction, DivideStyle, DivideWidth, Flex, FlexBasis, + FlexGrow, Justify, JustifyItems, Order, Row, Strategy, Wrap, }; pub use super::primitives::grid::{ Columns, Grid, GridAmount, GridAutoFlow, GridAutoSize, GridElementColumn, GridElementRow, @@ -53,7 +53,7 @@ pub mod prelude { Range, Select, TextArea, TextInput, TimePicker, Toggle, }; pub use super::primitives::link::Link; - pub use super::primitives::list::{OrderedList, UnorderedList}; + pub use super::primitives::list::{HorizontalList, ListEntry, OrderedList, UnorderedList}; pub use super::primitives::margin::Margin; pub use super::primitives::padding::Padding; pub use super::primitives::position::{ @@ -79,7 +79,9 @@ pub mod prelude { }; pub use super::primitives::visibility::Visibility; pub use super::primitives::width::{MaxWidth, MinWidth, Width}; - pub use super::primitives::{Context, NoBrowserAppearance, Nothing, Side, Size, script}; + pub use super::primitives::{ + Context, NoBrowserAppearance, Nothing, Optional, Side, Size, script, + }; pub use super::wrapper::{ _2XLScreen, Hover, LargeScreen, MediumScreen, Screen, SmallScreen, XLScreen, }; diff --git a/src/ui/primitives/grid.rs b/src/ui/primitives/grid.rs index 31d46c1..cd1e345 100644 --- a/src/ui/primitives/grid.rs +++ b/src/ui/primitives/grid.rs @@ -274,25 +274,21 @@ impl GridElement { } pub fn span(mut self, value: GridElementValue) -> Self { - self.1.push(format!( - "{}-span-{}", - self.2, - match value { - GridElementValue::_1 => "1", - GridElementValue::_2 => "2", - GridElementValue::_3 => "3", - GridElementValue::_4 => "4", - GridElementValue::_5 => "5", - GridElementValue::_6 => "6", - GridElementValue::_7 => "7", - GridElementValue::_8 => "8", - GridElementValue::_9 => "9", - GridElementValue::_10 => "10", - GridElementValue::_11 => "11", - GridElementValue::_12 => "12", - GridElementValue::Auto => "full", - } - )); + self.1.push(format!("{}-span-{}", self.2, match value { + GridElementValue::_1 => "1", + GridElementValue::_2 => "2", + GridElementValue::_3 => "3", + GridElementValue::_4 => "4", + GridElementValue::_5 => "5", + GridElementValue::_6 => "6", + GridElementValue::_7 => "7", + GridElementValue::_8 => "8", + GridElementValue::_9 => "9", + GridElementValue::_10 => "10", + GridElementValue::_11 => "11", + GridElementValue::_12 => "12", + GridElementValue::Auto => "full", + })); self } diff --git a/src/ui/primitives/input/form.rs b/src/ui/primitives/input/form.rs index 51d6ffb..b9ba8b3 100644 --- a/src/ui/primitives/input/form.rs +++ b/src/ui/primitives/input/form.rs @@ -1,6 +1,4 @@ -use std::{collections::HashMap, fmt::Write}; - -use maud::{Markup, PreEscaped, Render, html}; +use maud::{Markup, Render, html}; use crate::{ auth::{User, csrf::CSRF}, diff --git a/src/ui/primitives/input/mod.rs b/src/ui/primitives/input/mod.rs index 9402a40..5feb21d 100644 --- a/src/ui/primitives/input/mod.rs +++ b/src/ui/primitives/input/mod.rs @@ -93,7 +93,7 @@ impl UIWidget for TextInputWidget { Vec::new() } - fn render_with_class(&self, class: &str) -> Markup { + fn render_with_class(&self, _: &str) -> Markup { let mut attrs = self.attrs.clone(); if self.password { @@ -303,6 +303,7 @@ pub struct NumberInputWidget { buttons: bool, } +#[allow(non_snake_case)] pub fn NumberInput() -> NumberInputWidget { NumberInputWidget { inner: None, diff --git a/src/ui/primitives/list.rs b/src/ui/primitives/list.rs index 447fb4c..160bc86 100644 --- a/src/ui/primitives/list.rs +++ b/src/ui/primitives/list.rs @@ -116,6 +116,7 @@ impl UIWidget for ListWidget { // TODO : List data backed list + reorderable + add + remove + crud +#[allow(non_snake_case)] pub fn CheckIconRounded() -> PreEscaped { html! { svg class="w-3.5 h-3.5 me-2 text-green-500 dark:text-green-400 shrink-0" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20" { @@ -124,6 +125,7 @@ pub fn CheckIconRounded() -> PreEscaped { } } +#[allow(non_snake_case)] pub fn CheckIconRoundedGray() -> PreEscaped { html! { svg class="w-3.5 h-3.5 me-2 text-gray-500 dark:text-gray-400 shrink-0" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20" { @@ -132,6 +134,7 @@ pub fn CheckIconRoundedGray() -> PreEscaped { } } +#[allow(non_snake_case)] pub fn ListEntry( icon: I, inner: T, @@ -144,6 +147,7 @@ pub fn ListEntry( } } +#[allow(non_snake_case)] pub fn CheckIcon() -> PreEscaped { html! { svg class="shrink-0 w-3.5 h-3.5 text-green-500 dark:text-green-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 12" {