Skip to main content

priv/registry/checkbox.json

{
  "files": [
    {
      "content": "defmodule Shadix.Components.Checkbox do\n  @moduledoc \"\"\"\n  Checkbox component adapted from shadcn/ui (new-york-v4).\n\n  Renders a native `<input type=\"checkbox\">` (with a preceding hidden `\"false\"`\n  input so an unchecked box still submits a value) and is field-aware: it derives\n  its `id`, `name`, `value`, and `errors` from a `Phoenix.HTML.FormField`.\n\n  The box is the `appearance-none` input; the check mark is a sibling `<svg>`\n  overlay shown via `peer-checked:visible`. It uses `text-primary-foreground`\n  (via `currentColor`) so the check contrasts correctly in both light and dark\n  mode — unlike a fixed-colour background-image. No JavaScript, no Radix.\n\n  Caller-supplied `class` is appended last (to the input); Tailwind cascade\n  layers ensure it wins over the defaults.\n  \"\"\"\n  use Phoenix.Component\n\n  import Shadix.Cn\n  import Shadix.Form\n\n  @base \"peer size-4 shrink-0 appearance-none rounded-[4px] border border-input bg-transparent shadow-xs transition-shadow outline-none checked:border-primary checked:bg-primary dark:checked:bg-primary focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:ring-destructive/40\"\n\n  attr(:field, Phoenix.HTML.FormField, required: true)\n  attr(:class, :string, default: nil)\n  attr(:rest, :global, include: ~w(disabled required readonly autofocus))\n\n  def checkbox(assigns) do\n    %{id: id, name: name, value: value, errors: errors} = field_attrs(assigns.field)\n    assigns = assign(assigns, id: id, name: name, value: value, errors: errors)\n    assigns = assign(assigns, :checked, Phoenix.HTML.Form.normalize_value(\"checkbox\", value))\n    assigns = assign(assigns, :computed_class, cn([@base, assigns.class]))\n\n    ~H\"\"\"\n    <input type=\"hidden\" name={@name} value=\"false\" />\n    <span class=\"relative inline-grid size-4 shrink-0 *:[grid-area:1/1]\">\n      <input\n        type=\"checkbox\"\n        data-slot=\"checkbox\"\n        id={@id}\n        name={@name}\n        value=\"true\"\n        checked={@checked}\n        class={@computed_class}\n        aria-invalid={(@errors != [] && \"true\") || nil}\n        aria-describedby={(@errors != [] && \"#{@id}-error\") || nil}\n        {@rest}\n      />\n      <svg\n        class=\"pointer-events-none invisible size-3.5 place-self-center text-primary-foreground peer-checked:visible\"\n        viewBox=\"0 0 24 24\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        stroke-width=\"3\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n        aria-hidden=\"true\"\n      >\n        <path d=\"M20 6 9 17l-5-5\" />\n      </svg>\n    </span>\n    <p\n      :if={@errors != []}\n      id={\"#{@id}-error\"}\n      data-slot=\"form-message\"\n      class=\"text-destructive text-sm mt-1\"\n    >\n      {List.first(@errors)}\n    </p>\n    \"\"\"\n  end\nend\n",
      "path": "checkbox.ex"
    }
  ],
  "hooks": [],
  "name": "checkbox",
  "npm_deps": [],
  "registry_deps": [
    "cn",
    "form"
  ]
}