feat: initial commit
This commit is contained in:
4
.babelrc
Normal file
4
.babelrc
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"sourceType": "unambiguous",
|
||||
"presets": [["@babel/preset-env", { "modules": false }]]
|
||||
}
|
||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
node_modules/
|
||||
dist/
|
||||
7990
package-lock.json
generated
Normal file
7990
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
32
package.json
Normal file
32
package.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "portfolio-website",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "webpack serve --mode development",
|
||||
"build": "webpack --mode production"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.28.5",
|
||||
"@babel/preset-env": "^7.28.5",
|
||||
"autoprefixer": "^10.4.22",
|
||||
"babel-loader": "^10.0.0",
|
||||
"css-loader": "^7.1.2",
|
||||
"html-loader": "^5.1.0",
|
||||
"html-webpack-plugin": "^5.6.5",
|
||||
"mini-css-extract-plugin": "^2.9.4",
|
||||
"postcss": "^8.5.6",
|
||||
"postcss-loader": "^8.2.0",
|
||||
"tailwindcss": "^3.4.18",
|
||||
"webpack": "^5.103.0",
|
||||
"webpack-cli": "^6.0.1",
|
||||
"webpack-dev-server": "^5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/postcss": "^4.1.17"
|
||||
}
|
||||
}
|
||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
BIN
src/images/profile.jpg
Normal file
BIN
src/images/profile.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
1244
src/index.html
Normal file
1244
src/index.html
Normal file
File diff suppressed because it is too large
Load Diff
154
src/index.js
Normal file
154
src/index.js
Normal file
@ -0,0 +1,154 @@
|
||||
import "./styles.css";
|
||||
|
||||
// Set year in footer
|
||||
const yearEl = document.getElementById("year");
|
||||
if (yearEl) {
|
||||
yearEl.textContent = new Date().getFullYear().toString();
|
||||
}
|
||||
|
||||
// Hero entrance animation
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
const heroEls = document.querySelectorAll("[data-hero]");
|
||||
heroEls.forEach((el, idx) => {
|
||||
setTimeout(() => {
|
||||
el.classList.add("animate-fade-in-up");
|
||||
el.classList.remove("opacity-0", "translate-y-6");
|
||||
}, 150 * idx);
|
||||
});
|
||||
});
|
||||
|
||||
// Scroll animations for sections
|
||||
const animatedSections = document.querySelectorAll("[data-animate]");
|
||||
animatedSections.forEach((section) => {
|
||||
section.classList.add(
|
||||
"opacity-0",
|
||||
"translate-y-8",
|
||||
"transition-all",
|
||||
"duration-700"
|
||||
);
|
||||
});
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add("animate-fade-in-up");
|
||||
entry.target.classList.remove("opacity-0", "translate-y-8");
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
},
|
||||
{ threshold: 0.12 }
|
||||
);
|
||||
|
||||
animatedSections.forEach((section) => observer.observe(section));
|
||||
|
||||
// tailwind.config = {
|
||||
// theme: {
|
||||
// extend: {
|
||||
// fontFamily: {
|
||||
// sans: [
|
||||
// "Inter",
|
||||
// "ui-sans-serif",
|
||||
// "system-ui",
|
||||
// "-apple-system",
|
||||
// "BlinkMacSystemFont",
|
||||
// '"Segoe UI"',
|
||||
// "sans-serif",
|
||||
// ],
|
||||
// heading: [
|
||||
// "Montserrat",
|
||||
// "ui-sans-serif",
|
||||
// "system-ui",
|
||||
// "-apple-system",
|
||||
// "BlinkMacSystemFont",
|
||||
// '"Segoe UI"',
|
||||
// "sans-serif",
|
||||
// ],
|
||||
// },
|
||||
// colors: {
|
||||
// primary: "#1e90ff", // dodgerblue
|
||||
// "bg-primary": "#1e90ff",
|
||||
// "bg-dark": "#020617", // slate-950-ish
|
||||
// "card-dark": "#020617",
|
||||
// "card-elevated": "#020617",
|
||||
// },
|
||||
// boxShadow: {
|
||||
// glow: "0 0 40px rgba(30,144,255,0.45)",
|
||||
// },
|
||||
// keyframes: {
|
||||
// "fade-in-up": {
|
||||
// "0%": { opacity: "0", transform: "translateY(20px)" },
|
||||
// "100%": { opacity: "1", transform: "translateY(0)" },
|
||||
// },
|
||||
// "fade-in": {
|
||||
// "0%": { opacity: "0" },
|
||||
// "100%": { opacity: "1" },
|
||||
// },
|
||||
// "scale-in": {
|
||||
// "0%": { opacity: "0", transform: "scale(0.96)" },
|
||||
// "100%": { opacity: "1", transform: "scale(1)" },
|
||||
// },
|
||||
// "glow-pulse": {
|
||||
// "0%,100%": { boxShadow: "0 0 0 rgba(30,144,255,0.0)" },
|
||||
// "50%": { boxShadow: "0 0 40px rgba(30,144,255,0.5)" },
|
||||
// },
|
||||
// "border-spin": {
|
||||
// "0%": { transform: "rotate(0deg)" },
|
||||
// "100%": { transform: "rotate(360deg)" },
|
||||
// },
|
||||
// },
|
||||
// animation: {
|
||||
// "fade-in-up": "fade-in-up 0.8s ease-out forwards",
|
||||
// "fade-in": "fade-in 1s ease-out forwards",
|
||||
// "scale-in": "scale-in 0.7s ease-out forwards",
|
||||
// "glow-pulse": "glow-pulse 2s ease-in-out infinite",
|
||||
// "border-spin": "border-spin 8s linear infinite",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
|
||||
// --- SCRIPTING
|
||||
|
||||
// Set year
|
||||
// document.getElementById("year").textContent = new Date()
|
||||
// .getFullYear()
|
||||
// .toString();
|
||||
|
||||
// // Hero entrance animation
|
||||
// window.addEventListener("DOMContentLoaded", () => {
|
||||
// const heroEls = document.querySelectorAll("[data-hero]");
|
||||
// heroEls.forEach((el, idx) => {
|
||||
// setTimeout(() => {
|
||||
// el.classList.add("animate-fade-in-up");
|
||||
// el.classList.remove("opacity-0", "translate-y-6");
|
||||
// }, 150 * idx);
|
||||
// });
|
||||
// });
|
||||
|
||||
// // Scroll animations for sections
|
||||
// const animatedSections = document.querySelectorAll("[data-animate]");
|
||||
// animatedSections.forEach((section) => {
|
||||
// section.classList.add(
|
||||
// "opacity-0",
|
||||
// "translate-y-8",
|
||||
// "transition-all",
|
||||
// "duration-700"
|
||||
// );
|
||||
// });
|
||||
|
||||
// const observer = new IntersectionObserver(
|
||||
// (entries) => {
|
||||
// entries.forEach((entry) => {
|
||||
// if (entry.isIntersecting) {
|
||||
// entry.target.classList.add("animate-fade-in-up");
|
||||
// entry.target.classList.remove("opacity-0", "translate-y-8");
|
||||
// observer.unobserve(entry.target);
|
||||
// }
|
||||
// });
|
||||
// },
|
||||
// { threshold: 0.12 }
|
||||
// );
|
||||
|
||||
// animatedSections.forEach((section) => observer.observe(section));
|
||||
16
src/styles.css
Normal file
16
src/styles.css
Normal file
@ -0,0 +1,16 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
body {
|
||||
@apply bg-bg-dark text-slate-100 antialiased;
|
||||
}
|
||||
|
||||
/* Hide scrollbars on cards but keep scroll behavior */
|
||||
.no-scrollbar::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.no-scrollbar {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
67
tailwind.config.js
Normal file
67
tailwind.config.js
Normal file
@ -0,0 +1,67 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ["./src/**/*.{html,js,ts,jsx,tsx}"],
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: [
|
||||
"Inter",
|
||||
"ui-sans-serif",
|
||||
"system-ui",
|
||||
"-apple-system",
|
||||
"BlinkMacSystemFont",
|
||||
'"Segoe UI"',
|
||||
"sans-serif",
|
||||
],
|
||||
heading: [
|
||||
"Montserrat",
|
||||
"ui-sans-serif",
|
||||
"system-ui",
|
||||
"-apple-system",
|
||||
"BlinkMacSystemFont",
|
||||
'"Segoe UI"',
|
||||
"sans-serif",
|
||||
],
|
||||
},
|
||||
colors: {
|
||||
primary: "#1e90ff", // dodgerblue
|
||||
"bg-dark": "#020617",
|
||||
"card-dark": "#020617",
|
||||
"card-elevated": "#020617",
|
||||
},
|
||||
boxShadow: {
|
||||
glow: "0 0 40px rgba(30,144,255,0.45)",
|
||||
},
|
||||
keyframes: {
|
||||
"fade-in-up": {
|
||||
"0%": { opacity: "0", transform: "translateY(20px)" },
|
||||
"100%": { opacity: "1", transform: "translateY(0)" },
|
||||
},
|
||||
"fade-in": {
|
||||
"0%": { opacity: "0" },
|
||||
"100%": { opacity: "1" },
|
||||
},
|
||||
"scale-in": {
|
||||
"0%": { opacity: "0", transform: "scale(0.96)" },
|
||||
"100%": { opacity: "1", transform: "scale(1)" },
|
||||
},
|
||||
"glow-pulse": {
|
||||
"0%,100%": { boxShadow: "0 0 0 rgba(30,144,255,0.0)" },
|
||||
"50%": { boxShadow: "0 0 40px rgba(30,144,255,0.5)" },
|
||||
},
|
||||
"border-spin": {
|
||||
"0%": { transform: "rotate(0deg)" },
|
||||
"100%": { transform: "rotate(360deg)" },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
"fade-in-up": "fade-in-up 0.8s ease-out forwards",
|
||||
"fade-in": "fade-in 1s ease-out forwards",
|
||||
"scale-in": "scale-in 0.7s ease-out forwards",
|
||||
"glow-pulse": "glow-pulse 2s ease-in-out infinite",
|
||||
"border-spin": "border-spin 8s linear infinite",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
58
webpack.config.js
Normal file
58
webpack.config.js
Normal file
@ -0,0 +1,58 @@
|
||||
const path = require("path");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const isProd = argv.mode === "production";
|
||||
|
||||
return {
|
||||
entry: "./src/index.js",
|
||||
output: {
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
filename: isProd ? "js/[name].[contenthash].js" : "js/[name].js",
|
||||
clean: true,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.html$/i,
|
||||
loader: "html-loader",
|
||||
},
|
||||
{
|
||||
test: /\.m?js$/,
|
||||
exclude: /node_modules/,
|
||||
use: "babel-loader",
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"],
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)$/i,
|
||||
type: "asset/resource",
|
||||
generator: {
|
||||
filename: "images/[name][hash][ext][query]",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
template: "./src/index.html",
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: isProd ? "css/[name].[contenthash].css" : "css/[name].css",
|
||||
}),
|
||||
],
|
||||
devServer: {
|
||||
static: "./dist",
|
||||
hot: true,
|
||||
open: true,
|
||||
port: 5173,
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".js"],
|
||||
},
|
||||
devtool: isProd ? "source-map" : "eval-source-map",
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user