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
55 lines
1.6 KiB
TypeScript
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>
|
|
);
|
|
}
|