rearch links, routes + add resume link
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
import "./about.scss";
|
import "./about.scss";
|
||||||
import {lazy, PropsWithChildren} from "react";
|
import {HTMLProps, lazy} from "react";
|
||||||
|
import {Link} from "../router/Link";
|
||||||
|
import {Path} from "../router/router";
|
||||||
|
|
||||||
const About = lazy(() => import("./About.mdx"));
|
const About = lazy(() => import("./About.mdx"));
|
||||||
|
|
||||||
@@ -15,8 +17,8 @@ export default function AboutPage() {
|
|||||||
</main>
|
</main>
|
||||||
}
|
}
|
||||||
|
|
||||||
function ExternalLink(props: PropsWithChildren & { href: string }) {
|
function ExternalLink(props: HTMLProps<HTMLAnchorElement>) {
|
||||||
return (
|
return (
|
||||||
<a href={props.href} className="link external-link" target="_blank">{props.children}</a>
|
<Link {...props} href={props.href as Path} className="external-link" target="_blank">{props.children}</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
BIN
src/img/resume.pdf
Executable file
BIN
src/img/resume.pdf
Executable file
Binary file not shown.
38
src/index.d.ts
vendored
38
src/index.d.ts
vendored
@@ -19,49 +19,71 @@ declare module '*.md' {
|
|||||||
export default MDXComponent;
|
export default MDXComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '*.pdf' {
|
||||||
|
import {Path} from "./router/router";
|
||||||
|
|
||||||
|
const src: Path;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
|
||||||
declare module '*.avif' {
|
declare module '*.avif' {
|
||||||
const src: string;
|
import {Path} from "./router/router";
|
||||||
|
|
||||||
|
const src: Path;
|
||||||
export default src;
|
export default src;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '*.bmp' {
|
declare module '*.bmp' {
|
||||||
const src: string;
|
import {Path} from "./router/router";
|
||||||
|
|
||||||
|
const src: Path;
|
||||||
export default src;
|
export default src;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '*.gif' {
|
declare module '*.gif' {
|
||||||
const src: string;
|
import {Path} from "./router/router";
|
||||||
|
|
||||||
|
const src: Path;
|
||||||
export default src;
|
export default src;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '*.jpg' {
|
declare module '*.jpg' {
|
||||||
const src: string;
|
import {Path} from "./router/router";
|
||||||
|
|
||||||
|
const src: Path;
|
||||||
export default src;
|
export default src;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '*.jpeg' {
|
declare module '*.jpeg' {
|
||||||
const src: string;
|
import {Path} from "./router/router";
|
||||||
|
|
||||||
|
const src: Path;
|
||||||
export default src;
|
export default src;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '*.png' {
|
declare module '*.png' {
|
||||||
const src: string;
|
import {Path} from "./router/router";
|
||||||
|
|
||||||
|
const src: Path;
|
||||||
export default src;
|
export default src;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '*.webp' {
|
declare module '*.webp' {
|
||||||
const src: string;
|
import {Path} from "./router/router";
|
||||||
|
|
||||||
|
const src: Path;
|
||||||
export default src;
|
export default src;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '*.svg' {
|
declare module '*.svg' {
|
||||||
|
import {Path} from "./router/router";
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
export const ReactComponent: React.FunctionComponent<React.SVGProps<
|
export const ReactComponent: React.FunctionComponent<React.SVGProps<
|
||||||
SVGSVGElement
|
SVGSVGElement
|
||||||
> & { title?: string }>;
|
> & { title?: string }>;
|
||||||
|
|
||||||
const src: string;
|
const src: Path;
|
||||||
export default src;
|
export default src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,10 @@ import React from 'react';
|
|||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
import {RouterProvider} from "./router/RouterContext";
|
import {RouterProvider} from "./router/RouterContext";
|
||||||
import {Route} from "./router/Route";
|
|
||||||
import "@fontsource/inter"; // Defaults to weight 400
|
import "@fontsource/inter"; // Defaults to weight 400
|
||||||
import "@fontsource/neuton"; // Defaults to weight 400
|
import "@fontsource/neuton";
|
||||||
|
import {Routes} from "./router/Route";
|
||||||
|
|
||||||
const Canvas = React.lazy(() => import("./index/Canvas"));
|
|
||||||
const About = React.lazy(() => import("./about/AboutPage"));
|
|
||||||
const Nav = React.lazy(() => import("./nav/Nav"));
|
const Nav = React.lazy(() => import("./nav/Nav"));
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(
|
const root = ReactDOM.createRoot(
|
||||||
@@ -18,15 +16,7 @@ root.render(
|
|||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<RouterProvider>
|
<RouterProvider>
|
||||||
<Nav/>
|
<Nav/>
|
||||||
<Route path="/">
|
<Routes/>
|
||||||
<Canvas/>
|
|
||||||
</Route>
|
|
||||||
<Route path="/about">
|
|
||||||
<About/>
|
|
||||||
</Route>
|
|
||||||
<Route path="/articles">
|
|
||||||
<div>Test</div>
|
|
||||||
</Route>
|
|
||||||
</RouterProvider>
|
</RouterProvider>
|
||||||
</React.StrictMode>
|
</React.StrictMode>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,21 +1,33 @@
|
|||||||
import {useState} from "react";
|
|
||||||
import {Link} from "../router/Link";
|
import {Link} from "../router/Link";
|
||||||
import {motion} from "framer-motion";
|
import {motion} from "framer-motion";
|
||||||
|
import {ROUTES} from "../router/Route";
|
||||||
|
import ResumePdf from "../img/resume.pdf";
|
||||||
|
|
||||||
export function Links() {
|
export function Links() {
|
||||||
const [links] = useState(["About", "Articles"]);
|
|
||||||
|
|
||||||
return <div className="links">
|
return <div className="links">
|
||||||
{ links.map(() => /* add spacers for flexbox */ <div/> )}
|
<Spacers length={ROUTES.length + 1} />
|
||||||
<Title/>
|
|
||||||
{ links.map(link => <Link href={`/${link}`}><h3>{link}</h3></Link>) }
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
function Title() {
|
|
||||||
return (
|
|
||||||
<Link href="/" className="name">
|
<Link href="/" className="name">
|
||||||
<motion.h1 className="name">Tymur Arsentiev</motion.h1>
|
<motion.h1 className="name">Tymur Arsentiev</motion.h1>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
{
|
||||||
|
ROUTES.map(([path, name]) =>
|
||||||
|
<Link key={path} href={path}>
|
||||||
|
<h3>{name}</h3>
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<Link key={ResumePdf} href={ResumePdf} target="_blank">
|
||||||
|
<h3>Resume</h3>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
function Spacers(props: {length: number}) {
|
||||||
|
const spacers = [];
|
||||||
|
for (let i = 0; i < props.length; i++) {
|
||||||
|
spacers.push(<div key={i}/>);
|
||||||
|
}
|
||||||
|
|
||||||
|
return spacers;
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,20 @@
|
|||||||
import "./link.scss";
|
import "./link.scss";
|
||||||
|
|
||||||
import React, {PropsWithChildren} from "react";
|
import React, {HTMLProps, ReactNode} from "react";
|
||||||
import {useRouter} from "./RouterContext";
|
import {useRouter} from "./RouterContext";
|
||||||
import {Path} from "./router";
|
import {Path} from "./router";
|
||||||
|
|
||||||
export function Link(props: {className?: string, href: Path, replace?: boolean } & PropsWithChildren) {
|
export function Link(props: {href: Path, children : ReactNode, target?: '_blank' } & HTMLProps<HTMLAnchorElement>) {
|
||||||
const {children, className, href} = props;
|
let {children, className, href} = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
className = `${className} link`;
|
||||||
|
|
||||||
function onClick(event: React.MouseEvent) {
|
function onClick(event: React.MouseEvent) {
|
||||||
|
// perform the default action if _blank
|
||||||
|
if(props.target === "_blank") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if(window.location.pathname === href) {
|
if(window.location.pathname === href) {
|
||||||
router.replacePage(props.href);
|
router.replacePage(props.href);
|
||||||
@@ -17,5 +23,7 @@ export function Link(props: {className?: string, href: Path, replace?: boolean }
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <a onClick={onClick} href={href} className={`${className} link`}>{children}</a>
|
return <a {...props} onClick={onClick} className={className}>
|
||||||
|
{children}
|
||||||
|
</a>
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,31 @@
|
|||||||
import {PropsWithChildren} from "react";
|
import React, {PropsWithChildren} from "react";
|
||||||
import {useRouter} from "./RouterContext";
|
import {useRouter} from "./RouterContext";
|
||||||
import {Path} from "./router";
|
import {Path} from "./router";
|
||||||
|
|
||||||
export function Route(props: PropsWithChildren & {path: Path}) {
|
const Canvas = React.lazy(() => import("../index/Canvas"));
|
||||||
|
const About = React.lazy(() => import("../about/AboutPage"));
|
||||||
|
|
||||||
|
export const ROUTES: [Path, string][] = [
|
||||||
|
["/", "Home"],
|
||||||
|
["/about", "About"],
|
||||||
|
["/articles", "Articles"]
|
||||||
|
];
|
||||||
|
|
||||||
|
function Route(props: PropsWithChildren & {path: Path}) {
|
||||||
const {path, children} = props;
|
const {path, children} = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
return router.current.toLowerCase() === path ? <>{children}</> : <></>
|
return <>{router.current === path && children}</>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function Routes() {
|
||||||
|
return <>
|
||||||
|
<Route path={ROUTES[0]![0]}>
|
||||||
|
<Canvas/>
|
||||||
|
</Route>
|
||||||
|
<Route path={ROUTES[1]![0]}>
|
||||||
|
<About/>
|
||||||
|
</Route>
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user