Compare commits

..

10 Commits

Author SHA1 Message Date
Mariia Shabelnik
90398455f1 stuff 2023-10-12 09:56:13 +02:00
Mariia Shabelnik
90da024c00 test 2022-09-08 23:28:13 +02:00
Mariia Shabelnik
a2d35650c6 added scroll motion 2022-07-27 23:36:00 +02:00
Mariia Shabelnik
f237dff5c7 update logo color 2022-07-27 21:07:04 +02:00
Mariia Shabelnik
279b5ad3d0 color update 2022-07-27 20:02:45 +02:00
Mariia Shabelnik
f538f7b844 playing with css 2022-07-27 19:26:06 +02:00
Mariia Shabelnik
deb67c4a68 Merge branch 'main' of ssh://git.flach.io:2224/mariia/portfolio 2022-07-27 18:35:21 +02:00
Mariia Shabelnik
b3e699f4b1 add hamb_menu 2022-07-27 18:34:46 +02:00
Mariia Shabelnik
c4e8900e24 add hamb_menu 2022-07-27 18:34:18 +02:00
37eb8de494
Added build files 2022-07-27 18:23:35 +02:00
24 changed files with 2449 additions and 319 deletions

4
.dockerignore Normal file
View File

@ -0,0 +1,4 @@
node_modules/
.git
.envrc
.gitignore

35
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,35 @@
stages:
- build
- deploy
variables:
TAG_LATEST: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:latest
TAG_COMMIT: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA
build:
image: docker:latest
stage: build
tags:
- deployment
script:
- echo "Building"
- export
- docker build -t $TAG_COMMIT -t $TAG_LATEST .
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker push $TAG_COMMIT
- docker push $TAG_LATEST
deploy:
image: docker:latest
stage: deploy
tags:
- deployment
script:
- echo "Deploying"
- chmod og= $ID_RSA
- apk update && apk add openssh-client
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker pull $TAG_COMMIT"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker container rm -f $DOCKER_NAME || true"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker run -d --network=$DOCKER_NETWORK --restart unless-stopped --name $DOCKER_NAME $TAG_COMMIT"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "/usr/local/bin/caddycontrol -host $CADDYCONTROL_HOST -dial $CADDYCONTROL_DIAL"

5
Caddyfile Normal file
View File

@ -0,0 +1,5 @@
:80 {
root * /usr/share/caddy
try_files {path} /index.html
file_server
}

14
Dockerfile Normal file
View File

@ -0,0 +1,14 @@
FROM node:17.1.0-alpine3.12 as builder
WORKDIR /app
COPY package.json ./
COPY package-lock.json ./
RUN npm install
COPY ./ ./
RUN NODE_ENV=production npm run build
FROM caddy:2-alpine
WORKDIR /usr/share/caddy
COPY Caddyfile /etc/caddy/Caddyfile
COPY --from=builder ./app/dist .

View File

@ -2,8 +2,21 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link
rel="icon"
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22>
<text y=%22.9em%22 font-size=%2290%22>
👋
</text>
</svg>"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;700&display=swap"
rel="stylesheet"
/>
<title>Mariia Shabelnik</title> <title>Mariia Shabelnik</title>
</head> </head>
<body> <body>

2152
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,19 +4,26 @@
"version": "0.0.0", "version": "0.0.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite --host",
"build": "vite build", "build": "vite build",
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"hamburger-react": "^2.5.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-router-dom": "^6.3.0" "react-image-gallery": "^1.3.0",
"react-router-dom": "^6.3.0",
"react-scroll-motion": "^0.3.0",
"recoil": "^0.7.7"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^18.0.15", "@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6", "@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "^2.0.0", "@vitejs/plugin-react": "^2.0.0",
"autoprefixer": "^10.4.15",
"postcss": "^8.4.29",
"tailwindcss": "^3.3.3",
"vite": "^3.0.0" "vite": "^3.0.0"
} }
} }

6
postcss.config.js Normal file
View File

@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

