style & layout updates

This commit is contained in:
rhiannon morris 2023-06-21 19:58:01 +02:00
parent ebd08fb2e5
commit 485b90fb46
9 changed files with 65 additions and 159 deletions

View File

@ -1,7 +1,7 @@
module Date
(Date (..),
Day (..), dayNum, exact,
formatLong, formatShort, formatRSS, formatSlash,
formatLong, formatShort, formatRSS, formatSlash, formatTooltip,
parseP, parseS, parseA)
where
@ -9,7 +9,7 @@ import Control.Applicative
import qualified Text.ParserCombinators.ReadP as ReadP
import Text.ParserCombinators.ReadP (ReadP, readS_to_P, readP_to_S, (<++))
import Data.Time hiding (Day)
import Data.Char (isSpace)
import Data.Char (isSpace, toLower)
import BuilderQQ
import Data.Function (on)
import Data.Maybe (fromMaybe)
@ -60,6 +60,15 @@ formatShort (Date {month, day}) = [b|$day'$month'|] where
Unknown -> ""
month' = formatTime defaultTimeLocale "%b" $ fromGregorian 1 month 1
formatTooltip :: Date -> Builder
formatTooltip (Date {year, month, day}) = [b|$day'$month' $year|] where
day' = case day of
Exact d -> [b|$d $&|]
Approx d -> [b|$d? $&|]
Unknown -> ""
month' = map toLower $
formatTime defaultTimeLocale "%b" $ fromGregorian 1 month 1
formatRSS :: Date -> Builder
formatRSS = fromString . format . toTime where
format = formatTime defaultTimeLocale "%a, %d %b %_Y %T GMT"

View File

