background

This commit is contained in:
JMARyA 2025-01-20 12:18:27 +01:00
parent ddd2e363c2
commit 01e33afd93
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
3 changed files with 363 additions and 13 deletions

View file

@ -133,3 +133,81 @@ impl UIColor for Colors {
} }
} }
} }
// TODO : Gradient
pub struct Gradient {
start: Box<dyn UIColor>,
middle: Option<Box<dyn UIColor>>,
end: Option<Box<dyn UIColor>>,
pos_start: Option<u8>,
pos_middle: Option<u8>,
pos_end: Option<u8>,
}
impl Gradient {
pub fn from<C: UIColor + 'static>(start: C) -> Self {
Self {
start: Box::new(start),
middle: None,
end: None,
pos_end: None,
pos_middle: None,
pos_start: None,
}
}
pub fn via<C: UIColor + 'static>(mut self, middle: C) -> Self {
self.middle = Some(Box::new(middle));
self
}
pub fn to<C: UIColor + 'static>(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<String> {
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
}
}

View file

@ -38,9 +38,8 @@ impl UIWidget for AppBarWidget {
} }
fn render_with_class(&self, _: &str) -> Markup { fn render_with_class(&self, _: &str) -> Markup {
Padding(Shadow::medium(Background( Padding(Shadow::medium(
Gray::_800, Background(Header(
Header(
Padding( Padding(
Flex( Flex(
Div() Div()
@ -70,8 +69,9 @@ impl UIWidget for AppBarWidget {
.items_center(), .items_center(),
) )
.x(ScreenValue::_6), .x(ScreenValue::_6),
), ))
))) .color(Gray::_800),
))
.y(ScreenValue::_2) .y(ScreenValue::_2)
.render() .render()
} }

View file

@ -1,16 +1,98 @@
use maud::{Markup, Render, html}; use maud::{Markup, Render, html};
use crate::ui::{UIWidget, color::UIColor}; use crate::ui::{
UIWidget,
color::{Gradient, UIColor},
};
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn Background<T: UIWidget + 'static, C: UIColor + 'static>( pub fn Background<T: UIWidget + 'static>(inner: T) -> BackgroundWidget {
color: C, BackgroundWidget(
inner: T, Box::new(inner),
) -> BackgroundWidget { None,
BackgroundWidget(Box::new(inner), Box::new(color)) None,
None,
None,
None,
None,
None,
None,
None,
None,
)
} }
pub struct BackgroundWidget(Box<dyn UIWidget>, Box<dyn UIColor>); pub struct BackgroundWidget(
// Inner
Box<dyn UIWidget>,
// Background Color
Option<Box<dyn UIColor>>,
// Background Attachment
Option<BackgroundScrollAttachment>,
Option<BackgroundClip>,
Option<BackgroundOrigin>,
Option<BackgroundRepeat>,
Option<BackgroundSize>,
// Background Image URL
Option<String>,
// Gradient
Option<BackgroundGradient>,
Option<Gradient>,
Option<BackgroundPosition>,
);
impl BackgroundWidget {
pub fn color<C: UIColor + 'static>(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 { impl Render for BackgroundWidget {
fn render(&self) -> Markup { fn render(&self) -> Markup {
@ -24,7 +106,49 @@ impl UIWidget for BackgroundWidget {
} }
fn base_class(&self) -> Vec<String> { fn base_class(&self) -> Vec<String> {
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<String> { fn extended_class(&self) -> Vec<String> {
@ -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",
}
}
}