BIN
public/img/placeholder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,12 +1,46 @@
body {
margin: 0;
font-family: "Roboto Mono", monospace;
background-color: #302f39;
color: white;
}
.container { .container {
border: 2px solid red;
max-width: 1000px; max-width: 1000px;
margin: 0 auto; margin: 0 auto;
padding: 0 1em;
}
.nav .container {
height: 4em;
}
.content {
margin-top: 5em;
} }
.nav { .nav {
background-color: rgb(84, 84, 84); background-color: #302f38;
height: 3em; height: 4em;
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 100000;
}
/*box-shadow: inset 0px 3px 20px 10px rgba(0, 0, 0, 0.3);*/
.nav a {
text-decoration: none;
color: #e5e5ff;
transition: 0.3s;
}
.nav a:hover {
color: #fff;
text-shadow: 0 0 5px #f2ef00;
} }
.nav-items { .nav-items {
@ -21,5 +55,55 @@
} }
.menu-items div { .menu-items div {
margin-left: 1em;
}
.logo {
font-size: 2em;
font-weight: bold;
}
.logo a {
text-shadow: 0 0 5px #ccff00, 0 0 15px #ccff00;
z-index: 10000;
}
.hamburger {
display: none;
}
.copyright {
font-size: 0.7em;
text-align: center;
}
.hamburger-menu {
background-color: #302f38;
z-index: 100;
position: fixed;
right: 0;
backdrop-filter: blur(3px) contrast(60%);
-webkit-backdrop-filter: blur(3px) contrast(60%);
top: 4em;
bottom: 0;
left: 0px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-end;
}
.hamburger-menu a {
font-size: 2em;
text-decoration: none;
margin-right: 1em; margin-right: 1em;
} }
@media screen and (max-width: 768px) {
.hamburger {
display: inline;
}
.menu-items {
display: none;
}
}

View File

@ -1,21 +1,28 @@
import "./App.css"; //import "./App.css";
import { Routes, Route, Link } from "react-router-dom"; import { Routes, Route } from "react-router-dom";
import Home from "./pages/Home"; import Home from "./pages/Home";
import Experiance from "./pages/Experiance"; import Experience from "./pages/Experience";
import Contact from "./pages/Contact"; import Contact from "./pages/Contact";
import Footer from "./components/Footer"; import Footer from "./components/Footer";
import Header from "./components/Header"; import Header from "./components/Header";
import ExperianceDetail from "./pages/ExperienceDetail";
import { RecoilRoot } from "recoil";
function App() { function App() {
return ( return (
<div> <div className="text-white">
<RecoilRoot>
<main className=" min-h-screen">
<Header /> <Header />
<Routes> <Routes>
<Route path="/" element={<Home />} /> <Route path="/" element={<Home />} />
<Route path="experiance" element={<Experiance />} /> <Route path="/experience" element={<Experience />} />
<Route path="contact" element={<Contact />} /> <Route path="/contact" element={<Contact />} />
<Route path="/experience/:id" element={<ExperianceDetail />} />
</Routes> </Routes>
<Footer /> <Footer />
</main>
</RecoilRoot>
</div> </div>
); );
} }

View File

@ -1,5 +1,12 @@
function Footer() { function Footer() {
return <div className="container">Footer</div>; const fullYear = new Date().getFullYear();
return (
<footer className="container mx-auto my-10 px-6 sticky top-[95vh]">
<div className=" text-center text-sm text-white/50 ">
© {fullYear} Mariia Shabelnik, all rights reserved
</div>
</footer>
);
} }
export default Footer; export default Footer;

View File

@ -1,25 +1,58 @@
import { Routes, Route, Link } from "react-router-dom"; import { Link, useLocation } from "react-router-dom";
import { Turn as Hamburger } from "hamburger-react";
import { useState } from "react";
function Header() { function Header() {
const [isOpen, setOpen] = useState(false);
const menuTimeout = 400;
const location = useLocation();
const menu = [
{ link: "/", title: ".me()" },
{ link: "/experience", title: ".experience()" },
{ link: "/contact", title: ".contact()" },
];
const menuUI = menu.map((item) => {
let className = "drop-shadow-light hover:drop-shadow-doublelight";
if (location.pathname === item.link) {
className += " text-white";
} else {
className += " text-white/40";
}
return ( return (
<div className="nav"> <li key={item.link}>
<div className="container nav-items"> <Link className={className} to={item.link}>
<div className="logo"> {item.title}
<Link to="/">LOGO</Link> </Link>
</div> </li>
<div className="menu-items"> );
<div> });
<Link to="/">About</Link>
</div> return (
<div> <header className="sticky top-0 z-50 backdrop-blur-sm bg-bgColor/90 ">
<Link to="/experiance">Experiance</Link> <div className="container mx-auto">
</div> <nav className="flex items-center mx-4 py-4">
<div> <div className="flex-none text-4xl font-black">
<Link to="/contact">Contact</Link> <Link
</div> className=" drop-shadow-doublelight hover:drop-shadow-light"
to="/"
>
MS.
</Link>
</div> </div>
{/* <div className="hamburger">
<Hamburger color="#e5e5ff" toggled={isOpen} toggle={setOpen} />
</div> */}
<div className="grow"></div>
<div className="flex-none ">
<ul className="flex flex-row gap-4 text-lg">{menuUI}</ul>
</div> </div>
</nav>
{isOpen && hamburgerMenu}
</div> </div>
</header>
); );
} }

