{
"files": [
{
"content": "defmodule Shadix.Components.Button do\n @moduledoc \"\"\"\n A button styled with the shadcn variant/size system.\n\n Renders a `<button>` carrying `data-slot=\"button\"` plus `data-variant` and\n `data-size` for stable styling/targeting. Caller-supplied `class` is appended\n last; Tailwind cascade layers ensure it wins over the defaults.\n \"\"\"\n use Phoenix.Component\n\n import Shadix.Cn\n\n @base \"inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none active:not-aria-[haspopup]:translate-y-px focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\"\n\n @variants %{\n \"default\" => \"bg-primary text-primary-foreground hover:bg-primary/90\",\n \"destructive\" =>\n \"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40\",\n \"outline\" =>\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n \"secondary\" => \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n \"ghost\" => \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n \"link\" => \"text-primary underline-offset-4 hover:underline\"\n }\n\n @sizes %{\n \"default\" => \"h-9 px-4 py-2 has-[>svg]:px-3\",\n \"sm\" => \"h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5\",\n \"lg\" => \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n \"icon\" => \"size-9\"\n }\n\n attr(:variant, :string,\n default: \"default\",\n values: ~w(default secondary destructive outline ghost link)\n )\n\n attr(:size, :string, default: \"default\", values: ~w(default sm lg icon))\n attr(:type, :string, default: \"button\")\n attr(:class, :string, default: nil)\n attr(:rest, :global, include: ~w(disabled form name value autofocus))\n slot(:inner_block, required: true)\n\n def button(assigns) do\n class =\n cn([\n @base,\n Map.fetch!(@variants, assigns.variant),\n Map.fetch!(@sizes, assigns.size),\n assigns.class\n ])\n\n assigns = assign(assigns, :computed_class, class)\n\n ~H\"\"\"\n <button\n type={@type}\n data-slot=\"button\"\n data-variant={@variant}\n data-size={@size}\n class={@computed_class}\n {@rest}\n >\n {render_slot(@inner_block)}\n </button>\n \"\"\"\n end\nend\n",
"path": "button.ex"
}
],
"hooks": [],
"name": "button",
"npm_deps": [],
"registry_deps": [
"cn"
]
}