mirror of
https://codeberg.org/simonrepp/hyper8.git
synced 2026-08-14 13:45:27 +02:00
Sketch out mobile navigation, link title to home, write lqips to js site tree
This commit is contained in:
@@ -11,7 +11,7 @@ const siteTreeElements = siteTree.querySelector('.elements');
|
||||
const siteTreeStatus = siteTree.querySelector('[role="status"]');
|
||||
|
||||
const indexSuffix = window.location.pathname.endsWith('index.html') ? 'index.html' : '';
|
||||
const rootPrefix = siteTree.dataset.rootPrefix;
|
||||
const rootPrefix = document.querySelector('.home').getAttribute('href');
|
||||
|
||||
// We only render the site tree elements (which are displayed during
|
||||
// browsing/searching) into the DOM when, or shortly before, we need them,
|
||||
@@ -123,14 +123,16 @@ function initializeSiteTree() {
|
||||
? traversal.map(ancestor => ancestor.title).join(' > ')
|
||||
: collection.title;
|
||||
|
||||
const spanInfo = document.createElement('span');
|
||||
spanInfo.textContent = NAVIGATION_JS_T.xxxVideos(collection.videos.length);
|
||||
|
||||
collection.element = document.createElement('a');
|
||||
collection.element.classList.add('collection');
|
||||
collection.element.href = rootPrefix + collection.sitePath + indexSuffix;
|
||||
collection.element.appendChild(spanText);
|
||||
collection.element.appendChild(spanInfo);
|
||||
|
||||
if (collection.videos.length) {
|
||||
const spanInfo = document.createElement('span');
|
||||
spanInfo.textContent = NAVIGATION_JS_T.xxxVideos(collection.videos.length);
|
||||
collection.element.appendChild(spanInfo);
|
||||
}
|
||||
|
||||
siteTreeElements.appendChild(collection.element);
|
||||
|
||||
@@ -156,6 +158,16 @@ function initializeSiteTree() {
|
||||
siteTreeInitialized = true;
|
||||
}
|
||||
|
||||
// TODO: Currently unused but kept around in case we want to pick it up again
|
||||
// (the lqip property is available as video.lqip in the siteContent tree structure).
|
||||
// function lqipToRadialGradient(lqip) {
|
||||
// const [ne, nw, se, sw] = lqip;
|
||||
// return `radial-gradient(ellipse at top right, rgb(${ne[0]},${ne[1]},${ne[2]}), transparent),` +
|
||||
// `radial-gradient(ellipse at top left, rgb(${nw[0]},${nw[1]},${nw[2]}), transparent),` +
|
||||
// `radial-gradient(ellipse at bottom right, rgb(${se[0]},${se[1]},${se[2]}), transparent),` +
|
||||
// `radial-gradient(ellipse at bottom left, rgb(${sw[0]},${sw[1]},${sw[2]}), transparent)`;
|
||||
// }
|
||||
|
||||
function toggleBrowse() {
|
||||
function updateVideo(video) {
|
||||
video.element.classList.remove('visible');
|
||||
|
||||
@@ -35,9 +35,12 @@ body {
|
||||
border-radius: .2rem;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
padding: .3rem 0;
|
||||
padding: .2rem 0;
|
||||
}
|
||||
.browse:focus-visible {
|
||||
background: var(--fg-2);
|
||||
color: var(--bg-1);
|
||||
}
|
||||
.browse:focus-visible { background: var(--bg-3); }
|
||||
button {
|
||||
color: var(--fg-2);
|
||||
font-size: inherit;
|
||||
@@ -132,11 +135,19 @@ header {
|
||||
}
|
||||
header .navigation {
|
||||
align-items: center;
|
||||
column-gap: .1em;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
header .navigation > :not(:first-child) { padding-inline-start: .35em; }
|
||||
header .navigation > :not(:last-child) { padding-inline-end: .35em; }
|
||||
header .navigation > :nth-child(1) { padding-inline-end: .3em; }
|
||||
header .navigation > :nth-child(1) {
|
||||
align-items: center;
|
||||
column-gap: .3em;
|
||||
display: flex;
|
||||
}
|
||||
header .navigation > :nth-child(2) { padding-inline: .3em; }
|
||||
header .navigation > :nth-child(3) { padding-inline-start: .3em; }
|
||||
header .navigation > :not(:last-child) { }
|
||||
header .title { color: var(--fg-1); }
|
||||
img {
|
||||
display: block;
|
||||
@@ -495,6 +506,7 @@ img {
|
||||
background: var(--bg-1);
|
||||
border: 1px solid var(--bg-3);
|
||||
border-radius: .5em;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
max-height: 80dvh;
|
||||
min-width: min(34rem, 100vw);
|
||||
@@ -511,6 +523,7 @@ img {
|
||||
}
|
||||
.site_tree .elements a {
|
||||
align-items: center;
|
||||
border-radius: .2rem;
|
||||
column-gap: .7rem;
|
||||
display: flex;
|
||||
padding: .5rem;
|
||||
@@ -704,6 +717,18 @@ video {
|
||||
@media (min-width: 44rem) {
|
||||
.videos_grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||
}
|
||||
@media (max-width: 45rem) {
|
||||
.site_tree {
|
||||
background: linear-gradient(var(--bg-1), var(--bg-1-85));
|
||||
border: none;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
max-height: unset;
|
||||
padding: .5rem;
|
||||
top: 2.5rem;
|
||||
width: 100vw;
|
||||
}
|
||||
}
|
||||
@media (min-width: 53rem) {
|
||||
.feed_grid { grid-template-columns: 1fr 1fr; }
|
||||
}
|
||||
|
||||
+5
-3
@@ -125,7 +125,7 @@ impl Layout {
|
||||
{close_icon}
|
||||
</button>
|
||||
</div>
|
||||
<div class="site_tree" data-root-prefix="{root_prefix}">
|
||||
<div class="site_tree">
|
||||
<div role="status"></div>
|
||||
<div class="elements"></div>
|
||||
</div>
|
||||
@@ -192,8 +192,10 @@ impl Layout {
|
||||
<div class="layout">
|
||||
<header>
|
||||
<div class="navigation">
|
||||
{logo_polychrome_icon}
|
||||
<span class="title">{e_site_title}</span>
|
||||
<a class="home" href="{root_prefix}">
|
||||
{logo_polychrome_icon}
|
||||
<span class="title">{e_site_title}</span>
|
||||
</a>
|
||||
{browse}
|
||||
{search}
|
||||
</div>
|
||||
|
||||
+25
-13
@@ -47,22 +47,34 @@ pub fn generate_navigation_js(
|
||||
let translations = &site.language.translations;
|
||||
|
||||
fn video_js(translations: &Translations, video: &Video) -> String {
|
||||
let image = video.poster
|
||||
.as_ref()
|
||||
.and_then(|poster| poster.assets.as_ref())
|
||||
.map(|assets| assets.max_160.target_filename("poster"));
|
||||
let title = video.title_or_slug_or_generic_label(&translations);
|
||||
let image;
|
||||
let lqip;
|
||||
match &video.poster {
|
||||
Some(poster) => {
|
||||
image = if let Some(assets) = &poster.assets {
|
||||
let target_filename = assets.max_160.target_filename("poster");
|
||||
format!("image:'{target_filename}',")
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
lqip = if let Some(poster_meta) = &poster.poster_meta {
|
||||
format!("lqip:{},", poster_meta.lqip.js_array())
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
}
|
||||
None => {
|
||||
image = String::new();
|
||||
lqip = String::new();
|
||||
}
|
||||
}
|
||||
|
||||
let site_path = video.site_path.normalized();
|
||||
|
||||
let r_image = if let Some(file_name) = image {
|
||||
format!("image:'{file_name}',")
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
let title = video.title_or_slug_or_generic_label(&translations);
|
||||
let title_escaped = js_escape_inside_single_quoted_string(title);
|
||||
|
||||
format!("{{{r_image}sitePath:'{site_path}',title:'{title_escaped}'}}")
|
||||
format!("{{{lqip}{image}sitePath:'{site_path}',title:'{title_escaped}'}}")
|
||||
}
|
||||
|
||||
fn playlist_js(playlist: &Playlist, translations: &Translations) -> String {
|
||||
|
||||
@@ -37,6 +37,15 @@ impl Lqip {
|
||||
format!("background: {ne}, {nw}, {se}, {sw};")
|
||||
}
|
||||
|
||||
pub fn js_array(&self) -> String {
|
||||
let ne = format!("[{},{},{}]", self.ne.0, self.ne.1, self.ne.2);
|
||||
let nw = format!("[{},{},{}]", self.nw.0, self.nw.1, self.nw.2);
|
||||
let se = format!("[{},{},{}]", self.se.0, self.se.1, self.se.2);
|
||||
let sw = format!("[{},{},{}]", self.sw.0, self.sw.1, self.sw.2);
|
||||
|
||||
format!("[{ne},{nw},{se},{sw}]")
|
||||
}
|
||||
|
||||
pub fn new() -> Lqip {
|
||||
Lqip {
|
||||
ne: (0, 0, 0),
|
||||
|
||||
Reference in New Issue
Block a user