fix
This commit is contained in:
@@ -74,7 +74,7 @@ export default function GamePageContent({
|
|||||||
return (
|
return (
|
||||||
<div className="mx-auto w-full max-w-6xl px-4 sm:px-8 py-6 space-y-6">
|
<div className="mx-auto w-full max-w-6xl px-4 sm:px-8 py-6 space-y-6">
|
||||||
<div className="grid gap-6 lg:grid-cols-[2fr_1fr]">
|
<div className="grid gap-6 lg:grid-cols-[2fr_1fr]">
|
||||||
<div className="rounded-2xl overflow-hidden bg-surface0/40 ring-1 ring-surface1/60">
|
<div className="rounded-2xl overflow-hidden bg-surface0/40 ring-1 ring-surface1/60 aspect-video">
|
||||||
<LazyLoadedImage
|
<LazyLoadedImage
|
||||||
imgId={`GameThumbnail_${game.rootPlaceId}`}
|
imgId={`GameThumbnail_${game.rootPlaceId}`}
|
||||||
alt={game.name}
|
alt={game.name}
|
||||||
|
|||||||
@@ -15,20 +15,6 @@ body {
|
|||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--ctp-base: 240 21.052631735801697% 14.901961386203766%; /* base */
|
|
||||||
--ctp-mantle: 240 21.311475336551666% 11.96078434586525%; /* mantle */
|
|
||||||
--ctp-crust: 240 23.404255509376526% 8.627450853586197%; /* crust */
|
|
||||||
--ctp-text: 226 63.93442749977112% 88.03921341896057%; /* text */
|
|
||||||
--ctp-subtext0: 227 23.076922595500946% 71.96078300476074%; /* subtext0 */
|
|
||||||
--ctp-subtext1: 227 35.29411852359772% 80.0000011920929%; /* subtext1 */
|
|
||||||
--ctp-surface0: 237 16.239316761493683% 22.94117659330368%; /* surface0 */
|
|
||||||
--ctp-surface1: 234 13.20754736661911% 31.176471710205078%; /* surface1 */
|
|
||||||
--ctp-surface2: 233 12.05937068939209% 39.607844948768616%; /* surface2 */
|
|
||||||
--ctp-blue: 217 91.86992049217224% 75.88235139846802%; /* blue */
|
|
||||||
--ctp-green: 115 54.09836173057556% 76.07843279838562%; /* green */
|
|
||||||
--ctp-yellow: 41 86.04651093482971% 83.13725590705872%; /* yellow */
|
|
||||||
--ctp-red: 343 81.25% 74.90196228027344%; /* red */
|
|
||||||
|
|
||||||
--background: 240 21.052631735801697% 14.901961386203766%; /* base */
|
--background: 240 21.052631735801697% 14.901961386203766%; /* base */
|
||||||
--foreground: 226 63.93442749977112% 88.03921341896057%; /* text */
|
--foreground: 226 63.93442749977112% 88.03921341896057%; /* text */
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export default function RootLayout({
|
|||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body
|
<body
|
||||||
className={`${geistSans.variable} ${geistMono.variable} antialiased overflow-x-hidden`}
|
className={`${geistSans.variable} ${geistMono.variable} antialiased overflow-x-hidden mocha`}
|
||||||
>
|
>
|
||||||
<ReactQueryProvider>
|
<ReactQueryProvider>
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
|
|||||||
7
bun.lock
7
bun.lock
@@ -5,7 +5,8 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "roblox",
|
"name": "roblox",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@catppuccin/tailwindcss": "^1.0.0",
|
"@catppuccin/palette": "^1.7.1",
|
||||||
|
"@catppuccin/tailwindcss": "0.1.6",
|
||||||
"@hookform/resolvers": "^5.2.2",
|
"@hookform/resolvers": "^5.2.2",
|
||||||
"@ocbwoy3/libocbwoy3": "^0.0.6",
|
"@ocbwoy3/libocbwoy3": "^0.0.6",
|
||||||
"@radix-ui/react-accordion": "^1.2.12",
|
"@radix-ui/react-accordion": "^1.2.12",
|
||||||
@@ -76,7 +77,9 @@
|
|||||||
"packages": {
|
"packages": {
|
||||||
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
||||||
|
|
||||||
"@catppuccin/tailwindcss": ["@catppuccin/tailwindcss@1.0.0", "", {}, "sha512-l8pOlcYe2ncGd8a1gUmL5AHmKlxR2+CHuG5kt4Me6IZwzntW1DoLmj89BH+DcsPHBsdDGLrTSv35emlYyU3FeQ=="],
|
"@catppuccin/palette": ["@catppuccin/palette@1.7.1", "", {}, "sha512-aRc1tbzrevOTV7nFTT9SRdF26w/MIwT4Jwt4fDMc9itRZUDXCuEDBLyz4TQMlqO9ZP8mf5Hu4Jr6D03NLFc6Gw=="],
|
||||||
|
|
||||||
|
"@catppuccin/tailwindcss": ["@catppuccin/tailwindcss@0.1.6", "", { "peerDependencies": { "tailwindcss": ">=3.0.0" } }, "sha512-V+Y0AwZ5SSyvOVAcDl7Ng30xy+m82OKnEJ+9+kcZZ7lRyXuZrAb2GScdq9XR3v+ggt8qiZ/G4TvaC9cJ88AAXA=="],
|
||||||
|
|
||||||
"@date-fns/tz": ["@date-fns/tz@1.4.1", "", {}, "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA=="],
|
"@date-fns/tz": ["@date-fns/tz@1.4.1", "", {}, "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA=="],
|
||||||
|
|
||||||
|
|||||||
@@ -14,13 +14,34 @@ import Link from "next/link";
|
|||||||
import { useGameLaunch } from "@/components/providers/GameLaunchProvider";
|
import { useGameLaunch } from "@/components/providers/GameLaunchProvider";
|
||||||
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
||||||
import GamePageContent from "@/app/games/[id]/content";
|
import GamePageContent from "@/app/games/[id]/content";
|
||||||
import { Maximize2 } from "lucide-react";
|
import { Maximize2, ThumbsUp, User } from "lucide-react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
interface GameCardProps {
|
interface GameCardProps {
|
||||||
game: ContentMetadata;
|
game: ContentMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const formatPlayerCount = (count: number) => {
|
||||||
|
if (count <= 1000) {
|
||||||
|
return count.toLocaleString();
|
||||||
|
}
|
||||||
|
|
||||||
|
const units = [
|
||||||
|
{ value: 1_000_000_000, suffix: "B" },
|
||||||
|
{ value: 1_000_000, suffix: "M" },
|
||||||
|
{ value: 1_000, suffix: "K" }
|
||||||
|
];
|
||||||
|
|
||||||
|
const unit = units.find(({ value }) => count >= value);
|
||||||
|
if (!unit) {
|
||||||
|
return count.toLocaleString();
|
||||||
|
}
|
||||||
|
|
||||||
|
const scaled = count / unit.value;
|
||||||
|
const digits = scaled < 10 ? 1 : 0;
|
||||||
|
return `${scaled.toFixed(digits).replace(/\.0$/, "")}${unit.suffix}`;
|
||||||
|
};
|
||||||
|
|
||||||
export const GameCard = React.memo(function GameCard({ game }: GameCardProps) {
|
export const GameCard = React.memo(function GameCard({ game }: GameCardProps) {
|
||||||
const { launchGame } = useGameLaunch();
|
const { launchGame } = useGameLaunch();
|
||||||
const totalVotes = game.totalUpVotes + game.totalDownVotes;
|
const totalVotes = game.totalUpVotes + game.totalDownVotes;
|
||||||
@@ -32,8 +53,6 @@ export const GameCard = React.memo(function GameCard({ game }: GameCardProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<ContextMenu>
|
|
||||||
<ContextMenuTrigger>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-left"
|
className="text-left"
|
||||||
@@ -49,7 +68,7 @@ export const GameCard = React.memo(function GameCard({ game }: GameCardProps) {
|
|||||||
game.rootPlaceId.toString()
|
game.rootPlaceId.toString()
|
||||||
}
|
}
|
||||||
alt={game.name}
|
alt={game.name}
|
||||||
className="object-fill w-full h-full"
|
className="object-cover w-full h-full"
|
||||||
lazyFetch={false} // ALWAYS fetch immediately
|
lazyFetch={false} // ALWAYS fetch immediately
|
||||||
size="384x216" // match game thumbnail size
|
size="384x216" // match game thumbnail size
|
||||||
/>
|
/>
|
||||||
@@ -61,52 +80,25 @@ export const GameCard = React.memo(function GameCard({ game }: GameCardProps) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-crust/50 via-transparent to-transparent opacity-0 transition-opacity group-hover:opacity-100" />
|
<div className="pointer-events-none absolute inset-0 bg-linear-to-t from-crust/50 via-transparent to-transparent opacity-0 transition-opacity group-hover:opacity-100" />
|
||||||
<div className="text-blue bg-base/90 font-mono flex right-2 bottom-2 absolute rounded-lg px-2 py-1 text-xs shadow-sm ring-1 ring-surface0/60 backdrop-blur">
|
|
||||||
{game.playerCount.toLocaleString()}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm font-semibold text-text line-clamp-2">
|
<p className="text-sm font-semibold text-text line-clamp-1">
|
||||||
{game.name}
|
{game.name}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs text-subtext1">
|
<p className="text-xs text-subtext1 space-x-2">
|
||||||
{rating}% rating
|
<span>
|
||||||
|
<ThumbsUp className="inline w-3 h-3 -translate-y-0.5 fill-text" />{" "}
|
||||||
|
{rating}%
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<User className="inline w-3 h-3 -translate-y-0.5 fill-text" />{" "}
|
||||||
|
{formatPlayerCount(game.playerCount)}
|
||||||
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</ContextMenuTrigger>
|
|
||||||
<ContextMenuContent className="min-w-[180px] p-1">
|
|
||||||
<ContextMenuItem>
|
|
||||||
<Link href={`/games/${game.rootPlaceId}`}>Open</Link>
|
|
||||||
</ContextMenuItem>
|
|
||||||
<ContextMenuItem
|
|
||||||
onClick={() => {
|
|
||||||
launchGame(game.rootPlaceId.toString());
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Play
|
|
||||||
</ContextMenuItem>
|
|
||||||
<ContextMenuSeparator />
|
|
||||||
<ContextMenuItem
|
|
||||||
onClick={() => {
|
|
||||||
navigator.clipboard.writeText(
|
|
||||||
`${game.rootPlaceId}`
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Copy placeId
|
|
||||||
</ContextMenuItem>
|
|
||||||
<ContextMenuItem
|
|
||||||
onClick={() => {
|
|
||||||
navigator.clipboard.writeText(`${game.universeId}`);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Copy universeId
|
|
||||||
</ContextMenuItem>
|
|
||||||
</ContextMenuContent>
|
|
||||||
</ContextMenu>
|
|
||||||
<DialogContent className="max-w-6xl h-[75vh] w-[96vw] max-h-[90vh] overflow-hidden bg-crust ring-1 ring-surface0/60 p-0">
|
<DialogContent className="max-w-6xl h-[75vh] w-[96vw] max-h-[90vh] overflow-hidden bg-crust ring-1 ring-surface0/60 p-0">
|
||||||
<DialogTitle className="sr-only" hidden>
|
<DialogTitle className="sr-only" hidden>
|
||||||
{game.name}
|
{game.name}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ export const QuickTopUI = React.memo(function () {
|
|||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
<div className="z-50 fixed top-4 right-4 flex gap-2 items-center text-text">
|
<div className="z-1000 fixed top-4 right-4 flex gap-2 items-center text-text">
|
||||||
<StupidHoverThing text="Change Outfit">
|
<StupidHoverThing text="Change Outfit">
|
||||||
<button
|
<button
|
||||||
className="rounded-full bg-surface0/70 ring-1 ring-surface1/60 flex items-center justify-center h-10 w-10 text-text shadow-sm transition hover:bg-surface1/70 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue/60"
|
className="rounded-full bg-surface0/70 ring-1 ring-surface1/60 flex items-center justify-center h-10 w-10 text-text shadow-sm transition hover:bg-surface1/70 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue/60"
|
||||||
@@ -141,7 +141,8 @@ export const QuickTopUI = React.memo(function () {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="rounded-full bg-surface0/70 ring-1 ring-surface1/60 flex items-center h-10 px-3 gap-2 text-text shadow-sm">
|
<div className="rounded-full bg-surface0/70 ring-1 ring-surface1/60 flex items-center h-10 px-3 gap-2 text-text shadow-sm">
|
||||||
<RobuxIcon className="w-5 h-5 text-green" />
|
<RobuxIcon className="w-5 h-5 text-text" />{" "}
|
||||||
|
{/* keep it text-text */}
|
||||||
<p className="text-sm font-super-mono tabular-nums">
|
<p className="text-sm font-super-mono tabular-nums">
|
||||||
{robux ? robux.toLocaleString() : "..."}
|
{robux ? robux.toLocaleString() : "..."}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
"lint": "bunx --bun next lint"
|
"lint": "bunx --bun next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@catppuccin/tailwindcss": "^1.0.0",
|
"@catppuccin/palette": "^1.7.1",
|
||||||
|
"@catppuccin/tailwindcss": "0.1.6",
|
||||||
"@hookform/resolvers": "^5.2.2",
|
"@hookform/resolvers": "^5.2.2",
|
||||||
"@ocbwoy3/libocbwoy3": "^0.0.6",
|
"@ocbwoy3/libocbwoy3": "^0.0.6",
|
||||||
"@radix-ui/react-accordion": "^1.2.12",
|
"@radix-ui/react-accordion": "^1.2.12",
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
import type { Config } from "tailwindcss";
|
import type { Config } from "tailwindcss";
|
||||||
|
import { flavors } from "@catppuccin/palette";
|
||||||
|
|
||||||
|
const ctpColors: Record<string, string> = {};
|
||||||
|
for (const [name, color] of Object.entries(flavors.mocha.colors)) {
|
||||||
|
ctpColors[name] = color.hex;
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
darkMode: "class",
|
darkMode: "class",
|
||||||
@@ -12,19 +18,7 @@ export default {
|
|||||||
colors: {
|
colors: {
|
||||||
background: "hsl(var(--background))",
|
background: "hsl(var(--background))",
|
||||||
foreground: "hsl(var(--foreground))",
|
foreground: "hsl(var(--foreground))",
|
||||||
base: "hsl(var(--ctp-base))",
|
...ctpColors,
|
||||||
mantle: "hsl(var(--ctp-mantle))",
|
|
||||||
crust: "hsl(var(--ctp-crust))",
|
|
||||||
text: "hsl(var(--ctp-text))",
|
|
||||||
subtext0: "hsl(var(--ctp-subtext0))",
|
|
||||||
subtext1: "hsl(var(--ctp-subtext1))",
|
|
||||||
surface0: "hsl(var(--ctp-surface0))",
|
|
||||||
surface1: "hsl(var(--ctp-surface1))",
|
|
||||||
surface2: "hsl(var(--ctp-surface2))",
|
|
||||||
blue: "hsl(var(--ctp-blue))",
|
|
||||||
green: "hsl(var(--ctp-green))",
|
|
||||||
yellow: "hsl(var(--ctp-yellow))",
|
|
||||||
red: "hsl(var(--ctp-red))",
|
|
||||||
card: {
|
card: {
|
||||||
DEFAULT: "hsl(var(--card))",
|
DEFAULT: "hsl(var(--card))",
|
||||||
foreground: "hsl(var(--card-foreground))"
|
foreground: "hsl(var(--card-foreground))"
|
||||||
|
|||||||
Reference in New Issue
Block a user