From 01e33afd938bb0553ec4aba0bc7fa42b9cabff47 Mon Sep 17 00:00:00 2001 From: JMARyA Date: Mon, 20 Jan 2025 12:18:27 +0100 Subject: [PATCH] background --- src/ui/color.rs | 78 +++++++++ src/ui/components/appbar.rs | 10 +- src/ui/primitives/background.rs | 288 +++++++++++++++++++++++++++++++- 3 files changed, 363 insertions(+), 13 deletions(-) diff --git a/src/ui/color.rs b/src/ui/color.rs index c42e898..4671712 100644 --- a/src/ui/color.rs +++ b/src/ui/color.rs @@ -133,3 +133,81 @@ impl UIColor for Colors { } } } + +// TODO : Gradient + +pub struct Gradient { + start: Box, + middle: Option>, + end: Option>, + pos_start: Option, + pos_middle: Option, + pos_end: Option, +} + +impl Gradient { + pub fn from(start: C) -> Self { + Self { + start: Box::new(start), + middle: None, + end: None, + pos_end: None, + pos_middle: None, + pos_start: None, + } + } + + pub fn via(mut self, middle: C) -> Self { + self.middle = Some(Box::new(middle)); + self + } + + pub fn to(mut self, end: C) -> Self { + self.end = Some(Box::new(end)); + self + } + + pub fn step_start(mut self, percentage: u8) -> Self { + assert!(percentage <= 100, "Percentage should be under 100%"); + self.pos_start = Some(percentage); + self + } + + pub fn step_middle(mut self, percentage: u8) -> Self { + assert!(percentage <= 100, "Percentage should be under 100%"); + self.pos_middle = Some(percentage); + self + } + + pub fn step_end(mut self, percentage: u8) -> Self { + assert!(percentage <= 100, "Percentage should be under 100%"); + self.pos_end = Some(percentage); + self + } + + pub fn color_class(&self) -> Vec { + let mut classes = vec![format!("from-{}", self.start.color_class())]; + + if let Some(via) = &self.middle { + classes.push(format!("via-{}", via.color_class())); + } + + if let Some(end) = &self.end { + classes.push(format!("to-{}", end.color_class())); + } + + if let Some(step) = &self.pos_start { + classes.push(format!("from-{step}%")); + } + + if let Some(step) = &self.pos_middle { + classes.push(format!("via-{step}%")); + } + + if let Some(step) = &self.pos_end { + classes.push(format!("to-{step}%")); + } + + classes + } +} diff --git a/src/ui/components/appbar.rs b/src/ui/components/appbar.rs index 50fbbb8..8145568 100644 --- a/src/ui/components/appbar.rs +++ b/src/ui/components/appbar.rs @@ -38,9 +38,8 @@ impl UIWidget for AppBarWidget { } fn render_with_class(&self, _: &str) -> Markup { - Padding(Shadow::medium(Background( - Gray::_800, - Header( + Padding(Shadow::medium( + Background(Header( Padding( Flex( Div() @@ -70,8 +69,9 @@ impl UIWidget for AppBarWidget { .items_center(), ) .x(ScreenValue::_6), - ), - ))) + )) + .color(Gray::_800), + )) .y(ScreenValue::_2) .render() } diff --git a/src/ui/primitives/background.rs b/src/ui/primitives/background.rs index e07503e..dbd000f 100644 --- a/src/ui/primitives/background.rs +++ b/src/ui/primitives/background.rs @@ -1,16 +1,98 @@ use maud::{Markup, Render, html}; -use crate::ui::{UIWidget, color::UIColor}; +use crate::ui::{ + UIWidget, + color::{Gradient, UIColor}, +}; #[allow(non_snake_case)] -pub fn Background( - color: C, - inner: T, -) -> BackgroundWidget { - BackgroundWidget(Box::new(inner), Box::new(color)) +pub fn Background(inner: T) -> BackgroundWidget { + BackgroundWidget( + Box::new(inner), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ) } -pub struct BackgroundWidget(Box, Box); +pub struct BackgroundWidget( + // Inner + Box, + // Background Color + Option>, + // Background Attachment + Option, + Option, + Option, + Option, + Option, + // Background Image URL + Option, + // Gradient + Option, + Option, + Option, +); + +impl BackgroundWidget { + pub fn color(mut self, color: C) -> Self { + self.1 = Some(Box::new(color)); + self + } + + pub fn image(mut self, url: &str) -> Self { + self.7 = Some(url.to_string()); + self + } + + pub fn none(mut self) -> Self { + self.8 = Some(BackgroundGradient::None); + self + } + + pub fn gradient(mut self, direction: BackgroundGradient, gradient: Gradient) -> Self { + self.8 = Some(direction); + self.9 = Some(gradient); + self + } + + pub fn position(mut self, position: BackgroundPosition) -> Self { + self.10 = Some(position); + self + } + + pub fn scroll(mut self, attachment: BackgroundScrollAttachment) -> Self { + self.2 = Some(attachment); + self + } + + pub fn clip(mut self, clip: BackgroundClip) -> Self { + self.3 = Some(clip); + self + } + + pub fn origin(mut self, origin: BackgroundOrigin) -> Self { + self.4 = Some(origin); + self + } + + pub fn repeat(mut self, repeat: BackgroundRepeat) -> Self { + self.5 = Some(repeat); + self + } + + pub fn size(mut self, size: BackgroundSize) -> Self { + self.6 = Some(size); + self + } +} impl Render for BackgroundWidget { fn render(&self) -> Markup { @@ -24,7 +106,49 @@ impl UIWidget for BackgroundWidget { } fn base_class(&self) -> Vec { - vec![format!("bg-{}", self.1.color_class())] + let mut ret = Vec::new(); + + if let Some(color) = &self.1 { + ret.push(format!("bg-{}", color.color_class())); + } + + if let Some(attachment) = &self.2 { + ret.push(attachment.to_value().to_string()); + } + + if let Some(clip) = &self.3 { + ret.push(clip.to_value().to_string()); + } + + if let Some(origin) = &self.4 { + ret.push(origin.to_value().to_string()); + } + + if let Some(repeat) = &self.5 { + ret.push(repeat.to_value().to_string()); + } + + if let Some(size) = &self.6 { + ret.push(size.to_value().to_string()); + } + + if let Some(image) = &self.7 { + ret.push(format!("bg-[url('{image}')]")); + } + + if let Some(gradient) = &self.8 { + ret.push(gradient.to_value().to_string()); + } + + if let Some(gradient) = &self.9 { + ret.extend_from_slice(&gradient.color_class()); + } + + if let Some(position) = &self.10 { + ret.push(position.to_value().to_string()); + } + + ret } fn extended_class(&self) -> Vec { @@ -47,3 +171,151 @@ impl UIWidget for BackgroundWidget { } } } + +/// Controlling how a background image behaves when scrolling. +pub enum BackgroundScrollAttachment { + /// Fix the background image relative to the viewport. + Fixed, + /// Scroll the background image with the container and the viewport. + Local, + /// Scroll the background image with the viewport, but not with the container. + Scroll, +} + +impl BackgroundScrollAttachment { + pub const fn to_value(&self) -> &str { + match self { + BackgroundScrollAttachment::Fixed => "bg-fixed", + BackgroundScrollAttachment::Local => "bg-local", + BackgroundScrollAttachment::Scroll => "bg-scroll", + } + } +} + +pub enum BackgroundClip { + Border, + Padding, + Content, + Text, +} + +impl BackgroundClip { + pub const fn to_value(&self) -> &str { + match self { + BackgroundClip::Border => "bg-clip-border", + BackgroundClip::Padding => "bg-clip-padding", + BackgroundClip::Content => "bg-clip-content", + BackgroundClip::Text => "bg-clip-text", + } + } +} + +pub enum BackgroundOrigin { + Border, + Padding, + Content, +} + +impl BackgroundOrigin { + pub const fn to_value(&self) -> &str { + match self { + BackgroundOrigin::Border => "bg-origin-border", + BackgroundOrigin::Padding => "bg-origin-padding", + BackgroundOrigin::Content => "bg-origin-content", + } + } +} + +pub enum BackgroundRepeat { + Repeat, + NoRepeat, + RepeatX, + RepeatY, + Round, + Space, +} + +impl BackgroundRepeat { + pub const fn to_value(&self) -> &str { + match self { + BackgroundRepeat::Repeat => "bg-repeat", + BackgroundRepeat::NoRepeat => "bg-no-repeat", + BackgroundRepeat::RepeatX => "bg-repeat-x", + BackgroundRepeat::RepeatY => "bg-repeat-y", + BackgroundRepeat::Round => "bg-repeat-round", + BackgroundRepeat::Space => "bg-repeat-space", + } + } +} + +pub enum BackgroundSize { + Auto, + Cover, + Contain, +} + +impl BackgroundSize { + pub const fn to_value(&self) -> &str { + match self { + BackgroundSize::Auto => "bg-auto", + BackgroundSize::Cover => "bg-cover", + BackgroundSize::Contain => "bg-contain", + } + } +} + +pub enum BackgroundGradient { + None, + ToTop, + ToTopRight, + ToRight, + ToBottomRight, + ToBottom, + ToBottomLeft, + ToLeft, + ToTopLeft, +} + +impl BackgroundGradient { + pub const fn to_value(&self) -> &str { + match self { + BackgroundGradient::None => "bg-none", + BackgroundGradient::ToTop => "bg-gradient-to-t", + BackgroundGradient::ToTopRight => "bg-gradient-to-tr", + BackgroundGradient::ToRight => "bg-gradient-to-r", + BackgroundGradient::ToBottomRight => "bg-gradient-to-br", + BackgroundGradient::ToBottom => "bg-gradient-to-b", + BackgroundGradient::ToBottomLeft => "bg-gradient-to-bl", + BackgroundGradient::ToLeft => "bg-gradient-to-l", + BackgroundGradient::ToTopLeft => "bg-gradient-to-tl", + } + } +} + +pub enum BackgroundPosition { + Bottom, + Center, + Left, + LeftBottom, + LeftTop, + Right, + RightBottom, + RightTop, + Top, +} + +impl BackgroundPosition { + pub const fn to_value(&self) -> &str { + match self { + BackgroundPosition::Bottom => "bg-bottom", + BackgroundPosition::Center => "bg-center", + BackgroundPosition::Left => "bg-left", + BackgroundPosition::LeftBottom => "bg-left-bottom", + BackgroundPosition::LeftTop => "bg-left-top", + BackgroundPosition::Right => "bg-right", + BackgroundPosition::RightBottom => "bg-right-bottom", + BackgroundPosition::RightTop => "bg-right-top", + BackgroundPosition::Top => "bg-top", + } + } +}