{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "card",
  "type": "registry:ui",
  "title": "Card",
  "description": "Structural container — Header / Title / Description / Action / Content / Footer slots. Pure layout primitive; pair with htmx for content swaps.",
  "files": [
    {
      "path": "registry/ui/card.tsx",
      "type": "registry:ui",
      "target": "components/ui/card.tsx",
      "content": "/** @jsxImportSource hono/jsx */\nimport type { PropsWithChildren } from \"hono/jsx\"\nimport { cn, type ClassValue } from \"@/registry/lib/cn\"\n\n// Card — shadcn-htmx, htmx v4 + Tailwind v4.\n//\n// Source of truth (1:1 class strings):\n//   repos/shadcn-ui/apps/v4/registry/new-york-v4/ui/card.tsx\n//\n// Card is structural — a rounded container with a Header / Title /\n// Description / Content / Footer layout. No interactivity, no JS.\n// Pair it with htmx attributes on inner elements when you need to swap\n// the contents server-side.\n\ntype CardAs = \"div\" | \"article\" | \"section\" | \"li\" | \"aside\"\n\nexport function Card(\n  props: PropsWithChildren<\n    {\n      class?: ClassValue\n      id?: string\n      // Semantic element. shadcn upstream hardcodes <div>; we default to\n      // <div> for backwards-compat but encourage <article> for self-\n      // contained content (product card, blog tile, comment) and\n      // <section> for thematic groups inside a landmark.\n      // See repos/mdn/files/en-us/web/html/reference/elements/article/index.md:10,65-68\n      as?: CardAs\n      // Pair with the id of the CardTitle inside so the rendered <article>\n      // / <section> has an accessible name for AT landmark navigation.\n      ariaLabelledby?: string\n      ariaLabel?: string\n    } & Record<string, any>\n  >,\n) {\n  const { class: className, children, as = \"div\", ariaLabelledby, ariaLabel, ...rest } = props\n  const Tag: any = as\n  return (\n    <Tag\n      data-slot=\"card\"\n      class={cn(\n        \"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm\",\n        className,\n      )}\n      aria-labelledby={ariaLabelledby}\n      aria-label={ariaLabel}\n      {...rest}\n    >\n      {children}\n    </Tag>\n  )\n}\n\nexport function CardHeader(\n  props: PropsWithChildren<{ class?: ClassValue }>,\n) {\n  return (\n    <div\n      data-slot=\"card-header\"\n      class={cn(\n        \"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6\",\n        props.class,\n      )}\n    >\n      {props.children}\n    </div>\n  )\n}\n\ntype CardTitleAs = \"div\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\"\n\nexport function CardTitle(\n  props: PropsWithChildren<{\n    class?: ClassValue\n    // Render as a real heading so an `as=\"article\"|\"section\"` Card gets a\n    // child heading and contributes to the document outline. Default \"div\"\n    // preserves shadcn upstream behaviour.\n    // See repos/mdn/files/en-us/web/html/reference/elements/article/index.md:66\n    //     repos/mdn/files/en-us/web/html/reference/elements/section/index.md:55\n    as?: CardTitleAs\n    // Lets Card's aria-labelledby reference this visible title, giving a\n    // section/article card its accessible name (region landmark naming).\n    // See repos/mdn/files/en-us/web/accessibility/aria/reference/roles/region_role/index.md:25,29\n    id?: string\n  }>,\n) {\n  const { class: className, children, as = \"div\", id } = props\n  const Tag: any = as\n  return (\n    <Tag data-slot=\"card-title\" id={id} class={cn(\"leading-none font-semibold\", className)}>\n      {children}\n    </Tag>\n  )\n}\n\nexport function CardDescription(\n  props: PropsWithChildren<{ class?: ClassValue }>,\n) {\n  return (\n    <div\n      data-slot=\"card-description\"\n      class={cn(\"text-sm text-muted-foreground\", props.class)}\n    >\n      {props.children}\n    </div>\n  )\n}\n\n// Sits in the top-right of CardHeader; the header grid auto-detects it and\n// switches to two columns via `has-data-[slot=card-action]:grid-cols-[1fr_auto]`.\nexport function CardAction(\n  props: PropsWithChildren<{ class?: ClassValue }>,\n) {\n  return (\n    <div\n      data-slot=\"card-action\"\n      class={cn(\n        \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n        props.class,\n      )}\n    >\n      {props.children}\n    </div>\n  )\n}\n\nexport function CardContent(\n  props: PropsWithChildren<{ class?: ClassValue }>,\n) {\n  return (\n    <div data-slot=\"card-content\" class={cn(\"px-6\", props.class)}>\n      {props.children}\n    </div>\n  )\n}\n\nexport function CardFooter(\n  props: PropsWithChildren<{ class?: ClassValue }>,\n) {\n  return (\n    <div\n      data-slot=\"card-footer\"\n      class={cn(\"flex items-center px-6 [.border-t]:pt-6\", props.class)}\n    >\n      {props.children}\n    </div>\n  )\n}\n"
    },
    {
      "path": "registry/jinja2/card.html",
      "type": "registry:file",
      "target": "templates/components/card.html",
      "content": "{# Card macros — shadcn-htmx, htmx v4 + Tailwind v4.\n   Mirrors registry/ui/card.tsx.\n\n   Usage:\n     {% from \"components/card.html\" import card_open, card_close,\n        card_header_open, card_header_close,\n        card_title, card_description,\n        card_content_open, card_content_close,\n        card_footer_open, card_footer_close %}\n\n     {{ card_open() }}\n       {{ card_header_open() }}\n         {{ card_title(\"Account\") }}\n         {{ card_description(\"Update your account settings here.\") }}\n       {{ card_header_close() }}\n       {{ card_content_open() }}\n         <p>Body content…</p>\n       {{ card_content_close() }}\n       {{ card_footer_open() }}\n         <button class=\"…\">Save</button>\n       {{ card_footer_close() }}\n     {{ card_close() }} #}\n\n{% macro card_open(extra_class=\"\") -%}\n<div data-slot=\"card\" class=\"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm {{ extra_class }}\">\n{%- endmacro %}\n{% macro card_close() %}</div>{% endmacro %}\n\n{% macro card_header_open(extra_class=\"\") -%}\n<div data-slot=\"card-header\" class=\"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6 {{ extra_class }}\">\n{%- endmacro %}\n{% macro card_header_close() %}</div>{% endmacro %}\n\n{# `as` renders a real heading (h1-h6) so an as=\"article\"/\"section\" card gets a\n   child heading per the document-outline guidance; default \"div\" keeps shadcn\n   upstream behaviour. `id` lets card_open(aria_labelledby=...) name the card.\n   See repos/mdn/files/en-us/web/html/reference/elements/article/index.md:66\n       repos/mdn/files/en-us/web/accessibility/aria/reference/roles/region_role/index.md:25,29 #}\n{% macro card_title(text, extra_class=\"\", as=\"div\", id=\"\") -%}\n<{{ as }} data-slot=\"card-title\"{% if id %} id=\"{{ id }}\"{% endif %} class=\"leading-none font-semibold {{ extra_class }}\">{{ text }}</{{ as }}>\n{%- endmacro %}\n\n{% macro card_description(text, extra_class=\"\") -%}\n<div data-slot=\"card-description\" class=\"text-sm text-muted-foreground {{ extra_class }}\">{{ text }}</div>\n{%- endmacro %}\n\n{% macro card_action_open(extra_class=\"\") -%}\n<div data-slot=\"card-action\" class=\"col-start-2 row-span-2 row-start-1 self-start justify-self-end {{ extra_class }}\">\n{%- endmacro %}\n{% macro card_action_close() %}</div>{% endmacro %}\n\n{% macro card_content_open(extra_class=\"\") -%}\n<div data-slot=\"card-content\" class=\"px-6 {{ extra_class }}\">\n{%- endmacro %}\n{% macro card_content_close() %}</div>{% endmacro %}\n\n{% macro card_footer_open(extra_class=\"\") -%}\n<div data-slot=\"card-footer\" class=\"flex items-center px-6 [.border-t]:pt-6 {{ extra_class }}\">\n{%- endmacro %}\n{% macro card_footer_close() %}</div>{% endmacro %}\n"
    },
    {
      "path": "registry/go-templates/card.tmpl",
      "type": "registry:file",
      "target": "components/card.tmpl",
      "content": "{{/*\n  Card templates — shadcn-htmx, htmx v4 + Tailwind v4.\n  Mirrors registry/ui/card.tsx.\n\n  Each named template wraps an HTML chunk. To compose, hand-assemble the\n  HTML in your handler (Go html/template has no caller block syntax):\n\n      type CardArgs struct {\n          Title       string\n          Description string\n          Content     template.HTML\n          Footer      template.HTML\n          Action      template.HTML // optional, sits in the top-right\n          // Optional: render CardTitle as a real heading (h1-h6) so an\n          // article/section card has a child heading for the document\n          // outline; empty => \"div\" (shadcn upstream default).\n          // See repos/mdn/.../elements/article/index.md:66 ; section/index.md:55\n          TitleAs string\n          // Optional: id on CardTitle so a section/article card can name\n          // itself via aria-labelledby (region landmark naming).\n          // See repos/mdn/.../roles/region_role/index.md:25,29\n          TitleID string\n      }\n\n      tpl.ExecuteTemplate(w, \"card\", CardArgs{\n          Title:       \"Account\",\n          Description: \"Update your settings here.\",\n          Content:     template.HTML(`<p>Body content…</p>`),\n          Footer:      template.HTML(`<button>Save</button>`),\n      })\n*/}}\n\n{{define \"card\"}}\n<div data-slot=\"card\" class=\"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm\">\n  {{- if or .Title .Description .Action}}\n  <div data-slot=\"card-header\" class=\"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6\">\n    {{- if .Title}}{{$t := or .TitleAs \"div\"}}<{{$t}} data-slot=\"card-title\"{{if .TitleID}} id=\"{{.TitleID}}\"{{end}} class=\"leading-none font-semibold\">{{.Title}}</{{$t}}>{{end}}\n    {{- if .Description}}<div data-slot=\"card-description\" class=\"text-sm text-muted-foreground\">{{.Description}}</div>{{end}}\n    {{- if .Action}}<div data-slot=\"card-action\" class=\"col-start-2 row-span-2 row-start-1 self-start justify-self-end\">{{.Action}}</div>{{end}}\n  </div>\n  {{- end}}\n  {{- if .Content}}\n  <div data-slot=\"card-content\" class=\"px-6\">{{.Content}}</div>\n  {{- end}}\n  {{- if .Footer}}\n  <div data-slot=\"card-footer\" class=\"flex items-center px-6 [.border-t]:pt-6\">{{.Footer}}</div>\n  {{- end}}\n</div>\n{{end}}\n"
    },
    {
      "path": "registry/phoenix/card.ex",
      "type": "registry:file",
      "target": "lib/my_app_web/components/card.ex",
      "content": "defmodule ShadcnHtmx.Components.Card do\n  @moduledoc \"\"\"\n  Card — shadcn-htmx, htmx v4 + Tailwind v4 for Phoenix.\n\n  Mirrors registry/ui/card.tsx. Structural container with\n  Header / Title / Description / Action / Content / Footer slots.\n\n  ## Examples\n\n      <.card>\n        <.card_header>\n          <.card_title>Account</.card_title>\n          <.card_description>Update your settings here.</.card_description>\n        </.card_header>\n        <.card_content>\n          <p>Body content…</p>\n        </.card_content>\n        <.card_footer>\n          <button>Save</button>\n        </.card_footer>\n      </.card>\n  \"\"\"\n\n  use Phoenix.Component\n\n  attr :class, :string, default: nil\n  attr :rest, :global\n  slot :inner_block, required: true\n\n  def card(assigns) do\n    ~H\"\"\"\n    <div\n      data-slot=\"card\"\n      class={[\"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm\", @class]}\n      {@rest}\n    >\n      {render_slot(@inner_block)}\n    </div>\n    \"\"\"\n  end\n\n  attr :class, :string, default: nil\n  slot :inner_block, required: true\n\n  def card_header(assigns) do\n    ~H\"\"\"\n    <div\n      data-slot=\"card-header\"\n      class={[\n        \"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6\",\n        @class\n      ]}\n    >\n      {render_slot(@inner_block)}\n    </div>\n    \"\"\"\n  end\n\n  attr :class, :string, default: nil\n  # Render as a real heading (h1-h6) so an as=\"article\"/\"section\" card gets a\n  # child heading for the document outline; default \"div\" keeps shadcn upstream.\n  # See repos/mdn/files/en-us/web/html/reference/elements/article/index.md:66\n  #     repos/mdn/files/en-us/web/html/reference/elements/section/index.md:55\n  attr :as, :string, default: \"div\", values: ~w(div h1 h2 h3 h4 h5 h6)\n  # id lets a section/article card reference this title via aria-labelledby\n  # (region landmark naming).\n  # See repos/mdn/files/en-us/web/accessibility/aria/reference/roles/region_role/index.md:25,29\n  attr :id, :string, default: nil\n  slot :inner_block, required: true\n\n  def card_title(assigns) do\n    ~H\"\"\"\n    <.dynamic_tag tag_name={@as} data-slot=\"card-title\" id={@id} class={[\"leading-none font-semibold\", @class]}>\n      {render_slot(@inner_block)}\n    </.dynamic_tag>\n    \"\"\"\n  end\n\n  attr :class, :string, default: nil\n  slot :inner_block, required: true\n\n  def card_description(assigns) do\n    ~H\"\"\"\n    <div data-slot=\"card-description\" class={[\"text-sm text-muted-foreground\", @class]}>\n      {render_slot(@inner_block)}\n    </div>\n    \"\"\"\n  end\n\n  attr :class, :string, default: nil\n  slot :inner_block, required: true\n\n  def card_action(assigns) do\n    ~H\"\"\"\n    <div\n      data-slot=\"card-action\"\n      class={[\"col-start-2 row-span-2 row-start-1 self-start justify-self-end\", @class]}\n    >\n      {render_slot(@inner_block)}\n    </div>\n    \"\"\"\n  end\n\n  attr :class, :string, default: nil\n  slot :inner_block, required: true\n\n  def card_content(assigns) do\n    ~H\"\"\"\n    <div data-slot=\"card-content\" class={[\"px-6\", @class]}>\n      {render_slot(@inner_block)}\n    </div>\n    \"\"\"\n  end\n\n  attr :class, :string, default: nil\n  slot :inner_block, required: true\n\n  def card_footer(assigns) do\n    ~H\"\"\"\n    <div\n      data-slot=\"card-footer\"\n      class={[\"flex items-center px-6 [.border-t]:pt-6\", @class]}\n    >\n      {render_slot(@inner_block)}\n    </div>\n    \"\"\"\n  end\nend\n"
    },
    {
      "path": "registry/html/card.html",
      "type": "registry:file",
      "target": "snippets/card.html",
      "content": "<!--\n  shadcn-htmx — raw HTML card snippet.\n\n  Mirrors registry/ui/card.tsx. Just divs with the right Tailwind classes —\n  no JS, no special CSS.\n\n  CARD:             flex flex-col gap-6 rounded-xl border bg-card py-6\n                    text-card-foreground shadow-sm\n  CARD HEADER:      @container/card-header grid auto-rows-min\n                    grid-rows-[auto_auto] items-start gap-2 px-6\n                    has-data-[slot=card-action]:grid-cols-[1fr_auto]\n                    [.border-b]:pb-6\n  CARD TITLE:       leading-none font-semibold\n  CARD DESCRIPTION: text-sm text-muted-foreground\n  CARD ACTION:      col-start-2 row-span-2 row-start-1 self-start\n                    justify-self-end\n  CARD CONTENT:     px-6\n  CARD FOOTER:      flex items-center px-6 [.border-t]:pt-6\n-->\n\n<!-- Basic -->\n<div data-slot=\"card\"\n  class=\"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm\">\n  <div data-slot=\"card-header\"\n    class=\"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6\">\n    <div data-slot=\"card-title\" class=\"leading-none font-semibold\">Account</div>\n    <div data-slot=\"card-description\" class=\"text-sm text-muted-foreground\">\n      Update your account preferences and notification settings.\n    </div>\n  </div>\n  <div data-slot=\"card-content\" class=\"px-6\">\n    <p class=\"text-sm\">Body content goes here.</p>\n  </div>\n  <div data-slot=\"card-footer\" class=\"flex items-center px-6 [.border-t]:pt-6\">\n    <button class=\"inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground hover:bg-primary/90\">\n      Save\n    </button>\n  </div>\n</div>\n\n<!-- With CardAction (top-right header slot) -->\n<div data-slot=\"card\"\n  class=\"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm\">\n  <div data-slot=\"card-header\"\n    class=\"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6\">\n    <div data-slot=\"card-title\" class=\"leading-none font-semibold\">Untitled draft</div>\n    <div data-slot=\"card-description\" class=\"text-sm text-muted-foreground\">\n      Last edited 12 minutes ago.\n    </div>\n    <div data-slot=\"card-action\" class=\"col-start-2 row-span-2 row-start-1 self-start justify-self-end\">\n      <button class=\"inline-flex size-7 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground\" aria-label=\"More\">\n        <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"size-4\" aria-hidden=\"true\">\n          <circle cx=\"12\" cy=\"12\" r=\"1\" /><circle cx=\"19\" cy=\"12\" r=\"1\" /><circle cx=\"5\" cy=\"12\" r=\"1\" />\n        </svg>\n      </button>\n    </div>\n  </div>\n  <div data-slot=\"card-content\" class=\"px-6\">\n    <p class=\"text-sm text-muted-foreground\">3 unread comments.</p>\n  </div>\n</div>\n\n<!-- As a landmark: <section> card named by its heading.\n     CardTitle is rendered as a real heading (h2) with an id, and the card\n     references it via aria-labelledby so the region landmark gets its name\n     from the visible title. A <section> with an accessible name is exposed\n     as role=region — prefer the semantic element over an explicit role.\n     See repos/mdn/.../elements/section/index.md:55\n         repos/mdn/.../roles/region_role/index.md:25,29 -->\n<section data-slot=\"card\" aria-labelledby=\"card-title-billing\"\n  class=\"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm\">\n  <div data-slot=\"card-header\"\n    class=\"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6\">\n    <h2 data-slot=\"card-title\" id=\"card-title-billing\" class=\"leading-none font-semibold\">Billing</h2>\n    <div data-slot=\"card-description\" class=\"text-sm text-muted-foreground\">\n      Manage your subscription and payment method.\n    </div>\n  </div>\n  <div data-slot=\"card-content\" class=\"px-6\">\n    <p class=\"text-sm\">Your plan renews on the 1st of each month.</p>\n  </div>\n</section>\n"
    }
  ]
}