12
src/components/Tags.jsx Normal file
View File

@ -0,0 +1,12 @@
function Tags({ listOfTags }) {
const tagList = listOfTags.map((itemTag, keyTag) => {
return (
<div className={`bg-indigo-500/40 py-2 px-4 rounded-full `} key={keyTag}>
{itemTag}
</div>
);
});
return <div className="text-xs flex gap-4 mt-6 ">{tagList}</div>;
}
export default Tags;

View File

@ -1,3 +1,8 @@
@import "react-image-gallery/styles/css/image-gallery.css";
@tailwind base;
@tailwind components;
@tailwind utilities;
body { body {
margin: 0; background-color: #302f39;
} }

View File

@ -1,6 +1,6 @@
function Contact() { function Contact() {
return ( return (
<div className="container"> <div className="container content">
<h1>Welcome to Contact</h1> <h1>Welcome to Contact</h1>
</div> </div>
); );

View File

@ -1,9 +0,0 @@
function Experiance() {
return (
<div className="container">
<h1>Welcome to Experiance</h1>
</div>
);
}
export default Experiance;

59
src/pages/Experience.jsx Normal file
View File

@ -0,0 +1,59 @@
import { Link } from "react-router-dom";
import { useRecoilValue } from "recoil";
import { projectsAtom } from "../store";
import Tags from "../components/Tags";
function Experiance() {
const experianceList = useRecoilValue(projectsAtom);
const experianceListUI = experianceList.map((item, key) => {
const position = key % 2;
const imgClasses = ["flex-1", "hidden", "md:block"];
if (position === 1) {
imgClasses.push("md:order-last");
}
return (
<section className="flex flex-col md:flex-row gap-4 mb-12" key={item.id}>
<div className={imgClasses.join(" ")}>
<img className="rounded-md" src={item.img[0]} />
</div>
<div className="flex-1 flex flex-col">
<div>
<h2 className="text-2xl mb-4"> {item.title}</h2>
</div>
<div>
<img
className="block md:hidden mb-4 rounded-md"
src={item.img[0]}
/>
</div>
<div className="text-sm">
<p>{item.info}</p>
</div>
<Tags listOfTags={item.tags} />
<div className="grow"></div>
<div className=" text-right">
<Link
className=" drop-shadow-doublelight hover:drop-shadow-light "
to={`/experience/${item.id}`}
>
read more
</Link>
</div>
</div>
</section>
);
});
return (
<div className="container mx-auto my-10 px-6">
<h1>Welcome to Experiance</h1>
<div className="py-4">{experianceListUI}</div>
</div>
);
}
export default Experiance;

View File

@ -0,0 +1,61 @@
import { useParams } from "react-router-dom";
import { useRecoilValue } from "recoil";
import { projectsAtom } from "../store";
import ImageGallery from "react-image-gallery";
import Tags from "../components/Tags";
function ExperianceDetail() {
const { id } = useParams();
const experianceList = useRecoilValue(projectsAtom);
//shorter variant of Find function with IF-sats
const myProject = experianceList.find((item) => item.id === id);
if (myProject === undefined) {
return (
<div className="container mx-auto my-10 px-6">
404 the project does not exists
</div>
);
}
const projectImg = myProject.img.map((item) => {
return { original: item, thumbnail: item };
});
let linkUI = <></>;
if (myProject.link !== undefined) {
linkUI = (
<a href={myProject.link} target="_blank">
Visit page
</a>
);
}
return (
<div className="container mx-auto my-10 px-6">
<div className="flex">
<div className="flex-1">
<h1>Project: {myProject.title}</h1>
</div>
<Tags listOfTags={myProject.tags} />
</div>
{linkUI}
<div className="py-4 mb-8">{myProject.info}</div>
<div className="">
<ImageGallery
showThumbnails={false}
showBullets={true}
autoPlay={true}
slideDuration={1000}
slideInterval={4000}
items={projectImg}
/>
</div>
</div>
);
}
export default ExperianceDetail;

View File

@ -1,8 +1,77 @@
import {
Animator,
ScrollContainer,
ScrollPage,
batch,
Fade,
FadeIn,
FadeOut,
Move,
MoveIn,
MoveOut,
Sticky,
StickyIn,
StickyOut,
Zoom,
ZoomIn,
ZoomOut,
} from "react-scroll-motion";
function Home() { function Home() {
const ZoomInScrollOut = batch(StickyIn(), FadeIn(), ZoomIn());
const FadeUp = batch(Fade(), Move(), Sticky());
return ( return (
<div className="container"> <ScrollContainer>
<h1>Welcome to Home + About me</h1> <ScrollPage>
<Animator animation={batch(Fade(), Sticky(), MoveOut(0, 200))}>
<span>Hello, my name is Mariia 😀</span>
</Animator>
<span style={{ fontSize: "40px" }}>
<Animator animation={MoveIn(-1000, 0)}>Hello Guys 👋🏻</Animator>
</span>
</ScrollPage>
<ScrollPage>
<Animator animation={ZoomInScrollOut}>
<span style={{ fontSize: "40px" }}>I'm Frontend developer </span>
</Animator>
</ScrollPage>
<ScrollPage>
<Animator animation={FadeUp}>
<span style={{ fontSize: "40px" }}>I'm Webbdesigner </span>
</Animator>
</ScrollPage>
<ScrollPage>
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "100%",
}}
>
<span style={{ fontSize: "40px" }}>
<Animator animation={MoveIn(1000, 0)}>Nice to meet you 🙋🏻</Animator>
- I'm Dante Chun -
<Animator animation={MoveOut(1000, 0)}>Good bye 🏻</Animator>
<Animator animation={MoveOut(-1000, 0)}>See you 💛</Animator>
</span>
</div> </div>
</ScrollPage>
<ScrollPage>
<Animator animation={batch(Fade(), Sticky())}>
<span style={{ fontSize: "40px" }}>Done</span>
<br />
<span style={{ fontSize: "30px" }}>
There's FadeAnimation, MoveAnimation, StickyAnimation, ZoomAnimation
</span>
</Animator>
</ScrollPage>
</ScrollContainer>
); );
} }

