Compare commits

..

9 Commits

Author SHA1 Message Date
e52b3374e5 Added build folder to git 2026-06-16 21:39:28 +03:00
d35974aadb Fix build warning 2026-06-16 21:38:16 +03:00
8cdf3e04ce Fix archive page on mobile 2026-06-16 21:26:24 +03:00
8f8d593ff0 Fixing TS linter errors 2026-06-16 21:17:42 +03:00
6f46083a90 Fix fade in clsoing of performer card 2026-06-16 21:10:30 +03:00
1f8b9bedc0 Improved Archive page 2026-06-16 21:03:22 +03:00
62a87a1169 Add Archive link back 2026-06-15 23:16:41 +03:00
38cb38f53f Fix warnings and remove dist folder 2026-06-15 23:11:11 +03:00
6ff218e0f3 Fix Dart Sass legacy JS API deprecation warning
- Upgrade sass from 1.99.0 to 1.101.0 (latest)
- Add css.preprocessorOptions.scss.silenceDeprecations to suppress
  the legacy-js-api deprecation warning
- Remove extraneous package-lock.json (using bun)

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-15 23:08:03 +03:00
41 changed files with 1640 additions and 5057 deletions

2
.gitignore vendored
View File

@@ -32,4 +32,4 @@ yarn-error.log*
.vercel
# typescript
*.tsbuildinfo
*.tsbuildinfo

View File

