Glrk UI

Card

A simplified wrapper for Shadcn Card with flexible option handling and automatic type conversion

Card Title
Card Description

Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorum, voluptas nisi natus dolores debitis facere a nam? Libero itaque enim ullam ab iste reiciendis, nemo aliquid ratione saepe non dicta.

Installation

npx shadcn@latest add @glrk-ui/card

If you haven't set up the prerequisites yet, check out Prerequest section.

Copy and paste the following code into your project.

ui/card.tsx
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-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",
        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-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",
        className
      )}
      {...props}
    />
  )
}

function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="card-title"
      className={cn(
        "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-4 group-data-[size=sm]/card:px-3", 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 bg-muted/50 p-4 group-data-[size=sm]/card:p-3",
        className
      )}
      {...props}
    />
  )
}

type CardWrapperProps = {
  title?: React.ReactNode
  description?: React.ReactNode
  children?: React.ReactNode
  footer?: React.ReactNode
  actions?: React.ReactNode
  wrapperCls?: string
  headerCls?: string
  titleCls?: string
  descriptionCls?: string
  contentCls?: string
  footerCls?: string
}

function CardWrapper({
  title,
  description,
  children,
  footer,
  actions,
  wrapperCls,
  headerCls,
  titleCls,
  descriptionCls,
  contentCls,
  footerCls,
}: CardWrapperProps) {
  return (
    <Card className={cn(wrapperCls)}>
      <CardHeader className={cn(headerCls)}>
        {title && <CardTitle className={cn(titleCls)}>{title}</CardTitle>}
        {description && <CardDescription className={cn(descriptionCls)}>{description}</CardDescription>}

        {actions}
      </CardHeader>

      {
        children &&
        <CardContent className={cn(contentCls)}>
          {children}
        </CardContent>
      }

      {footer
        ? typeof footer === "string"
          ? <CardFooter className={cn(footerCls)}>{footer}</CardFooter>
          : footer
        : null
      }
    </Card>
  )
}

export {
  Card,
  CardHeader,
  CardFooter,
  CardTitle,
  CardAction,
  CardDescription,
  CardContent,
  CardWrapper,
}

Usage

Basic

import { CardWrapper } from "@/components/ui/card";

export function Basic() {
  return (
    <CardWrapper
      title="Card Title"
      description="Card Description"
      footer="Card Footer"
    >
      <p>Card Content</p>
    </CardWrapper>
  )
}

Reference

CardWrapper

Prop

Type