Game UI
Panel
The menu window: header, body, and a footer for key hints.
stablev0.2.0 Chromium 103 ui-scale safe
Install
Copies the file into
components/ds/, with its registry dependencies and npm packages. See Installation for the one-time setup.bunx shadcn@3 add @fastrp/panelExamples
An inventory window
Tony Montana
Envanter
QE
Ağırlık18.4 / 30 KG
The HUD, over the city
Meters, ring meters and key hints composed as a game draws them.

$15,150
$700
EBuzdolabıGKapıyı kilitle
API
<Panel />A menu window: the game panel — translucent, blurred, framed, lit along its top edge — with a header, a body and a footer for its key hints. The surface of every in-game menu; `Card` is the same surface for content in a page.
| Prop | Type | Default | Notes |
|---|---|---|---|
| accent | boolean | false | An accent line along the top edge — the panel with focus. |
| texture | "none" | "scanlines" | "grain" | "hatch" | none | A texture over the surface: display scanlines, film grain or diagonal hatching. |
<PanelFooter />Takes the props of what it wrapsThe foot of the window, darker, for its key hints and the primary action.
<PanelHeader />The title bar: eyebrow and title on the left; key hints, tabs or a close on the right.
| Prop | Type | Default | Notes |
|---|---|---|---|
| title* | ReactNode | — | |
| eyebrow | ReactNode | — | The small label over the title: a section, a character name. |
Dependencies
npm
- None
Registry
- @fastrp/utils
Source
components/ds/panel.tsxShowHide
import type * as React from 'react';
import { cn } from '@/lib/utils';
// @fast-ds [email protected]
const TEXTURE = {
none: '',
scanlines: 'tex-scanlines',
grain: 'tex-grain',
hatch: 'tex-hatch',
} as const;
export type PanelProps = React.ComponentProps<'section'> & {
/** A texture over the surface: display scanlines, film grain or diagonal hatching. */
texture?: keyof typeof TEXTURE;
/** An accent line along the top edge — the panel with focus. */
accent?: boolean;
};
/**
* A menu window: the game panel — translucent, blurred, framed, lit along its top edge — with a
* header, a body and a footer for its key hints. The surface of every in-game menu; `Card` is
* the same surface for content in a page.
*/
function Panel({ texture = 'none', accent = false, className, children, ...props }: PanelProps) {
return (
<section
data-slot="panel"
className={cn('panel flex flex-col overflow-hidden', className)}
{...props}
>
{texture !== 'none' && (
<span
aria-hidden
className={cn('pointer-events-none absolute inset-0', TEXTURE[texture])}
/>
)}
{accent && (
<span
aria-hidden
className="pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-primary to-transparent"
/>
)}
{children}
</section>
);
}
export type PanelHeaderProps = Omit<React.ComponentProps<'header'>, 'title'> & {
title: React.ReactNode;
/** The small label over the title: a section, a character name. */
eyebrow?: React.ReactNode;
};
/** The title bar: eyebrow and title on the left; key hints, tabs or a close on the right. */
function PanelHeader({ title, eyebrow, className, children, ...props }: PanelHeaderProps) {
return (
<header
data-slot="panel-header"
className={cn(
'relative flex items-end justify-between gap-6 border-b border-foreground/10 px-[var(--card-pad)] pb-4 pt-5',
className,
)}
{...props}
>
<div className="flex min-w-0 flex-col gap-1">
{eyebrow && <span className="text-eyebrow uppercase text-muted-foreground">{eyebrow}</span>}
<h2 className="truncate font-display text-3xl leading-none text-foreground">{title}</h2>
</div>
{children && <div className="flex shrink-0 items-center gap-3">{children}</div>}
</header>
);
}
function PanelBody({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="panel-body"
className={cn('relative min-h-0 flex-1 overflow-y-auto p-[var(--card-pad)]', className)}
{...props}
/>
);
}
/** The foot of the window, darker, for its key hints and the primary action. */
function PanelFooter({ className, ...props }: React.ComponentProps<'footer'>) {
return (
<footer
data-slot="panel-footer"
className={cn(
'relative flex items-center justify-between gap-4 border-t border-foreground/10 bg-black/20 px-[var(--card-pad)] py-3',
className,
)}
{...props}
/>
);
}
export { Panel, PanelBody, PanelFooter, PanelHeader };