{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"icon-button","type":"registry:ui","title":"IconButton","description":"Square or circular icon-only button built on Button, with a required accessible label","author":"fancy-ui <https://fancy-ui.rama.app>","categories":["actions"],"registryDependencies":["https://fancy-ui.rama.app/r/button.json","https://fancy-ui.rama.app/r/internals-dom.json","https://fancy-ui.rama.app/r/sound.json","https://fancy-ui.rama.app/r/utils.json"],"files":[{"path":"react/src/components/icon-button/IconButton.tsx","content":"\"use client\";\n\nimport { forwardRef, type MouseEvent, type ReactNode } from \"react\";\nimport { cn } from \"../../utils\";\nimport { Button, type ButtonProps } from \"../button/Button\";\nimport type { ButtonVariant, ButtonSize } from \"../button/types\";\n\n/** `\"square\"` keeps the size's own radius; `\"circle\"` rounds it fully. */\nexport type IconButtonShape = \"square\" | \"circle\";\n\nexport interface IconButtonProps extends Omit<\n\tButtonProps,\n\t\"iconStart\" | \"iconEnd\" | \"fullWidth\" | \"label\" | \"children\"\n> {\n\t/**\n\t * Accessible name. Required, not optional: an icon-only control has no\n\t * visible text to fall back on, so without this the control would have\n\t * no name at all in the accessibility tree.\n\t */\n\tlabel: string;\n\t/** Visual treatment, forwarded to the underlying Button. */\n\tvariant?: ButtonVariant;\n\t/** Sets the button's square footprint (30 / 36 / 42px) and its resting radius. */\n\tsize?: ButtonSize;\n\t/** Square keeps the size's own radius; circle rounds it fully. */\n\tshape?: IconButtonShape;\n\t/** Native `type`. Ignored once `href` is set — an anchor has no `type`. */\n\ttype?: \"button\" | \"submit\" | \"reset\";\n\t/** Greys the button out and makes it inert to pointer and keyboard activation. */\n\tdisabled?: boolean;\n\t/**\n\t * Swaps the icon for a spinner and marks the control `aria-busy`, without\n\t * dimming it the way `disabled` does. Activation is blocked exactly like\n\t * `disabled`.\n\t */\n\tloading?: boolean;\n\t/** Renders an `<a>` instead of a `<button>` when set. */\n\thref?: string;\n\t/** Anchor `target`. `\"_blank\"` forces a safe `rel` regardless of what `rel` says. */\n\ttarget?: string;\n\t/** Anchor `rel`. Widened, never narrowed — see `target`. */\n\trel?: string;\n\t/** Fires on activation. Never called while `disabled` or `loading`. */\n\tonClick?: (event: MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void;\n\t/** The icon, rendered centred with no label alongside it. */\n\tchildren?: ReactNode;\n\t/** Additional CSS classes. */\n\tclassName?: string;\n\t/**\n\t * Plays the `hover` cue on mouse/pen pointer enter and the `press` cue on\n\t * click. Off by default; only audible once the user has enabled sound.\n\t */\n\tsound?: boolean;\n}\n\n// A fixed square replaces Button's own horizontal padding — an icon-only\n// control centres on its glyph rather than growing to fit a label. Each\n// size's radius already matches Button's own scale, so only `circle`\n// below needs to override it.\nconst SIZE_CLASSES: Record<ButtonSize, string> = {\n\tsm: \"size-[30px] px-0 py-0\",\n\tmd: \"size-[36px] px-0 py-0\",\n\tlg: \"size-[42px] px-0 py-0\",\n};\n\n// Ghost reads as more subtle icon-only: with no label to carry visual\n// weight, it rests at the muted tone rather than Button's own\n// full-strength foreground, and only brightens on hover/focus.\nconst VARIANT_EXTRA_CLASSES: Partial<Record<ButtonVariant, string>> = {\n\tghost: \"text-muted-foreground\",\n};\n\nexport const IconButton = forwardRef<HTMLButtonElement | HTMLAnchorElement, IconButtonProps>(\n\t(\n\t\t{\n\t\t\tlabel,\n\t\t\tvariant = \"outline\",\n\t\t\tsize = \"md\",\n\t\t\tshape = \"square\",\n\t\t\ttype = \"button\",\n\t\t\tdisabled = false,\n\t\t\tloading = false,\n\t\t\thref = undefined,\n\t\t\ttarget = undefined,\n\t\t\trel = undefined,\n\t\t\tchildren,\n\t\t\tclassName,\n\t\t\tsound = false,\n\t\t\t...restProps\n\t\t},\n\t\tref\n\t) => {\n\t\tconst classes = cn(\n\t\t\t\"ft-icon-btn\",\n\t\t\tSIZE_CLASSES[size],\n\t\t\tshape === \"circle\" && \"rounded-full\",\n\t\t\tVARIANT_EXTRA_CLASSES[variant],\n\t\t\tclassName\n\t\t);\n\n\t\treturn (\n\t\t\t<Button\n\t\t\t\t{...restProps}\n\t\t\t\tref={ref}\n\t\t\t\tvariant={variant}\n\t\t\t\tsize={size}\n\t\t\t\ttype={type}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tloading={loading}\n\t\t\t\thref={href}\n\t\t\t\ttarget={target}\n\t\t\t\trel={rel}\n\t\t\t\tlabel={label}\n\t\t\t\tsound={sound}\n\t\t\t\ticonStart={children}\n\t\t\t\tclassName={classes}\n\t\t\t/>\n\t\t);\n\t}\n);\n\nIconButton.displayName = \"IconButton\";\n","type":"registry:ui","target":"@ui/fancy/components/icon-button/IconButton.tsx"},{"path":"react/src/components/icon-button/index.ts","content":"\"use client\";\n\nexport { IconButton } from \"./IconButton\";\nexport type { IconButtonProps, IconButtonShape } from \"./IconButton\";\n","type":"registry:ui","target":"@ui/fancy/components/icon-button/index.ts"}],"meta":{"license":"MIT","package":"fancy-ui-react","version":"0.7.0","source":"https://fancy-ui.rama.app/docs/components/icon-button?framework=react"}}