Unify the logic of Buttons and Windows in Main dir

I struggled to add the `Webrings` button earlier
So that warranted a much-needed revisit of the logic
This commit is contained in:
Taevas 2025-04-12 14:15:38 +02:00
parent b1f0300a11
commit b8f8af8782
15 changed files with 262 additions and 356 deletions

View file

@ -1,6 +1,6 @@
import React from "react";
export default function TabButton({
export default function WindowButton({
colors,
onClick,
content,

78
src/Main/Header/index.tsx Normal file
View file

@ -0,0 +1,78 @@
import React from "react";
import AnimateHeight from "react-animate-height";
import Translatable from "#parts/Translatable.tsx";
import {type WindowDetails, LanguageContext, WindowContext} from "#contexts";
import type { OpenableWindow } from "#Main/index.tsx";
import WindowButton from "./WindowButton.tsx";
export default function Header({
openableWindows,
setLang,
setWindows,
}: {
openableWindows: OpenableWindow[]
setLang: React.Dispatch<React.SetStateAction<string>>;
setWindows: React.Dispatch<React.SetStateAction<WindowDetails[]>>;
}) {
const lang = React.useContext(LanguageContext);
const windows = React.useContext(WindowContext);
const isWindowOpened = (window_id: string) => windows.map((w) => w.id).includes(window_id);
const toggleWindow = (window_id: string) => {
if (isWindowOpened(window_id)) {
setWindows(windows.filter((t) => t.id !== window_id));
} else {
if (window.innerWidth >= 1024) {
setWindows([...windows.map((w) => {
const newPriority = w.priority === "z-40" ? "z-30" :
w.priority === "z-30" ? "z-20" : "z-10";
return {id: w.id, priority: newPriority};
}), {id: window_id, priority: "z-40"}]);
} else {
setWindows([{id: window_id, priority: "z-40"}]);
}
}
};
const buttons = openableWindows.map((w) => {
return <WindowButton
key={`button-${w.id}`}
colors={`${w.colors} ${isWindowOpened(w.id) ? "brightness-75" : ""}`}
onClick={() => toggleWindow(w.id)}
content={w.title.long}
/>;
});
return (
<header className="bg-blue-600 text-white lg:border-solid lg:border-white lg:border-8 lg:rounded-xl lg:mb-8">
<AnimateHeight
id="intro"
duration={300}
height={windows.length ? 0 : "auto"}
>
<div className="bg-white text-blue-600 relative justify-center items-center pb-4 pt-2 lg:rounded-b-xl lg:pt-0 lg:px-4 hover:brightness-110 active:brightness-110">
<Translatable
en={<h1 className="text-6xl md:text-8xl">Hi, I'm Taevas!</h1>}
fr={<h1 className="text-6xl md:text-8xl">Bonjour, je m'appelle <span className="text-nowrap">Taevas !</span></h1>}
/>
<h2 className="text-3xl pt-4 md:pt-2">
<Translatable
en={"If you're here, you're probably interested by who I am and what I do"}
fr={"Si vous êtes ici, vous êtes alors probablement intéressé·e par qui je suis et ce que je fais"}
/>
</h2>
</div>
</AnimateHeight>
<nav className="p-4">
<WindowButton
colors={"from-slate-500 to-slate-600 hover:from-slate-700 hover:to-slate-600"}
onClick={() => setLang(lang !== "en" ? "en" : "fr")}
content={lang === "fr" ? "🇬🇧" : "🇫🇷"}
/>
{...buttons}
</nav>
</header>
);
}

View file

@ -1,99 +0,0 @@
import React from "react";
import TabButton from "./TabButton.tsx";
import Translatable from "#parts/Translatable.tsx";
import {type TabDetails, LanguageContext, TabContext} from "#contexts";
export default function TabButtons({
setLang,
setTabs,
}: {
setLang: React.Dispatch<React.SetStateAction<string>>;
setTabs: React.Dispatch<React.SetStateAction<TabDetails[]>>;
}) {
const lang = React.useContext(LanguageContext);
const tabs = React.useContext(TabContext);
const isTabActive = (id: string) => tabs.map((t) => t.id).includes(id);
const toggleTab = (tab: string) => {
if (isTabActive(tab)) {
setTabs(tabs.filter((t) => t.id !== tab));
} else {
if (window.innerWidth >= 1024) {
setTabs([...tabs.map((tab) => {
const newPriority = tab.priority === "z-40" ? "z-30" :
tab.priority === "z-30" ? "z-20" : "z-10";
return {id: tab.id, priority: newPriority};
}), {id: tab, priority: "z-40"}]);
} else {
setTabs([{id: tab, priority: "z-40"}]);
}
}
};
return (
<nav className="relative justify-center items-center">
<TabButton
colors={"from-slate-500 to-slate-600 hover:from-slate-700 hover:to-slate-600"}
onClick={() => {
setLang(lang !== "en" ? "en" : "fr");
}}
content={lang === "fr" ? "🇬🇧" : "🇫🇷"}
/>
<TabButton
colors={`from-purple-500 to-purple-600 hover:from-purple-700 hover:to-purple-600 ${isTabActive("about") ? "brightness-75" : ""}`}
onClick={() => {
toggleTab("about");
}}
content={
<Translatable
en="About me"
fr="À propos de moi"
/>
}
/>
<TabButton
colors={`from-emerald-500 to-emerald-600 hover:from-emerald-700 hover:to-emerald-600 ${isTabActive("projects") ? "brightness-75" : ""}`}
onClick={() => {
toggleTab("projects");
}}
content={
<Translatable
en="My projects"
fr="Mes projets"
/>
}
/>
<TabButton
colors={`from-blue-500 to-blue-600 hover:from-blue-700 hover:to-blue-600 ${isTabActive("contact") ? "brightness-75" : ""}`}
onClick={() => {
toggleTab("contact");
}}
content={
<Translatable
en="Contact me"
fr="Me contacter"
/>
}
/>
<TabButton
colors={`from-rose-500 to-rose-600 hover:from-rose-700 hover:to-rose-600 ${isTabActive("support") ? "brightness-75" : ""}`}
onClick={() => {
toggleTab("support");
}}
content={
<Translatable
en="Support me"
fr="Me soutenir"
/>
}
/>
<TabButton
colors={`from-cyan-500 to-cyan-600 hover:from-cyan-700 hover:to-cyan-600 ${isTabActive("webrings") ? "brightness-75" : ""}`}
onClick={() => {
toggleTab("webrings");
}}
content="Webrings"
/>
</nav>
);
}

View file

@ -1,45 +0,0 @@
import React from "react";
import AnimateHeight from "react-animate-height";
import TabButtons from "./TabButtons/index.tsx";
import Translatable from "#parts/Translatable.tsx";
import {type TabDetails, TabContext} from "#contexts";
export default function MainWindow({
setLang,
setTabs,
}: {
setLang: React.Dispatch<React.SetStateAction<string>>;
setTabs: React.Dispatch<React.SetStateAction<TabDetails[]>>;
}) {
const tabs = React.useContext(TabContext);
return (
<div className="bg-blue-600 text-white lg:border-solid lg:border-white lg:border-8 lg:rounded-xl lg:mb-8">
<AnimateHeight
id="intro"
duration={300}
height={tabs.length ? 0 : "auto"}
>
<div className="bg-white text-blue-600 relative justify-center items-center pb-4 pt-2 lg:rounded-b-xl lg:pt-0 lg:px-4 hover:brightness-110 active:brightness-110">
<Translatable
en={<h1 className="text-6xl md:text-8xl">Hi, I'm Taevas!</h1>}
fr={<h1 className="text-6xl md:text-8xl">Bonjour, je m'appelle <span className="text-nowrap">Taevas !</span></h1>}
/>
<h2 className="text-3xl pt-4 md:pt-2">
<Translatable
en={"If you're here, you're probably interested by who I am and what I do"}
fr={"Si vous êtes ici, vous êtes alors probablement intéressé·e par qui je suis et ce que je fais"}
/>
</h2>
</div>
</AnimateHeight>
<div className="p-4">
<TabButtons
setLang={setLang}
setTabs={setTabs}
/>
</div>
</div>
);
}

View file

@ -1,60 +0,0 @@
import React from "react";
import Tab from "../Tab.tsx";
import Translatable from "#parts/Translatable.tsx";
import {UserMultiple} from "@carbon/icons-react";
import {type TabDetails} from "#contexts";
import Link from "#parts/Link.tsx";
export default function Webrings({
setTabs,
}: {
setTabs: React.Dispatch<React.SetStateAction<TabDetails[]>>;
}) {
const elements = [
<div className="pb-4" key="webrings-list">
<iframe id="bucket-webring" className="w-full h-[3rem]" src="https://webring.bucketfish.me/embed.html?name=Taevas&lightmode=true"/>
</div>,
<div className="text-left" key="webrings-intro">
<p className="pb-2">
<Translatable
en={<><Link link="https://en.wikipedia.org/wiki/Webring" text="Webrings"/> are kinda thought of as <b>something from the past,</b> mainly because search engines had become good at their job in the 2000s, and also partly because of how much everything has become centralized on a few websites.</>}
fr={<>Les <Link link="https://fr.wikipedia.org/wiki/Webring" text="Webrings"/> sont un peu perçus comme <b>une chose du passé</b>, surtout parce que les moteurs de recherche sont devenus bons à ce qu'ils sont censés faire dans les années 2000, mais aussi un peu parce que tout est devenu bien plus centralisé sur certains sites.</>}
/>
</p>
<p className="pb-2">
<Translatable
en={<>However, <b>they've kinda been making a comeback</b> thanks to fans of the <Link link="https://en.wikipedia.org/wiki/Web_2.0#Web_1.0" text="Web 1.0"/> such as the people that are on <Link link="https://neocities.org/" text="Neocities"/>. Furthermore, people have been reporting that search engines have been becoming worse over the past few years!</>}
fr={<>Néanmoins, <b>ils sont un peu revenus</b> grâce aux fans du Web 1.0, tel que les gens qui sont sur <Link link="https://neocities.org/" text="Neocities"/>. Et aussi, il est parfois dit que les moteurs de recherche sont devenus pires durant ces dernières années !</>}
/>
</p>
<p className="pb-2">
<Translatable
en={<>Finally, don't you think <b>it's hard to discover personal websites?</b> Like, if I asked you to find the website of someone you don't know, your best bet would likely be to go on the nerdiest Fediverse instance you know of and to click on a few profiles there in the hope of finding a link, I think.</>}
fr={<>Enfin, n'êves-vous pas d'accord pour dire <b>qu'il est difficile de trouver des sites web personnels ?</b> Genre, si je vous demandais de trouver le site de quelqu'un que vous ne connaissez pas, la meilleure façon serait probablement d'aller sur l'instance Fediverse la plus nerd que vous connaissez et de cliquer sur quelques profils dans l'espoir de trouver un lien, en tout cas je pense.</>}
/>
</p>
<p className="pb-2">
<Translatable
en={<>The Webrings above can be thought of as <b>curated lists of like-minded people, so feel free to surf through those once you're done here!</b></>}
fr={<>Les Webrings ci-dessus peuvent être considérés comme des <b>listes de personnes comme moi, alors allez y surfer une fois que vous avez fini ici !</b></>}
/>
</p>
</div>
];
return (
<Tab
setTabs={setTabs}
id="webrings"
name={
<Translatable
en="Webrings"
fr="Webrings"
/>
}
elements={elements}
logo={<UserMultiple size={48} fill=""/>}
position="lg:left-[700px] lg:top-[400px]"
/>
);
}

View file

@ -1,23 +0,0 @@
import React from "react";
import {type TabDetails} from "#contexts";
import About from "./About/index.tsx";
import Contact from "./Contact/index.tsx";
import Projects from "./Projects/index.tsx";
import Support from "./Support/index.tsx";
import Webrings from "./Webrings/index.tsx";
export default function Tabs({
setTabs,
}: {
setTabs: React.Dispatch<React.SetStateAction<TabDetails[]>>;
}) {
return (
<>
<About setTabs={setTabs} />
<Projects setTabs={setTabs} />
<Contact setTabs={setTabs} />
<Support setTabs={setTabs} />
<Webrings setTabs={setTabs} />
</>
);
}

View file

@ -1,16 +1,9 @@
import React from "react";
import Tab from "../Tab.tsx";
import Translatable from "#parts/Translatable.tsx";
import {UserProfile} from "@carbon/icons-react";
import {type TabDetails} from "#contexts";
import Link from "#parts/Link.tsx";
export default function About({
setTabs,
}: {
setTabs: React.Dispatch<React.SetStateAction<TabDetails[]>>;
}) {
const elements = [(
export default function About() {
return (
<div className="order-1" key="about">
<div className="ml-auto max-w-3xl text-left">
<img className="m-4 float-right h-24" src="/assets/brittany.jpg" alt="Flag of Brittany" title="Flag of Brittany"/>
@ -49,21 +42,5 @@ export default function About({
/>
</div>
</div>
)];
return (
<Tab
setTabs={setTabs}
id="about"
name={
<Translatable
en="About"
fr="À propos"
/>
}
elements={elements}
logo={<UserProfile size={48} fill=""/>}
position="lg:left-[100px] lg:top-[200px]"
/>
);
}

View file

@ -1,18 +1,11 @@
import React from "react";
import Tab from "../Tab.tsx";
import {MailAll} from "@carbon/icons-react";
import CopyField from "#parts/CopyField.tsx";
import ButtonLink from "#parts/ButtonLink.tsx";
import Translatable from "#parts/Translatable.tsx";
import Link from "#parts/Link.tsx";
import {type TabDetails} from "#contexts";
export default function Contact({
setTabs,
}: {
setTabs: React.Dispatch<React.SetStateAction<TabDetails[]>>;
}) {
const elements = [(
export default function Contact() {
return (
<div className="text-left" key="contact">
<Translatable
en={<p>It is my belief that it's actually difficult to communicate with the people you want on the internet, I find emails to be bad for real-time communication, some other platforms enshittify themselves too much, while others do not quite offer the best user experience in my honest opinion.</p>}
@ -34,21 +27,5 @@ export default function Contact({
fr={<ButtonLink link="https://matrix.to/#/@taevas:matrix.org" text="lien matrix.to" />}
/>
</div>
)];
return (
<Tab
setTabs={setTabs}
id="contact"
name={
<Translatable
en="Contact"
fr="Contacter"
/>
}
elements={elements}
logo={<MailAll size={48} fill=""/>}
position="lg:left-[400px] lg:top-[300px]"
/>
);
}

View file

@ -1,16 +1,9 @@
import React from "react";
import Tab from "../Tab.tsx";
import Translatable from "#parts/Translatable.tsx";
import {Devices} from "@carbon/icons-react";
import {type TabDetails} from "#contexts";
import Link from "#parts/Link.tsx";
export default function Projects({
setTabs,
}: {
setTabs: React.Dispatch<React.SetStateAction<TabDetails[]>>;
}) {
const elements = [(
export default function Projects() {
return (
<div className="inline-block text-left" key="projects">
<div className="border-b-4 pb-4">
<a href="https://tttaevas.itch.io/swordventure" target="_blank" rel="noreferrer"><img className="m-4 float-right w-40" src="/assets/swordventure.png" alt="SwordVenture thumbnail"/></a>
@ -106,21 +99,5 @@ export default function Projects({
/>
</div>
</div>
)];
return (
<Tab
setTabs={setTabs}
id="projects"
name={
<Translatable
en="Projects"
fr="Projets"
/>
}
elements={elements}
logo={<Devices size={48} fill=""/>}
position="lg:left-[250px] lg:top-[250px]"
/>
);
}

View file

@ -1,16 +1,9 @@
import React from "react";
import Tab from "../Tab.tsx";
import Translatable from "#parts/Translatable.tsx";
import {UserFavorite} from "@carbon/icons-react";
import {type TabDetails} from "#contexts";
import ButtonLink from "#parts/ButtonLink.tsx";
export default function Support({
setTabs,
}: {
setTabs: React.Dispatch<React.SetStateAction<TabDetails[]>>;
}) {
const elements = [(
export default function Support() {
return (
<div className="pb-2" key="support">
<p>
<b>
@ -37,21 +30,5 @@ export default function Support({
fr={<ButtonLink link="https://ko-fi.com/taevas" text="Soutenez-moi sur Ko-fi !"/>}
/>
</div>
)];
return (
<Tab
setTabs={setTabs}
id="support"
name={
<Translatable
en="Support"
fr="Soutenir"
/>
}
elements={elements}
logo={<UserFavorite size={48} fill=""/>}
position="lg:left-[550px] lg:top-[350px]"
/>
);
}

View file

@ -0,0 +1,39 @@
import React from "react";
import Translatable from "#parts/Translatable.tsx";
import Link from "#parts/Link.tsx";
export default function Webrings() {
return (
<div key="webrings">
<div className="pb-4" key="webrings-list">
<iframe id="bucket-webring" className="w-full h-[3rem]" src="https://webring.bucketfish.me/embed.html?name=Taevas&lightmode=true"/>
</div>,
<div className="text-left" key="webrings-intro">
<p className="pb-2">
<Translatable
en={<><Link link="https://en.wikipedia.org/wiki/Webring" text="Webrings"/> are kinda thought of as <b>something from the past,</b> mainly because search engines had become good at their job in the 2000s, and also partly because of how much everything has become centralized on a few websites.</>}
fr={<>Les <Link link="https://fr.wikipedia.org/wiki/Webring" text="Webrings"/> sont un peu perçus comme <b>une chose du passé</b>, surtout parce que les moteurs de recherche sont devenus bons à ce qu'ils sont censés faire dans les années 2000, mais aussi un peu parce que tout est devenu bien plus centralisé sur certains sites.</>}
/>
</p>
<p className="pb-2">
<Translatable
en={<>However, <b>they've kinda been making a comeback</b> thanks to fans of the <Link link="https://en.wikipedia.org/wiki/Web_2.0#Web_1.0" text="Web 1.0"/> such as the people that are on <Link link="https://neocities.org/" text="Neocities"/>. Furthermore, people have been reporting that search engines have been becoming worse over the past few years!</>}
fr={<>Néanmoins, <b>ils sont un peu revenus</b> grâce aux fans du Web 1.0, tel que les gens qui sont sur <Link link="https://neocities.org/" text="Neocities"/>. Et aussi, il est parfois dit que les moteurs de recherche sont devenus pires durant ces dernières années !</>}
/>
</p>
<p className="pb-2">
<Translatable
en={<>Finally, don't you think <b>it's hard to discover personal websites?</b> Like, if I asked you to find the website of someone you don't know, your best bet would likely be to go on the nerdiest Fediverse instance you know of and to click on a few profiles there in the hope of finding a link, I think.</>}
fr={<>Enfin, n'êves-vous pas d'accord pour dire <b>qu'il est difficile de trouver des sites web personnels ?</b> Genre, si je vous demandais de trouver le site de quelqu'un que vous ne connaissez pas, la meilleure façon serait probablement d'aller sur l'instance Fediverse la plus nerd que vous connaissez et de cliquer sur quelques profils dans l'espoir de trouver un lien, en tout cas je pense.</>}
/>
</p>
<p className="pb-2">
<Translatable
en={<>The Webrings above can be thought of as <b>curated lists of like-minded people, so feel free to surf through those once you're done here!</b></>}
fr={<>Les Webrings ci-dessus peuvent être considérés comme des <b>listes de personnes comme moi, alors allez y surfer une fois que vous avez fini ici !</b></>}
/>
</p>
</div>
</div>
);
}

View file

@ -1,39 +1,39 @@
import React, {Component} from "react";
import AnimateHeight from "react-animate-height";
import type Translatable from "#parts/Translatable.tsx";
import {type TabDetails, TabContext} from "#contexts";
import {type WindowDetails, WindowContext} from "#contexts";
export default class Tab extends Component<{
setTabs: React.Dispatch<React.SetStateAction<TabDetails[]>>;
export default class Window extends Component<{
setWindows: React.Dispatch<React.SetStateAction<WindowDetails[]>>;
id: string;
name: ReturnType<typeof Translatable>;
elements: React.JSX.Element[];
logo?: React.JSX.Element;
position?: string;
}> {
static contextType = TabContext;
context!: React.ContextType<typeof TabContext>;
static contextType = WindowContext;
context!: React.ContextType<typeof WindowContext>;
private readonly div = React.createRef<HTMLDivElement>();
private readonly header = React.createRef<HTMLDivElement>();
render() {
return (
<TabContext.Consumer>
{tabs => (
<WindowContext.Consumer>
{windows => (
<AnimateHeight
className={`absolute w-full lg:w-[625px] lg:rounded-xl ${this.props.position}
bg-blue-800/75 hover:bg-blue-800/80 active:bg-blue-800/70 backdrop-brightness-75 backdrop-contrast-150 backdrop-blur
shadow-[12px_12px_0_0] shadow-blue-950/75
${tabs.find((t) => t.id === this.props.id)?.priority ?? "z-50"}`}
${windows.find((w) => w.id === this.props.id)?.priority ?? "z-50"}`}
ref={this.div}
duration={250}
height={tabs.map((t) => t.id).includes(this.props.id) ? "auto" : 0}
height={windows.map((w) => w.id).includes(this.props.id) ? "auto" : 0}
>
<div ref={this.header} className="relative bg-white lg:rounded-xl h-12 hover:brightness-110 lg:hover:cursor-grab lg:active:cursor-move">
{this.props.logo ? <div className="absolute start-0 h-0 ml-2 invisible lg:visible fill-gray-600">{this.props.logo}</div> : <></>}
<div className="absolute end-0 w-0 sm:w-10 mr-1 mt-1 invisible lg:visible cursor-pointer
rounded-full fill-red-500 hover:fill-black hover:bg-red-500 active:brightness-50" onClick={() => {
this.props.setTabs(tabs.filter((t) => t.id !== this.props.id));
this.props.setWindows(windows.filter((w) => w.id !== this.props.id));
}}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<path d="M24 9.4L22.6 8L16 14.6L9.4 8L8 9.4l6.6 6.6L8 22.6L9.4 24l6.6-6.6l6.6 6.6l1.4-1.4l-6.6-6.6L24 9.4z"/>
@ -49,7 +49,7 @@ export default class Tab extends Component<{
</div>
</AnimateHeight>
)}
</TabContext.Consumer>
</WindowContext.Consumer>
);
}
@ -76,14 +76,14 @@ export default class Tab extends Component<{
});
this.div.current?.addEventListener("pointerdown", () => {
const tabs = this.context;
this.props.setTabs(tabs.map((tab) => {
if (tab.id === this.props.id) {
return {id: tab.id, priority: "z-40"};
const windows = this.context;
this.props.setWindows(windows.map((w) => {
if (w.id === this.props.id) {
return {id: w.id, priority: "z-40"};
} else {
const newPriority = tab.priority === "z-40" ? "z-30" :
tab.priority === "z-30" ? "z-20" : "z-10";
return {id: tab.id, priority: newPriority};
const newPriority = w.priority === "z-40" ? "z-30" :
w.priority === "z-30" ? "z-20" : "z-10";
return {id: w.id, priority: newPriority};
}
}));
});

View file

@ -0,0 +1,37 @@
import React from "react";
import {type WindowDetails} from "#contexts";
import type { OpenableWindow } from "#Main/index.tsx";
import Window from "./Window";
export default function Windows({
openableWindows,
setWindows
}: {
openableWindows: OpenableWindow[];
setWindows: React.Dispatch<React.SetStateAction<WindowDetails[]>>;
}) {
const lefts = [
"lg:left-[50px]",
"lg:left-[100px]",
"lg:left-[150px]",
"lg:left-[200px]",
"lg:left-[250px]",
"lg:left-[300px]",
"lg:left-[350px]",
"lg:left-[400px]",
];
const windows = openableWindows.map((w, i) => {
return <Window
key={`window-${w.id}`}
setWindows={setWindows}
id={w.id}
name={w.title.short}
elements={[w.content]}
logo={w.icon}
position={lefts[i]}
/>;
});
return <>{...windows}</>;
}

View file

@ -1,11 +1,82 @@
import React, {useEffect, useState} from "react";
import MainWindow from "./MainWindow/index.tsx";
import Tabs from "./Tabs/index.tsx";
import {type TabDetails, LanguageContext, TabContext} from "#contexts";
import Header from "./Header/index.tsx";
import Windows from "./Windows/index.tsx";
import {type WindowDetails, LanguageContext, WindowContext} from "#contexts";
import Translatable from "#parts/Translatable.tsx";
import { Devices, MailAll, UserFavorite, UserMultiple, UserProfile } from "@carbon/icons-react";
import About from "./Windows/Content/About.tsx";
import Projects from "./Windows/Content/Projects.tsx";
import Contact from "./Windows/Content/Contact.tsx";
import Support from "./Windows/Content/Support.tsx";
import Webrings from "./Windows/Content/Webrings.tsx";
export interface OpenableWindow {
/** Used for React keys and tracking what's opened and what's not */
id: string
title: {
/** Used for places where width is unimportant, like buttons */
long: React.JSX.Element
/** Used for places where **width IS important**, like the top of a window */
short: React.JSX.Element
}
/** Classes, intended for buttons */
colors: string
/** An icon from Carbon, intended to make certain things feel less empty */
icon: React.JSX.Element
/** The content of the window */
content: React.JSX.Element
}
export default function MainContent() {
const [lang, setLang] = useState<string>(localStorage.getItem("lang") ?? "en");
const [tabs, setTabs] = useState<TabDetails[]>([]);
const [windows, setWindows] = useState<WindowDetails[]>([]);
const [openableWindows] = useState<OpenableWindow[]>([{
id: "about",
title: {
long: <Translatable en="About me" fr="À propos de moi"/>,
short: <Translatable en="About" fr="À propos"/>
},
colors: "from-purple-500 to-purple-600 hover:from-purple-700 hover:to-purple-600",
icon: <UserProfile size={48} fill=""/>,
content: <About/>
}, {
id: "projects",
title: {
long: <Translatable en="My projects" fr="Mes projets"/>,
short: <Translatable en="Projects" fr="Projets"/>
},
colors: "from-emerald-500 to-emerald-600 hover:from-emerald-700 hover:to-emerald-600",
icon: <MailAll size={48} fill=""/>,
content: <Projects/>
}, {
id: "contact",
title: {
long: <Translatable en="Contact me" fr="Me contacter"/>,
short: <Translatable en="Contact" fr="Contacter"/>
},
colors: "from-blue-500 to-blue-600 hover:from-blue-700 hover:to-blue-600",
icon: <Devices size={48} fill=""/>,
content: <Contact/>
}, {
id: "support",
title: {
long: <Translatable en="Support me" fr="Me soutenir"/>,
short: <Translatable en="Support" fr="Soutenir"/>
},
colors: "from-rose-500 to-rose-600 hover:from-rose-700 hover:to-rose-600",
icon: <UserFavorite size={48} fill=""/>,
content: <Support/>
}, {
id: "webrings",
title: {
long: <Translatable en="Webrings"/>,
short: <Translatable en="Webrings"/>
},
colors: "from-cyan-500 to-cyan-600 hover:from-cyan-700 hover:to-cyan-600",
icon: <UserMultiple size={48} fill=""/>,
content: <Webrings/>
}]);
useEffect(() => {
localStorage.setItem("lang", lang);
@ -14,10 +85,10 @@ export default function MainContent() {
return (
<main className="text-lg/6 h-screen w-screen max-w-[1632px] m-auto lg:pl-[50px] lg:pr-[413px] lg:py-12">
<LanguageContext.Provider value={lang}>
<TabContext.Provider value={tabs}>
<MainWindow setLang={setLang} setTabs={setTabs}/>
<Tabs setTabs={setTabs}/>
</TabContext.Provider>
<WindowContext.Provider value={windows}>
<Header openableWindows={openableWindows} setLang={setLang} setWindows={setWindows}/>
<Windows openableWindows={openableWindows} setWindows={setWindows}/>
</WindowContext.Provider>
</LanguageContext.Provider>
</main>
);

View file

@ -1,9 +1,9 @@
import React from "react";
export interface TabDetails {
export interface WindowDetails {
id: string;
priority: string;
}
export const LanguageContext = React.createContext<string>("en");
export const TabContext = React.createContext<TabDetails[]>([]);
export const WindowContext = React.createContext<WindowDetails[]>([]);