71
src/store.js Normal file
View File

@ -0,0 +1,71 @@
import { atom } from "recoil";
const experianceList = [
{
id: "46bf76ae-8915-4e5d-ae92-4151be80e75a",
title: "Netzero web",
info: "Lorem ipsum dolor, sit amet consectetur adipisicing elit. Beatae cumque laborum, placeat nobis fugit nemo ipsa voluptates error quo possimus ea velit quos voluptatum magnam id eius quam accusamus. Eum blanditiis aperiam minus inventore laboriosam, et vel ipsam perspiciatis a facilis cum, iure alias recusandae dolorem adipisci illum. Quo maxime nisi minus mollitia praesentium cumque, temporibus incidunt nulla culpa eligendi consequatur doloremque repudiandae aspernatur quas necessitatibus tenetur. Similique fuga rerum provident distinctio doloremque qui accusamus, sequi voluptate eveniet voluptatum autem odio placeat quasi temporibus quas nulla laborum sunt tenetur dolorum, incidunt error porro amet modi? Temporibus amet optio mollitia omnis?",
img: [
"/img/placeholder.png",
"/img/placeholder.png",
"/img/placeholder.png",
"/img/placeholder.png",
],
tags: ["react", "vite", "wordpress"],
link: "https://www.net0.se",
},
{
id: "55515a25-deb1-451c-bc7d-006d293f54aa",
title: "Lets fly",
info: "Lorem ipsum dolor, sit amet consectetur adipisicing elit. Beatae cumque laborum, placeat nobis fugit nemo ipsa voluptates error quo possimus ea velit quos voluptatum magnam id eius quam accusamus. Eum blanditiis aperiam minus inventore laboriosam, et vel ipsam perspiciatis a facilis cum, iure alias recusandae dolorem adipisci illum. Quo maxime nisi minus mollitia praesentium cumque, temporibus incidunt nulla culpa eligendi consequatur doloremque repudiandae aspernatur quas necessitatibus tenetur. Similique fuga rerum provident distinctio doloremque qui accusamus, sequi voluptate eveniet voluptatum autem odio placeat quasi temporibus quas nulla laborum sunt tenetur dolorum, incidunt error porro amet modi? Temporibus amet optio mollitia omnis?",
img: [
"/img/placeholder.png",
"/img/placeholder.png",
"/img/placeholder.png",
"/img/placeholder.png",
],
tags: ["react", "vite", "shopify"],
link: undefined,
},
{
id: "e93a5d54-3442-4b19-b568-8ae550aa09fe",
title: "Project 3",
info: "Lorem ipsum dolor, sit amet consectetur adipisicing elit. Beatae cumque laborum, placeat nobis fugit nemo ipsa voluptates error quo possimus ea velit quos voluptatum magnam id eius quam accusamus. Eum blanditiis aperiam minus inventore laboriosam, et vel ipsam perspiciatis a facilis cum, iure alias recusandae dolorem adipisci illum. Quo maxime nisi minus mollitia praesentium cumque, temporibus incidunt nulla culpa eligendi consequatur doloremque repudiandae aspernatur quas necessitatibus tenetur. Similique fuga rerum provident distinctio doloremque qui accusamus, sequi voluptate eveniet voluptatum autem odio placeat quasi temporibus quas nulla laborum sunt tenetur dolorum, incidunt error porro amet modi? Temporibus amet optio mollitia omnis?",
img: [
"/img/placeholder.png",
"/img/placeholder.png",
"/img/placeholder.png",
"/img/placeholder.png",
],
tags: ["react", "vite", "wordpress"],
link: undefined,
},
{
id: "cedeb531-0409-4e1f-b7e9-9668dcaa5e71",
title: "Project 4",
info: "Lorem ipsum dolor, sit amet consectetur adipisicing elit. Beatae cumque laborum, placeat nobis fugit nemo ipsa voluptates error quo possimus ea velit quos voluptatum magnam id eius quam accusamus. Eum blanditiis aperiam minus inventore laboriosam, et vel ipsam perspiciatis a facilis cum, iure alias recusandae dolorem adipisci illum. Quo maxime nisi minus mollitia praesentium cumque, temporibus incidunt nulla culpa eligendi consequatur doloremque repudiandae aspernatur quas necessitatibus tenetur. Similique fuga rerum provident distinctio doloremque qui accusamus, sequi voluptate eveniet voluptatum autem odio placeat quasi temporibus quas nulla laborum sunt tenetur dolorum, incidunt error porro amet modi? Temporibus amet optio mollitia omnis?",
img: [
"/img/placeholder.png",
"/img/placeholder.png",
"/img/placeholder.png",
"/img/placeholder.png",
],
tags: ["react", "vite", "wordpress"],
link: undefined,
},
{
id: "5e2ea8b8-bb1e-4c9d-a723-42406bf7be72",
title: "Project 5",
info: "Lorem ipsum dolor, sit amet consectetur adipisicing elit. Beatae cumque laborum, placeat nobis fugit nemo ipsa voluptates error quo possimus ea velit quos voluptatum magnam id eius quam accusamus. Eum blanditiis aperiam minus inventore laboriosam, et vel ipsam perspiciatis a facilis cum, iure alias recusandae dolorem adipisci illum. Quo maxime nisi minus mollitia praesentium cumque, temporibus incidunt nulla culpa eligendi consequatur doloremque repudiandae aspernatur quas necessitatibus tenetur. Similique fuga rerum provident distinctio doloremque qui accusamus, sequi voluptate eveniet voluptatum autem odio placeat quasi temporibus quas nulla laborum sunt tenetur dolorum, incidunt error porro amet modi? Temporibus amet optio mollitia omnis?",
img: [
"/img/placeholder.png",
"/img/placeholder.png",
"/img/placeholder.png",
"/img/placeholder.png",
],
tags: ["react", "vite", "wordpress"],
link: undefined,
},
];
export const projectsAtom = atom({ key: "projects", default: experianceList });

28
tailwind.config.js Normal file
View File

@ -0,0 +1,28 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
fontFamily: {
sans: ["Roboto Mono", "system-ui"],
headline: ["Roboto Mono", "system-ui"],
},
extend: {
colors: {
neon: "#ccff00",
bgColor: "#302f39",
},
dropShadow: {
light: "0 0 5px theme('colors.indigo.800')",
doublelight: [
"0 0 5px theme('colors.lime.400')",
"0 0 15px theme('colors.yellow.400')",
],
active: [
"0 0 5px theme('colors.lime.400')",
"0 0 15px theme('colors.indigo.950')",
],
},
},
},
plugins: [],
};

View File

@ -1,7 +1,7 @@
import { defineConfig } from 'vite' import { defineConfig } from "vite";
import react from '@vitejs/plugin-react' import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react()] plugins: [react()],
}) });