Component
Card
A panel — solid, glass or ghost — with optional accent ticks.
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/cardExamples
Solid
Sunucu · 01
Los Santos
Ana şehir. Ekonomi, meslekler, çeteler ve polis.
Açık248 / 300 oyuncu
Sunucu · 02
Janti
Yeni şehir. Kendi ekonomisi, kendi kuralları.
BakımdaYakında açılıyor
Glass and ghost
Glass
Tint, blur and a rim of light.
Over footage and gradients.
Ghost
A frame and no ground.
Grouping on a surface.
API
<Card />A panel. Compose it from `CardHeader`, `CardTitle`, `CardDescription`, `CardContent` and `CardFooter`; each section pads itself with `--card-pad`, so a card with only content still breathes.
| Prop | Type | Default | Notes |
|---|---|---|---|
| ticks | boolean | — | Frame the card's opposite corners in the accent — for the one card that leads. |
| variant | "glass" | "ghost" | "solid" | — |
<CardEyebrow />Takes the props of what it wrapsThe small tracked label above a card's title.
<CardTitle />Takes the props of what it wrapsThe display voice, sized for a card.
Dependencies
npm
- class-variance-authority@^0.7.1
Registry
- @fastrp/corner-ticks
- @fastrp/utils
Source
components/ds/card.tsxShowHide
import { cva, type VariantProps } from 'class-variance-authority';
import type * as React from 'react';
import { CornerTicks } from '@/components/ds/corner-ticks';
import { cn } from '@/lib/utils';
// @fast-ds [email protected]
const cardVariants = cva('relative flex flex-col text-card-foreground', {
variants: {
variant: {
/** The game panel: translucent, blurred, framed, lit along its top edge. */
solid: 'panel overflow-hidden',
/** Over footage or a gradient — lighter than a panel. Solid in the FiveM NUI. */
glass: 'glass rounded-xl',
/** No ground of its own: a grouping on an existing surface. */
ghost: 'rounded-xl border border-foreground/10 bg-transparent',
},
},
defaultVariants: { variant: 'solid' },
});
export type CardProps = React.ComponentProps<'div'> &
VariantProps<typeof cardVariants> & {
/** Frame the card's opposite corners in the accent — for the one card that leads. */
ticks?: boolean;
};
/**
* A panel. Compose it from `CardHeader`, `CardTitle`, `CardDescription`, `CardContent` and
* `CardFooter`; each section pads itself with `--card-pad`, so a card with only content still
* breathes.
*/
function Card({ className, variant, ticks, children, ...props }: CardProps) {
return (
<div data-slot="card" className={cn(cardVariants({ variant }), className)} {...props}>
{ticks && <CornerTicks tone="primary" corners={['top-left', 'bottom-right']} />}
{children}
</div>
);
}
function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card-header"
className={cn(
'flex flex-col gap-1.5 p-[var(--card-pad)] pb-0 last:pb-[var(--card-pad)]',
className,
)}
{...props}
/>
);
}
/** The display voice, sized for a card. */
function CardTitle({ className, ...props }: React.ComponentProps<'h3'>) {
return (
<h3
data-slot="card-title"
className={cn('font-display text-3xl leading-none text-foreground', className)}
{...props}
/>
);
}
function CardDescription({ className, ...props }: React.ComponentProps<'p'>) {
return (
<p
data-slot="card-description"
className={cn('text-sm leading-relaxed text-muted-foreground', className)}
{...props}
/>
);
}
/** The small tracked label above a card's title. */
function CardEyebrow({ className, ...props }: React.ComponentProps<'span'>) {
return (
<span
data-slot="card-eyebrow"
className={cn('text-eyebrow uppercase text-muted-foreground', className)}
{...props}
/>
);
}
function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card-content"
className={cn('flex-1 p-[var(--card-pad)]', className)}
{...props}
/>
);
}
function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card-footer"
className={cn(
'flex items-center gap-3 border-t border-foreground/10 bg-black/15 px-[var(--card-pad)] py-4',
className,
)}
{...props}
/>
);
}
export {
Card,
CardContent,
CardDescription,
CardEyebrow,
CardFooter,
CardHeader,
CardTitle,
cardVariants,
};