shshadcn-htmx

Components

Figure

Self-contained, referenced content — an image, diagram, code block, or quotation — wrapped in a native <figure> whose <figcaption> supplies its accessible name. Distinct from a Card's generic surface: a figure can be moved out of the main flow without breaking it. Zero JavaScript.

Installation

1. Install via the shadcn CLI

npx shadcn@latest add http://localhost/r/figure.json

2. Use it

components/ui/figure.tsx
import {
  Figure,
  FigureCaption,
  FigureContent,
  FigureCredit,
} from "@/components/ui/figure"

// Image with a caption below
<Figure>
  <img src="/elephant.jpg" alt="An elephant at sunset" class="w-full rounded-md" />
  <FigureCaption>An elephant at sunset</FigureCaption>
</Figure>

// Code block with a legend on top
<Figure captionSide="top">
  <FigureCaption>Detect the browser via navigator</FigureCaption>
  <FigureContent>
    <pre class="overflow-x-auto p-4"><code>navigator.userAgent</code></pre>
  </FigureContent>
</Figure>
Or copy the source manually
components/ui/figure.tsx
/** @jsxImportSource hono/jsx */
import type { Child, PropsWithChildren } from "hono/jsx"
import { cn, type ClassValue } from "@/registry/lib/cn"

// Figure — shadcn-htmx, htmx v4 + Tailwind v4.
//
// Self-contained captioned content — an image, diagram, code block, or
// quotation — wrapped in a native <figure> whose <figcaption> supplies the
// figure's accessible name. Unlike <Card> (a generic styled surface),
// <Figure> is *referential*: it stands apart from the main flow and can be
// moved elsewhere without breaking it, and the caption is semantically tied
// to the content. No interactivity, no JavaScript.
//
// Built on (native elements; we add nothing the platform doesn't ship):
//   - <figure> — represents self-contained content, optionally captioned;
//     the figure, its caption, and its contents are one unit. Implicit ARIA
//     role "figure".
//       repos/mdn/files/en-us/web/html/reference/elements/figure/index.md
//   - <figcaption> — caption/legend for the parent <figure>; provides the
//     <figure> its accessible name. Must be the figure's first or last child
//     (the first <figcaption> found is presented as the caption).
//       repos/mdn/files/en-us/web/html/reference/elements/figcaption/index.md
//
// Anatomy mirrors shadcn's Card family (read for intent only, not copied —
// different element, different semantics):
//   repos/shadcn-ui/apps/v4/registry/new-york-v4/ui/card.tsx
//
// Theme tokens only: border / bg-card / text-card-foreground for the surface,
// text-muted-foreground for the caption, bg-muted for plain content slots.

// Where the caption sits relative to the content. Both are valid per the
// spec (first OR last child); we render the <figcaption> in the chosen DOM
// position so the accessible name is correct either way.
export type FigureCaptionSide = "top" | "bottom"

type FigureProps = PropsWithChildren<{
  class?: ClassValue
  id?: string
  // Caption position. "bottom" (default) reads as a credit/label under the
  // content; "top" reads as a legend introducing it (common for code blocks
  // and quotations). See the MDN figure examples.
  captionSide?: FigureCaptionSide
  // Forward hx-*, data-*, aria-* and standard global attributes onto the
  // <figure> root.
  [key: string]: unknown
}>

// Surface: a bordered card-like box. We keep it visually distinct from the
// document body but lighter than a full Card (no shadow) so it reads as
// "referenced content", not a UI panel. Caption position is purely a matter
// of DOM order (figcaption first vs last) — both are spec-valid — so it needs
// no extra class; the column flow handles either. `data-caption-side` records
// the author's intent for styling hooks / tests.
const root =
  "flex flex-col gap-3 overflow-hidden rounded-lg border bg-card p-3 text-card-foreground"

export function Figure(props: FigureProps) {
  const {
    class: className,
    id,
    captionSide = "bottom",
    children,
    ...rest
  } = props

  return (
    <figure
      id={id}
      data-slot="figure"
      data-caption-side={captionSide}
      class={cn(root, className)}
      {...rest}
    >
      {children}
    </figure>
  )
}

// The content slot — image, code block, quote, diagram. Optional thin wrapper
// that gives non-replaced content (code, quotes) a muted backdrop and rounds
// it to match the surface. For a bare <img> you can skip this and put the
// image directly in <Figure>.
export function FigureContent(
  props: PropsWithChildren<{ class?: ClassValue }>,
) {
  return (
    <div
      data-slot="figure-content"
      class={cn(
        "overflow-hidden rounded-md bg-muted text-sm text-foreground",
        props.class,
      )}
    >
      {props.children}
    </div>
  )
}

