chore: pills desktop complete

Signed-off-by: Ameya Shenoy <shenoy.ameya@gmail.com>
This commit is contained in:
Ameya Shenoy 2025-06-07 14:09:58 +05:30
parent 57f3540834
commit b1f81a6b62
3 changed files with 84 additions and 25 deletions

View file

@ -1,6 +1,6 @@
import type { Metadata } from "next";
import { ThemeProvider } from "@/components/theme-provider";
import { Geist, Geist_Mono, Space_Grotesk } from "next/font/google";
import { Geist, Geist_Mono, Space_Grotesk, Space_Mono } from "next/font/google";
import "./globals.css";
import { NavigationMenu } from "@/components/Navbar";
@ -20,6 +20,12 @@ const spaceGroteskSans = Space_Grotesk({
subsets: ["latin"],
});
const spaceMono = Space_Mono({
weight: ["400", "700"],
variable: "--font-space-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Ameya Shenoy",
description:
@ -34,7 +40,7 @@ export default function RootLayout({
return (
<html lang="en" suppressHydrationWarning>
<body
className={`${geistSans.variable} ${geistMono.variable} ${spaceGroteskSans.variable} antialiased`}
className={`${geistSans.variable} ${geistMono.variable} ${spaceGroteskSans.variable} ${spaceMono.variable} antialiased`}
>
<ThemeProvider
attribute="class"

View file

@ -17,6 +17,9 @@ export function NavigationMenu() {
<Button variant="ghost">
<Link href="/talk">Talk</Link>
</Button>
<Button variant="ghost">
<Link href="/references">References</Link>
</Button>
<ModeToggle />
</div>
);

View file

@ -5,7 +5,7 @@ import { useTheme } from "next-themes";
import Matter from "matter-js";
export function World() {
const containerRef = useRef(null);
const containerRef = useRef<HTMLDivElement>(null);
const { resolvedTheme } = useTheme();
const getRandomXY = (width: number, height: number, radius: number) => {
@ -15,23 +15,25 @@ export function World() {
};
const getBgColor = () => {
if (typeof window !== "undefined") {
return (
getComputedStyle(document.documentElement)
.getPropertyValue("--color-background")
.trim() || "#f0f0f0"
);
return getComputedStyle(document.documentElement)
.getPropertyValue("--color-background")
.trim();
}
return "#f0f0f0";
};
useEffect(() => {
const container = containerRef.current;
if (!container) {
return;
}
const width = container.offsetWidth;
const height = container.offsetHeight;
const bgColor = getBgColor();
const {
Engine,
Events,
Render,
Bodies,
Composite,
@ -103,21 +105,6 @@ export function World() {
render: { fillStyle: "green" },
});
const pillHeight = 50;
const pill = Matter.Bodies.rectangle(randomX, randomY, 200, pillHeight, {
chamfer: { radius: pillHeight / 2 },
isStatic: false,
density: 0.001,
friction: 0.05,
frictionAir: 0.01,
render: {
fillStyle: "rgba(255, 255, 255, 0)", // transparent fill
strokeStyle: "#000000", // black border
lineWidth: 2,
},
});
// Mouse interaction
const mouse = Mouse.create(render.canvas);
const mouseConstraint = MouseConstraint.create(engine, {
@ -129,6 +116,69 @@ export function World() {
},
});
let pills: Matter.Body[] = [];
const pillsToRender = [
"ENGINEERING MANAGER",
"NIX",
"PRINCIPAL ENGINEER",
"AI",
];
pillsToRender.forEach(function (pillText) {
const fontSize = 32;
const ctx = render.canvas.getContext("2d");
ctx.font = `${fontSize}px Arial`;
const textWidth = ctx.measureText(pillText).width;
const pillHeight = fontSize * 2;
const pillWidth = textWidth + pillHeight;
[randomX, randomY] = getRandomXY(width, height, radius);
const pill = Matter.Bodies.rectangle(
randomX,
randomY,
pillWidth,
pillHeight,
{
chamfer: { radius: pillHeight / 2 },
isStatic: false,
density: 0.001,
friction: 0.05,
frictionAir: 0.01,
render: {
fillStyle: "rgba(255, 255, 255, 0)", // transparent fill
strokeStyle: "#000000", // black border
lineWidth: 1,
},
},
);
pills.push(pill);
const text = document.createElement("div");
Object.assign(text.style, {
position: "absolute",
width: `${pillWidth}px`,
height: `${pillHeight}px`,
display: "flex",
justifyContent: "center",
alignItems: "center",
fontFamily: "Space Mono",
fontSize: `${fontSize}px`,
color: "black",
pointerEvents: "none",
});
text.innerText = pillText;
render.canvas.getContext("2d").measure;
document.body.appendChild(text);
Events.on(engine, "afterUpdate", () => {
text.style.left = `${pill.position.x - pillWidth / 2 + 60}px`;
text.style.top = `${pill.position.y + pillHeight / 2 - 4}px`;
text.style.transform = `rotate(${pill.angle}rad)`;
});
});
// Add all elements to the world
Composite.add(engine.world, [
ground,
@ -138,7 +188,7 @@ export function World() {
ballGreen,
ballBlue,
ballRed,
pill,
...pills,
mouseConstraint,
]);