articles canvas mode

This commit is contained in:
2026-04-13 01:26:21 -05:00
parent 8c47404d02
commit 0aa0cc72a7
7 changed files with 65 additions and 69 deletions

View File

@@ -1,28 +1,67 @@
import {useArticle} from "./ArticleContext";
import "./list.sass";
import {ReactComponent as BoxSvg} from "../img/blog-box.svg";
import {Article, ARTICLES} from "./articles";
import {motion} from "motion/react";
import {AnimateFade} from "../animations";
import {Canvas} from "@react-three/fiber";
import {Environment, Html, OrbitControls} from "@react-three/drei";
import MilkyWay from "../img/2k_stars_milky_way.jpg";
import {Sun} from "../index/Canvas";
import {Bloom, EffectComposer, Vignette} from "@react-three/postprocessing";
import {useEffect, useState} from "react";
import {Reader} from "./Reader";
import {useRouter} from "../router/RouterContext";
import {Path} from "../router/router";
const ARTICLE_QUERY = "a";
const main = AnimateFade();
export default function ArticlesList() {
return <motion.main animate={main.animate} initial={main.initial} className="art-ctr">
<section className="spacer"/>
<section className="articles">
{
ARTICLES.map(a =>
<BlogBox key={a.name} article={a} />
)
const [article, setArticle] = useState<Article | null>(null);
const router = useRouter();
useEffect(() => {
const params = new URLSearchParams(location.search);
if(params.has(ARTICLE_QUERY)) {
const id = Number.parseInt(params.get(ARTICLE_QUERY)!);
setArticle(ARTICLES[id] ?? null);
}
}, [setArticle]);
useEffect(() => {
if(!article) {
// query param
const params = new URLSearchParams(location.search);
if(params.has(ARTICLE_QUERY)) {
router.replacePage(location.pathname as Path);
}
</section>
<section className="spacer"/>
} else {
const id = ARTICLES.indexOf(article);
router.replacePage(`${location.pathname}?${ARTICLE_QUERY}=${id}` as Path);
}
}, [article]);
return <motion.main animate={main.animate} initial={main.initial} className="art-ctr">
<Canvas camera={{position: [0,0,20]}}>
<Environment background files={MilkyWay}/>
<EffectComposer>
<Bloom luminanceThreshold={0} luminanceSmoothing={0.9} />
<Vignette eskil={false} offset={0.1} darkness={1.1} />
</EffectComposer>
<Sun/>
<OrbitControls enablePan={false} enableZoom />
<Html className="articles" zIndexRange={[100,0]} prepend center transform>
{
ARTICLES.map(a => <BlogBox setReading={setArticle} article={a}/>)
}
</Html>
</Canvas>
<Reader post={article} setPost={setArticle}/>
</motion.main>
}
function BlogBox(props: { article: Article }) {
const {article, article: {name, description, thumbnail, published} } = props;
const [, setReading] = useArticle();
function BlogBox(props: { article: Article, setReading: (_: Article | null) => void }) {
const {article, setReading, article: {name, description, thumbnail, published} } = props;
return (
<button className="link" onClick={() => setReading(article)}>