@@ -11,7 +11,7 @@
"react-router-dom": "^6.22.0",
"react-transition-group": "^4.4.2",
"reactstrap": "^9.1.1",
"sass": "^1.99.0",
"sass": "^1.101.0",
},
"devDependencies": {
"@types/react": "^18.2.0",
@@ -232,7 +232,7 @@
"caniuse-lite": ["caniuse-lite@1.0.30001787", "", {}, "sha512-mNcrMN9KeI68u7muanUpEejSLghOKlVhRqS/Za2IeyGllJ9I9otGpR9g3nsw7n4W378TE/LyIteA0+/FOZm4Kg=="],
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
"chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="],
"classnames": ["classnames@2.3.1", "", {}, "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="],
@@ -312,17 +312,17 @@
"reactstrap": ["reactstrap@9.1.1", "", { "dependencies": { "@babel/runtime": "^7.12.5", "@popperjs/core": "^2.6.0", "classnames": "^2.2.3", "prop-types": "^15.5.8", "react-popper": "^2.2.4", "react-transition-group": "^4.4.2" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-XlQI5qKHQ4QMpye4GxLgoj8rv+qsypvzMcs2KA11DeYjT82LcS48ttfNqOodDYyeCYv8t89gd9THXkjGhoYp5A=="],
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
"readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="],
"rollup": ["rollup@4.60.2", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.2", "@rollup/rollup-android-arm64": "4.60.2", "@rollup/rollup-darwin-arm64": "4.60.2", "@rollup/rollup-darwin-x64": "4.60.2", "@rollup/rollup-freebsd-arm64": "4.60.2", "@rollup/rollup-freebsd-x64": "4.60.2", "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", "@rollup/rollup-linux-arm-musleabihf": "4.60.2", "@rollup/rollup-linux-arm64-gnu": "4.60.2", "@rollup/rollup-linux-arm64-musl": "4.60.2", "@rollup/rollup-linux-loong64-gnu": "4.60.2", "@rollup/rollup-linux-loong64-musl": "4.60.2", "@rollup/rollup-linux-ppc64-gnu": "4.60.2", "@rollup/rollup-linux-ppc64-musl": "4.60.2", "@rollup/rollup-linux-riscv64-gnu": "4.60.2", "@rollup/rollup-linux-riscv64-musl": "4.60.2", "@rollup/rollup-linux-s390x-gnu": "4.60.2", "@rollup/rollup-linux-x64-gnu": "4.60.2", "@rollup/rollup-linux-x64-musl": "4.60.2", "@rollup/rollup-openbsd-x64": "4.60.2", "@rollup/rollup-openharmony-arm64": "4.60.2", "@rollup/rollup-win32-arm64-msvc": "4.60.2", "@rollup/rollup-win32-ia32-msvc": "4.60.2", "@rollup/rollup-win32-x64-gnu": "4.60.2", "@rollup/rollup-win32-x64-msvc": "4.60.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ=="],
"sass": ["sass@1.99.0", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.1.5", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": "sass.js" }, "sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q=="],
"sass": ["sass@1.101.0", "", { "dependencies": { "chokidar": "^5.0.0", "immutable": "^5.1.5", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-OL3GoQyoUdDt843DpVmDO6y2k1sc5IhUDSpu8XucEI+35neq5QivZ1iuegnpraEVTJXlQGK1gl27zKcTLEPbQw=="],
"scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="],
"semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"source-map-js": ["source-map-js@1.0.2", "", {}, "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
@@ -338,8 +338,6 @@
"dom-helpers/csstype": ["csstype@3.1.0", "", {}, "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="],
"postcss/source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"@types/react-transition-group/@types/react/csstype": ["csstype@3.1.0", "", {}, "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="],
}
}

6
declarations.d.ts vendored
View File

@@ -2,3 +2,9 @@ declare module "*.module.scss" {
const classes: { [key: string]: string };
export default classes;
}
declare module "react-transition-group/CSSTransition" {
import { ComponentType } from "react";
const CSSTransition: ComponentType<any>;
export default CSSTransition;
}

1
dist/assets/index-BHL1kCFY.css vendored Normal file

File diff suppressed because one or more lines are too long

67
dist/assets/index-Dj6kuw_y.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
dist/collaborators/aviador.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

BIN
dist/collaborators/naantali.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
dist/collaborators/prosinervo.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
dist/collaborators/siltala.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

BIN
dist/collaborators/skr.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

BIN
dist/collaborators/teos.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
dist/collaborators/vaihela.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

16
dist/index.html vendored
View File

@@ -3,6 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<title>Runosaari</title>
<link
href="https://fonts.googleapis.com/css?family=Crimson+Text&display=optional"
@@ -10,19 +11,14 @@
/>
<meta property="og:title" content="Runosaari" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://www.runosaari.net/" />
<meta property="og:image:url" content="https://www.runosaari.net/runosaari-logo.jpg" />
<meta property="og:url" content="https://www.runosaari.fi/" />
<meta property="og:image:url" content="https://www.runosaari.fi/runosaari-logo.jpg" />
<meta property="og:image:type" content="image/jpg" />
<meta property="og:image:width" content="1516" />
<meta property="og:image:height" content="582" />
<meta property="og:description" content="Runofestivaali saariston sylissä 11. - 13.6.2026" />
<script
defer
src="https://diamond-rabbit.pikapod.net/script.js"
data-website-id="2778daae-4fd3-45c5-babe-9b9b988a75d4"
></script>
<script type="module" crossorigin src="/assets/index-JqxfPGLe.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-F7gmz0E2.css">
<meta property="og:description" content="Runofestivaali saariston sylissä 12. - 13.6.2026" />
<script type="module" crossorigin src="/assets/index-Dj6kuw_y.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BHL1kCFY.css">
</head>
<body>
<div id="root"></div>

BIN
dist/performers/2026/djangomania.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

BIN
dist/performers/2026/haiva.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
dist/performers/2026/helena-sinervo.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

BIN
dist/performers/2026/jouni-inkala.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

BIN
dist/performers/2026/juurakko.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

BIN
dist/performers/2026/kulmala.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
dist/performers/2026/olli-heikkonen.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

BIN
dist/performers/2026/outi-illuusia.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
dist/performers/2026/paaskynen.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
dist/performers/2026/pegasos.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

BIN
dist/performers/2026/sinivaara.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
dist/performers/2026/susiluoto.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
dist/performers/2026/zoila.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

6309
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,7 @@
"name": "runosaari",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
@@ -15,7 +16,7 @@
"react-router-dom": "^6.22.0",
"react-transition-group": "^4.4.2",
"reactstrap": "^9.1.1",
"sass": "^1.99.0"
"sass": "^1.101.0"
},
"devDependencies": {
"@types/react": "^18.2.0",

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { CSSTransition } from 'react-transition-group';
import CSSTransition from 'react-transition-group/CSSTransition';
import shared from '../../styles/Shared.module.scss';
import styles from '../../styles/Archive.module.scss';
import PerformersData2021 from '../../data/performers/2021';
@@ -28,15 +28,26 @@ const sortedYears = Object.keys(dataByYear).map(Number).sort((a, b) => b - a);
const Archive = () => {
const [performersByYear, setPerformersByYear] = useState<Record<number, PerformerCard[]>>({});
const [expandedYears, setExpandedYears] = useState<Record<number, boolean>>({});
useEffect(() => {
const initial: Record<number, PerformerCard[]> = {};
const initialExpanded: Record<number, boolean> = {};
for (const year of sortedYears) {
initial[year] = dataByYear[year].map((p) => ({ ...p, showDesc: false }));
initialExpanded[year] = false;
}
setPerformersByYear(initial);
setExpandedYears(initialExpanded);
}, []);
const toggleYear = (year: number) => {
setExpandedYears((prev) => ({
...prev,
[year]: !prev[year],
}));
};
const togglePerformerDesc = (year: number, id: string) => {
setPerformersByYear((prev) => ({
...prev,
@@ -51,50 +62,70 @@ const Archive = () => {
<h1>Arkisto</h1>
{sortedYears.map((year) => (
<React.Fragment key={year}>
<h2 className={styles.year}>{year}</h2>
{(performersByYear[year] ?? []).map((p) => (
<div className={styles.performerContainer} key={p.id}>
<img
className={styles.performerImage}
src={'/performers/' + year + '/' + p.id + '.jpg'}
width={100}
height={100}
loading="lazy"
alt={p.name}
/>
<div className={styles.performerTextContainer}>
<div
className={styles.performerTitle}
onClick={() => togglePerformerDesc(year, p.id)}
>
<h2>{p.name}</h2>
<button className={shared.openingChevron}>
{p.showDesc ? (
<BiChevronDown size='3rem' />
) : (
<BiChevronLeft size='3rem' />
)}
</button>
</div>
<CSSTransition
in={p.showDesc}
timeout={1000}
classNames='fadeTransition'
>
{p.showDesc ? (
<div>
{p.paragraphs.map((parag, index) => (
<p key={index}>{parag.toString()}</p>
))}
<div
className={styles.yearTitle}
onClick={() => toggleYear(year)}
>
<h2 className={styles.year}>{year}</h2>
<button className={shared.openingChevron}>
{expandedYears[year] ? (
<BiChevronDown size='3rem' />
) : (
<BiChevronLeft size='3rem' />
)}
</button>
</div>
<div className={styles.yearPerformers}>
<CSSTransition
in={expandedYears[year]}
timeout={300}
classNames='fadeTransition'
unmountOnExit
>
<div className={styles.yearPerformersContent}>
{(performersByYear[year] ?? []).map((p) => (
<div className={styles.performerContainer} key={p.id}>
<img
className={styles.performerImage}
src={'/performers/' + year + '/' + p.id + '.jpg'}
width={100}
height={100}
loading="lazy"
alt={p.name}
/>
<div className={styles.performerTextContainer}>
<div
className={styles.performerTitle}
onClick={() => togglePerformerDesc(year, p.id)}
>
<h2>{p.name}</h2>
<button className={shared.openingChevron}>
{p.showDesc ? (
<BiChevronDown size='3rem' />
) : (
<BiChevronLeft size='3rem' />
)}
</button>
</div>
<CSSTransition
in={p.showDesc}
timeout={300}
classNames='fadeTransition'
unmountOnExit
>
<div>
{p.paragraphs.map((parag, index) => (
<p key={index}>{parag.toString()}</p>
))}
</div>
</CSSTransition>
<hr />
</div>
) : (
<span></span>
)}
</CSSTransition>
<hr />
</div>
))}
</div>
</div>
))}
</CSSTransition>
</div>
</React.Fragment>
))}
</section>

View File

@@ -3,6 +3,8 @@ import Program from './Program';
import styles from '../../styles/Index.module.scss';
import Lead from '../components/Lead';
import Collaboration from '../components/Collaboration';
import { Link } from 'react-router-dom';
import { FiExternalLink } from 'react-icons/all';
const Index = () => {
return (
@@ -15,6 +17,10 @@ const Index = () => {
{/* <Workshops /> */}
{/* <Info /> */}
{/* <Archive /> */}
<Link to="/archive">
<span className={styles.archiveLinkText}>Aiempien vuosien esiintyjiä</span>
<FiExternalLink fontSize={20} />
</Link>
</div>
);
};

View File

@@ -7,11 +7,40 @@
margin-bottom: 1em;
}
.yearTitle {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
width: 100%;
margin-bottom: 1em;
h2 {
flex: 1;
min-width: 0;
}
h2:hover {
color: rgb(117, 117, 117);
transition: color 0.3s;
}
}
.yearPerformers {
width: 100%;
overflow: hidden;
}
.yearPerformersContent {
width: 100%;
}
.performerContainer {
display: flex;
justify-content: flex-start;
align-items: flex-start;
width: 90%;
width: 100%;
box-sizing: border-box;
p {
padding-left: 1rem;
@@ -22,14 +51,14 @@
width: 100%;
margin-top: 2rem;
margin-bottom: 2rem;
width: 100%;
}
}
.performerTextContainer {
width: 80%;
flex: 1;
margin-left: 1rem;
margin-top: 1rem;
min-width: 0;
}
.performerTitle {
@@ -41,7 +70,8 @@
h2 {
margin-left: 1rem;
width: 100%;
flex: 1;
min-width: 0;
}
h2:hover {

View File

@@ -15,3 +15,11 @@
}
}
}
.archiveLinkText {
font-size: 2.5rem;
margin-right: 1rem;
color: #2f273e;
text-decoration: none;
font-weight: bold;
}

View File

@@ -18,6 +18,8 @@
text-align: center;
width: 47rem;
max-width: 100%;
padding: 0 1rem;
box-sizing: border-box;
margin-bottom: 4rem;
}

View File

@@ -15,3 +15,36 @@
opacity: 0;
transition: opacity 1000ms;
}
// Height transition for Archive page
.heightTransition-enter {
max-height: 0;
overflow: hidden;
}
.heightTransition-enter-active {
max-height: 10000px;
overflow: hidden;
transition: max-height 300ms ease-out;
}
.heightTransition-enter-done {
max-height: 10000px;
overflow: hidden;
}
.heightTransition-exit {
max-height: 10000px;
overflow: hidden;
}
.heightTransition-exit-active {
max-height: 0;
overflow: hidden;
transition: max-height 300ms ease-out;
}
.heightTransition-exit-done {
max-height: 0;
overflow: hidden;
}

View File

@@ -13,5 +13,5 @@
"jsx": "react-jsx",
"strict": true
},
"include": ["src", "data", "types"]
"include": ["src", "data", "types", "declarations.d.ts"]
}

View File

@@ -7,4 +7,11 @@ export default defineConfig({
port: 8089,
allowedHosts: ["runosaari.fi", "www.runosaari.fi"],
},
css: {
preprocessorOptions: {
scss: {
silenceDeprecations: ["legacy-js-api"],
},
},
},
});