Files
Space-Game/packages/ui/src/primitives/Panel.tsx
francy51 57633addfe chore: sync codebase remediation, gameplay systems, and docs
Security & infrastructure:
- Remove unused services/ (auth, spacetimedb) and auth.db
- Add .env.example template, expand .gitignore for env/db files
- Add GitHub Actions CI + commitlint config and workflows
- Add manual vendor chunking and source maps to docs/site vite configs

Shared UI & docs app:
- Add ARIA props and focus-visible rings to Button/Panel
- Add ButtonAsLink primitive; use shared Button in NotFound
- Wire @void-nav/ui into docs app; refresh content pages
- Replace Todo page with Kanban board

Gameplay (Bevy):
- Add ai module (behavior, faction, navigation, perception, spawning, states)
- Add narrative module (events, history, synthesis, ui)
- Refine galaxy contents and in-system flight/scene systems
2026-06-16 11:49:13 -04:00

55 lines
1.6 KiB
TypeScript

import type { HTMLAttributes, ReactNode } from "react";
export type PanelProps = HTMLAttributes<HTMLElement> & {
/** HTML tag to render (defaults to section) */
as?: "article" | "section" | "div" | "aside" | "main";
children: ReactNode;
/** Accessible label for screen readers */
"aria-label"?: string;
/** Reference to another element that describes this panel */
"aria-describedby"?: string;
/** Identifies this panel as a landmark region */
role?: "region" | "article" | "complementary" | "main";
};
/**
* Panel component for grouping related content with proper semantics.
*
* Renders a styled container with semantic HTML and accessibility support.
* Use this to create visually distinct sections of your interface.
*
* @example
* // Default section
* <Panel>
* <h2>Section Title</h2>
* <p>Section content...</p>
* </Panel>
*
* @example
* // With accessibility
* <Panel aria-label="Search results" role="region">
* {results}
* </Panel>
*/
export function Panel({ as: Tag = "section", children, className = "", role, ...props }: PanelProps) {
const { "aria-label": ariaLabel, "aria-describedby": ariaDescribedby, ...restProps } = props;
return (
<Tag
role={role}
aria-label={ariaLabel}
aria-describedby={ariaDescribedby}
className={[
"rounded-lg border border-border bg-surface/92 p-5 shadow-[0_16px_60px_rgba(0,0,0,0.22)]",
"focus-within:ring-2 focus-within:ring-border focus-within:ring-offset-2 focus-within:ring-offset-bg",
className,
]
.filter(Boolean)
.join(" ")}
{...restProps}
>
{children}
</Tag>
);
}