Displays a card with header, content, and footer.
Installation
npx shadcn@latest add @caprice/cardpnpm dlx shadcn@latest add @caprice/cardyarn dlx shadcn@latest add @caprice/cardbunx shadcn@latest add @caprice/cardnpm install @caprice-ui/reactpnpm add @caprice-ui/reactyarn add @caprice-ui/reactbun add @caprice-ui/reactInstall the following dependencies:
npm install @base-ui/react lucide-reactpnpm add @base-ui/react lucide-reactyarn add @base-ui/react lucide-reactbun add @base-ui/react lucide-reactAdd a cn helper
import { cn as merge } from 'cn';
import type { VariantProps } from 'cva';
import { defineConfig } from 'cva/config';
import { getSchema } from 'cva/tools';
export const { cva, cx: cn } = defineConfig({
cx: merge,
});
export type { VariantProps };
export { getSchema };
Copy and paste the following code into your project.
import { mergeProps } from '@base-ui/react';
import { useRender } from '@base-ui/react/use-render';
import { cn } from '@/lib/utils';
/**
* A card component that displays content in a styled container.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Card](https://caprice-ui.com/docs/components/card)
*/
export namespace Root {
export type Props = useRender.ComponentProps<'div'>;
}
export function Root({ className, render, ...props }: Root.Props) {
const defaultProps: useRender.ElementProps<'div'> & { 'data-slot'?: string } = {
'data-slot': 'card',
className: cn(
'relative flex flex-col gap-6 rounded-xl bg-card py-6 text-card-foreground shadow-sm ring ring-ring/28 dark:ring-ring/40',
className
),
};
return useRender({
defaultTagName: 'div',
render,
props: mergeProps<'div'>(defaultProps, props),
});
}
/**
* A header that contains the title and description of the card.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Card](https://caprice-ui.com/docs/components/card)
*/
export namespace Header {
export type Props = useRender.ComponentProps<'div'>;
}
export function Header({ className, render, ...props }: Header.Props) {
const defaultProps: useRender.ElementProps<'div'> & { 'data-slot'?: string } = {
'data-slot': 'card-header',
className: cn(
'@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',
className
),
};
return useRender({
defaultTagName: 'div',
render,
props: mergeProps<'div'>(defaultProps, props),
});
}
/**
* A title that displays the main content of the card.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Card](https://caprice-ui.com/docs/components/card)
*/
export namespace Title {
export type Props = useRender.ComponentProps<'div'>;
}
export function Title({ className, render, ...props }: Title.Props) {
const defaultProps: useRender.ElementProps<'div'> & { 'data-slot'?: string } = {
'data-slot': 'card-title',
className: cn('font-semibold leading-none', className),
};
return useRender({
defaultTagName: 'div',
render,
props: mergeProps<'div'>(defaultProps, props),
});
}
/**
* A description that displays additional information about the card.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Card](https://caprice-ui.com/docs/components/card)
*/
export namespace Description {
export type Props = useRender.ComponentProps<'div'>;
}
export function Description({ className, render, ...props }: Description.Props) {
const defaultProps: useRender.ElementProps<'div'> & { 'data-slot'?: string } = {
'data-slot': 'card-description',
className: cn('text-muted-foreground text-sm', className),
};
return useRender({
defaultTagName: 'div',
render,
props: mergeProps<'div'>(defaultProps, props),
});
}
/**
* A footer that contains the actions of the card.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Card](https://caprice-ui.com/docs/components/card)
*/
export namespace Footer {
export type Props = useRender.ComponentProps<'div'>;
}
export function Footer({ className, render, ...props }: Footer.Props) {
const defaultProps: useRender.ElementProps<'div'> & { 'data-slot'?: string } = {
'data-slot': 'card-footer',
className: cn('flex items-center px-6 [.border-t]:pt-6', className),
};
return useRender({
defaultTagName: 'div',
render,
props: mergeProps<'div'>(defaultProps, props),
});
}
/**
* An action that displays a button or link in the card.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Card](https://caprice-ui.com/docs/components/card)
*/
export namespace Action {
export type Props = useRender.ComponentProps<'div'>;
}
export function Action({ className, render, ...props }: Action.Props) {
const defaultProps: useRender.ElementProps<'div'> & { 'data-slot'?: string } = {
'data-slot': 'card-action',
className: cn('col-start-2 row-span-2 row-start-1 self-start justify-self-end', className),
};
return useRender({
defaultTagName: 'div',
render,
props: mergeProps<'div'>(defaultProps, props),
});
}
/**
* A panel that contains the content of the card.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Card](https://caprice-ui.com/docs/components/card)
*/
export namespace Panel {
export type Props = useRender.ComponentProps<'div'>;
}
export function Panel({ className, render, ...props }: Panel.Props) {
const defaultProps: useRender.ElementProps<'div'> & { 'data-slot'?: string } = {
'data-slot': 'card-panel',
className: cn('px-6', className),
};
return useRender({
defaultTagName: 'div',
render,
props: mergeProps<'div'>(defaultProps, props),
});
}
/**
* @deprecated Use {@link Panel} instead
* @see {@link https://caprice-ui.com/docs/components/card}
*/
export const Content = Panel;
Update the import paths to match your project setup.
Usage
import * as Card from "@/components/caprice-ui/card"import * as Card from "@caprice-ui/react/card"<Card.Root>
<Card.Header>
<Card.Title>Title</Card.Title>
<Card.Description>Description</Card.Description>
<Card.Action>
<Button variant="link">Sign Up</Button>
</Card.Action>
</Card.Header>
<Card.Panel>Some content</Card.Panel>
</Card.Root>Examples
Inset
Differences with shadcn/ui / Radix
If you're familiar with Radix UI and shadcn/ui, most patterns will carry over. This guide points out the differences so you can start using Caprice UI without surprises.
Key changes
Comparison Example
Accessibility
API Reference
Last updated on