Картка
Блок з рамкою для інформаційних панелей, тарифних планів та таблиць продуктів — верхній колонтитул, основний вміст та нижній колонтитул із ефектом «жорсткої тіні» у стилі необруталізму.
import { Button } from "@/components/ui/button"
import {
Card,Картка групує пов’язаний контент у самодостатню рамку з необов’язковими слотами header, content і footer. Під нею немає примітиву — це звичайна розмітка, оформлена за рецептом необруталізму: товста рамка, різка тінь зі зміщенням і заголовок шрифтом heading.
Коли це стане в пригоді:
- Панелі дашборда — плитки метрик, графіки та стрічки активності в сітці.
- Тарифи — назва й ціна плану в header, можливості в body, кнопка купівлі у footer.
- Окремі форми — вхід, реєстрація та налаштування, яким потрібна візуальна межа.
Встановлення#
pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/card.jsonnpx shadcn@latest add https://neobrutalism.com/r/base/card.jsonyarn dlx shadcn@latest add https://neobrutalism.com/r/base/card.jsonbunx --bun shadcn@latest add https://neobrutalism.com/r/base/card.json
Скопіюйте та вставте наведений нижче код у свій проєкт.
import * as React from "react"
import { cn } from "@/lib/utils"
function Card({
className,
size = "default",
...props
}: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
return (
<div
data-slot="card"
data-size={size}
className={cn(
"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded border-2 bg-card py-(--card-spacing) text-sm text-card-foreground shadow-md [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
className
)}
{...props}
/>
)
}
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-header"
className={cn(
"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
className
)}
{...props}
/>
)
}
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-title"
className={cn(
"cn-font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",
className
)}
{...props}
/>
)
}
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-description"
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
)
}
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-action"
className={cn(
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
className
)}
{...props}
/>
)
}
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-content"
className={cn("px-(--card-spacing)", className)}
{...props}
/>
)
}
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-footer"
className={cn(
"flex items-center rounded-b-xl border-t-2 bg-muted/50 p-(--card-spacing)",
className
)}
{...props}
/>
)
}
export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardAction,
CardDescription,
CardContent,
}
Оновіть шляхи імпорту відповідно до структури вашого проєкту.
Використання#
import {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card"<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
<CardAction>Card Action</CardAction>
</CardHeader>
<CardContent>
<p>Card Content</p>
</CardContent>
<CardFooter>
<p>Card Footer</p>
</CardFooter>
</Card>Композиція#
Використайте наведену композицію, щоб зібрати Card:
Card
├── CardHeader
│ ├── CardTitle
│ ├── CardDescription
│ └── CardAction
├── CardContent
└── CardFooterПриклади#
Розмір#
Використайте проп size="sm", щоб встановити розмір card на малий. Варіант малого розміру використовує менші відступи.
import { ChevronRightIcon } from "lucide-react"
import { Button } from "@/components/ui/button"Відступи#
Крім пропа size, ви можете використати CSS-змінну --card-spacing, щоб керувати відступами між секціями та внутрішнім відступом частин card.
"use client"
import * as React from "react"Використайте від'ємні поля з -mx-(--card-spacing), щоб вміст простягався від краю до краю, залишаючись вирівняним із внутрішнім відступом card. Коли вміст від краю до краю розташований над нижнім колонтитулом, використайте -mb-(--card-spacing) на CardContent, щоб прибрати проміжок між секціями.
import { Button } from "@/components/ui/button"
import {
Card,Зображення#
Додайте зображення перед заголовком card, щоб створити card із зображенням.
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {RTL#
Щоб увімкнути підтримку RTL у Neobrutalism, перегляньте посібник з налаштування RTL.
"use client"
import * as React from "react"Доступність#
Картка суто презентаційна — кожна частина рендерить звичайний <div> без неявної ролі, тож нічого не додає до дерева доступності. CardTitle не є елементом заголовка: вкладіть справжній <h2>–<h4>, коли заголовок має з’явитися в структурі документа. Для клікабельних карток кладіть посилання або кнопку всередину й розтягуйте її область натискання на поверхню — ніколи не вішайте onClick на сам <div> картки.
Довідник API#
Card#
Компонент Card — це кореневий контейнер для вмісту card.
| Prop | Type | Default |
|---|---|---|
size | "default" | "sm" | "default" |
className | string | - |
CardHeader#
Компонент CardHeader використовується для заголовка, опису та необов'язкової дії.
| Prop | Type | Default |
|---|---|---|
className | string | - |
CardTitle#
Компонент CardTitle використовується для заголовка card.
| Prop | Type | Default |
|---|---|---|
className | string | - |
CardDescription#
Компонент CardDescription використовується для допоміжного тексту під заголовком.
| Prop | Type | Default |
|---|---|---|
className | string | - |
CardAction#
Компонент CardAction розміщує вміст у верхньому правому куті заголовка (наприклад, кнопку або badge).
| Prop | Type | Default |
|---|---|---|
className | string | - |
CardContent#
Компонент CardContent використовується для основного тіла card.
| Prop | Type | Default |
|---|---|---|
className | string | - |
CardFooter#
Компонент CardFooter використовується для дій та другорядного вмісту в нижній частині card.
| Prop | Type | Default |
|---|---|---|
className | string | - |
Журнал змін#
Змінна відступів#
Якщо ви оновлюєтеся з попередньої версії компонента Card, вам потрібно застосувати такі зміни, щоб використати змінну --card-spacing:
Оновіть класи відступів кореня Card.
Замініть жорстко закодовані gap і вертикальний padding на --card-spacing та встановіть на корені значення для типового й малого розміру:
className={cn(
- "group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
+ "group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
className
)}Оновіть класи відступів CardHeader.
Замініть горизонтальний padding і відступ рамки спільною змінною:
className={cn(
- "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3",
+ "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
className
)}Оновіть класи відступів CardContent і CardFooter.
Використайте --card-spacing для внутрішнього відступу вмісту та padding нижнього колонтитула:
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-content"
- className={cn("px-4 group-data-[size=sm]/card:px-3", className)}
+ className={cn("px-(--card-spacing)", className)}
{...props}
/>
)
} className={cn(
- "flex items-center rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/card:p-3",
+ "flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)",
className
)}Після застосування цих змін ви можете налаштувати відступи card, встановивши --card-spacing на Card за допомогою класу довільної властивості:
function Example() {
return <Card className="[--card-spacing:--spacing(6)]">...</Card>
}