// The caption — renders a native <figcaption>, which gives the parent
// <figure> its accessible name. Keep it concise; it is the figure's label,
// not its body. Use <FigureCredit> inside for a secondary line (source,
// author) styled lighter.
export function FigureCaption(
  props: PropsWithChildren<{ class?: ClassValue; id?: string }>,
) {
  return (
    <figcaption
      id={props.id}
      data-slot="figure-caption"
      class={cn(
        "px-1 text-sm leading-snug text-muted-foreground",
        props.class,
      )}
    >
      {props.children}
    </figcaption>
  )
}

// Optional secondary line inside a caption (attribution / source / date),
// rendered a touch smaller. Purely presentational; stays inside <figcaption>
// so it remains part of the accessible name.
export function FigureCredit(
  props: PropsWithChildren<{ class?: ClassValue }>,
) {
  return (
    <span
      data-slot="figure-credit"
      class={cn("mt-1 block text-xs text-muted-foreground/80", props.class)}
    >
      {props.children}
    </span>
  )
}

export type { FigureProps }
export type FigureChild = Child

1. Save the file

Copy figure.html into templates/components/.

2. Use it

templates/components/figure.html
{% from "components/figure.html" import figure, figure_content, figure_caption, figure_credit %}

{% call figure() %}
  <img src="/elephant.jpg" alt="An elephant at sunset" class="w-full rounded-md">
  {% call figure_caption() %}An elephant at sunset{% endcall %}
{% endcall %}
View source
templates/components/figure.html
{# Figure macros — shadcn-htmx, htmx v4 + Tailwind v4.
   Mirrors registry/ui/figure.tsx.

   Self-contained captioned content (image, diagram, code, quote) in a native
   <figure>; the <figcaption> supplies the figure's accessible name. Zero JS.
     MDN figure:     repos/mdn/files/en-us/web/html/reference/elements/figure/index.md
     MDN figcaption: repos/mdn/files/en-us/web/html/reference/elements/figcaption/index.md

   The <figcaption> must be the figure's first or last child; choose
   caption_side accordingly and put the figure_caption(...) call in that DOM
   position yourself (this mirrors how the .tsx renders children in order).

   Usage:
     {% from "components/figure.html" import figure, figure_content,
        figure_caption, figure_credit %}

     {% call figure(caption_side="bottom") %}
       <img src="/elephant.jpg" alt="An elephant at sunset" class="w-full rounded-md">
       {% call figure_caption() %}An elephant at sunset{% endcall %}
     {% endcall %} #}

{% macro figure(caption_side="bottom", id=none, extra_class="", **attrs) -%}
<figure
  {%- if id %} id="{{ id }}"{% endif %}
  data-slot="figure"
  data-caption-side="{{ caption_side }}"
  class="flex flex-col gap-3 overflow-hidden rounded-lg border bg-card p-3 text-card-foreground {{ extra_class }}"
  {%- for k, v in attrs.items() %} {{ k|replace('_','-') }}="{{ v }}"{% endfor %}>{{ caller() }}</figure>
{%- endmacro %}

{% macro figure_content(extra_class="") -%}
<div data-slot="figure-content" class="overflow-hidden rounded-md bg-muted text-sm text-foreground {{ extra_class }}">{{ caller() }}</div>
{%- endmacro %}

{% macro figure_caption(id=none, extra_class="") -%}
<figcaption {% if id %}id="{{ id }}" {% endif %}data-slot="figure-caption" class="px-1 text-sm leading-snug text-muted-foreground {{ extra_class }}">{{ caller() }}</figcaption>
{%- endmacro %}

{% macro figure_credit(extra_class="") -%}
<span data-slot="figure-credit" class="mt-1 block text-xs text-muted-foreground/80 {{ extra_class }}">{{ caller() }}</span>
{%- endmacro %}

1. Save the file

Add figure.tmpl alongside your templates.

2. Use it

components/figure.tmpl
{{template "figure" (dict
  "Body" "<img src=\"/elephant.jpg\" alt=\"An elephant at sunset\" class=\"w-full rounded-md\">"
  "Caption" "An elephant at sunset")}}
View source
components/figure.tmpl
{{/*
  Figure template — shadcn-htmx, htmx v4 + Tailwind v4.
  Mirrors registry/ui/figure.tsx.

  Self-contained captioned content (image, diagram, code, quote) in a native
  <figure>; the <figcaption> supplies the figure's accessible name. Zero JS.
    MDN figure:     repos/mdn/files/en-us/web/html/reference/elements/figure/index.md
    MDN figcaption: repos/mdn/files/en-us/web/html/reference/elements/figcaption/index.md

  The <figcaption> must be the figure's first or last child. The "figure"
  template renders Caption first when CaptionSide == "top", otherwise last,
  matching the .tsx DOM order. Compose the inner content/caption yourself via
  the helper templates if you need finer control.

      type FigureArgs struct {
          CaptionSide string        // "bottom" (default) | "top"
          ID          string
          Class       string
          Caption     template.HTML // <figcaption> inner HTML
          Body        template.HTML // content (img / code block / quote …)
      }
*/}}

{{define "figure-caption"}}
{{- $id := .ID -}}
<figcaption {{if $id}}id="{{$id}}" {{end}}data-slot="figure-caption" class="px-1 text-sm leading-snug text-muted-foreground {{.Class}}">{{htmlSafe .Body}}</figcaption>
{{end}}

{{define "figure-content"}}
<div data-slot="figure-content" class="overflow-hidden rounded-md bg-muted text-sm text-foreground {{.Class}}">{{htmlSafe .Body}}</div>
{{end}}

{{define "figure-credit"}}
<span data-slot="figure-credit" class="mt-1 block text-xs text-muted-foreground/80 {{.Class}}">{{htmlSafe .Body}}</span>
{{end}}

{{define "figure"}}
{{- $side := or .CaptionSide "bottom" -}}
<figure {{if .ID}}id="{{.ID}}" {{end}}data-slot="figure" data-caption-side="{{$side}}" class="flex flex-col gap-3 overflow-hidden rounded-lg border bg-card p-3 text-card-foreground {{.Class}}">
{{- if eq $side "top" -}}
{{- if .Caption}}<figcaption data-slot="figure-caption" class="px-1 text-sm leading-snug text-muted-foreground">{{htmlSafe .Caption}}</figcaption>{{end -}}
{{- htmlSafe .Body -}}
{{- else -}}
{{- htmlSafe .Body -}}
{{- if .Caption}}<figcaption data-slot="figure-caption" class="px-1 text-sm leading-snug text-muted-foreground">{{htmlSafe .Caption}}</figcaption>{{end -}}
{{- end -}}
</figure>
{{end}}

1. Save the file

Drop figure.ex into lib/my_app_web/components/.

2. Use it

lib/my_app_web/components/figure.ex
<.figure>
  <img src="/elephant.jpg" alt="An elephant at sunset" class="w-full rounded-md" />
  <.figure_caption>An elephant at sunset</.figure_caption>
</.figure>
View source
lib/my_app_web/components/figure.ex
defmodule ShadcnHtmx.Components.Figure do
  @moduledoc """
  Figure — shadcn-htmx, htmx v4 + Tailwind v4 for Phoenix.

  Mirrors registry/ui/figure.tsx. Self-contained captioned content (image,
  diagram, code block, quotation) in a native `<figure>`; the `<figcaption>`
  supplies the figure's accessible name. No JavaScript.

    MDN figure:     repos/mdn/files/en-us/web/html/reference/elements/figure/index.md
    MDN figcaption: repos/mdn/files/en-us/web/html/reference/elements/figcaption/index.md

  The `<figcaption>` must be the figure's first or last child. Pass
  `caption_side="top"` to render the caption above the content (legend),
  otherwise it renders below (credit/label).

  ## Examples

      <.figure>
        <img src="/elephant.jpg" alt="An elephant at sunset" class="w-full rounded-md" />
        <.figure_caption>An elephant at sunset</.figure_caption>
      </.figure>

      <.figure caption_side="top">
        <.figure_caption>
          Get browser details <.figure_credit>via navigator</.figure_credit>
        </.figure_caption>
        <.figure_content>
          <pre class="overflow-x-auto p-4"><code>navigator.userAgent</code></pre>
        </.figure_content>
      </.figure>
  """

  use Phoenix.Component

  attr :caption_side, :string, default: "bottom", values: ~w(top bottom)
  attr :class, :string, default: nil
  attr :rest, :global
  slot :inner_block, required: true

  def figure(assigns) do
    ~H"""
    <figure
      data-slot="figure"
      data-caption-side={@caption_side}
      class={[
        "flex flex-col gap-3 overflow-hidden rounded-lg border bg-card p-3 text-card-foreground",
        @class
      ]}
      {@rest}
    >
      {render_slot(@inner_block)}
    </figure>
    """
  end

  attr :class, :string, default: nil
  slot :inner_block, required: true

  def figure_content(assigns) do
    ~H"""
    <div
      data-slot="figure-content"
      class={["overflow-hidden rounded-md bg-muted text-sm text-foreground", @class]}
    >
      {render_slot(@inner_block)}
    </div>
    """
  end

  attr :id, :string, default: nil
  attr :class, :string, default: nil
  slot :inner_block, required: true

  def figure_caption(assigns) do
    ~H"""
    <figcaption
      id={@id}
      data-slot="figure-caption"
      class={["px-1 text-sm leading-snug text-muted-foreground", @class]}
    >
      {render_slot(@inner_block)}
    </figcaption>
    """
  end

  attr :class, :string, default: nil
  slot :inner_block, required: true

  def figure_credit(assigns) do
    ~H"""
    <span
      data-slot="figure-credit"
      class={["mt-1 block text-xs text-muted-foreground/80", @class]}
    >
      {render_slot(@inner_block)}
    </span>
    """
  end
end

1. Save the file

Paste the markup; relies only on theme tokens.

2. Use it

snippets/figure.html
<figure data-slot="figure" data-caption-side="bottom"
        class="flex flex-col gap-3 overflow-hidden rounded-lg border bg-card p-3 text-card-foreground">
  <img src="/elephant.jpg" alt="An elephant at sunset" class="w-full rounded-md">
  <figcaption data-slot="figure-caption"
              class="px-1 text-sm leading-snug text-muted-foreground">
    An elephant at sunset
  </figcaption>
</figure>
View source
snippets/figure.html
<!--
  shadcn-htmx — raw HTML figure snippets.
  Mirrors registry/ui/figure.tsx.

  Self-contained captioned content (image, diagram, code, quote) in a native
  <figure>; the <figcaption> gives the <figure> its accessible name. The
  caption must be the figure's first or last child. Zero JavaScript —
  Tailwind theme tokens only.

    MDN figure:     repos/mdn/files/en-us/web/html/reference/elements/figure/index.md
    MDN figcaption: repos/mdn/files/en-us/web/html/reference/elements/figcaption/index.md

  ROOT:
    flex flex-col gap-3 overflow-hidden rounded-lg border bg-card p-3 text-card-foreground
  data-caption-side="top" | "bottom" records where the figcaption sits.
-->

<!-- Image with a caption below (the common case) -->
<figure data-slot="figure" data-caption-side="bottom"
        class="flex flex-col gap-3 overflow-hidden rounded-lg border bg-card p-3 text-card-foreground">
  <img src="/elephant.jpg" alt="An elephant at sunset"
       class="w-full rounded-md">
  <figcaption data-slot="figure-caption"
              class="px-1 text-sm leading-snug text-muted-foreground">
    An elephant at sunset
    <span data-slot="figure-credit" class="mt-1 block text-xs text-muted-foreground/80">
      Photo: J. Doe / CC BY 4.0
    </span>
  </figcaption>
</figure>

<!-- Code block with a legend on top -->
<figure data-slot="figure" data-caption-side="top"
        class="flex flex-col gap-3 overflow-hidden rounded-lg border bg-card p-3 text-card-foreground">
  <figcaption data-slot="figure-caption"
              class="px-1 text-sm leading-snug text-muted-foreground">
    Get browser details using <code>navigator</code>.
  </figcaption>
  <div data-slot="figure-content"
       class="overflow-hidden rounded-md bg-muted text-sm text-foreground">
    <pre class="overflow-x-auto p-4"><code>console.log(navigator.userAgent);</code></pre>
  </div>
</figure>

<!-- Quotation: blockquote content, attribution in the caption -->
<figure data-slot="figure" data-caption-side="bottom"
        class="flex flex-col gap-3 overflow-hidden rounded-lg border bg-card p-3 text-card-foreground">
  <div data-slot="figure-content"
       class="overflow-hidden rounded-md bg-muted text-sm text-foreground">
    <blockquote class="border-l-2 border-border px-4 py-3 italic">
      If debugging is the process of removing software bugs, then programming
      must be the process of putting them in.
    </blockquote>
  </div>
  <figcaption data-slot="figure-caption"
              class="px-1 text-sm leading-snug text-muted-foreground">
    — Edsger W. Dijkstra
  </figcaption>
</figure>

Examples

Captioned image

An <img> followed by a <figcaption>. The caption becomes the figure's accessible name.

The <figcaption> is the figure's caption and its accessible name: a screen reader announces "An elephant at sunset, figure". The <img> still needs its own alt; the two serve different jobs. A nested FigureCredit stays inside the caption so attribution is part of that name.

Gradient placeholder, 640 by 360
An elephant at sunsetPhoto: J. Doe / CC BY 4.0
<Figure>
  <img src="/elephant.jpg" alt="An elephant at sunset" class="w-full rounded-md" />
  <FigureCaption>
    An elephant at sunset
    <FigureCredit>Photo: J. Doe / CC BY 4.0</FigureCredit>
  </FigureCaption>
</Figure>
{% call figure() %}
  <img src="/elephant.jpg" alt="An elephant at sunset" class="w-full rounded-md">
  {% call figure_caption() %}
    An elephant at sunset
    {% call figure_credit() %}Photo: J. Doe / CC BY 4.0{% endcall %}
  {% endcall %}
{% endcall %}
{{template "figure" (dict
  "Body" "<img src=\"/elephant.jpg\" alt=\"An elephant at sunset\" class=\"w-full rounded-md\">"
  "Caption" "An elephant at sunset<span data-slot=\"figure-credit\" class=\"mt-1 block text-xs text-muted-foreground/80\">Photo: J. Doe / CC BY 4.0</span>")}}
<.figure>
  <img src="/elephant.jpg" alt="An elephant at sunset" class="w-full rounded-md" />
  <.figure_caption>
    An elephant at sunset
    <.figure_credit>Photo: J. Doe / CC BY 4.0</.figure_credit>
  </.figure_caption>
</.figure>
<div class="w-full max-w-sm">
  <figure data-slot="figure" data-caption-side="bottom" class="flex flex-col gap-3 overflow-hidden rounded-lg border bg-card p-3 text-card-foreground">
    <img src="data:image/svg+xml;utf8,%3Csvg%20xmlns%3D&#39;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&#39;%20width%3D&#39;640&#39;%20height%3D&#39;360&#39;%3E%3Cdefs%3E%3ClinearGradient%20id%3D&#39;g&#39;%20x1%3D&#39;0&#39;%20y1%3D&#39;0&#39;%20x2%3D&#39;1&#39;%20y2%3D&#39;1&#39;%3E%3Cstop%20offset%3D&#39;0&#39;%20stop-color%3D&#39;%252306b6d4&#39;%2F%3E%3Cstop%20offset%3D&#39;1&#39;%20stop-color%3D&#39;%25237c3aed&#39;%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Crect%20width%3D&#39;640&#39;%20height%3D&#39;360&#39;%20fill%3D&#39;url(%2523g)&#39;%2F%3E%3Ctext%20x%3D&#39;50%25&#39;%20y%3D&#39;50%25&#39;%20fill%3D&#39;white&#39;%20font-family%3D&#39;sans-serif&#39;%20font-size%3D&#39;28&#39;%20text-anchor%3D&#39;middle&#39;%20dominant-baseline%3D&#39;middle&#39;%3E640%20%C3%97%20360%3C%2Ftext%3E%3C%2Fsvg%3E" alt="Gradient placeholder, 640 by 360" class="w-full rounded-md"/>
    <figcaption data-slot="figure-caption" class="px-1 text-sm leading-snug text-muted-foreground">
      An elephant at sunset
      <span data-slot="figure-credit" class="mt-1 block text-xs text-muted-foreground/80">Photo: J. Doe / CC BY 4.0</span>
    </figcaption>
  </figure>
</div>

Code block with a legend on top

captionSide="top" renders the <figcaption> first, as a legend introducing the snippet.

The spec allows the <figcaption> to be the figure's first or last child — the first one found is the caption. Set captionSide="top" and place the caption before the content for a legend. FigureContent gives non-replaced content a muted backdrop.

Read the user-agent string via navigator.
console.log(navigator.userAgent);
<Figure captionSide="top">
  <FigureCaption>
    Read the user-agent string via <code>navigator</code>.
  </FigureCaption>
  <FigureContent>
    <pre class="overflow-x-auto p-4"><code>console.log(navigator.userAgent);</code></pre>
  </FigureContent>
</Figure>
{% call figure(caption_side="top") %}
  {% call figure_caption() %}Read the user-agent string via <code>navigator</code>.{% endcall %}
  {% call figure_content() %}
    <pre class="overflow-x-auto p-4"><code>console.log(navigator.userAgent);</code></pre>
  {% endcall %}
{% endcall %}
{{template "figure" (dict
  "CaptionSide" "top"
  "Caption" "Read the user-agent string via <code>navigator</code>."
  "Body" "<div data-slot=\"figure-content\" class=\"overflow-hidden rounded-md bg-muted text-sm text-foreground\"><pre class=\"overflow-x-auto p-4\"><code>console.log(navigator.userAgent);</code></pre></div>")}}
<.figure caption_side="top">
  <.figure_caption>
    Read the user-agent string via <code>navigator</code>.
  </.figure_caption>
  <.figure_content>
    <pre class="overflow-x-auto p-4"><code>console.log(navigator.userAgent);</code></pre>
  </.figure_content>
</.figure>
<div class="w-full max-w-md">
  <figure data-slot="figure" data-caption-side="top" class="flex flex-col gap-3 overflow-hidden rounded-lg border bg-card p-3 text-card-foreground">
    <figcaption data-slot="figure-caption" class="px-1 text-sm leading-snug text-muted-foreground">
      Read the user-agent string via
      <code>navigator</code>
      .
    </figcaption>
    <div data-slot="figure-content" class="overflow-hidden rounded-md bg-muted text-sm text-foreground">
      <pre class="overflow-x-auto p-4">
        <code>console.log(navigator.userAgent);</code>
      </pre>
    </div>
  </figure>
</div>

Quotation with attribution

A <blockquote> inside FigureContent; the <figcaption> carries the attribution.

Per the MDN quotation example, the quoted text is the content and the source is the caption. Keep the attribution in the <figcaption> so it remains the figure's accessible name.

If debugging is the process of removing software bugs, then programming must be the process of putting them in.
— Edsger W. Dijkstra
<Figure>
  <FigureContent>
    <blockquote class="border-l-2 border-border px-4 py-3 italic">
      If debugging is the process of removing software bugs, then
      programming must be the process of putting them in.
    </blockquote>
  </FigureContent>
  <FigureCaption>— Edsger W. Dijkstra</FigureCaption>
</Figure>
{% call figure() %}
  {% call figure_content() %}
    <blockquote class="border-l-2 border-border px-4 py-3 italic">…</blockquote>
  {% endcall %}
  {% call figure_caption() %}— Edsger W. Dijkstra{% endcall %}
{% endcall %}
{{template "figure" (dict
  "Body" "<div data-slot=\"figure-content\" class=\"overflow-hidden rounded-md bg-muted text-sm text-foreground\"><blockquote class=\"border-l-2 border-border px-4 py-3 italic\">…</blockquote></div>"
  "Caption" "— Edsger W. Dijkstra")}}
<.figure>
  <.figure_content>
    <blockquote class="border-l-2 border-border px-4 py-3 italic"></blockquote>
  </.figure_content>
  <.figure_caption>Edsger W. Dijkstra</.figure_caption>
</.figure>
<div class="w-full max-w-md">
  <figure data-slot="figure" data-caption-side="bottom" class="flex flex-col gap-3 overflow-hidden rounded-lg border bg-card p-3 text-card-foreground">
    <div data-slot="figure-content" class="overflow-hidden rounded-md bg-muted text-sm text-foreground">
      <blockquote class="border-l-2 border-border px-4 py-3 italic">
        If debugging is the process of removing software bugs, then programming must be the process of putting them in.
      </blockquote>
    </div>
    <figcaption data-slot="figure-caption" class="px-1 text-sm leading-snug text-muted-foreground">— Edsger W. Dijkstra</figcaption>
  </figure>
</div>

API Reference

<Figure>

PropTypeDefaultDescription
captionSide"bottom"|"top""bottom"
Where the <figcaption> sits relative to the content. "bottom" reads as a credit/label below; "top" reads as a legend introducing the content (common for code blocks). The spec allows the caption as the figure's first or last child, so place the caption in that DOM order.MDN<figure>
idstring
Forwarded onto the <figure> root.
classstring
Extra Tailwind classes appended to the root element.
hx-*any
Any htmx attribute. Forwarded onto the underlying element.htmxAttribute reference