aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-01-19 21:44:03 +0100
committermetamuffin <metamuffin@disroot.org>2023-01-19 21:44:03 +0100
commit146243df99605f04f708d3db0eab3c8f78bc61d6 (patch)
tree2ff2061eed7b7a2a408321e72de2d092abafd1f4
parentcadb3057d06a38abfac9067cbdc59ce3d926a658 (diff)
downloadjellything-146243df99605f04f708d3db0eab3c8f78bc61d6.tar
jellything-146243df99605f04f708d3db0eab3c8f78bc61d6.tar.bz2
jellything-146243df99605f04f708d3db0eab3c8f78bc61d6.tar.zst
smoooooth ui
-rw-r--r--server/src/routes/ui/node.rs24
-rw-r--r--server/src/routes/ui/style/layout.css132
2 files changed, 126 insertions, 30 deletions
diff --git a/server/src/routes/ui/node.rs b/server/src/routes/ui/node.rs
index 9162982..855da45 100644
--- a/server/src/routes/ui/node.rs
+++ b/server/src/routes/ui/node.rs
@@ -7,7 +7,7 @@ use crate::{
};
use anyhow::{anyhow, Context};
use log::info;
-use rocket::{get, uri, State};
+use rocket::{get, http::ContentType, uri, State};
use std::{ops::Deref, path::PathBuf, sync::Arc};
use tokio::fs::File;
@@ -54,8 +54,11 @@ markup::define! {
}
ItemCard(item: Arc<Item>) {
div.card.item {
- a[href=&uri!(r_library_node(&item.lib_path)).to_string()] {
- img[src=uri!(r_item_assets(&item.lib_path)).to_string()];
+ div.banner {
+ a[href=&uri!(r_library_node(&item.lib_path)).to_string()] {
+ img[src=uri!(r_item_assets(&item.lib_path)).to_string()];
+ }
+ div.hover { a[href=&player_uri(&item.lib_path)] { "▶" } }
}
a[href=&uri!(r_library_node(&item.lib_path)).to_string()] {
p.title { @item.info.title }
@@ -63,17 +66,15 @@ markup::define! {
}
}
ItemPage(item: Arc<Item>) {
+ // TODO different image here
+ img.backdrop[src=uri!(r_item_assets(&item.lib_path)).to_string()];
div.page.item {
- div.backdrop {
- // TODO different image here
- img[src=uri!(r_item_assets(&item.lib_path)).to_string()];
- }
div.banner {
img[src=uri!(r_item_assets(&item.lib_path)).to_string()];
}
div.title {
h1 { @item.info.title }
- a[href=&player_uri(&item.lib_path)] { "Watch now" }
+ a.play[href=&player_uri(&item.lib_path)] { "Watch now" }
}
div.details {
h3 { "Lorem Ipsum!" }
@@ -84,7 +85,10 @@ markup::define! {
}
#[get("/item_assets/<path..>")]
-pub async fn r_item_assets(path: PathBuf, state: &State<AppState>) -> Result<File, MyError> {
+pub async fn r_item_assets(
+ path: PathBuf,
+ state: &State<AppState>,
+) -> Result<(ContentType, File), MyError> {
let node = state
.library
.nested_path(&path)
@@ -98,5 +102,5 @@ pub async fn r_item_assets(path: PathBuf, state: &State<AppState>) -> Result<Fil
.ok_or(anyhow!("no banner available"))?,
);
info!("loading asset from {path:?}");
- Ok(File::open(path).await?)
+ Ok((ContentType::WEBP, File::open(path).await?))
}
diff --git a/server/src/routes/ui/style/layout.css b/server/src/routes/ui/style/layout.css
index 6a63ccc..913bd77 100644
--- a/server/src/routes/ui/style/layout.css
+++ b/server/src/routes/ui/style/layout.css
@@ -5,37 +5,57 @@
:root {
--card-size: 12em;
+ --bar-height: 5em;
+ --banner-aspect: 1.41;
+ --accent-light: rgb(255, 163, 87);
+ --accent-dark: rgb(199, 90, 0);
+ --backdrop-height: 18em;
+ --background-dark: #070707;
+ --background-light: #1c1c1c;
+}
+
+::selection {
+ background-color: var(--accent-dark);
}
* {
color: rgb(218, 218, 218);
font-family: "Cantarell", sans-serif;
font-weight: 500;
+
+ scrollbar-width: thin;
+ scrollbar-color: var(--background-light) #0000;
}
body {
- background-color: #070707;
+ background-color: var(--background-dark);
width: 100vw;
margin: 0px;
padding: 0px;
}
-img {
- width: 100%;
- height: 100%;
- object-fit: cover;
-}
-
nav {
- position: absolute;
+ z-index: 90;
+ position: fixed;
top: 0px;
left: 0px;
padding: 1em;
width: calc(100vw - 2em);
height: 2em;
+ backdrop-filter: blur(6px);
background-color: #1c1c1c9a;
}
+nav a {
+ border: 0px solid transparent;
+ border-radius: 5px;
+ padding: 0.5em;
+ text-decoration: none;
+}
+nav a:hover {
+ background-color: #ffffff10;
+}
+
nav h1 {
margin: 0px;
font-size: 1.5em;
@@ -44,6 +64,8 @@ nav h1 {
}
#main {
+ display: block;
+ margin-top: var(--bar-height);
}
.error {
@@ -62,7 +84,6 @@ option {
}
.page.dir {
- margin-top: 5em;
padding: 1em;
padding-left: 3em;
padding-right: 3em;
@@ -78,16 +99,12 @@ option {
.card.item {
width: var(--card-size);
- height: calc(var(--card-size) * 1.41);
+ height: calc(var(--card-size) * var(--banner-aspect));
padding: 1em;
}
.card.dir {
width: calc(var(--card-size) * 2);
- height: calc(var(--card-size) * 1.41);
-}
-.card a {
- width: 100%;
- height: 100%;
+ height: calc(var(--card-size) * var(--banner-aspect));
}
.card.item .title {
@@ -95,15 +112,90 @@ option {
text-align: center;
text-overflow: ellipsis;
}
-
-.page.item .backdrop {
+.card.item .banner {
+ display: grid;
+}
+.card.item .banner a {
+ grid-area: 1 / 1;
+}
+.card.item .banner a img {
width: 100%;
- margin-bottom: calc(-100% * 1.41 + 18em);
+ height: 100%;
+ object-fit: cover;
+ object-position: center;
}
-.page.item .backdrop img {
+.card.item .banner .hover {
+ pointer-events: none;
+ grid-area: 1 / 1;
+ transition: opacity 0.3s, backdrop-filter 0.3s;
+ opacity: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+.card.item .banner:hover .hover {
+ opacity: 1;
+ background-color: #0004;
+ backdrop-filter: blur(3px);
+}
+.card.item .banner .hover a {
+ text-decoration: none;
+ font-stretch: 200%;
+ width: 1em;
+ height: 1em;
+ line-height: 1;
+ margin: auto;
+ padding: 0.4em 0.3em 0.4em 0.5em;
+ border-radius: 50%;
+ font-size: 2.2em;
+ pointer-events: all;
+ background-color: #0005;
+ transition: background-color 0.2s, font-size 0.2s;
+}
+.card.item .banner .hover a:hover {
+ background-color: #0008;
+ font-size: 3em;
+}
+
+.backdrop {
+ width: 100%;
+ height: calc(var(--backdrop-height) + 5em);
+ margin-top: calc(-1 * var(--bar-height));
+ margin-bottom: -5em;
+ mask-image: linear-gradient(
+ rgba(0, 0, 0, 1),
+ transparent calc(var(--backdrop-height) + 5em)
+ );
mask-mode: alpha;
- mask-image: linear-gradient(rgba(0, 0, 0, 1), transparent 30%);
+ pointer-events: none;
+ object-fit: cover;
+ object-position: center;
+}
+.page.item {
+ position: relative;
+ width: 100%;
}
.page.item .banner {
width: max(8em, 20%);
+ float: left;
+ margin: 3em;
+ margin-top: -1em;
+}
+.page.item .banner img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ object-position: center;
+}
+
+.page.item .title h1 {
+ display: inline;
+ margin-right: 1em;
+}
+.page.item .title .play {
+ display: inline;
+ font-stretch: 200%;
+}
+.page.item .title .play::before {
+ content: "▶ ";
}