본문으로 건너뛰기
언어

Cardstandard

관련 내용을 한 상자에 담는 카드(card)입니다. shadcn base-nova 의 원본을 그대로 담은 아이템이며 `div` 로 그립니다.

설치

pnpm
pnpm dlx shadcn@4.23.0 add @uikit/card

Default

card-example.tsx
"use client"
import * as React from "react"
import {  Example,  ExampleWrapper,} from "@/components/example"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"import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"import { Input } from "@/components/ui/input"import {  ToggleGroup,  ToggleGroupItem,} from "@/components/ui/toggle-group"import { CaptionsIcon, PlusIcon } from "lucide-react"
const spacingOptions = [  {    className: "[--card-spacing:--spacing(4)]",    label: "16px",    value: "4",  },  {    className: "[--card-spacing:--spacing(5)]",    label: "20px",    value: "5",  },  {    className: "[--card-spacing:--spacing(6)]",    label: "24px",    value: "6",  },  {    className: "[--card-spacing:--spacing(8)]",    label: "32px",    value: "8",  },]
export default function CardExample() {  return (    <ExampleWrapper>      <CardDefault />      <CardSmall />      <CardContentEdgeToEdge />      <CardCustomSpacing />      <CardHeaderWithBorder />      <CardFooterWithBorder />      <CardHeaderWithBorderSmall />      <CardFooterWithBorderSmall />      <CardWithImage />      <CardWithImageSmall />      <CardLogin />      <CardMeetingNotes />    </ExampleWrapper>  )}
function CardContentEdgeToEdge() {  return (    <Example title="Content Edge to Edge">      <Card className="mx-auto w-full max-w-sm">        <CardHeader>          <CardTitle>Terms of Service</CardTitle>          <CardDescription>            Review the terms before accepting the agreement.          </CardDescription>        </CardHeader>        <CardContent className="-mb-(--card-spacing) px-0">          <div tabIndex={0} className="max-h-48 space-y-4 overflow-y-scroll border-t bg-muted/50 px-(--card-spacing) py-4 text-sm leading-relaxed">            <p>              These terms govern your use of the workspace, including access to              shared documents, project files, and collaboration tools.            </p>            <p>              You are responsible for the content you upload and for ensuring              that your team has the appropriate permissions to view or edit it.            </p>            <p>              We may update features or limits as the service evolves. When              those changes materially affect your workflow, we will notify your              workspace administrators.            </p>            <p>              By continuing, you agree to keep your account credentials secure              and to follow your organization&apos;s acceptable use policies.            </p>          </div>        </CardContent>        <CardFooter className="justify-end gap-2">          <Button variant="outline">Decline</Button>          <Button>Accept</Button>        </CardFooter>      </Card>    </Example>  )}
function CardCustomSpacing() {  const [spacing, setSpacing] = React.useState("4")  const selectedSpacing = spacingOptions.find(    (option) => option.value === spacing  )
  return (    <Example title="Custom Spacing">      <div className="mx-auto grid w-full max-w-sm gap-4">        <ToggleGroup          value={[spacing]}          onValueChange={(value) => {            if (value[0]) {              setSpacing(value[0])            }          }}          variant="outline"          size="sm"          className="justify-center"        >          {spacingOptions.map((option) => (            <ToggleGroupItem key={option.value} value={option.value}>              {option.label}            </ToggleGroupItem>          ))}        </ToggleGroup>        <Card className={selectedSpacing?.className}>          <CardHeader>            <CardTitle>Release Health</CardTitle>            <CardDescription>              Track readiness across launch signals.            </CardDescription>          </CardHeader>          <CardContent>            <div className="grid gap-2 rounded-lg bg-muted/50 p-3 text-sm style-lyra:rounded-none style-sera:rounded-none">              <div className="flex items-center justify-between gap-2">                <span className="text-muted-foreground">Checks passed</span>                <span className="font-medium">24 / 26</span>              </div>              <div className="flex items-center justify-between gap-2">                <span className="text-muted-foreground">Open blockers</span>                <span className="font-medium">2</span>              </div>            </div>          </CardContent>        </Card>      </div>    </Example>  )}
