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

View file

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

View file

@ -5,7 +5,7 @@ import { useTheme } from "next-themes";
import Matter from "matter-js"; import Matter from "matter-js";
export function World() { export function World() {
const containerRef = useRef(null); const containerRef = useRef<HTMLDivElement>(null);
const { resolvedTheme } = useTheme(); const { resolvedTheme } = useTheme();
const getRandomXY = (width: number, height: number, radius: number) => { const getRandomXY = (width: number, height: number, radius: number) => {
@ -15,23 +15,25 @@ export function World() {
}; };
const getBgColor = () => { const getBgColor = () => {
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
return ( return getComputedStyle(document.documentElement)
getComputedStyle(document.documentElement) .getPropertyValue("--color-background")
.getPropertyValue("--color-background") .trim();
.trim() || "#f0f0f0"
);
} }
return "#f0f0f0";
}; };
useEffect(() => { useEffect(() => {
const container = containerRef.current; const container = containerRef.current;
if (!container) {
return;
}
const width = container.offsetWidth; const width = container.offsetWidth;
const height = container.offsetHeight; const height = container.offsetHeight;
const bgColor = getBgColor(); const bgColor = getBgColor();
const { const {
Engine, Engine,
Events,
Render, Render,
Bodies, Bodies,
Composite, Composite,
@ -103,21 +105,6 @@ export function World() {
render: { fillStyle: "green" }, 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 // Mouse interaction
const mouse = Mouse.create(render.canvas); const mouse = Mouse.create(render.canvas);
const mouseConstraint = MouseConstraint.create(engine, { 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 // Add all elements to the world
Composite.add(engine.world, [ Composite.add(engine.world, [
ground, ground,
@ -138,7 +188,7 @@ export function World() {
ballGreen, ballGreen,
ballBlue, ballBlue,
ballRed, ballRed,
pill, ...pills,
mouseConstraint, mouseConstraint,
]); ]);