{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"icon-tile","type":"registry:ui","title":"Square container that gives icons a consistent surface","description":"Square container that gives icons a consistent surface","dependencies":["class-variance-authority","radix-ui"],"registryDependencies":[],"files":[{"path":"icon-tile.tsx","type":"registry:ui","content":"// Title: Icon Tile\n// Description: Square container that gives icons a consistent surface\n\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\n/**\n * CSS variable architecture:\n *\n * The root owns four variables so every part of the tile stays in proportion\n * and stays overridable from a single `className`:\n *\n * --icon-tile-size tile width/height\n * --icon-tile-icon-size glyph size applied to child svgs\n * --icon-tile-radius corner radius (also drives the nested inner card)\n * --icon-tile-inset gap between the outer ring and the inner card\n *\n * The `frame` and `soft` variants paint their inner card with an `::after`\n * pseudo element instead of a wrapper node. `isolate` makes the root a stacking\n * context, so the negative z-index pseudo paints above the root background but\n * below the in-flow icon - no extra DOM, and `asChild` composition keeps working.\n *\n * Tone: `soft` and `solid` derive every fill and border from `currentColor`, so\n * a single text color class (e.g. `text-success`) retints the whole tile. They\n * default to `text-primary`; override it to recolor without touching internals.\n */\nconst iconTileVariants = cva(\n [\n \"relative inline-flex shrink-0 items-center justify-center align-middle\",\n \"size-(--icon-tile-size) rounded-(--icon-tile-radius)\",\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=size-])]:size-(--icon-tile-icon-size)\",\n ],\n {\n variants: {\n variant: {\n /** Plain bordered surface. The quiet default for list rows and toolbars. */\n outline: \"border border-border bg-background dark:bg-input/32\",\n /** Raised muted fill with a background-colored ring. Reads as a physical chip. */\n elevated:\n \"border-2 border-background bg-muted text-accent-foreground shadow-[0_1px_3px_0_rgb(0_0_0/0.14)] dark:border\",\n /**\n * Tinted double container: an opacity-filled outer ring with no border\n * around a bordered inner card, all derived from `currentColor`. The\n * quiet, colorful sibling of `frame`. Retint with a text color class.\n */\n soft: [\n \"isolate p-(--icon-tile-inset) text-primary bg-current/10\",\n \"after:absolute after:-z-10 after:inset-(--icon-tile-inset)\",\n \"after:rounded-[calc(var(--icon-tile-radius)-var(--icon-tile-inset))]\",\n \"after:border after:border-current/20 after:bg-current/5\",\n ],\n /** Filled tone with a contrasting glyph. Retint with `bg-*` + a text color. */\n solid: \"bg-primary text-primary-foreground\",\n /** Double container - a muted ring around an inset card, matching Frame. */\n frame: [\n \"isolate border border-border bg-muted/50 p-(--icon-tile-inset)\",\n \"after:absolute after:-z-10 after:inset-(--icon-tile-inset)\",\n \"after:rounded-[calc(var(--icon-tile-radius)-var(--icon-tile-inset))]\",\n \"after:border after:border-border after:bg-card after:shadow-xs\",\n ],\n },\n size: {\n xs: \"[--icon-tile-size:--spacing(6)] [--icon-tile-icon-size:--spacing(3.5)] [--icon-tile-inset:--spacing(0.5)]\",\n sm: \"[--icon-tile-size:--spacing(8)] [--icon-tile-icon-size:--spacing(4)] [--icon-tile-inset:--spacing(0.5)]\",\n default:\n \"[--icon-tile-size:--spacing(10)] [--icon-tile-icon-size:--spacing(4.5)] [--icon-tile-inset:--spacing(0.75)]\",\n lg: \"[--icon-tile-size:--spacing(12)] [--icon-tile-icon-size:--spacing(5.5)] [--icon-tile-inset:--spacing(0.75)]\",\n xl: \"[--icon-tile-size:--spacing(14)] [--icon-tile-icon-size:--spacing(7)] [--icon-tile-inset:--spacing(1)]\",\n },\n /**\n * `default`: active style radius. `full`: circular.\n * The plain value is the fallback outside a style scope; the `style-*`\n * tokens win by specificity inside one, and survive the registry\n * transform as the single resolved value per generated style.\n */\n radius: {\n default:\n \"[--icon-tile-radius:var(--radius-md)] [--icon-tile-radius:var(--radius-2xl)]\",\n full: \"[--icon-tile-radius:calc(infinity*1px)]\",\n },\n },\n defaultVariants: {\n variant: \"outline\",\n size: \"default\",\n radius: \"default\",\n },\n }\n)\n\ninterface IconTileProps\n extends React.ComponentProps<\"span\">, VariantProps {\n asChild?: boolean\n}\n\nfunction IconTile({\n className,\n variant = \"outline\",\n size = \"default\",\n radius = \"default\",\n asChild = false,\n ...props\n}: IconTileProps) {\n const Comp = asChild ? Slot.Root : \"span\"\n\n return (\n \n )\n}\n\nexport { IconTile, iconTileVariants, type IconTileProps }","target":"components/neui/icon-tile.tsx"}]}