Restructure into pnpm monorepo with game shell, docs, and SpacetimeDB backend

- Restructure flat static prototype into pnpm workspace monorepo
- apps/game: playable shell with R3F 3D scene, HUD, SpacetimeDB connection
- apps/docs: design docs and prototypes
- apps/site: landing page
- packages/ui: shared Button and Panel primitives
- services/spacetimedb: backend module (9 tables, 11 reducers)
- Archive legacy static files to archive/legacy-static/
- Game loop: connect, undock, target, approach, dock, mine, sell
- Add pnpm-workspace.yaml, tsconfig.base.json, spacetime.json
This commit is contained in:
2026-05-31 17:56:56 -04:00
parent 436f282fa8
commit 316a44661b
234 changed files with 3717 additions and 101 deletions

View File

@@ -0,0 +1,55 @@
import type { ButtonHTMLAttributes, AnchorHTMLAttributes, ReactNode } from "react";
type ButtonTone = "primary" | "secondary" | "ghost";
type BaseProps = {
children: ReactNode;
className?: string;
tone?: ButtonTone;
};
type NativeButtonProps = BaseProps &
ButtonHTMLAttributes<HTMLButtonElement> & {
href?: never;
};
type AnchorButtonProps = BaseProps &
AnchorHTMLAttributes<HTMLAnchorElement> & {
href: string;
};
export type ButtonProps = NativeButtonProps | AnchorButtonProps;
const tones: Record<ButtonTone, string> = {
primary: "border-accent bg-accent text-bg hover:bg-accent-hover",
secondary: "border-border bg-surface-raised text-fg hover:border-border-light hover:bg-surface-hover",
ghost: "border-transparent bg-transparent text-cyan hover:border-border-light hover:bg-surface",
};
export function Button({ children, className = "", tone = "secondary", ...props }: ButtonProps) {
const classes = [
"inline-flex min-h-10 cursor-pointer items-center justify-center gap-2 rounded-md border px-4 py-2 text-sm font-semibold transition-colors duration-150 disabled:cursor-not-allowed disabled:opacity-55",
tones[tone],
className,
]
.filter(Boolean)
.join(" ");
if ("href" in props) {
const anchorProps = props as Omit<AnchorButtonProps, keyof BaseProps>;
return (
<a className={classes} {...anchorProps}>
{children}
</a>
);
}
const buttonProps = props as Omit<NativeButtonProps, keyof BaseProps>;
return (
<button className={classes} {...buttonProps}>
{children}
</button>
);
}