Search for a command to run...
Displays a card with header, content, and footer.
npx shadcn@latest add @zaidan/cardpnpx shadcn add @zaidan/cardyarn dlx shadcn@latest add @zaidan/cardbunx shadcn@latest add @zaidan/cardCopy and paste the following code into your project.
1import { type ComponentProps, mergeProps, splitProps } from "solid-js";2import { cn } from "~/lib/utils";3
4type CardProps = ComponentProps<"div"> & { size?: "default" | "sm" };5
6const Card = (props: CardProps) => {7 const mergedProps = mergeProps({ size: "default" } as const, props);8 const [local, others] = splitProps(mergedProps, ["class", "size"]);9 return (10 <div11 data-slot="card"12 data-size={local.size}13 class={cn("group/card z-card flex flex-col", local.class)}14 {...others}15 />16 );17};18
19type CardHeaderProps = ComponentProps<"div">;20
21const CardHeader = (props: CardHeaderProps) => {22 const [local, others] = splitProps(props, ["class"]);23 return (24 <div25 data-slot="card-header"26 class={cn(27 "group/card-header @container/card-header z-card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]",28 local.class,29 )}30 {...others}31 />32 );33};34
35type CardTitleProps = ComponentProps<"div">;36
37const CardTitle = (props: CardTitleProps) => {38 const [local, others] = splitProps(props, ["class"]);39 return <div data-slot="card-title" class={cn("z-card-title", local.class)} {...others} />;40};41
42type CardDescriptionProps = ComponentProps<"div">;43
44const CardDescription = (props: CardDescriptionProps) => {45 const [local, others] = splitProps(props, ["class"]);46 return (47 <div data-slot="card-description" class={cn("z-card-description", local.class)} {...others} />48 );49};50
51type CardActionProps = ComponentProps<"div">;52
53const CardAction = (props: CardActionProps) => {54 const [local, others] = splitProps(props, ["class"]);55 return (56 <div57 data-slot="card-action"58 class={cn(59 "z-card-action col-start-2 row-span-2 row-start-1 self-start justify-self-end",60 local.class,61 )}62 {...others}63 />64 );65};66
67type CardContentProps = ComponentProps<"div">;68
69const CardContent = (props: CardContentProps) => {70 const [local, others] = splitProps(props, ["class"]);71 return <div data-slot="card-content" class={cn("z-card-content", local.class)} {...others} />;72};73
74type CardFooterProps = ComponentProps<"div">;75
76const CardFooter = (props: CardFooterProps) => {77 const [local, others] = splitProps(props, ["class"]);78 return (79 <div80 data-slot="card-footer"81 class={cn("z-card-footer flex items-center", local.class)}82 {...others}83 />84 );85};86
87export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };Here are the source code of all the examples from the preview page:
import { Button } from "~/components/ui/button";import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle,} from "~/components/ui/card";function CardDefault() { return ( <Example title="Default Size"> <Card size="default" class="mx-auto w-full max-w-sm"> <CardHeader> <CardTitle>Default Card</CardTitle> <CardDescription>This card uses the default size variant.</CardDescription> </CardHeader> <CardContent> <p> The card component supports a size prop that defaults to "default" for standard spacing and sizing. </p> </CardContent> <CardFooter> <Button variant="outline" class="w-full"> Action </Button> </CardFooter> </Card> </Example> );}import { Button } from "~/components/ui/button";import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle,} from "~/components/ui/card";function CardSmall() { return ( <Example title="Small Size"> <Card size="sm" class="mx-auto w-full max-w-sm"> <CardHeader> <CardTitle>Small Card</CardTitle> <CardDescription>This card uses the small size variant.</CardDescription> </CardHeader> <CardContent> <p> The card component supports a size prop that can be set to "sm" for a more compact appearance. </p> </CardContent> <CardFooter> <Button variant="outline" size="sm" class="w-full"> Action </Button> </CardFooter> </Card> </Example> );}import { Card, CardContent, CardDescription, CardHeader, CardTitle,} from "~/components/ui/card";function CardHeaderWithBorder() { return ( <Example title="Header with Border"> <Card class="mx-auto w-full max-w-sm"> <CardHeader class="border-b"> <CardTitle>Header with Border</CardTitle> <CardDescription>This is a card with a header that has a bottom border.</CardDescription> </CardHeader> <CardContent> <p> The header has a border-b class applied, creating a visual separation between the header and content sections. </p> </CardContent> </Card> </Example> );}import { Button } from "~/components/ui/button";import { Card, CardContent, CardFooter,} from "~/components/ui/card";function CardFooterWithBorder() { return ( <Example title="Footer with Border"> <Card class="mx-auto w-full max-w-sm"> <CardContent> <p> The footer has a border-t class applied, creating a visual separation between the content and footer sections. </p> </CardContent> <CardFooter class="border-t"> <Button variant="outline" class="w-full"> Footer with Border </Button> </CardFooter> </Card> </Example> );}import { Card, CardContent, CardDescription, CardHeader, CardTitle,} from "~/components/ui/card";function CardHeaderWithBorderSmall() { return ( <Example title="Header with Border (Small)"> <Card size="sm" class="mx-auto w-full max-w-sm"> <CardHeader class="border-b"> <CardTitle>Header with Border</CardTitle> <CardDescription> This is a small card with a header that has a bottom border. </CardDescription> </CardHeader> <CardContent> <p> The header has a border-b class applied, creating a visual separation between the header and content sections. </p> </CardContent> </Card> </Example> );}import { Button } from "~/components/ui/button";import { Card, CardContent, CardFooter,} from "~/components/ui/card";function CardFooterWithBorderSmall() { return ( <Example title="Footer with Border (Small)"> <Card size="sm" class="mx-auto w-full max-w-sm"> <CardContent> <p> The footer has a border-t class applied, creating a visual separation between the content and footer sections. </p> </CardContent> <CardFooter class="border-t"> <Button variant="outline" size="sm" class="w-full"> Footer with Border </Button> </CardFooter> </Card> </Example> );}import { Plus } from "lucide-solid";import { Button } from "~/components/ui/button";import { Card, CardDescription, CardFooter, CardHeader, CardTitle,} from "~/components/ui/card";function CardWithImage() { return ( <Example title="With Image"> <Card size="default" class="relative mx-auto w-full max-w-sm pt-0"> <div class="absolute inset-0 z-30 aspect-video bg-primary opacity-50 mix-blend-color" /> <img src="https://images.unsplash.com/photo-1604076850742-4c7221f3101b?q=80&w=1887&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" alt="Landscape by mymind on Unsplash" title="Landscape by mymind on Unsplash" class="relative z-20 aspect-video w-full object-cover brightness-60 grayscale" /> <CardHeader> <CardTitle>Beautiful Landscape</CardTitle> <CardDescription> A stunning view that captures the essence of natural beauty. </CardDescription> </CardHeader> <CardFooter> <Button class="w-full"> <Plus data-icon="inline-start" /> Button </Button> </CardFooter> </Card> </Example> );}import { Plus } from "lucide-solid";import { Button } from "~/components/ui/button";import { Card, CardDescription, CardFooter, CardHeader, CardTitle,} from "~/components/ui/card";function CardWithImageSmall() { return ( <Example title="With Image (Small)"> <Card size="sm" class="relative mx-auto w-full max-w-sm pt-0"> <div class="absolute inset-0 z-30 aspect-video bg-primary opacity-50 mix-blend-color" /> <img src="https://images.unsplash.com/photo-1604076850742-4c7221f3101b?q=80&w=1887&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" alt="Landscape by mymind on Unsplash" title="Landscape by mymind on Unsplash" class="relative z-20 aspect-video w-full object-cover brightness-60 grayscale" /> <CardHeader> <CardTitle>Beautiful Landscape</CardTitle> <CardDescription> A stunning view that captures the essence of natural beauty. </CardDescription> </CardHeader> <CardFooter> <Button size="sm" class="w-full"> <Plus data-icon="inline-start" /> Button </Button> </CardFooter> </Card> </Example> );}import { Button } from "~/components/ui/button";import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle,} from "~/components/ui/card";import { Field, FieldGroup, FieldLabel } from "~/components/ui/field";import { Input } from "~/components/ui/input";function CardLogin() { return ( <Example title="Login"> <Card class="mx-auto w-full max-w-sm"> <CardHeader> <CardTitle>Login to your account</CardTitle> <CardDescription>Enter your email below to login to your account</CardDescription> </CardHeader> <CardContent> <form> <FieldGroup> <Field> <FieldLabel for="email">Email</FieldLabel> <Input id="email" type="email" placeholder="m@example.com" required /> </Field> <Field> <div class="flex items-center"> <FieldLabel for="password">Password</FieldLabel> <a href="#" class="ml-auto inline-block underline-offset-4 hover:underline"> Forgot your password? </a> </div> <Input id="password" type="password" required /> </Field> </FieldGroup> </form> </CardContent> <CardFooter class="flex-col gap-2"> <Button type="submit" class="w-full"> Login </Button> <Button variant="outline" class="w-full"> Login with Google </Button> <div class="mt-4 text-center"> Don't have an account?{" "} <a href="#" class="underline underline-offset-4"> Sign up </a> </div> </CardFooter> </Card> </Example> );}import { Captions } from "lucide-solid";import { Avatar, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage,} from "~/components/ui/avatar";import { Button } from "~/components/ui/button";import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle,} from "~/components/ui/card";function CardMeetingNotes() { return ( <Example title="Meeting Notes"> <Card class="mx-auto w-full max-w-sm"> <CardHeader> <CardTitle>Meeting Notes</CardTitle> <CardDescription>Transcript from the meeting with the client.</CardDescription> <CardAction> <Button variant="outline" size="sm"> <Captions data-icon="inline-start" /> Transcribe </Button> </CardAction> </CardHeader> <CardContent> <p>Client requested dashboard redesign with focus on mobile responsiveness.</p> <ol class="mt-4 flex list-decimal flex-col gap-2 pl-6"> <li>New analytics widgets for daily/weekly metrics</li> <li>Simplified navigation menu</li> <li>Dark mode support</li> <li>Timeline: 6 weeks</li> <li>Follow-up meeting scheduled for next Tuesday</li> </ol> </CardContent> <CardFooter> <AvatarGroup> <Avatar> <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" /> <AvatarFallback>CN</AvatarFallback> </Avatar> <Avatar> <AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" /> <AvatarFallback>LR</AvatarFallback> </Avatar> <Avatar> <AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" /> <AvatarFallback>ER</AvatarFallback> </Avatar> <AvatarGroupCount>+8</AvatarGroupCount> </AvatarGroup> </CardFooter> </Card> </Example> );}