Use the Empty component to display an empty state.
Installation
npx shadcn@latest add @caprice/emptypnpm dlx shadcn@latest add @caprice/emptyyarn dlx shadcn@latest add @caprice/emptybunx shadcn@latest add @caprice/emptynpm 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 { defineConfig, getSchema, type VariantProps } from 'cva';
import { twMerge } from 'tailwind-merge';
export const { cva, cx: cn } = defineConfig({
hooks: {
onComplete: (className: string) => twMerge(className),
},
});
export type { VariantProps };
export { getSchema };
Copy and paste the following code into your project.
import { mergeProps, useRender } from '@base-ui/react';
import { cn, cva, type VariantProps } from '@/lib/utils';
/**
* Groups all parts of the empty state.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Empty](https://caprice-ui.com/docs/components/empty)
*/
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': 'empty',
className: cn(
'flex min-w-0 flex-1 flex-col items-center justify-center gap-6 text-balance rounded-lg border-dashed p-6 text-center md:p-12',
className
),
};
return useRender({
defaultTagName: 'div',
render,
props: mergeProps<'div'>(defaultProps, props),
});
}
/**
* A container for the empty state media, title, and description.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Empty](https://caprice-ui.com/docs/components/empty)
*/
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': 'empty-header',
className: cn('flex max-w-sm flex-col items-center gap-2 text-center', className),
};
return useRender({
defaultTagName: 'div',
render,
props: mergeProps<'div'>(defaultProps, props),
});
}
const emptyMediaVariants = cva({
base: 'mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0',
variants: {
variant: {
default: 'bg-transparent',
icon: "flex size-10 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-6",
},
},
defaultVariants: {
variant: 'default',
},
});
export namespace Media {
export type Variants = VariantProps<typeof emptyMediaVariants>;
export type Props = useRender.ComponentProps<'div'> & Media.Variants;
}
/**
* A visual representation of the empty state.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Empty](https://caprice-ui.com/docs/components/empty)
*/
export function Media({ className, variant = 'default', render, ...props }: Media.Props) {
const defaultProps: useRender.ElementProps<'div'> & { 'data-slot'?: string } = {
'data-slot': 'empty-icon',
className: cn(emptyMediaVariants({ variant, className })),
};
return useRender({
defaultTagName: 'div',
render,
props: mergeProps<'div'>(defaultProps, props),
});
}
/**
* The title of the empty state.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Empty](https://caprice-ui.com/docs/components/empty)
*/
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': 'empty-title',
className: cn('font-medium text-lg tracking-tight', className),
};
return useRender({
defaultTagName: 'div',
render,
props: mergeProps<'div'>(defaultProps, props),
});
}
/**
* The description of the empty state.
* Renders a `<p>` element.
*
* Documentation: [Caprice UI Empty](https://caprice-ui.com/docs/components/empty)
*/
export namespace Description {
export type Props = useRender.ComponentProps<'p'>;
}
export function Description({ className, render, ...props }: Description.Props) {
const defaultProps: useRender.ElementProps<'p'> & { 'data-slot'?: string } = {
'data-slot': 'empty-description',
className: cn(
'text-muted-foreground text-sm/relaxed [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4',
className
),
};
return useRender({
defaultTagName: 'p',
render,
props: mergeProps<'p'>(defaultProps, props),
});
}
/**
* A container for the empty state content.
* Renders a `<div>` element.
*
* Documentation: [Caprice UI Empty](https://caprice-ui.com/docs/components/empty)
*/
export namespace Content {
export type Props = useRender.ComponentProps<'div'>;
}
export function Content({ className, render, ...props }: Content.Props) {
const defaultProps: useRender.ElementProps<'div'> & { 'data-slot'?: string } = {
'data-slot': 'empty-content',
className: cn(
'flex w-full min-w-0 max-w-sm flex-col items-center gap-4 text-balance text-sm',
className
),
};
return useRender({
defaultTagName: 'div',
render,
props: mergeProps<'div'>(defaultProps, props),
});
}
Update the import paths to match your project setup.
Usage
import * as Empty from "@/components/caprice-ui/empty"import * as Empty from "@caprice-ui/react/empty"Last updated on