Skip to content

Commit

Permalink
feat: implement galleria
Browse files Browse the repository at this point in the history
  • Loading branch information
Azganoth committed Aug 13, 2023
1 parent 9b41dee commit 9a98aab
Show file tree
Hide file tree
Showing 103 changed files with 4,112 additions and 22 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BASE_PATH=/galleria-slideshow-site
5 changes: 4 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"extends": ["next/core-web-vitals", "prettier"]
"extends": ["next/core-web-vitals", "prettier"],
"rules": {
"@next/next/no-img-element": "off"
}
}
234 changes: 234 additions & 0 deletions app/[id]/page.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
.content {
padding: 24px;
margin-bottom: 73px; /* footer height */
}

.painting {
position: relative;
}

.viewButton {
position: absolute;
top: 16px;
left: 16px;
}

.hero {
height: 280px;
object-fit: cover;
}

.legend {
position: absolute;
left: 0;
bottom: 0;
right: 47px;
padding: 24px;
transform: translateY(54px);
background: var(--color-white);
}

.legendPainting {
margin-bottom: 8px;
color: var(--color-black);
font-size: 24px;
font-weight: bold;
line-height: 1.2;
}

.legendArtist {
font-size: 15px;
}

.legendImage {
position: absolute;
top: 100%;
left: 16px;
width: 64px;
height: 64px;
}

.info {
margin-top: 98px;
}

.year {
margin-bottom: -26px;
color: var(--color-light-gray);
font-size: 100px;
font-weight: bold;
line-height: 1;
text-align: right;
}

.description {
margin-bottom: 40px;
font-weight: bold;
line-height: 2;
}

.source {
font-size: 9px;
letter-spacing: 1.93px;
text-decoration: underline;
text-transform: uppercase;
}

.footer {
position: fixed;
left: 0;
bottom: 0;
right: 0;
background: var(--color-white);
}

.controls {
position: relative;
display: flex;
align-items: center;
padding: 17px 24px 16px;
}

.progress,
.progress::after {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
}

.progress {
background: var(--color-gray);
}

.progress::after {
content: '';
background: var(--color-black);
transform: scaleX(var(--progress));
transform-origin: left;
}

.controlPainting {
margin-bottom: 9px;
color: var(--color-black);
font-size: 14px;
font-weight: bold;
}

.controlArtist {
opacity: 75%;
color: var(--color-black);
font-size: 10px;
}

@media (min-width: 768px) {
.content {
padding: 40px;
margin-bottom: 97px; /* footer height */
}

.viewButton {
top: unset;
bottom: 16px;
}

.hero {
width: 475px;
height: 560px;
}

.legend {
left: unset;
top: 0;
bottom: unset;
right: 0;
padding: 0 0 67px 65px;
width: 445px;
transform: none;
}

.legendPainting {
margin-bottom: 24px;
font-size: 56px;
line-height: 1.14;
}

.legendImage {
top: 100%;
left: unset;
right: 55px;
width: 128px;
height: 128px;
}

.info {
margin-top: 64px;
}

.year {
margin-bottom: -75px;
font-size: 200px;
line-height: 0.75;
text-align: left;
}

.description {
margin-bottom: 68px;
}

.context {
margin: 0 116px 68px;
}

.controls {
padding: 25px 41px;
}

.controlPainting {
margin-bottom: 8px;
font-size: 18px;
}

.controlArtist {
font-size: 13px;
}
}

@media (min-width: 1440px) {
.content {
display: flex;
align-items: flex-start;
gap: 30px;
padding: 100px 40px 75px;
}

.hero {
margin-right: 380px;
width: 475px;
height: 560px;
}

.legendImage {
top: 496px;
left: 95px;
right: unset;
}

.info {
margin-top: 0;
}

.year {
margin-bottom: -35px;
text-align: right;
}

.description {
margin-bottom: 165px;
}

.context {
margin: 0 125px 53px 1px;
}
}
114 changes: 114 additions & 0 deletions app/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import styles from './page.module.css';
import type { Metadata } from 'next';
import { paintings } from '@/data';
import Header from '@/_components/Header';
import Lightbox from '@/_components/Lightbox';
import MediaControl from '@/_components/MediaControl';
import normalizeUrl from '@/_utils/normalizeUrl';

export async function generateStaticParams() {
return paintings.map(({ id }) => ({ id }));
}

type Props = {
params: {
id: string;
};
};

export function generateMetadata({ params: { id } }: Props): Metadata {
const { name, description } = paintings.find(
(painting) => painting.id === id,
)!;
return {
title: `Galleria - ${name}`,
description: description.slice(0, description.indexOf('.') + 1),
};
}

export default function Page({ params: { id } }: Props) {
const paintingIndex = paintings.findIndex((painting) => painting.id === id);
const lastPaintingIndex = paintings.length - 1;

const painting = paintings[paintingIndex];
const previousPainting = paintings[paintingIndex - 1];
const nextPainting = paintings[paintingIndex + 1];

const paintingName = painting.name;
const paintingDescription = painting.description;
const paintingYear = painting.year;
const paintingImages = painting.images;

const artistName = painting.artist.name;
const artistImage = painting.artist.image;

const source = painting.source;

return (
<>
<Header action="stop" />
<main className={styles.content}>
<section className={styles.painting}>
<picture>
<source
media="(min-width: 768px)"
srcSet={normalizeUrl(paintingImages.hero.large)}
/>
<img
className={styles.hero}
src={normalizeUrl(paintingImages.hero.small)}
alt={`${paintingName} painting.`}
/>
</picture>
<Lightbox
className={styles.viewButton}
name={paintingName}
url={normalizeUrl(paintingImages.gallery)}
/>
<div className={styles.legend}>
<h1 className={styles.legendPainting}>{paintingName}</h1>
<p className={styles.legendArtist}>{artistName}</p>
<img
className={styles.legendImage}
src={normalizeUrl(artistImage)}
alt={artistName}
/>
</div>
</section>
<div className={styles.info}>
<div className={styles.year}>{paintingYear}</div>
<div className={styles.context}>
<p className={styles.description}>{paintingDescription}</p>
<a className={styles.source} href={source}>
Go to source
</a>
</div>
</div>
</main>
<footer className={styles.footer}>
<div className={styles.controls}>
<div
className={styles.progress}
style={{
['--progress' as string]: `${
(paintingIndex + 1) / (lastPaintingIndex + 1)
}`,
}}
></div>
<div>
<h2 className={styles.controlPainting}>{paintingName}</h2>
<p className={styles.controlArtist}>{artistName}</p>
</div>
<MediaControl
action="previous"
href={previousPainting ? `/${previousPainting.id}` : undefined}
/>
<MediaControl
action="next"
href={nextPainting ? `/${nextPainting.id}` : undefined}
/>
</div>
</footer>
</>
);
}
1 change: 1 addition & 0 deletions app/_assets/icon-back-button.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/_assets/icon-next-button.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/_assets/icon-view-image.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/_assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 9a98aab

Please sign in to comment.