jengacore.shadcn registry · Tailwind v4 · Radix and Base UI
Components
shadcn, restyled · @jengacore/card

Card

Bordered card on canvas, radius-lg, whisper shadow, optional mint `tint` and a mono CardEyebrow.

Participants · 14
Onboarding queue
Three participants are waiting for certificate approval.
The oldest request is 4 days old.
Recommended
Enable the high contrast theme on the NOC wall
Use the tint once per view, for the highlighted item.

Install

terminal
npx shadcn@latest add @jengacore/card

Without the namespace configured: npx shadcn@latest add https://ui.jengacore.com/r/<new-york-v4|base-nova>/card.json

Registry dependencies

Source

components/ui/card.tsx
import * as React from "react"

import { cn } from "@/lib/utils"

/**
 * Bordered `card` surface on `canvas`: radius-lg, 1px border, a whisper of shadow. As on the reference board,
 * the header sits on a hairline (14 × 18 px), the body is padded 16 × 18 px, the footer sits on a hairline too.
 * `tint` (mint) at most once per view, for the highlighted item. No coloured left borders.
 */
function Card({
  className,
  size = "default",
  tint = false,
  ...props
}: React.ComponentProps<"div"> & { size?: "default" | "sm"; tint?: boolean }) {
  return (
    <div
      data-slot="card"
      data-size={size}
      className={cn(
        "group/card overflow-hidden rounded-lg border border-border bg-card text-card-foreground shadow-card contrast:border-input",
        tint && "border-transparent bg-secondary text-secondary-foreground",
        className
      )}
      {...props}
    />
  )
}

function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="card-header"
      className={cn(
        "grid auto-rows-min items-start gap-0.5 border-b border-border px-[18px] py-3.5 group-data-[size=sm]/card:px-4 group-data-[size=sm]/card:py-3",
        "has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-action]:gap-x-3 group-data-[tint=true]/card:border-current/10",
        className
      )}
      {...props}
    />
  )
}

function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
  return <div data-slot="card-title" className={cn("text-[15px] leading-[22px] font-semibold", className)} {...props} />
}

function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
  return <div data-slot="card-description" className={cn("text-[13px] leading-[18px] text-muted-foreground", className)} {...props} />
}

/** Eyebrow above a card title: mono, uppercase, with its unit or currency. */
function CardEyebrow({ className, ...props }: React.ComponentProps<"div">) {
  return <div data-slot="card-eyebrow" className={cn("eyebrow", className)} {...props} />
}

function CardAction({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="card-action"
      className={cn("col-start-2 row-span-3 row-start-1 flex items-center gap-1 self-center justify-self-end", className)}
      {...props}
    />
  )
}

function CardContent({ className, ...props }: React.ComponentProps<"div">) {
  return <div data-slot="card-content" className={cn("px-[18px] py-4 group-data-[size=sm]/card:px-4 group-data-[size=sm]/card:py-3", className)} {...props} />
}

/** Alias kept for apps that called the body CardBody (Msingi). */
const CardBody = CardContent

function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="card-footer"
      className={cn("flex items-center gap-2 border-t border-border px-[18px] py-3 group-data-[size=sm]/card:px-4", className)}
      {...props}
    />
  )
}

export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent, CardBody, CardEyebrow }