commit b0069864d941356ef0f33249b972ccd94620812e
parent 2ee90a260c01af48b79b7542935c731eb9683e23
Author: Jackson G. Kaindume <seestem@merely.tech>
Date: Sat, 20 Aug 2022 23:47:33 +0200
add slider
Diffstat:
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
+ )
+ }
+}