Update page design
This commit is contained in:
@ -14,7 +14,8 @@
|
|||||||
<section>
|
<section>
|
||||||
<ul>
|
<ul>
|
||||||
{#each (items || album.items) as item (item.item)}
|
{#each (items || album.items) as item (item.item)}
|
||||||
<Photo src={`${base}${item.item}`} {album} {item} />
|
{@const src = `${base}${item.item}`}
|
||||||
|
<Photo {src} {album} {item} />
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
@ -22,10 +23,18 @@
|
|||||||
<style>
|
<style>
|
||||||
section {
|
section {
|
||||||
display: block;
|
display: block;
|
||||||
|
padding: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
display: flex;
|
--image-width: 24rem;
|
||||||
|
--image-height: calc(var(--image-width) * 2 / 3);
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, var(--image-width));
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 80rem;
|
||||||
|
margin: 0 auto;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
gap: 1em;
|
gap: 1em;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,140 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { str, strf } from "$lib/data/language";
|
||||||
import Icon from "./Icon.svelte";
|
import Icon from "./Icon.svelte";
|
||||||
|
|
||||||
export let title = 'Galerie';
|
/** The album. */
|
||||||
export let description = '';
|
export let album: Album | undefined = undefined;
|
||||||
|
|
||||||
|
/** The title. Set to `undefined` (or leave unset) to use the title the album (if exists, `Galerie` otherwise). */
|
||||||
|
export let title: string | undefined = undefined;
|
||||||
|
|
||||||
|
/** The description. Set to `undefined` (or leave unset) to use the description the album (if exists, `Fotogalerie von Luca Bosin` otherwise). */
|
||||||
|
export let description: string | undefined = undefined;
|
||||||
|
|
||||||
|
/** The back link. Set to `undefined` (or leave unset) to hide the back link. */
|
||||||
export let back: string | undefined = undefined;
|
export let back: string | undefined = undefined;
|
||||||
|
|
||||||
|
/** Base URL */
|
||||||
|
export let base = '';
|
||||||
|
|
||||||
|
$: displayTitle = title || (album && album.title ? $strf(album.title) : $str('gallery'));
|
||||||
|
$: displayDescription = description || (album && album.description ? $strf(album.description) : $str('gallery-description'));
|
||||||
|
$: displayAuthors = album && album.authors ? (
|
||||||
|
Array.isArray(album.authors) ?
|
||||||
|
album.authors.join(', '):
|
||||||
|
typeof album.authors === 'string' ?
|
||||||
|
album.authors:
|
||||||
|
"unknown author"):
|
||||||
|
"Luca Bosin";
|
||||||
|
$: displayAuthorsTitle = album && album.authors ? (
|
||||||
|
Array.isArray(album.authors) ?
|
||||||
|
album.authors.length > 1 ?
|
||||||
|
$str('authors'):
|
||||||
|
$str('author'):
|
||||||
|
typeof album.authors === 'string' ?
|
||||||
|
$str('author'):
|
||||||
|
"unknown author"):
|
||||||
|
$str('author');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
<section class="title">
|
<section>
|
||||||
{#if back}
|
{#if back}
|
||||||
<a href={back}>
|
<a href={back}>
|
||||||
<Icon mdi="arrow-left" />
|
<Icon mdi="arrow-left" />
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
<h1>{title}</h1>
|
<h1>{displayTitle}</h1>
|
||||||
<p>{description}</p>
|
<p>{displayDescription}</p>
|
||||||
</section>
|
</section>
|
||||||
|
{#if album}
|
||||||
|
<section class="nospace">
|
||||||
|
<dl>
|
||||||
|
<dt>{displayAuthorsTitle}</dt>
|
||||||
|
<dd>{displayAuthors}</dd>
|
||||||
|
<dt>{$str('license')}</dt>
|
||||||
|
<dd><a href={`${base}/license`} tabindex="0">{album.license}</a></dd>
|
||||||
|
</dl>
|
||||||
|
<menu>
|
||||||
|
{#if album.allowDownload !== false}
|
||||||
|
<li>
|
||||||
|
<a href={`${base}/download`} tabindex="0">{$str('download-all')}</a>
|
||||||
|
</li>
|
||||||
|
{/if}
|
||||||
|
</menu>
|
||||||
|
</section>
|
||||||
|
{/if}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
header {
|
||||||
|
display: block;
|
||||||
|
padding: 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
section:not(.nospace) {
|
||||||
|
padding-top: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
padding-bottom: 1.5rem;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 80rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
margin-bottom: 1.2rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
row-gap: .25rem;
|
||||||
|
column-gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd a {
|
||||||
|
color: inherit;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd a:focus {
|
||||||
|
outline: 2px solid var(--main-text-color);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu :has(> *) {
|
||||||
|
padding-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu a {
|
||||||
|
display: inline-block;
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: var(--interactive-bg-color);
|
||||||
|
color: var(--interactive-text-color);
|
||||||
|
transition: background-color .2s, color .2s;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu a:hover {
|
||||||
|
background-color: var(--interactive-bg-hover-color);
|
||||||
|
color: var(--interactive-text-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu a:focus {
|
||||||
|
outline: 2px solid var(--main-text-color);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
/** Load the icon from the `$lib/icons` folder. */
|
/** Load the icon from the `$lib/icons` folder. */
|
||||||
async function loadIcon(mdi: string) {
|
async function loadIcon(mdi: string) {
|
||||||
if (mdi === mdiOld) return;
|
if (mdi === mdiOld) return;
|
||||||
path = (await import(`$lib/icons/${mdi}.js`)).default;
|
path = (await import(`$lib/icons/${mdi}.ts`)).default;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -17,8 +17,10 @@
|
|||||||
|
|
||||||
/** The click handler for the image. */
|
/** The click handler for the image. */
|
||||||
async function clickHandler(event: MouseEvent) {
|
async function clickHandler(event: MouseEvent) {
|
||||||
event.preventDefault();
|
|
||||||
console.log('click', event);
|
console.log('click', event);
|
||||||
|
if (!event.shiftKey && !event.ctrlKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The right click handler for the image. */
|
/** The right click handler for the image. */
|
||||||
@ -50,10 +52,10 @@
|
|||||||
<picture>
|
<picture>
|
||||||
<source media="(min-width: 2560px)" srcset="{src}/t/l" />
|
<source media="(min-width: 2560px)" srcset="{src}/t/l" />
|
||||||
<source media="(min-width: 1600px)" srcset="{src}/t/m" />
|
<source media="(min-width: 1600px)" srcset="{src}/t/m" />
|
||||||
<img src="{src}/t" {alt} loading={lazy ? 'lazy' : 'eager'} />
|
<img src="{src}/t" {alt} loading={lazy ? 'lazy' : 'eager'} {title} />
|
||||||
</picture>
|
</picture>
|
||||||
<figcaption>
|
<figcaption>
|
||||||
<b>{title}</b>
|
<strong>{title}</strong>
|
||||||
<cite>{author}</cite>
|
<cite>{author}</cite>
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
@ -67,25 +69,34 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
overflow: hidden;
|
|
||||||
min-width: 28.125em
|
|
||||||
}
|
}
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
width: 28.125em;
|
width: var(--image-width, 28.125em);
|
||||||
height: 18.75em;
|
height: var(--image-height, 18.75em);
|
||||||
background-color: rgba(0,0,0,.25);
|
background-color: rgba(0,0,0,.25);
|
||||||
background-image: linear-gradient(rgba(0,0,0,.125), rgba(0,0,0,.25)), var(--image);
|
background-image: linear-gradient(rgba(0,0,0,.125), rgba(0,0,0,.25)), var(--image);
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
picture {
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 28.125em;
|
width: var(--image-width, 28.125em);
|
||||||
height: 18.75em;
|
height: var(--image-height, 18.75em);
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
|
||||||
|
transform: scale(1.001);
|
||||||
|
transition: transform .5s cubic-bezier(.23,.13,.45,.97), clip-path .5s cubic-bezier(.23,.13,.45,.97);
|
||||||
}
|
}
|
||||||
|
|
||||||
figcaption {
|
figcaption {
|
||||||
@ -94,7 +105,7 @@
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 1em;
|
padding: 1.5em;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity .5s;
|
transition: opacity .5s;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@ -102,8 +113,9 @@
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
b {
|
strong {
|
||||||
font-size: 1.25em;
|
font-size: 1.25em;
|
||||||
|
letter-spacing: .05em;
|
||||||
}
|
}
|
||||||
|
|
||||||
cite {
|
cite {
|
||||||
@ -120,17 +132,31 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(0,0,0,.5);
|
background-color: transparent;;
|
||||||
color: inherit;
|
color: transparent;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
opacity: 0;
|
transition: background-color .5s, color .5s;
|
||||||
transition: opacity .5s;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
li:hover :is(figcaption, a) {
|
a:focus {
|
||||||
|
outline: 2px solid var(--main-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
li:hover img {
|
||||||
|
transform: scale(1.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
li:hover figcaption {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li:hover a {
|
||||||
|
background-color: rgba(0,0,0,.75);
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -5,6 +5,7 @@ export const language: Writable<TranslationKey> = writable('de');
|
|||||||
const translations: Record<TranslationKey, Record<string, string>> = {
|
const translations: Record<TranslationKey, Record<string, string>> = {
|
||||||
de: {
|
de: {
|
||||||
'gallery': 'Galerie',
|
'gallery': 'Galerie',
|
||||||
|
'gallery-description': 'Fotogalerie von Luca Bosin',
|
||||||
'album': 'Album',
|
'album': 'Album',
|
||||||
'albums': 'Alben',
|
'albums': 'Alben',
|
||||||
'photo': 'Foto',
|
'photo': 'Foto',
|
||||||
@ -19,9 +20,13 @@ const translations: Record<TranslationKey, Record<string, string>> = {
|
|||||||
'open-name': '{0} öffnen',
|
'open-name': '{0} öffnen',
|
||||||
'download': 'Herunterladen',
|
'download': 'Herunterladen',
|
||||||
'download-all': 'Alle herunterladen',
|
'download-all': 'Alle herunterladen',
|
||||||
|
'author': 'Autor',
|
||||||
|
'authors': 'Autoren',
|
||||||
|
'license': 'Lizenz',
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
'gallery': 'Gallery',
|
'gallery': 'Gallery',
|
||||||
|
'gallery-description': 'Photo gallery by Luca Bosin',
|
||||||
'album': 'Album',
|
'album': 'Album',
|
||||||
'albums': 'Albums',
|
'albums': 'Albums',
|
||||||
'photo': 'Photo',
|
'photo': 'Photo',
|
||||||
@ -36,6 +41,9 @@ const translations: Record<TranslationKey, Record<string, string>> = {
|
|||||||
'open-name': 'Open {0}',
|
'open-name': 'Open {0}',
|
||||||
'download': 'Download',
|
'download': 'Download',
|
||||||
'download-all': 'Download all',
|
'download-all': 'Download all',
|
||||||
|
'author': 'Author',
|
||||||
|
'authors': 'Authors',
|
||||||
|
'license': 'License',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,30 @@
|
|||||||
:root {
|
:root {
|
||||||
--main-text-color: #1a1a1a;
|
--main-text-color: #1a1a1a;
|
||||||
--main-bg-color: #fff;
|
--main-bg-color: #fff;
|
||||||
|
|
||||||
|
--interactive-color: var(--main-text-color);
|
||||||
|
|
||||||
|
--interactive-text-color: var(--main-text-color);
|
||||||
|
--interactive-text-hover-color: var(--main-bg-color);
|
||||||
|
--interactive-bg-color: #d4d4d4;
|
||||||
|
--interactive-bg-hover-color: var(--main-text-color);
|
||||||
|
|
||||||
|
--primary-color: #1a1a1a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (prefers-color-scheme: dark) {
|
@media screen and (prefers-color-scheme: dark) {
|
||||||
:root {
|
:root {
|
||||||
--main-text-color: #e7e7e7;
|
--main-text-color: #e7e7e7;
|
||||||
--main-bg-color: #1a1a1a;
|
--main-bg-color: #181818;
|
||||||
|
|
||||||
|
/* --interactive-color: var(--main-text-color); */
|
||||||
|
|
||||||
|
/* --interactive-text-color: var(--main-text-color); */
|
||||||
|
--interactive-text-hover-color: #fff;
|
||||||
|
--interactive-bg-color: #272727;
|
||||||
|
--interactive-bg-hover-color: #353535;
|
||||||
|
|
||||||
|
/* --primary-color: #1a1a1a; */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,7 +34,7 @@
|
|||||||
border: 0;
|
border: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
font-family: 'Roboto', 'Open Sans', sans-serif;
|
font-family: 'Poppins', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
@ -28,7 +46,7 @@ body,
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: sans-serif;
|
font-family: 'Poppins', sans-serif;
|
||||||
background-color: var(--main-bg-color);
|
background-color: var(--main-bg-color);
|
||||||
color: var(--main-text-color);
|
color: var(--main-text-color);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,17 +4,13 @@
|
|||||||
import Header from '$lib/components/Header.svelte';
|
import Header from '$lib/components/Header.svelte';
|
||||||
import Gallery from '$lib/components/Gallery.svelte';
|
import Gallery from '$lib/components/Gallery.svelte';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
|
import Footer from '$lib/components/Footer.svelte';
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Header title={$strf(data.album.title)}/>
|
|
||||||
<p>
|
|
||||||
<b>Description:</b> {#if data.album.description}{$strf(data.album.description)}{:else}<i>no description</i>{/if}<br />
|
|
||||||
<b>Authors: </b> {#if data.album.authors}{Array.isArray(data.album.authors) ? data.album.authors.join(', ') : data.album.authors}{:else}<i>unknown author</i>{/if}<br />
|
|
||||||
<b>Sorting Date:</b> {data.album.date}<br />
|
|
||||||
<b>License:</b> {data.album.license}<br />
|
|
||||||
</p>
|
|
||||||
<main>
|
<main>
|
||||||
|
<Header album={data.album} base={data.base} />
|
||||||
<Gallery album={data.album} base={`${data.base}/i/`} />
|
<Gallery album={data.album} base={`${data.base}/i/`} />
|
||||||
|
<Footer />
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
Reference in New Issue
Block a user