@ -12,7 +12,7 @@ import Data.Function (on, (&))
import qualified Data.HashMap.Strict as HashMap
import Data.HashSet (HashSet)
import qualified Data.HashSet as HashSet
import Data.List (intersperse, groupBy, sortBy, sortOn)
import Data.List (intersperse, groupBy, sortBy, sort)
import Data.Maybe
import qualified Data.Text.Lazy as Lazy
import System.FilePath (takeDirectory, joinPath, splitPath)
@ -52,9 +52,8 @@ make' root (GalleryInfo {title, desc, prefix, filters, hidden}) infos = [b|@0
<div class=page>
<header>
<h1>$title</h1>
<h2 class="right corner">
<a href=rss.xml>rss</a>
</h2>
<a class="right corner" href=rss.xml>rss</a>
<a class="left corner" href=$undir>back</a>
</header>
<nav id=filters>
@ -86,10 +85,6 @@ make' root (GalleryInfo {title, desc, prefix, filters, hidden}) infos = [b|@0
$6.items
</ul>
</main>
<footer>
<a href=$undir>all galleries</a>
</footer>
</div>
|]
where
@ -110,7 +105,7 @@ make' root (GalleryInfo {title, desc, prefix, filters, hidden}) infos = [b|@0
allTags = infos
& concatMap (map (,1) . tagsFor nsfw . #second)
& HashMap.fromListWith (+) & HashMap.toList
& sortOn (\(tag, count) -> (Down count, tag))
& sort
requireFilters = map (uncurry $ makeFilter "require" mempty) allTags
excludeFilters = map (uncurry $ makeFilter "exclude" hidden) allTags
@ -153,18 +148,12 @@ makeYearItems nsfw year infos = [b|@0
makeItem :: Bool -> FilePath -> Info -> Builder
makeItem nsfw file info@(Info {bg}) = [b|@0
<li class="item post$nsfw'" data-date="$date'" data-year=$year'
data-updated="$updated'"
<li class="item post$nsfw'" data-year=$year' data-updated="$updated'"
data-tags="$tags'">
<figure>
<a href="$dir">
<img src="$thumb" loading=lazy$bgStyle>
</a>
<figcaption>
<span class=date>$date'</span>
<span class=title>$title</span>
</figcaption>
</figure>
<a href="$dir">
<img src="$thumb" loading=lazy$bgStyle
title="$tooltip">
</a>
|]
where
title = fromMaybe (#title info) $ #galleryTitle info
@ -173,7 +162,10 @@ makeItem nsfw file info@(Info {bg}) = [b|@0
nsfw' = if nsfw && #anyNsfw info then [b| nsfw|] else ""
tags' = fold $ intersperse ";" $ map fromText $ tagsFor nsfw info
date = #latestDate info nsfw
date' = formatShort date
date' = formatTooltip date
year' = #year date
updated' = if #updated info nsfw then [b|true|] else [b|false|]
bgStyle = case bg of Other col -> [b| style="background: $col"|]; _ -> ""
tooltip =
let upd = if #updated info nsfw then "updated " else "" :: Builder in
[b|$title ($upd$date')|]

View File

@ -3,7 +3,8 @@
{-# OPTIONS_GHC -Wno-orphans #-}
module Info
(Info (..),
tagsFor, descFor, imagesFor, linksFor, updatesFor, compareFor, sortFor,
tagsFor, descFor, imagesFor, linksFor, updatesFor, lastUpdate,
compareFor, sortFor,
Artist (..), Images' (..), Images, Image (..), Desc (..), DescField (..),
Link (..), Update (..), Bg (..),
GalleryInfo (..), GalleryFilters (..), ArtistFilter (..), NsfwFilter (..),
@ -219,6 +220,10 @@ linksFor nsfw = if nsfw then #links else #sfwLinks
updatesFor :: Bool -> Info -> [(Date, [Update])]
updatesFor nsfw = if nsfw then #updates else #sfwUpdates
lastUpdate :: Bool -> Info -> Maybe Date
lastUpdate nsfw info =
case updatesFor nsfw info of [] -> Nothing; us -> Just $ fst $ last us
compareFor :: Bool -> Info -> Info -> Ordering
compareFor nsfw = comparing \i -> (#latestDate i nsfw, #sortEx i, #title i)

View File

@ -158,6 +158,7 @@ make' root siteName prefix nsfw _dataDir dir
<h2 id=date class="right corner">
$formattedDate $updateDate
</h2>
<a class="left corner" href=$undir>back to gallery</a>
</header>
$2.buttonBar
@ -180,10 +181,6 @@ make' root siteName prefix nsfw _dataDir dir
$6.tagsList
</div>
</main>
<footer>
<a href=$undir>back to gallery</a>
</footer>
</div>
<template id=cw-template>

View File

@ -130,7 +130,7 @@ function sortFilters(cmp) {
sort1('exclude');
}
function sortFiltersAlpha() {
function sortFiltersAlpha(e) {
function getName(x) {
if (x.nodeType == Node.ELEMENT_NODE) {
return x.getElementsByTagName('input')[0].value;
@ -139,9 +139,10 @@ function sortFiltersAlpha() {
}
}
sortFilters((a, b) => getName(a).localeCompare(getName(b)));
e.preventDefault();
}
function sortFiltersUses() {
function sortFiltersUses(e) {
function getUses(x) {
if (x.nodeType == Node.ELEMENT_NODE) {
return parseInt(x.getElementsByTagName('label')[0].dataset.count);
@ -150,6 +151,7 @@ function sortFiltersUses() {
}
}
sortFilters((a, b) => getUses(b) - getUses(a));
e.preventDefault();
}
@ -160,8 +162,8 @@ function setup() {
}
let items = Array.from(document.getElementsByClassName('post'));
itemsByYear = new Map;
itemsByYear = new Map;
for (let item of items) {
let year = item.dataset.year;
if (!itemsByYear.has(year)) itemsByYear.set(year, new Set);

View File

@ -28,7 +28,6 @@
--text-col: white;
--text-shadow-col: hsl(0, 0%, 0%, 75%);
--text-shadow: 2px 2px 3px var(--text-shadow-col);
--nsfw-sticker-rotate: 15deg;
--focus-box: 0 0 5px hsl(55deg, 60%, 90%, 80%);
--focus-text: hsl(334deg, 87%, 90%);
@ -53,6 +52,8 @@
margin: 0;
}
body { margin: 0; }
header {
text-align: center;
}
@ -65,12 +66,10 @@ h3 { font-size: 110%; }
.page {
background: var(--background);
border: var(--border);
position: relative;
padding: 2em 4em;
margin: 3em auto 3.5em;
border-radius: var(--border-radius);
margin: 0 auto;
color: var(--text-col);
text-shadow: var(--text-shadow);
@ -112,7 +111,7 @@ figure > img {
margin: 0;
padding: 0;
position: absolute;
top: 0.5em;
top: 1em;
font-size: 100%;
font-weight: 500;

View File

@ -3,13 +3,18 @@
:root {
--image-size: 200px;
--gap: 1em;
--badge-size: calc(1/4 * var(--image-size));
--gap: 0em;
}
@media (min-width: 1000px) {
.page { max-width: 80%; }
}
.page {
padding: 2em calc(1/4 * var(--image-size));
}
#filters {
margin: 1em 0 2em 0;
}
@ -33,7 +38,6 @@
.filterlist {
display: flex;
flex-flow: row wrap;
/* justify-content: space-between; */
padding: 0;
font-weight: 500;
@ -54,10 +58,7 @@
}
.filterlist label {
padding: 0.15em 0.4em;
border-radius: var(--button-radius);
background: var(--button-bg);
border: var(--button-border);
cursor: pointer;
}
.filterlist label::before {
@ -154,35 +155,18 @@
.item:not(.year-marker) {
box-shadow: var(--text-shadow);
border: var(--border-thickness) solid var(--border-col);
border-radius: 0.5em;
background: hsl(340, 45%, 65%);
outline: var(--border-thickness) solid var(--border-col);
background: hsl(0, 0%, 0%, 50%);
clip-path: polygon(5% 0, 95% 10%, 95% 100%, 5% 90%);
}
.item img {
clip-path: polygon(7% 2%, 93% 12%, 93% 98%, 7% 88%);
}
.item:focus-within {
box-shadow: var(--focus-box);
}
figure {
margin: 0;
padding: 0;
}
figcaption .date, figcaption .title {
position: absolute;
width: 100%;
border: 1px solid var(--border-col);
display: block;
text-align: center;
background: hsl(0, 0%, 0%, 75%);
text-shadow: none;
}
figcaption .date { top: -1px; left: -1px; }
figcaption .title { bottom: -1px; left: -1px; }
.date { text-transform: lowercase; }
.year-marker {
/* uncomment to reenable line breaks before year markers */
/* grid-area: auto / 1; */
@ -210,9 +194,8 @@ figcaption .title { bottom: -1px; left: -1px; }
}
.item.nsfw::before, .item[data-updated="true"]::after {
height: var(--size);
width: var(--size);
transform: var(--base-transform);
height: var(--badge-size);
width: var(--badge-size);
display: inline-block;
position: absolute;
@ -221,19 +204,18 @@ figcaption .title { bottom: -1px; left: -1px; }
}
.item.nsfw::before {
--size: calc(1/4 * var(--image-size));
--base-transform: rotate(var(--nsfw-sticker-rotate));
transform: rotate(15deg);
content: url(../18_plus_white.svg);
top: calc(1em + 3px);
right: 3px;
top: 11%;
right: 7%;
z-index: 100;
}
.item[data-updated="true"]::after {
--size: calc(1/4 * var(--image-size));
--base-transform: rotate(-8deg);
transform: rotate(-8deg);
content: url(../sparkles.svg);
bottom: calc(1em + 3px);
right: 3px;
bottom: 4%;
right: 7%;
}
footer {
@ -242,68 +224,6 @@ footer {
margin-top: 1em;
}
@media (hover) and (pointer: fine) {
.item:hover .date, .item:hover .title,
.item:hover::before, .item:hover::after {
filter: opacity(20%);
}
@media (prefers-reduced-motion: no-preference) {
figcaption .date, figcaption .title, .item::before, .item::after {
transition-property: filter, transform;
transition-duration: 0.15s;
transition-timing-function: ease-in-out;
}
.item:hover .title {
transform: translate(-20%, 80%) rotateZ(7deg);
}
.item:hover .date {
transform: translate(20%, -80%) rotateZ(7deg);
}
.item:hover::before {
transform: translate(1.5em, -1.5em) var(--base-transform);
}
.item:hover::after {
transform: translate(1.5em, 1.5em) var(--base-transform);
}
}
}
@media (not hover), (pointer: coarse) {
.item:not(.year-marker) {
height: min-content;
}
figcaption .date, figcaption .title {
position: initial;
}
figcaption .date {
border-bottom: none;
}
figcaption .title {
border-top: none;
}
figcaption .date::after {
content: ':';
}
.item a {
display: block;
height: var(--image-size);
}
.item img {
margin-bottom: 0;
}
}
@media (pointer: coarse) {
#filters label {
font-size: 150%;

View File

@ -9,6 +9,7 @@
.page {
width: 37.5em;
border-radius: var(--border-radius);
}
#title::before, #title::after {
@ -30,12 +31,11 @@
}
@media screen {
@media not speech {
.nsfw::after {
content: url(../18_plus_white.svg);
height: 1em;
width: 1em;
transform: rotate(var(--nsfw-sticker-rotate));
mix-blend-mode: hard-light;
margin-left: 0.3em;
}
@ -43,7 +43,7 @@
@media speech {
.nsfw::after {
content: ' (some nsfw)';
content: ' (contains adult content)';
}
}

View File

@ -18,7 +18,6 @@
position: relative;
overflow: hidden;
border: var(--border-thickness) solid var(--border-col);
border-radius: 1em;
box-shadow: var(--text-shadow);
background: hsl(340, 45%, 65%);
}
@ -76,20 +75,6 @@
}
}
/*
.nsfw-label::after {
content: url(../18_plus_white.svg);
display: inline-block;
height: 0.9em; width: 0.9em;
vertical-align: -0.07em;
padding-left: 0.25em;
}
:checked ~ .nsfw-label::after {
content: url(../18_plus.svg);
}
*/
#date { text-transform: lowercase; }
#info {
@ -104,9 +89,6 @@
align-items: baseline;
}
/* 'display: contents' removes things from the accessibility tree
* which is probably only a problem for screen readers?
*/
@media not speech {
.info-section {
display: contents;