{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "meter",
  "type": "registry:ui",
  "title": "Meter",
  "description": "The native <meter> element (ARIA role=\"meter\") — a gauge of a value within a known range with low/high/optimum zoning. Cross-browser fill colors via the meter pseudo-elements; includes an htmx live-gauge demo.",
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/ui/meter.tsx",
      "type": "registry:ui",
      "target": "components/ui/meter.tsx",
      "content": "/** @jsxImportSource hono/jsx */\nimport type { Child } from \"hono/jsx\"\nimport { cn, type ClassValue } from \"@/registry/lib/cn\"\n\n// Meter — shadcn-htmx, htmx v4 + Tailwind v4.\n//\n// Source of truth:\n//   shadcn/ui ships no Meter component. This is a native-platform addition\n//   distinct from Progress: a gauge of a value within a known range\n//   (battery, disk usage, score) — NOT task completion.\n//\n// We render the real native <meter> element (implicit role=\"meter\"), so the\n// browser supplies the role + value semantics and AT announces the gauge.\n//   repos/mdn/files/en-us/web/html/reference/elements/meter/index.md\n//     - value/min/max/low/high/optimum attributes (lines 33-48)\n//     - \"Implicit ARIA role: meter\" and \"Permitted ARIA roles: No role\n//       permitted\" (lines 123-134) — so we DO NOT set role/aria-value*; the\n//       element maps value/min/max onto aria-valuenow/min/max itself.\n//\n// APG: WAI-ARIA Meter pattern\n//   repos/aria-practices/content/patterns/meter/meter-pattern.html\n//     - Keyboard Interaction: \"Not applicable\" (line 46) — a meter is not\n//       interactive; no JS keyboard contract.\n//     - Accessible name via aria-labelledby (visible label) or aria-label\n//       (lines 61-64). We pair with a native <label for> in the docs.\n//     - aria-valuetext for human-readable values, e.g. \"50% (6 hours)\n//       remaining\" (lines 56-59) — surfaced via the `valuetext` prop.\n//\n// Cross-browser styling note: WebKit/Blink expose ::-webkit-meter-* and\n// Gecko exposes ::-moz-meter-bar. Both need `appearance: none` to accept\n// custom styles. Those pseudo-elements can't take Tailwind classes, so the\n// fill/track theming lives in app/styles/input.css scoped to\n// [data-slot=\"meter\"]. Tailwind utilities here only size the box.\n\nconst meterBase =\n  \"block h-2 w-full overflow-hidden rounded-full bg-primary/20 align-middle\"\n\nexport function meterClasses(opts?: { class?: ClassValue }): string {\n  return cn(meterBase, opts?.class)\n}\n\ntype MeterProps = {\n  // Current value. Clamped by the browser to [min, max].\n  value: number\n  min?: number\n  max?: number\n  // Lower/upper bounds of the \"low\" and \"high\" zones. Combined with optimum\n  // they drive the optimum / suboptimum / even-less-good fill color.\n  low?: number\n  high?: number\n  optimum?: number\n  id?: string\n  // Free-form units hint. The WHATWG HTML spec notes <meter> has no units\n  // attribute and that title is the only standard way to convey units\n  // (e.g. title=\"gigabytes\"). repos/whatwg-html/source meter section.\n  title?: string\n  // Accessible name — required when there's no linked <label>.\n  ariaLabel?: string\n  ariaLabelledby?: string\n  ariaDescribedby?: string\n  // Human-readable value for AT (e.g. \"12.4 GB of 16 GB\"). Falls back to the\n  // child text content the element already carries.\n  valuetext?: string\n  // Fallback text content for legacy AT and as the visible value in browsers\n  // without <meter> support. Defaults to a \"value/max\" string.\n  children?: Child\n  class?: ClassValue\n\n  // htmx — refresh the gauge from the server.\n  \"hx-get\"?: string\n  \"hx-post\"?: string\n  \"hx-target\"?: string\n  \"hx-swap\"?: string\n  \"hx-trigger\"?: string\n}\n\nexport function Meter(props: MeterProps) {\n  const {\n    value,\n    min = 0,\n    max = 1,\n    low,\n    high,\n    optimum,\n    id,\n    title,\n    ariaLabel,\n    ariaLabelledby,\n    ariaDescribedby,\n    valuetext,\n    children,\n    class: className,\n    ...rest\n  } = props\n  const fallback = children ?? `${value} / ${max}`\n  return (\n    <meter\n      id={id}\n      data-slot=\"meter\"\n      title={title}\n      value={value}\n      min={min}\n      max={max}\n      low={low}\n      high={high}\n      optimum={optimum}\n      aria-label={ariaLabel}\n      aria-labelledby={ariaLabelledby}\n      aria-describedby={ariaDescribedby}\n      aria-valuetext={valuetext}\n      class={meterClasses({ class: className })}\n      {...rest}\n    >\n      {fallback}\n    </meter>\n  )\n}\n"
    },
    {
      "path": "registry/jinja2/meter.html",
      "type": "registry:file",
      "target": "templates/components/meter.html",
      "content": "{# Meter macro — shadcn-htmx, htmx v4 + Tailwind v4.\n   Mirrors registry/ui/meter.tsx. Renders the native <meter> element\n   (implicit role=\"meter\"); cross-browser fill/track theming lives in\n   input.css scoped to [data-slot=\"meter\"].\n\n   Usage:\n       {% from \"components/meter.html\" import meter %}\n       <label for=\"disk\" class=\"text-sm font-medium\">Disk usage</label>\n       {{ meter(id=\"disk\", value=0.62, low=0.25, high=0.85, optimum=0.1,\n                value_text=\"12.4 GB of 16 GB\") }}\n#}\n\n{% macro meter(\n    value=0,\n    min=0,\n    max=1,\n    low=none,\n    high=none,\n    optimum=none,\n    id=none,\n    title=none,\n    aria_label=none,\n    aria_labelledby=none,\n    aria_describedby=none,\n    value_text=none,\n    text=none,\n    extra_class=\"\",\n    **attrs\n) %}\n{%- set base -%}\nblock h-2 w-full overflow-hidden rounded-full bg-primary/20 align-middle\n{%- endset -%}\n<meter class=\"{{ base }} {{ extra_class }}\"\n       {%- if id %} id=\"{{ id }}\"{% endif %}\n       {#- title is the spec-sanctioned way to convey units, e.g. \"gigabytes\" #}\n       {%- if title %} title=\"{{ title }}\"{% endif %}\n       value=\"{{ value }}\" min=\"{{ min }}\" max=\"{{ max }}\"\n       {%- if low is not none %} low=\"{{ low }}\"{% endif %}\n       {%- if high is not none %} high=\"{{ high }}\"{% endif %}\n       {%- if optimum is not none %} optimum=\"{{ optimum }}\"{% endif %}\n       {%- if aria_label %} aria-label=\"{{ aria_label }}\"{% endif %}\n       {%- if aria_labelledby %} aria-labelledby=\"{{ aria_labelledby }}\"{% endif %}\n       {%- if aria_describedby %} aria-describedby=\"{{ aria_describedby }}\"{% endif %}\n       {%- if value_text %} aria-valuetext=\"{{ value_text }}\"{% endif %}\n       data-slot=\"meter\"\n       {%- for k, v in attrs.items() %} {{ k|replace('_', '-') }}=\"{{ v }}\"{% endfor -%}\n  >{{ text if text is not none else (value ~ ' / ' ~ max) }}</meter>\n{% endmacro %}\n"
    },
    {
      "path": "registry/go-templates/meter.tmpl",
      "type": "registry:file",
      "target": "components/meter.tmpl",
      "content": "{{/*\n  Meter template — shadcn-htmx, htmx v4 + Tailwind v4.\n  Mirrors registry/ui/meter.tsx. Renders the native <meter> element\n  (implicit role=\"meter\"); fill/track theming lives in input.css scoped\n  to [data-slot=\"meter\"].\n\n  Usage:\n\n      {{template \"meter\" (dict\n          \"ID\" \"disk\" \"Value\" 0.62 \"Low\" 0.25 \"High\" 0.85 \"Optimum\" 0.1\n          \"ValueText\" \"12.4 GB of 16 GB\")}}\n\n  Low / High / Optimum are optional; pass them only when zoning the gauge.\n*/}}\n\n{{define \"meter\"}}\n{{- $base := \"block h-2 w-full overflow-hidden rounded-full bg-primary/20 align-middle\" -}}\n{{- $value := or .Value 0 -}}\n{{- $min := or .Min 0 -}}\n{{- $max := or .Max 1 -}}\n{{- $text := or .Text (printf \"%v / %v\" $value $max) -}}\n<meter class=\"{{$base}}{{if .Class}} {{.Class}}{{end}}\"\n       {{- if .ID}} id=\"{{.ID}}\"{{end}}\n       {{- /* title: spec-sanctioned way to convey units, e.g. \"gigabytes\" */}}\n       {{- if .Title}} title=\"{{.Title}}\"{{end}}\n       value=\"{{$value}}\" min=\"{{$min}}\" max=\"{{$max}}\"\n       {{- if .Low}} low=\"{{.Low}}\"{{end}}\n       {{- if .High}} high=\"{{.High}}\"{{end}}\n       {{- if .Optimum}} optimum=\"{{.Optimum}}\"{{end}}\n       {{- if .AriaLabel}} aria-label=\"{{.AriaLabel}}\"{{end}}\n       {{- if .AriaLabelledby}} aria-labelledby=\"{{.AriaLabelledby}}\"{{end}}\n       {{- if .AriaDescribedby}} aria-describedby=\"{{.AriaDescribedby}}\"{{end}}\n       {{- if .ValueText}} aria-valuetext=\"{{.ValueText}}\"{{end}}\n       data-slot=\"meter\"\n       {{- range $k, $v := .Attrs}} {{$k}}=\"{{$v}}\"{{end -}}\n  >{{$text}}</meter>\n{{end}}\n"
    },
    {
      "path": "registry/phoenix/meter.ex",
      "type": "registry:file",
      "target": "lib/my_app_web/components/meter.ex",
      "content": "defmodule ShadcnHtmx.Components.Meter do\n  @moduledoc \"\"\"\n  Meter — shadcn-htmx, htmx v4 + Tailwind v4 for Phoenix.\n\n  Renders the native `<meter>` element (implicit `role=\"meter\"`) — a gauge\n  of a value within a known range (battery, disk usage, score), NOT task\n  progress. For progress use the Progress component instead.\n\n  `low` / `high` / `optimum` drive the fill color via the cross-browser\n  meter pseudo-elements styled in input.css ([data-slot=\"meter\"]).\n\n  ## Examples\n\n      <label for=\"disk\" class=\"text-sm font-medium\">Disk usage</label>\n      <.meter id=\"disk\" value={0.62} low={0.25} high={0.85} optimum={0.1}\n        value_text=\"12.4 GB of 16 GB\" />\n\n      <.meter value={6} min={0} max={10} aria-label=\"Score\" />\n  \"\"\"\n\n  use Phoenix.Component\n\n  @base \"block h-2 w-full overflow-hidden rounded-full bg-primary/20 align-middle\"\n\n  attr :value, :float, default: 0.0\n  attr :min, :float, default: 0.0\n  attr :max, :float, default: 1.0\n  attr :low, :float, default: nil\n  attr :high, :float, default: nil\n  attr :optimum, :float, default: nil\n  attr :value_text, :string, default: nil\n  attr :text, :string, default: nil\n  attr :class, :string, default: nil\n\n  # title is the spec-sanctioned way to convey units on a meter, e.g.\n  # title=\"gigabytes\" (WHATWG HTML: <meter> has no units attribute).\n  attr :rest, :global,\n    include:\n      ~w(hx-get hx-post hx-put hx-patch hx-target hx-swap hx-trigger hx-vals hx-include\n         id title aria-label aria-labelledby aria-describedby)\n\n  def meter(assigns) do\n    assigns =\n      assigns\n      |> assign(:base, @base)\n      |> assign(:body, assigns.text || \"#{assigns.value} / #{assigns.max}\")\n\n    ~H\"\"\"\n    <meter\n      class={[@base, @class]}\n      value={@value}\n      min={@min}\n      max={@max}\n      low={@low}\n      high={@high}\n      optimum={@optimum}\n      aria-valuetext={@value_text}\n      data-slot=\"meter\"\n      {@rest}\n    >{@body}</meter>\n    \"\"\"\n  end\nend\n"
    },
    {
      "path": "registry/html/meter.html",
      "type": "registry:file",
      "target": "snippets/meter.html",
      "content": "<!--\n  shadcn-htmx — raw HTML meter snippets.\n\n  Mirrors registry/ui/meter.tsx. The native <meter> element carries the\n  implicit role=\"meter\" (do NOT add role/aria-value*; the browser maps\n  value/min/max onto aria-valuenow/min/max). Cross-browser fill + track\n  theming lives in input.css scoped to [data-slot=\"meter\"]; these snippets\n  only size the box with Tailwind utilities.\n\n  BASE: block h-2 w-full overflow-hidden rounded-full bg-primary/20 align-middle\n\n  Pair every <meter> with an accessible name — a linked <label for> (best)\n  or aria-label.\n-->\n\n<!-- Basic — value within a 0..1 range, labelled by a visible <label> -->\n<label for=\"battery\" class=\"text-sm font-medium\">Battery</label>\n<meter id=\"battery\" data-slot=\"meter\" value=\"0.75\"\n       class=\"block h-2 w-full overflow-hidden rounded-full bg-primary/20 align-middle\">75%</meter>\n\n<!-- Zoned — low/high/optimum color the fill (good / warning / danger).\n     title carries free-form units: the only spec-sanctioned units channel\n     for <meter> (WHATWG HTML — <meter> has no units attribute). -->\n<label for=\"disk\" class=\"text-sm font-medium\">Disk usage</label>\n<meter id=\"disk\" data-slot=\"meter\" value=\"0.62\" min=\"0\" max=\"1\"\n       low=\"0.25\" high=\"0.85\" optimum=\"0.1\" aria-valuetext=\"12.4 GB of 16 GB\"\n       title=\"gigabytes\"\n       class=\"block h-2 w-full overflow-hidden rounded-full bg-primary/20 align-middle\">12.4 GB of 16 GB</meter>\n\n<!-- Custom range + aria-label (no visible label) -->\n<meter data-slot=\"meter\" value=\"6\" min=\"0\" max=\"10\" low=\"3\" high=\"8\" optimum=\"10\"\n       aria-label=\"Exam score\"\n       class=\"block h-2 w-full overflow-hidden rounded-full bg-primary/20 align-middle\">6 / 10</meter>\n"
    }
  ]
}