function CardLogin() {  return (    <Example title="Login">      <Card className="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 htmlFor="email">Email</FieldLabel>                <Input                  id="email"                  type="email"                  placeholder="m@example.com"                  required                />              </Field>              <Field>                <div className="flex items-center">                  <FieldLabel htmlFor="password">Password</FieldLabel>                  <a                    href="#"                    className="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 className="flex-col gap-2">          <Button type="submit" className="w-full">            Login          </Button>          <Button variant="outline" className="w-full">            Login with Google          </Button>          <div className="mt-4 text-center">            Don&apos;t have an account?{" "}            <a href="#" className="underline underline-offset-4">              Sign up            </a>          </div>        </CardFooter>      </Card>    </Example>  )}
function CardMeetingNotes() {  return (    <Example title="Meeting Notes">      <Card className="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">              <CaptionsIcon data-icon="inline-start" />              Transcribe            </Button>          </CardAction>        </CardHeader>        <CardContent>          <p>            Client requested dashboard redesign with focus on mobile            responsiveness.          </p>          <ol className="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="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%208'%3E%3Crect%20width='8'%20height='8'%20fill='%2364748b'/%3E%3C/svg%3E" alt="@shadcn" />              <AvatarFallback>CN</AvatarFallback>            </Avatar>            <Avatar>              <AvatarImage                src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%208'%3E%3Crect%20width='8'%20height='8'%20fill='%230f766e'/%3E%3C/svg%3E"                alt="@maxleiter"              />              <AvatarFallback>LR</AvatarFallback>            </Avatar>            <Avatar>              <AvatarImage                src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%208'%3E%3Crect%20width='8'%20height='8'%20fill='%237c3aed'/%3E%3C/svg%3E"                alt="@evilrabbit"              />              <AvatarFallback>ER</AvatarFallback>            </Avatar>            <AvatarGroupCount>+8</AvatarGroupCount>          </AvatarGroup>        </CardFooter>      </Card>    </Example>  )}
function CardWithImage() {  return (    <Example title="With Image">      <Card size="default" className="relative mx-auto w-full max-w-sm pt-0">        <div className="absolute inset-0 z-30 aspect-video bg-primary opacity-50 mix-blend-color" />        <img          src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2394a3b8'/%3E%3C/svg%3E"          alt="Photo by mymind on Unsplash"          title="Photo by mymind on Unsplash"          className="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 className="w-full">            <PlusIcon data-icon="inline-start" />            Button          </Button>        </CardFooter>      </Card>    </Example>  )}
function CardWithImageSmall() {  return (    <Example title="With Image (Small)">      <Card size="sm" className="relative mx-auto w-full max-w-sm pt-0">        <div className="absolute inset-0 z-30 aspect-video bg-primary opacity-50 mix-blend-color" />        <img          src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2394a3b8'/%3E%3C/svg%3E"          alt="Photo by mymind on Unsplash"          title="Photo by mymind on Unsplash"          className="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" className="w-full">            <PlusIcon data-icon="inline-start" />            Button          </Button>        </CardFooter>      </Card>    </Example>  )}
function CardHeaderWithBorder() {  return (    <Example title="Header with Border">      <Card className="mx-auto w-full max-w-sm">        <CardHeader className="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>  )}
function CardFooterWithBorder() {  return (    <Example title="Footer with Border">      <Card className="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 className="border-t">          <Button variant="outline" className="w-full">            Footer with Border          </Button>        </CardFooter>      </Card>    </Example>  )}
function CardDefault() {  return (    <Example title="Default Size">      <Card size="default" className="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            &quot;default&quot; for standard spacing and sizing.          </p>        </CardContent>        <CardFooter>          <Button variant="outline" className="w-full">            Action          </Button>        </CardFooter>      </Card>    </Example>  )}
function CardSmall() {  return (    <Example title="Small Size">      <Card size="sm" className="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            &quot;sm&quot; for a more compact appearance.          </p>        </CardContent>        <CardFooter>          <Button variant="outline" size="sm" className="w-full">            Action          </Button>        </CardFooter>      </Card>    </Example>  )}
function CardHeaderWithBorderSmall() {  return (    <Example title="Header with Border (Small)">      <Card size="sm" className="mx-auto w-full max-w-sm">        <CardHeader className="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>  )}
function CardFooterWithBorderSmall() {  return (    <Example title="Footer with Border (Small)">      <Card size="sm" className="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 className="border-t">          <Button variant="outline" size="sm" className="w-full">            Footer with Border          </Button>        </CardFooter>      </Card>    </Example>  )}