htoml

HTML page templates described with a toml config
Log | Files | Refs | README

commit b0069864d941356ef0f33249b972ccd94620812e
parent 2ee90a260c01af48b79b7542935c731eb9683e23
Author: Jackson G. Kaindume <seestem@merely.tech>
Date:   Sat, 20 Aug 2022 23:47:33 +0200

add slider

Diffstat:
MREADME.md | 4++++
Msrc/main.rs | 1+
Asrc/slider.rs | 202+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 207 insertions(+), 0 deletions(-)

diff --git a/README.md b/README.md @@ -48,3 +48,7 @@ To generate .html files from .toml files run the following command: # This an example, use your own .toml files $ htoml index.toml about.toml contact.toml ``` + +## Credits + +- Pure HTML and CSS slider based on code by [David Lewis](https://codepen.io/dp_lewis/pen/WNZQzN) diff --git a/src/main.rs b/src/main.rs @@ -10,6 +10,7 @@ use std::{ pub mod common; pub mod htoml; pub mod sections; +pub mod slider; fn main() -> std::io::Result<()> { let mut htoml_files: Vec<PathBuf> = vec![]; diff --git a/src/slider.rs b/src/slider.rs @@ -0,0 +1,202 @@ +//! Pure HTML and CSS slider with keyboard support +//! By [David Lewis](https://codepen.io/dp_lewis/pen/WNZQzN) + +pub use crate::common::Export; +use serde::Deserialize; + +#[derive(Deserialize, Clone)] +pub struct Slide { + pub label: Option<String>, + pub image: Option<String>, +} + +/// A content slider with HTML and CSS +pub struct Slider; + +impl Slider { + pub fn export(slides: Vec<Slide>) -> Export { + let html = Slider::gen_triggers_html(&slides); + let css = format!( + r#" +* {{ +box-sizing: border-box; +}} + +#htoml_slide {{ +font-family: sans-serif; +overflow: hidden; +}} + + +label {{ +background: #444; +color: #fff; +transition: transform 400ms ease-out; +display: inline-block; + min-height: 100%; +width: 100vw; +position: relative; +z-index: 1; +text-align: center; +line-height: 100vh; +}} + +form {{ +position: relative; +top: 0; +left: 0; +bottom: 0; +right: 0; +white-space: nowrap; +}} + +input {{ +position: absolute; +}} + +.keys {{ +position: fixed; +z-index: 10; +bottom: 0; +left: 0; +right: 0; +padding: 1rem; +color: #fff; +text-align: center; +transition: all 300ms linear; +opacity: 0; +}} + +input:focus ~ .keys {{ +opacity: 0.8; +}} + +{} +"#, + Slider::gen_css(&slides) + ); + + Export { html, css } + } + + fn gen_triggers_html(slides: &Vec<Slide>) -> String { + let mut inputs = "".to_string(); + let mut labels = "".to_string(); + + for i in 0..slides.len() { + let mut text = "".to_string(); + + if let Some(l) = &slides[i].label { + text = l.to_string() + } + + inputs = format!( + r#"{}<input type="radio", name="fancy" value="{}" id="slideInput{}" />"#, + inputs, &text, i + ); + + labels = format!( + r#"{}<label for="slideInput{}">{}</label>"#, + labels, i, &text + ) + } + + format!( + r#" +<div id="htoml_slide"> + <form> + {} + {} + <div class="keys"> + Use left and right keys to navigate + </div> + </form> +</div>"#, + inputs, labels + ) + } + + pub fn gen_css(slides: &Vec<Slide>) -> String { + let mut counted_inputs = "".to_string(); + let mut transforms = "".to_string(); + let mut backgrounds = "".to_string(); + + for s in 0..slides.len() { + let mut img = "".to_string(); + + if let Some(i) = &slides[s].image { + img = format!("background-image: url(\"{}\")", i); + } + + counted_inputs = format!( + "{} +input:nth-of-type({}):checked ~ label:nth-of-type({})", + counted_inputs, + s + 1, + s + 1 + ); + + transforms = format!( + r#"{} +input:nth-of-type({}):checked ~ label {{transform: translate3d(-{}%, 0, 0);}}"#, + transforms, + s, + s * 100 + ); + + backgrounds = format!( + r#"{} +label[for="slideInput{}"] {{{}}}"#, + backgrounds, s, img + ) + } + + format!( + r#"{}{{ + z-index: 0; +}} + +{} + +label {{ +background: #444; +background-size: cover; +font-size: 3rem; +}} + +{} + +label:before, +label:after {{ +color: white; +display: block; +background: rgba(255,255,255,0.2); +position: absolute; +padding: 1rem; +font-size: 3rem; +height: 10rem; +vertical-align: middle; +line-height: 10rem; +top: 50%; +transform: translate3d(0, -50%, 0); +cursor: pointer; +}} + +label:before {{ +content: "\276D"; +right: 100%; +border-top-left-radius: 50%; +border-bottom-left-radius: 50%; +}} + +label:after {{ +content: "\276C"; +left: 0; +border-top-right-radius: 50%; +border-bottom-right-radius: 50%; +}} +"#, + counted_inputs, transforms, backgrounds + ) + } +}