Move Images and Tiles into the toolkit
Add a Profile toolkit struct
This commit is contained in:
parent
f6f603324a
commit
c86f4b3ff2
|
@ -43,7 +43,7 @@ img {
|
|||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: scale-down;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.toolkit-select {
|
||||
|
@ -339,6 +339,64 @@ img {
|
|||
}
|
||||
}
|
||||
|
||||
.toolkit-tiles {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
||||
|
||||
.toolkit-tile {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
picture {
|
||||
display: block;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
img {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.toolkit-link {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
font-style: none;
|
||||
font-weight: 500;
|
||||
color: $border-light;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
color: $border-light;
|
||||
}
|
||||
}
|
||||
|
||||
.toolkit-tile--overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
text-shadow: 1px 1px 1px $dark;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.toolkit-title--meta p {
|
||||
margin: 0;
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.toolkit-centered {
|
||||
width: 100%;
|
||||
max-width: 900px;
|
||||
|
|
50
toolkit/src/banner.rs
Normal file
50
toolkit/src/banner.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
use crate::image::Image;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Banner {
|
||||
image: Option<Rc<dyn Image>>,
|
||||
dark: bool,
|
||||
}
|
||||
|
||||
impl Banner {
|
||||
pub fn new() -> Self {
|
||||
Banner {
|
||||
image: None,
|
||||
dark: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn image(mut self, image: impl Image + 'static) -> Self {
|
||||
self.image = Some(Rc::new(image));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn dark(mut self, dark: bool) -> Self {
|
||||
self.dark = dark;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn image_opt(&self) -> Option<&dyn Image> {
|
||||
self.image.as_deref()
|
||||
}
|
||||
|
||||
pub(crate) fn class_string(&self) -> String {
|
||||
let mut classes = vec!["toolkit-banner".to_owned()];
|
||||
|
||||
if self.dark {
|
||||
classes.push("toolkit-dark".to_owned());
|
||||
}
|
||||
|
||||
classes.join(" ")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Banner {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
f.debug_struct("Banner")
|
||||
.field("dark", &self.dark)
|
||||
.field("image", &"Rc<dyn Image>")
|
||||
.finish()
|
||||
}
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
use std::{cell::RefCell, fmt};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum ButtonKind {
|
||||
Primary,
|
||||
|
@ -14,19 +12,8 @@ pub enum LinkKind {
|
|||
NewTab,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Button {
|
||||
pub(crate) inner: RefCell<Inner>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Button {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Button").field("inner", &"Inner").finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct Inner {
|
||||
pub(crate) label: String,
|
||||
pub(crate) kind: ButtonKind,
|
||||
pub(crate) classes: Vec<String>,
|
||||
|
@ -39,79 +26,71 @@ pub(crate) struct Inner {
|
|||
impl Button {
|
||||
pub fn primary(label: &str) -> Self {
|
||||
Button {
|
||||
inner: RefCell::new(Inner {
|
||||
label: label.to_owned(),
|
||||
..Inner::default()
|
||||
}),
|
||||
label: label.to_owned(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn primary_outline(label: &str) -> Self {
|
||||
Button {
|
||||
inner: RefCell::new(Inner {
|
||||
label: label.to_owned(),
|
||||
kind: ButtonKind::PrimaryOutline,
|
||||
..Inner::default()
|
||||
}),
|
||||
label: label.to_owned(),
|
||||
kind: ButtonKind::PrimaryOutline,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn outline(label: &str) -> Self {
|
||||
Button {
|
||||
inner: RefCell::new(Inner {
|
||||
label: label.to_owned(),
|
||||
kind: ButtonKind::Outline,
|
||||
..Inner::default()
|
||||
}),
|
||||
label: label.to_owned(),
|
||||
kind: ButtonKind::Outline,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn secondary(label: &str) -> Self {
|
||||
Button {
|
||||
inner: RefCell::new(Inner {
|
||||
label: label.to_owned(),
|
||||
kind: ButtonKind::Secondary,
|
||||
..Inner::default()
|
||||
}),
|
||||
label: label.to_owned(),
|
||||
kind: ButtonKind::Secondary,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kind(&self, kind: ButtonKind) -> &Self {
|
||||
self.inner.borrow_mut().kind = kind;
|
||||
pub fn kind(mut self, kind: ButtonKind) -> Self {
|
||||
self.kind = kind;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn classes(&self, classes: &[&str]) -> &Self {
|
||||
self.inner.borrow_mut().classes = classes.into_iter().map(|s| s.to_string()).collect();
|
||||
pub fn classes(mut self, classes: &[&str]) -> Self {
|
||||
self.classes = classes.into_iter().map(|s| s.to_string()).collect();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn href(&self, href: &str) -> &Self {
|
||||
self.inner.borrow_mut().href = Some(href.to_owned());
|
||||
pub fn href(mut self, href: &str) -> Self {
|
||||
self.href = Some(href.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn new_tab(&self) -> &Self {
|
||||
self.inner.borrow_mut().link_kind = LinkKind::NewTab;
|
||||
pub fn new_tab(mut self) -> Self {
|
||||
self.link_kind = LinkKind::NewTab;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn form(&self, action: &str) -> &Self {
|
||||
self.inner.borrow_mut().action = Some(action.to_owned());
|
||||
pub fn form(mut self, action: &str) -> Self {
|
||||
self.action = Some(action.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn dark(&self, dark: bool) -> &Self {
|
||||
self.inner.borrow_mut().dark = dark;
|
||||
pub fn dark(mut self, dark: bool) -> Self {
|
||||
self.dark = dark;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn class_string(&self) -> String {
|
||||
use ButtonKind::*;
|
||||
|
||||
let mut classes = self.inner.borrow().classes.clone();
|
||||
let mut classes = self.classes.clone();
|
||||
|
||||
let static_classes = match self.inner.borrow().kind {
|
||||
let static_classes = match self.kind {
|
||||
Primary => "toolkit-button toolkit-button__primary",
|
||||
PrimaryOutline => "toolkit-button toolkit-button__primary-outline",
|
||||
Outline => "toolkit-button toolkit-button__outline",
|
||||
|
@ -120,7 +99,7 @@ impl Button {
|
|||
|
||||
classes.push(static_classes.to_owned());
|
||||
|
||||
if self.inner.borrow().dark {
|
||||
if self.dark {
|
||||
classes.push("toolkit-dark".to_owned());
|
||||
}
|
||||
|
||||
|
|
|
@ -17,17 +17,17 @@ impl Card {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn centered(&mut self) -> &mut Self {
|
||||
pub fn centered(mut self) -> Self {
|
||||
self.classes.push("toolkit-centered".to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn classes(&mut self, classes: &[&str]) -> &mut Self {
|
||||
pub fn classes(mut self, classes: &[&str]) -> Self {
|
||||
self.classes = classes.into_iter().map(|s| s.to_string()).collect();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn dark(&mut self, dark: bool) -> &mut Self {
|
||||
pub fn dark(mut self, dark: bool) -> Self {
|
||||
self.dark = dark;
|
||||
self
|
||||
}
|
||||
|
|
|
@ -52,27 +52,27 @@ impl FileInput {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn multiple(&mut self) -> &mut Self {
|
||||
pub fn multiple(mut self) -> Self {
|
||||
self.multiple = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn classes(&mut self, classes: &[&str]) -> &mut Self {
|
||||
pub fn classes(mut self, classes: &[&str]) -> Self {
|
||||
self.classes = classes.into_iter().map(|s| s.to_string()).collect();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn accept(&mut self, accept: &str) -> &mut Self {
|
||||
pub fn accept(mut self, accept: &str) -> Self {
|
||||
self.accept = accept.to_string();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn no_group(&mut self) -> &mut Self {
|
||||
pub fn no_group(mut self) -> Self {
|
||||
self.group = false;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn dark(&mut self, dark: bool) -> &mut Self {
|
||||
pub fn dark(mut self, dark: bool) -> Self {
|
||||
self.dark = dark;
|
||||
self
|
||||
}
|
||||
|
|
65
toolkit/src/icon.rs
Normal file
65
toolkit/src/icon.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use crate::image::Image;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Icon {
|
||||
pub(crate) href: String,
|
||||
pub(crate) small: bool,
|
||||
pub(crate) dark: bool,
|
||||
image: Option<Rc<dyn Image>>,
|
||||
}
|
||||
|
||||
impl Icon {
|
||||
pub fn new(href: String) -> Self {
|
||||
Icon {
|
||||
href,
|
||||
small: false,
|
||||
dark: false,
|
||||
image: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn image(mut self, image: impl Image + 'static) -> Self {
|
||||
self.image = Some(Rc::new(image));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn dark(mut self, dark: bool) -> Self {
|
||||
self.dark = dark;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn small(mut self, small: bool) -> Self {
|
||||
self.small = small;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn image_opt(&self) -> Option<&dyn Image> {
|
||||
self.image.as_deref()
|
||||
}
|
||||
|
||||
pub(crate) fn class_string(&self) -> String {
|
||||
let mut classes = vec!["toolkit-icon--link".to_owned()];
|
||||
|
||||
if self.small {
|
||||
classes.push("toolkit-icon--link__small".to_owned());
|
||||
}
|
||||
|
||||
if self.dark {
|
||||
classes.push("toolkit-dark".to_owned());
|
||||
}
|
||||
|
||||
classes.join(" ")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Icon {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
f.debug_struct("Icon")
|
||||
.field("href", &self.href)
|
||||
.field("small", &self.dark)
|
||||
.field("dark", &self.dark)
|
||||
.field("image", &"Rc<dyn Image>")
|
||||
.finish()
|
||||
}
|
||||
}
|
86
toolkit/src/image.rs
Normal file
86
toolkit/src/image.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
pub trait Image {
|
||||
fn src(&self) -> String;
|
||||
|
||||
fn title(&self) -> String;
|
||||
|
||||
fn png_srcset(&self) -> Option<String>;
|
||||
fn jpeg_srcset(&self) -> Option<String>;
|
||||
fn webp_srcset(&self) -> Option<String>;
|
||||
}
|
||||
|
||||
impl<T> Image for &T
|
||||
where
|
||||
T: Image,
|
||||
{
|
||||
fn src(&self) -> String {
|
||||
T::src(self)
|
||||
}
|
||||
|
||||
fn title(&self) -> String {
|
||||
T::title(self)
|
||||
}
|
||||
|
||||
fn png_srcset(&self) -> Option<String> {
|
||||
T::png_srcset(self)
|
||||
}
|
||||
|
||||
fn jpeg_srcset(&self) -> Option<String> {
|
||||
T::jpeg_srcset(self)
|
||||
}
|
||||
|
||||
fn webp_srcset(&self) -> Option<String> {
|
||||
T::webp_srcset(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Image for Rc<T>
|
||||
where
|
||||
T: Image,
|
||||
{
|
||||
fn src(&self) -> String {
|
||||
T::src(self)
|
||||
}
|
||||
|
||||
fn title(&self) -> String {
|
||||
T::title(self)
|
||||
}
|
||||
|
||||
fn png_srcset(&self) -> Option<String> {
|
||||
T::png_srcset(self)
|
||||
}
|
||||
|
||||
fn jpeg_srcset(&self) -> Option<String> {
|
||||
T::jpeg_srcset(self)
|
||||
}
|
||||
|
||||
fn webp_srcset(&self) -> Option<String> {
|
||||
T::webp_srcset(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Image for Box<T>
|
||||
where
|
||||
T: Image,
|
||||
{
|
||||
fn src(&self) -> String {
|
||||
T::src(self)
|
||||
}
|
||||
|
||||
fn title(&self) -> String {
|
||||
T::title(self)
|
||||
}
|
||||
|
||||
fn png_srcset(&self) -> Option<String> {
|
||||
T::png_srcset(self)
|
||||
}
|
||||
|
||||
fn jpeg_srcset(&self) -> Option<String> {
|
||||
T::jpeg_srcset(self)
|
||||
}
|
||||
|
||||
fn webp_srcset(&self) -> Option<String> {
|
||||
T::webp_srcset(self)
|
||||
}
|
||||
}
|
|
@ -25,32 +25,32 @@ impl Input {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn kind(&mut self, kind: InputKind) -> &mut Self {
|
||||
pub fn kind(mut self, kind: InputKind) -> Self {
|
||||
self.kind = kind;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn value(&mut self, value: &str) -> &mut Self {
|
||||
pub fn value(mut self, value: &str) -> Self {
|
||||
self.value = Some(value.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn placeholder(&mut self, placeholder: &str) -> &mut Self {
|
||||
pub fn placeholder(mut self, placeholder: &str) -> Self {
|
||||
self.placeholder = Some(placeholder.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn value_opt(&mut self, value: Option<String>) -> &mut Self {
|
||||
pub fn value_opt(mut self, value: Option<String>) -> Self {
|
||||
self.value = value;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn classes(&mut self, classes: &[&str]) -> &mut Self {
|
||||
pub fn classes(mut self, classes: &[&str]) -> Self {
|
||||
self.classes = classes.into_iter().map(|s| s.to_string()).collect();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn dark(&mut self, dark: bool) -> &mut Self {
|
||||
pub fn dark(mut self, dark: bool) -> Self {
|
||||
self.dark = dark;
|
||||
self
|
||||
}
|
||||
|
|
|
@ -1,21 +1,31 @@
|
|||
include!(concat!(env!("OUT_DIR"), "/templates.rs"));
|
||||
|
||||
mod banner;
|
||||
mod button;
|
||||
mod card;
|
||||
mod file_input;
|
||||
mod icon;
|
||||
mod image;
|
||||
mod input;
|
||||
mod link;
|
||||
mod profile;
|
||||
mod select;
|
||||
mod text_input;
|
||||
mod tile;
|
||||
|
||||
pub use self::{
|
||||
banner::Banner,
|
||||
button::{Button, ButtonKind, LinkKind},
|
||||
card::Card,
|
||||
file_input::FileInput,
|
||||
icon::Icon,
|
||||
image::Image,
|
||||
input::{Input, InputKind},
|
||||
link::Link,
|
||||
profile::Profile,
|
||||
select::Select,
|
||||
text_input::TextInput,
|
||||
tile::Tile,
|
||||
};
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
|
|
|
@ -27,17 +27,17 @@ impl Link {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn title(&mut self, title: &str) -> &mut Self {
|
||||
pub fn title(mut self, title: &str) -> Self {
|
||||
self.title = Some(title.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn dark(&mut self, dark: bool) -> &mut Self {
|
||||
pub fn dark(mut self, dark: bool) -> Self {
|
||||
self.dark = dark;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn plain(&mut self, plain: bool) -> &mut Self {
|
||||
pub fn plain(mut self, plain: bool) -> Self {
|
||||
self.plain = plain;
|
||||
self
|
||||
}
|
||||
|
|
67
toolkit/src/profile.rs
Normal file
67
toolkit/src/profile.rs
Normal file
|
@ -0,0 +1,67 @@
|
|||
use crate::{banner::Banner, icon::Icon, image::Image};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Profile {
|
||||
pub(crate) handle: String,
|
||||
pub(crate) display_name: Option<String>,
|
||||
pub(crate) description: Option<String>,
|
||||
pub(crate) icon: Icon,
|
||||
pub(crate) banner: Banner,
|
||||
dark: bool,
|
||||
}
|
||||
|
||||
impl Profile {
|
||||
pub fn new(handle: String, href: String) -> Self {
|
||||
Profile {
|
||||
handle,
|
||||
display_name: None,
|
||||
description: None,
|
||||
icon: Icon::new(href),
|
||||
banner: Banner::new(),
|
||||
dark: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_name(mut self, display_name: &str) -> Self {
|
||||
self.display_name = Some(display_name.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn description(mut self, description: &str) -> Self {
|
||||
self.description = Some(description.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn icon_image(self, image: impl Image + 'static) -> Self {
|
||||
Profile {
|
||||
icon: self.icon.image(image),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn banner_image(self, image: impl Image + 'static) -> Self {
|
||||
Profile {
|
||||
banner: self.banner.image(image),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dark(self, dark: bool) -> Self {
|
||||
Profile {
|
||||
icon: self.icon.dark(dark),
|
||||
banner: self.banner.dark(dark),
|
||||
dark,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn class_string(&self) -> String {
|
||||
let mut classes = vec!["toolkit-profile".to_owned()];
|
||||
|
||||
if self.dark {
|
||||
classes.push("toolkit-dark".to_owned());
|
||||
}
|
||||
|
||||
classes.join(" ")
|
||||
}
|
||||
}
|
|
@ -24,22 +24,22 @@ impl Select {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn title(&mut self, title: &str) -> &mut Self {
|
||||
pub fn title(mut self, title: &str) -> Self {
|
||||
self.title = Some(title.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn default_option(&mut self, value: &str) -> &mut Self {
|
||||
pub fn default_option(mut self, value: &str) -> Self {
|
||||
self.default = Some(value.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_option(&mut self, text: String, value: String) -> &mut Self {
|
||||
pub fn add_option(mut self, text: String, value: String) -> Self {
|
||||
self.options.push(SelectOption { value, text });
|
||||
self
|
||||
}
|
||||
|
||||
pub fn options(&mut self, options: &[(&str, &str)]) -> &mut Self {
|
||||
pub fn options(mut self, options: &[(&str, &str)]) -> Self {
|
||||
self.options = options
|
||||
.iter()
|
||||
.map(|(text, value)| SelectOption {
|
||||
|
@ -50,7 +50,7 @@ impl Select {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn dark(&mut self, dark: bool) -> &mut Self {
|
||||
pub fn dark(mut self, dark: bool) -> Self {
|
||||
self.dark = dark;
|
||||
self
|
||||
}
|
||||
|
|
|
@ -17,47 +17,57 @@ impl TextInput {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn password(&mut self) -> &mut Self {
|
||||
self.input.kind(InputKind::Password);
|
||||
self
|
||||
pub fn password(self) -> Self {
|
||||
TextInput {
|
||||
input: self.input.kind(InputKind::Password),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn textarea(&mut self) -> &mut Self {
|
||||
self.input.kind(InputKind::TextArea);
|
||||
self
|
||||
pub fn textarea(self) -> Self {
|
||||
TextInput {
|
||||
input: self.input.kind(InputKind::TextArea),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn title(&mut self, title: &str) -> &mut Self {
|
||||
pub fn title(mut self, title: &str) -> Self {
|
||||
self.title = Some(title.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn value(&mut self, value: &str) -> &mut Self {
|
||||
self.input.value(value);
|
||||
self
|
||||
pub fn value(self, value: &str) -> Self {
|
||||
TextInput {
|
||||
input: self.input.value(value),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn placeholder(&mut self, placeholder: &str) -> &mut Self {
|
||||
self.input.placeholder(placeholder);
|
||||
self
|
||||
pub fn placeholder(self, placeholder: &str) -> Self {
|
||||
TextInput {
|
||||
input: self.input.placeholder(placeholder),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn classes(&mut self, classes: &[&str]) -> &mut Self {
|
||||
pub fn classes(mut self, classes: &[&str]) -> Self {
|
||||
self.classes = classes.into_iter().map(|s| s.to_string()).collect();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn value_opt(&mut self, value: Option<String>) -> &mut Self {
|
||||
self.input.value_opt(value);
|
||||
self
|
||||
pub fn value_opt(self, value: Option<String>) -> Self {
|
||||
TextInput {
|
||||
input: self.input.value_opt(value),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error_opt(&mut self, error: Option<String>) -> &mut Self {
|
||||
pub fn error_opt(mut self, error: Option<String>) -> Self {
|
||||
self.error = error;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn dark(&mut self, dark: bool) -> &mut Self {
|
||||
pub fn dark(mut self, dark: bool) -> Self {
|
||||
self.dark = dark;
|
||||
self
|
||||
}
|
||||
|
|
78
toolkit/src/tile.rs
Normal file
78
toolkit/src/tile.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use crate::image::Image;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum TileFlag {
|
||||
Normal,
|
||||
Primary,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Tile {
|
||||
pub(crate) title: Option<String>,
|
||||
pub(crate) description: Option<String>,
|
||||
pub(crate) link: Option<String>,
|
||||
pub(crate) flag: TileFlag,
|
||||
image: Rc<dyn Image>,
|
||||
}
|
||||
|
||||
impl Tile {
|
||||
pub fn new(image: impl Image + 'static) -> Self {
|
||||
Tile {
|
||||
title: None,
|
||||
description: None,
|
||||
link: None,
|
||||
flag: TileFlag::Normal,
|
||||
image: Rc::new(image),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn title(mut self, title: &str) -> Self {
|
||||
self.title = Some(title.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn description(mut self, description: &str) -> Self {
|
||||
self.description = Some(description.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn link(mut self, link: &str) -> Self {
|
||||
self.link = Some(link.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn flag(mut self, flag: TileFlag) -> Self {
|
||||
self.flag = flag;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn image(&self) -> &dyn Image {
|
||||
&*self.image
|
||||
}
|
||||
|
||||
pub(crate) fn class_string(&self) -> String {
|
||||
let mut classes = vec!["toolkit-tile".to_owned()];
|
||||
|
||||
match self.flag {
|
||||
TileFlag::Normal => (),
|
||||
TileFlag::Primary => {
|
||||
classes.push("toolkit-tile__primary".to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
classes.join(" ")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Tile {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
f.debug_struct("Tile")
|
||||
.field("title", &self.title)
|
||||
.field("description", &self.description)
|
||||
.field("link", &self.link)
|
||||
.field("flag", &self.flag)
|
||||
.field("image", &"Box<dyn Image>")
|
||||
.finish()
|
||||
}
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
@(dark: bool, img: Content)
|
||||
@use crate::banner::Banner;
|
||||
@use crate::templates::image;
|
||||
|
||||
@if dark {
|
||||
<div class="toolkit-banner toolkit-dark">
|
||||
@:img()
|
||||
</div>
|
||||
} else {
|
||||
<div class="toolkit-banner">
|
||||
@:img()
|
||||
</div>
|
||||
}
|
||||
@(banner: &Banner)
|
||||
|
||||
<div class="@banner.class_string()">
|
||||
@if let Some(img) = banner.image_opt() {
|
||||
@:image(img)
|
||||
}
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
@(button: &Button)
|
||||
|
||||
@if let Some(action) = button.inner.borrow().action.as_ref() {
|
||||
@if let Some(action) = button.action.as_ref() {
|
||||
<form class="@button.class_string()" method="POST" action="@action">
|
||||
@:button_inner(button)
|
||||
</form>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@use crate::Button;
|
||||
@use super::button;
|
||||
|
||||
@(buttons: &[&Button])
|
||||
@(buttons: &[Button])
|
||||
|
||||
<div class="toolkit-button-group">
|
||||
@for btn in buttons {
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
|
||||
@(button: &Button)
|
||||
|
||||
<span>@button.inner.borrow().label</span>
|
||||
@if let Some(href) = button.inner.borrow().href.as_ref() {
|
||||
@match button.inner.borrow().link_kind {
|
||||
<span>@button.label</span>
|
||||
@if let Some(href) = button.href.as_ref() {
|
||||
@match button.link_kind {
|
||||
LinkKind::CurrentTab => {
|
||||
<a href="@href" class="toolkit-button--action">@button.inner.borrow().label</a>
|
||||
<a href="@href" class="toolkit-button--action">@button.label</a>
|
||||
}
|
||||
LinkKind::NewTab => {
|
||||
<a href="@href" target="_blank" rel="noopener noreferer" class="toolkit-button--action">
|
||||
@button.inner.borrow().label
|
||||
@button.label
|
||||
</a>
|
||||
}
|
||||
}
|
||||
} else {
|
||||
<button class="toolkit-button--action">@button.inner.borrow().label</button>
|
||||
<button class="toolkit-button--action">@button.label</button>
|
||||
}
|
||||
|
|
|
@ -1,31 +1,12 @@
|
|||
@(href: &str, small: bool, dark: bool, picture: Content)
|
||||
@use crate::icon::Icon;
|
||||
@use crate::templates::image;
|
||||
|
||||
@if small {
|
||||
@if dark {
|
||||
<a href="@href" class="toolkit-icon--link toolkit-icon--link__small toolkit-dark">
|
||||
<div class="toolkit-icon">
|
||||
@:picture()
|
||||
</div>
|
||||
</a>
|
||||
} else {
|
||||
<a href="@href" class="toolkit-icon--link toolkit-icon--link__small">
|
||||
<div class="toolkit-icon">
|
||||
@:picture()
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
} else {
|
||||
@if dark {
|
||||
<a href="@href" class="toolkit-icon--link toolkit-dark">
|
||||
<div class="toolkit-icon">
|
||||
@:picture()
|
||||
</div>
|
||||
</a>
|
||||
} else {
|
||||
<a href="@href" class="toolkit-icon--link">
|
||||
<div class="toolkit-icon">
|
||||
@:picture()
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
}
|
||||
@(icon: &Icon)
|
||||
|
||||
<a href="@icon.href" class="@icon.class_string()">
|
||||
<div class="toolkit-icon">
|
||||
@if let Some(img) = icon.image_opt() {
|
||||
@:image(img)
|
||||
}
|
||||
</div>
|
||||
</a>
|
||||
|
|
17
toolkit/templates/image.rs.html
Normal file
17
toolkit/templates/image.rs.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
@use crate::image::Image;
|
||||
|
||||
@(image: &dyn Image)
|
||||
|
||||
<picture>
|
||||
@if let Some(srcset) = image.webp_srcset() {
|
||||
<source type="image/webp" srcset="@srcset" />
|
||||
}
|
||||
@if let Some(srcset) = image.png_srcset() {
|
||||
<source type="image/png" srcset="@srcset" />
|
||||
}
|
||||
@if let Some(srcset) = image.jpeg_srcset() {
|
||||
<source type="image/jpeg" srcset="@srcset" />
|
||||
}
|
||||
|
||||
<img src="@image.src()" title="@image.title()" alt="@image.title()" />
|
||||
</picture>
|
|
@ -1,49 +1,26 @@
|
|||
@use crate::templates::{icon, banner};
|
||||
@use crate::profile::Profile;
|
||||
|
||||
@(view_path: &str, display_name: Option<&str>, handle: &str, description: Option<&str>, dark: bool, icon_img: Content, banner_img: Content)
|
||||
@(profile: &Profile)
|
||||
|
||||
@if dark {
|
||||
<div class="toolkit-profile toolkit-dark">
|
||||
@:banner(dark, { @:banner_img() })
|
||||
<div class="toolkit-profile--content">
|
||||
<div class="toolkit-profile--content--top">
|
||||
@:icon(view_path, false, dark, { @:icon_img() })
|
||||
<div class="toolkit-profile--meta">
|
||||
<div class="toolkit-profile--meta--display">
|
||||
@if let Some(display_name) = display_name {
|
||||
@display_name
|
||||
} else {
|
||||
|
||||
}
|
||||
</div>
|
||||
<div class="toolkit-profile--meta--handle">@handle</div>
|
||||
<div class="@profile.class_string()">
|
||||
@:banner(&profile.banner)
|
||||
<div class="toolkit-profile--content">
|
||||
<div class="toolkit-profile--content--top">
|
||||
@:icon(&profile.icon)
|
||||
<div class="toolkit-profile--meta">
|
||||
<div class="toolkit-profile--meta--display">
|
||||
@if let Some(display_name) = &profile.display_name {
|
||||
@display_name
|
||||
} else {
|
||||
|
||||
}
|
||||
</div>
|
||||
<div class="toolkit-profile--meta--handle">@profile.handle</div>
|
||||
</div>
|
||||
@if let Some(description) = description {
|
||||
<div class="toolkit-profile--description">@description</div>
|
||||
}
|
||||
</div>
|
||||
@if let Some(description) = &profile.description {
|
||||
<div class="toolkit-profile--description">@description</div>
|
||||
}
|
||||
</div>
|
||||
} else {
|
||||
<div class="toolkit-profile">
|
||||
@:banner(dark, { @:banner_img() })
|
||||
<div class="toolkit-profile--content">
|
||||
<div class="toolkit-profile--content--top">
|
||||
@:icon(view_path, false, dark, { @:icon_img() })
|
||||
<div class="toolkit-profile--meta">
|
||||
<div class="toolkit-profile--meta--display">
|
||||
@if let Some(display_name) = display_name {
|
||||
@display_name
|
||||
} else {
|
||||
|
||||
}
|
||||
</div>
|
||||
<div class="toolkit-profile--meta--handle">@handle</div>
|
||||
</div>
|
||||
</div>
|
||||
@if let Some(description) = description {
|
||||
<div class="toolkit-profile--description">@description</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
|
13
toolkit/templates/tile.rs.html
Normal file
13
toolkit/templates/tile.rs.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
@use crate::link::Link;
|
||||
@use crate::tile::Tile;
|
||||
@use crate::templates::{link, tile_inner};
|
||||
|
||||
@(tile: &Tile)
|
||||
|
||||
@if let Some(href) = &tile.link {
|
||||
@:link(&Link::current_tab(href).plain(true).dark(true), {
|
||||
@:tile_inner(tile)
|
||||
})
|
||||
} else {
|
||||
@:tile_inner(tile)
|
||||
}
|
20
toolkit/templates/tile_inner.rs.html
Normal file
20
toolkit/templates/tile_inner.rs.html
Normal file
|
@ -0,0 +1,20 @@
|
|||
@use crate::tile::Tile;
|
||||
@use crate::templates::image;
|
||||
|
||||
@(tile: &Tile)
|
||||
|
||||
<div class="@tile.class_string()">
|
||||
<div class="toolkit-tile--overlay">
|
||||
@if tile.title.is_some() || tile.description.is_some() {
|
||||
<div class="toolkit-tile--meta">
|
||||
@if let Some(title) = &tile.title {
|
||||
<h2>@title</h2>
|
||||
}
|
||||
@if let Some(description) = &tile.description {
|
||||
<p>@description</p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@:image(tile.image())
|
||||
</div>
|
5
toolkit/templates/tiles.rs.html
Normal file
5
toolkit/templates/tiles.rs.html
Normal file
|
@ -0,0 +1,5 @@
|
|||
@(body: Content)
|
||||
|
||||
<div class="toolkit-tiles">
|
||||
@:body()
|
||||
</div>
|
Loading…
Reference in a new issue