Browse Source

feat: add second project list

master
Muthu Kumar 1 month ago
parent
commit
221bc03796
Failed to extract signature
  1. 21
      src/index.css
  2. 201
      src/pages/main/Work.tsx
  3. 75
      src/pages/main/data/project.ts

21
src/index.css

@ -1,11 +1,12 @@
:root { :root {
--bg-colour: rgb(0, 0, 0); --bg-colour: rgb(0, 0, 0);
--card-bg: rgb(18, 18, 18); --card-bg: rgb(18, 18, 18);
--card-tags: rgb(34, 34, 34); --card-tags: rgb(35, 35, 35);
--card-tags-hover: rgb(25, 25, 25); --card-tags-hover: rgb(30, 30, 30);
--primary-colour: rgb(255, 85, 85); --primary-colour: rgb(255, 85, 85);
--text-colour: rgb(210, 210, 210); --text-colour: rgb(210, 210, 210);
--text-subdued: rgb(150, 150, 150); --text-subdued: rgb(150, 150, 150);
--table-border: rgb(54, 54, 54);
--card-active: rgb(45, 45, 45); --card-active: rgb(45, 45, 45);
--card-active-border: rgb(60, 60, 60); --card-active-border: rgb(60, 60, 60);
--card-hover: rgb(15, 15, 15); --card-hover: rgb(15, 15, 15);
@ -46,22 +47,18 @@ h2,
h3, h3,
h4, h4,
h5, h5,
h6, h6 {
p {
margin: 0; margin: 0;
line-height: 1.5em; line-height: 1.5em;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 800; font-weight: 800;
color: var(--primary-colour); color: var(--primary-colour);
} }
p {
margin: 0;
line-height: 1.5em;
}
h1, h1,
h2 { h2 {
line-height: 1.2em; line-height: 1.2em;

201
src/pages/main/Work.tsx

@ -1,29 +1,13 @@
import React from "react"; import React from "react";
import { css } from "@emotion/css"; import { css, cx } from "@emotion/css";
import Container from "../../components/Container"; import Container from "../../components/Container";
import { projects } from "./data/project"; import { otherProjects, projects, type Project } from "./data/project";
type Project = {
title: string;
url?: string;
description: string;
cat: string;
tags: string[];
};
const ProjectUnit: React.FC<Project> = ({ const styles = {
title, project: css`
url,
description,
cat,
tags,
}) => {
return (
<div
className={css`
position: relative; position: relative;
background: var(--card-bg); background: var(--card-bg);
padding: 1.5rem; padding: 1.2rem;
cursor: default; cursor: default;
border-radius: 0.5rem; border-radius: 0.5rem;
@ -32,20 +16,72 @@ const ProjectUnit: React.FC<Project> = ({
transition: all 200ms; transition: all 200ms;
:hover { :hover {
filter: hue-rotate(30deg) invert(0.04); filter: invert(0.08);
transform: translateY(-0.2rem); transform: translateY(-0.2rem);
} }
`}>
header {
display: flex;
justify-content: space-between;
align-items: center;
}
h4 {
margin-bottom: 0.4rem;
}
`,
tag: css`
display: inline-block;
padding: 0.1rem 0.4rem;
background: var(--card-tags);
color: var(--text-colour);
border-radius: 0.2rem;
transition: all 200ms;
:hover {
background: var(--card-tags-hover);
}
& + & {
margin-left: 0.6rem;
}
`,
};
const ProjectUnit: React.FC<Project> = ({
title,
url,
description,
cat,
wip,
tags,
}) => {
return (
<div className={styles.project} title={title + (wip ? " (WIP)" : "")}>
<a <a
className={css` className={css`
display: block; display: flex;
flex-direction: column;
height: 100%;
text-decoration: none; text-decoration: none;
font-weight: 500; font-weight: 500;
cursor: ${wip ? "default" : "pointer"};
`} `}
href={url} href={url}
target="_blank" target="_blank"
rel="noreferrer"> rel="noreferrer">
<header>
<h4>{title}</h4> <h4>{title}</h4>
<span
className={css`
color: var(--text-subdued);
font-size: 0.8rem;
font-weight: 600;
font-family: monospace;
`}>
{"{"} {cat} {"}"}
</span>
</header>
<p <p
className={css` className={css`
color: #bdbdbd; color: #bdbdbd;
@ -62,48 +98,55 @@ const ProjectUnit: React.FC<Project> = ({
margin-top: auto; margin-top: auto;
`}> `}>
{tags.map(tag => ( {tags.map(tag => (
<span <span key={tag} className={styles.tag}>
key={tag}
className={css`
display: inline-block;
padding: 0.2rem 0.4rem;
background: var(--card-tags);
color: white;
border-radius: 0.2rem;
transition: all 200ms;
:hover {
background: var(--card-tags-hover);
}
& + & {
margin-left: 0.6rem;
}
`}>
{tag} {tag}
</span> </span>
))} ))}
</p> </p>
<span
className={css`
position: absolute;
right: 1rem;
bottom: 1rem;
color: #bbbbbb;
font-size: 0.8rem;
`}>
{cat}
</span>
</a> </a>
</div> </div>
); );
}; };
const otherProjectsStyle = css`
width: 100%;
border-collapse: collapse;
border-radius: 0.5rem;
overflow: hidden;
color: var(--text-colour);
* {
border-collapse: collapse;
}
th {
color: var(--text-subdued);
}
th,
td {
padding: 0.9rem 1rem;
text-align: left;
line-height: 1.6;
}
td {
border-top: 1px solid var(--table-border);
}
/* border-bottom: 1px solid var(--table-border); */
td a {
display: block;
min-width: max-content;
}
`;
const Exp: React.FC = () => { const Exp: React.FC = () => {
return ( return (
<Container> <Container>
<h2>Things I've built</h2> <h2>Things I've built</h2>
<p>Some tools, libraries, and apps over time:</p> <p>A few projects I'm proud of:</p>
<div <div
className={css` className={css`
display: grid; display: grid;
@ -115,6 +158,58 @@ const Exp: React.FC = () => {
<ProjectUnit {...unit} key={unit.title} /> <ProjectUnit {...unit} key={unit.title} />
))} ))}
</div> </div>
<hr />
<p>
Apart from the above, I've also built some other interesting stuff over
time using a variety of technologies:
</p>
<table className={otherProjectsStyle}>
<thead>
<tr>
<th>Project</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{otherProjects.map(unit => (
<tr key={unit.title}>
<td
className={css`
vertical-align: top;
`}>
<a
className={cx(
unit.wip &&
css`
color: var(--text-subdued);
cursor: default;
`,
)}
href={unit.url}
target="_blank"
rel="noreferrer"
title={unit.title + (unit.wip ? " (WIP)" : "")}>
{unit.title}
</a>
</td>
<td>
{unit.description}
<span
className={css`
margin-top: 0.4rem;
display: block;
color: var(--text-subdued);
font-size: 0.9rem;
font-weight: 600;
font-family: monospace;
`}>
# {unit.tags.join(", ")}
</span>
</td>
</tr>
))}
</tbody>
</table>
</Container> </Container>
); );
}; };

75
src/pages/main/data/project.ts

@ -1,6 +1,15 @@
export const projects = [ export type Project = {
title: string;
url?: string;
description: string;
cat: string;
tags: string[];
wip?: boolean;
};
export const projects: Project[] = [
{ {
title: window.location.hostname, title: window.location.hostname.split(".").slice(0, 2).join("."),
description: "This website.", description: "This website.",
url: "https://github.com/MKRhere/pw2", url: "https://github.com/MKRhere/pw2",
cat: "web", cat: "web",
@ -8,15 +17,15 @@ export const projects = [
}, },
{ {
title: "hyperactive", title: "hyperactive",
description: "Suite of web-app development libraries.", description: "Suite of fast, reactive web-app development libraries.",
url: "https://github.com/codefeathers/hyperactive", url: "https://github.com/codefeathers/hyperactive",
cat: "lib", cat: "lib",
tags: ["reactive", "ui-framework"], tags: ["reactive", "ui-framework"],
}, },
{ {
title: "denoland/node_shims", title: "deno shims",
description: description:
"Node shims for Deno’s runtime API. Contributed repo into official denoland.", "Node shims for Deno’s runtime API. Transferred to official denoland.",
url: "https://github.com/denoland/node_shims", url: "https://github.com/denoland/node_shims",
cat: "lib", cat: "lib",
tags: ["deno", "shims"], tags: ["deno", "shims"],
@ -24,31 +33,67 @@ export const projects = [
{ {
title: "Telegraf", title: "Telegraf",
description: description:
"Active maintainer of one of the most popular Telegram Bot API libraries for Node.", "Active maintainer of one of the most popular Telegram Bot API libraries for TypeScript.",
url: "https://github.com/telegraf/telegraf", url: "https://github.com/telegraf/telegraf",
cat: "lib", cat: "lib",
tags: ["typescript", "telegram", "bot-api"], tags: ["typescript", "telegram", "bot-api"],
}, },
{ {
title: "runtype", title: "mkr/cal",
description: "Safely bring runtime values into TypeScript.", description:
url: "https://codefeathers.github.io/runtype", "A complete calendar application with invites, task management, notetaking, and more.",
cat: "lib", url: "https://github.com/MKRhere/cal",
tags: ["typescript", "runtime"], cat: "web",
wip: true,
tags: ["hyperactive", "calendar"],
}, },
{ {
title: "Telecraft", title: "Telecraft",
description: "Pluggable Minecraft server administration toolkit.", description: "Pluggable Minecraft server administration toolkit.",
url: "https://github.com/MadrasMC/telecraft", url: "https://github.com/MadrasMC/telecraft",
cat: "tool", cat: "cli",
tags: ["minecraft", "node"], tags: ["minecraft", "node"],
}, },
];
export const otherProjects: Project[] = [
{
title: "true-pg",
description:
"The most complete PostgreSQL schema generator for TypeScript, Kysely, Zod, and others.",
url: "https://github.com/feathers-studio/true-pg",
cat: "lib",
tags: ["postgresql", "schema", "typescript", "kysely", "zod"],
},
{
title: "wiretap",
description:
"Extremely tiny debug logging utility for all JavaScript runtimes. Published as npm/yarn.",
url: "https://github.com/feathers-studio/wiretap",
cat: "lib",
tags: ["debug", "logging", "typescript"],
},
{ {
title: "Storymap (WIP)", title: "storymap",
description: description:
"Reverse-engineered thirdparty map renderer for Vintage Story in Zig ⚡️", "Reverse-engineered thirdparty map renderer for Vintage Story in Zig ⚡️",
// url: "https://github.com/MadrasMC/storymap", // url: "https://github.com/MadrasMC/storymap",
cat: "tool", cat: "cli",
tags: ["vintage-story", "zig", "wip"], tags: ["vintage-story", "zig"],
wip: true,
},
{
title: "i3-ts",
description: "TypeScript bindings for the i3 window manager.",
url: "https://github.com/feathers-studio/i3-ts",
cat: "lib",
tags: ["i3", "typescript", "bindings"],
},
{
title: "pg-extract",
description: "Extract data from PostgreSQL tables into a JSON array.",
url: "https://github.com/feathers-studio/pg-extract",
cat: "lib",
tags: ["postgresql", "json", "data-extraction"],
}, },
]; ];

Loading…
Cancel
Save