# Icons

A typed icon component with size variants and a custom icon set.

## Installation

```bash
npx shadcn@latest add https://reactdocs.canceydejean.dev/r/icons.json
```

[Registry JSON](https://reactdocs.canceydejean.dev/r/icons.json)

## Preview

```tsx
import Icon from "@/components/ui/icons/icon/icon";

export function Preview() {
  return <Icon icon="aperture" size="lg" />;
}
```


## Source

### index.tsx

```tsx
import {
  Aperture,
  ArrowLeft,
  ArrowRight,
  Check,
  ChevronLeft,
  ChevronRight,
  EyeIcon,
  Glasses,
  Layers,
  LucideFeather,
  PlayCircle,
  SearchIcon,
  ShieldCheck,
  ShoppingCart,
  Sun,
  User,
} from "lucide-react";

import Cloud from "./icon-set/cloud";
import KeyRounded from "./icon-set/key-rounded";
import MailRounded from "./icon-set/mail-rounded";
import NavArrow from "./icon-set/nav-arrow";
import XCircleSolid from "./icon-set/x-cirlcle-solid";

export const ICONS = {
  "nav-arrow": NavArrow,
  "x-circle-solid": XCircleSolid,
  cloud: Cloud,
  "key-rounded": KeyRounded,
  "mail-rounded": MailRounded,
  "arrow-right": ArrowRight,
  "arrow-left": ArrowLeft,
  sun: Sun,
  check: Check,
  "shield-check": ShieldCheck,
  glasses: Glasses,
  user: User,
  eye: EyeIcon,
  "chevron-left": ChevronLeft,
  "chevron-right": ChevronRight,
  "shopping-cart": ShoppingCart,
  search: SearchIcon,
  aperture: Aperture,
  feather: LucideFeather,
  "play-circle": PlayCircle,
  layers: Layers,
};
```


### icon/icon.tsx

```tsx
import { cn } from "cn";

import { ICONS } from "../index";
import type { IconProps } from "./icon.types";
import { iconVariants } from "./icon.variants";

export default function Icon({ icon, size, className, ...props }: IconProps) {
  const IconComponent = ICONS[icon];

  return (
    <IconComponent
      className={cn(iconVariants({ size }), className)}
      {...props}
    />
  );
}
```


### icon/icon.types.tsx

```tsx
import type { VariantProps } from "class-variance-authority";
import type { ComponentProps } from "react";

import type { ICONS } from "../index";
import type { iconVariants } from "./icon.variants";

export type IconVariants = VariantProps<typeof iconVariants>;
export type IconKey = keyof typeof ICONS;

export type BaseIconProps = ComponentProps<"svg">;

export type IconProps = BaseIconProps & {
  icon: IconKey;
  size?: IconVariants["size"];
};
```


### icon/icon.variants.ts

```ts
import { cva } from "class-variance-authority";

import { cn } from "cn"

const iconBase = cn("");

const iconConfig = {
  variants: {
    size: {
      sm: "size-3",
      md: "size-4",
      lg: "size-6",
    },
  },
  compoundVariants: [],

  defaultVariants: {
    size: "md" as const,
  },
} as const;

export const iconCva = cva(iconBase, {
  ...iconConfig,
  compoundVariants: [...iconConfig.compoundVariants],
});

// Export the size variants
export const ICON_SIZES = Object.keys(
  iconConfig.variants.size,
) as (keyof typeof iconConfig.variants.size)[];

export const iconVariants = iconCva;
```


### icon-grid.tsx

```tsx
import type { ComponentProps } from "react";

import { cn } from "cn";

export default function IconGrid({
  className,
  ...props
}: ComponentProps<"div">) {
  return (
    <div className={cn("grid grid-cols-12 gap-4", className)} {...props} />
  );
}
```


### icon-gallery.tsx

```tsx
import { Check, Search } from "lucide-react";
import { useCallback, useEffect, useRef, useState } from "react";

import { ICONS } from "./";
import IconGrid from "./icon-grid";
import Icon from "./icon/icon";
import type { IconKey } from "./icon/icon.types";

const ICON_LIST = Object.keys(ICONS) as IconKey[];

/* ─── Helper: debounce hook ─── */
function useDebouncedValue<T>(value: T, delay: number): T {
  const [debounced, setDebounced] = useState(value);

  useEffect(() => {
    const id = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(id);
  }, [value, delay]);

  return debounced;
}

/* ─── Icon card with copy-to-clipboard ─── */
function IconCard({ name }: { name: IconKey }) {
  const ref = useRef<HTMLDivElement>(null);
  const [copied, setCopied] = useState(false);

  const handleCopy = useCallback(() => {
    const svg = ref.current?.querySelector("svg");
    if (!svg) return;

    const svgString = svg.outerHTML;

    void navigator.clipboard.writeText(svgString).then(
      () => {
        setCopied(true);
        setTimeout(() => setCopied(false), 1500);
      },
      () => {
        /* clipboard API may not be available in all storybook envs */
      },
    );
  }, []);

  return (
    <button
      type="button"
      onClick={handleCopy}
      className="group relative flex cursor-pointer flex-col items-center gap-3 rounded-xl border border-border bg-background p-5 transition-all duration-200 hover:border-primary/30 hover:shadow-[0_2px_12px_rgba(0,0,0,0.06)] active:scale-[0.97]"
    >
      {/* Copied badge */}
      <div
        className={`pointer-events-none absolute inset-0 z-10 flex items-center justify-center rounded-xl bg-primary/95 transition-all duration-200 ${
          copied ? "scale-100 opacity-100" : "scale-95 opacity-0"
        }`}
      >
        <div className="flex items-center gap-1.5 text-primary-foreground">
          <Check className="size-3.5" strokeWidth={2.5} />
          <span className="text-xs font-semibold tracking-wide">Copied</span>
        </div>
      </div>

      {/* Icon */}
      <div
        ref={ref}
        className="flex size-10 items-center justify-center text-foreground transition-colors duration-200 group-hover:text-primary"
      >
        <Icon icon={name} size="lg" />
      </div>

      {/* Label */}
      <span className="w-full truncate text-center text-[11px] font-medium tracking-tight text-muted-foreground transition-colors duration-200 group-hover:text-foreground">
        {name}
      </span>

      {/* Hover hint */}
      <span className="absolute top-2 right-2 text-[9px] font-medium tracking-widest text-muted-foreground uppercase opacity-0 transition-opacity duration-200 group-hover:opacity-100">
        SVG
      </span>
    </button>
  );
}

export function IconGallery() {
  const [query, setQuery] = useState("");
  const debouncedQuery = useDebouncedValue(query, 200);

  const filtered = ICON_LIST.filter((name) =>
    name.toLowerCase().includes(debouncedQuery.toLowerCase()),
  );

  return (
    <div className="flex w-full flex-col gap-6">
      {/* Search */}
      <div className="relative">
        <Search className="pointer-events-none absolute top-1/2 left-3.5 size-4 -translate-y-1/2 text-muted-foreground" />
        <input
          type="text"
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          placeholder="Search icons..."
          className="h-11 w-full rounded-xl border border-border bg-background pr-4 pl-10 text-sm text-foreground transition-colors outline-none placeholder:text-muted-foreground focus:border-primary/40 focus:ring-2 focus:ring-primary/10"
        />
        {query && (
          <button
            type="button"
            onClick={() => setQuery("")}
            className="absolute top-1/2 right-3.5 -translate-y-1/2 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground"
          >
            Clear
          </button>
        )}
      </div>

      {/* Count */}
      <div className="flex items-center justify-between">
        <span className="text-xs font-medium text-muted-foreground">
          {filtered.length} icon{filtered.length !== 1 ? "s" : ""}
          {debouncedQuery && <span className="text-foreground"> matching "{debouncedQuery}"</span>}
        </span>
        <span className="text-[10px] font-medium tracking-widest text-muted-foreground/60 uppercase">
          Click to copy SVG
        </span>
      </div>

      {/* Grid */}
      {filtered.length > 0 ? (
        <IconGrid className="grid-cols-4 gap-3 sm:grid-cols-6 md:grid-cols-8 lg:grid-cols-8">
          {filtered.map((name) => (
            <IconCard key={name} name={name} />
          ))}
        </IconGrid>
      ) : (
        <div className="flex flex-col items-center justify-center gap-2 rounded-xl border border-dashed border-border py-16">
          <Search className="size-6 text-muted-foreground/40" />
          <p className="text-sm text-muted-foreground">No icons match "{debouncedQuery}"</p>
        </div>
      )}
    </div>
  );
}
```


### icon-set/cloud.tsx

```tsx
import type { SVGProps } from "react";

import { cn } from "cn";

export default function CloudIllustration({
  className,
  ...props
}: SVGProps<SVGSVGElement>) {
  return (
    <svg
      aria-hidden="true"
      viewBox="0 0 154 121"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      className={cn(className)}
      {...props}
    >
      <circle cx="77" cy="52" r="52" fill="#F5F5F5" />
      <g filter="url(#filter0_ddd_1266_30154)">
        <path
          d="M78.6 16C67.8273 16 58.2978 21.3233 52.4987 29.4829C50.605 29.0363 48.6301 28.8 46.6 28.8C32.4615 28.8 21 40.2615 21 54.4C21 68.5385 32.4615 80 46.6 80L110.6 80C122.971 80 133 69.9712 133 57.6C133 45.2288 122.971 35.2 110.6 35.2C109.721 35.2 108.854 35.2506 108.002 35.349C103.098 23.9677 91.7797 16 78.6 16Z"
          fill="#FAFAFA"
        />
        <path
          d="M78.5996 15.5C91.8552 15.5 103.255 23.4366 108.312 34.8145C109.064 34.7397 109.827 34.7002 110.6 34.7002C123.247 34.7002 133.5 44.9525 133.5 57.5996C133.5 70.0492 123.565 80.1785 111.191 80.4922L110.6 80.5H46.5996C32.1853 80.4998 20.5002 68.8147 20.5 54.4004C20.5 39.9859 32.1852 28.3 46.5996 28.2998C48.5525 28.2998 50.4558 28.5168 52.2871 28.9238C58.1932 20.7911 67.7778 15.5001 78.5996 15.5Z"
          stroke="black"
          strokeOpacity="0.08"
        />
        <ellipse
          cx="46.6"
          cy="54.3998"
          rx="25.6"
          ry="25.6"
          fill="url(#paint0_linear_1266_30154)"
        />
        <circle
          cx="78.6"
          cy="48"
          r="32"
          fill="url(#paint1_linear_1266_30154)"
        />
        <ellipse
          cx="110.6"
          cy="57.6002"
          rx="22.4"
          ry="22.4"
          fill="url(#paint2_linear_1266_30154)"
        />
      </g>
      <circle cx="22" cy="19" r="5" fill="#F5F5F5" />
      <circle cx="19" cy="109" r="7" fill="#F5F5F5" />
      <circle cx="146" cy="35" r="7" fill="#F5F5F5" />
      <circle cx="135" cy="8" r="4" fill="#F5F5F5" />
      <foreignObject x="45" y="54" width="64" height="64">
        <div
          style={{
            backdropFilter: "blur(4px)",
            clipPath: "url(#bgblur_0_1266_30154_clip_path)",
            height: "100%",
            width: "100%",
          }}
        ></div>
      </foreignObject>
      <g data-figma-bg-blur-radius="8">
        <path
          d="M53 86C53 72.7452 63.7452 62 77 62C90.2548 62 101 72.7452 101 86C101 99.2548 90.2548 110 77 110C63.7452 110 53 99.2548 53 86Z"
          fill="black"
          fillOpacity="0.2"
        />
        <path
          d="M71 90.9998C71 91.3511 71 91.5268 71.0157 91.6795C71.1457 92.9473 72.0626 93.9945 73.3021 94.291C73.4513 94.3267 73.6255 94.3499 73.9737 94.3963L80.5656 95.2753C82.442 95.5254 83.3803 95.6505 84.1084 95.361C84.7478 95.1068 85.2803 94.6406 85.6168 94.0405C86 93.3569 86 92.4104 86 90.5174V81.4823C86 79.5893 86 78.6428 85.6168 77.9592C85.2803 77.3591 84.7478 76.8929 84.1084 76.6387C83.3803 76.3491 82.442 76.4742 80.5656 76.7244L73.9737 77.6033C73.6255 77.6498 73.4514 77.673 73.3021 77.7087C72.0626 78.0052 71.1457 79.0524 71.0157 80.3202C71 80.4729 71 80.6485 71 80.9998M77 81.9998L81 85.9998M81 85.9998L77 89.9998M81 85.9998H68"
          stroke="white"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        />
      </g>
      <defs>
        <filter
          id="filter0_ddd_1266_30154"
          x="0"
          y="15"
          width="154"
          height="106"
          filterUnits="userSpaceOnUse"
          colorInterpolationFilters="sRGB"
        >
          <feFlood floodOpacity="0" result="BackgroundImageFix" />
          <feColorMatrix
            in="SourceAlpha"
            type="matrix"
            values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
            result="hardAlpha"
          />
          <feMorphology
            radius="1.5"
            operator="erode"
            in="SourceAlpha"
            result="effect1_dropShadow_1266_30154"
          />
          <feOffset dy="3" />
          <feGaussianBlur stdDeviation="1.5" />
          <feColorMatrix
            type="matrix"
            values="0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.04 0"
          />
          <feBlend
            mode="normal"
            in2="BackgroundImageFix"
            result="effect1_dropShadow_1266_30154"
          />
          <feColorMatrix
            in="SourceAlpha"
            type="matrix"
            values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
            result="hardAlpha"
          />
          <feMorphology
            radius="4"
            operator="erode"
            in="SourceAlpha"
            result="effect2_dropShadow_1266_30154"
          />
          <feOffset dy="8" />
          <feGaussianBlur stdDeviation="4" />
          <feColorMatrix
            type="matrix"
            values="0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.03 0"
          />
          <feBlend
            mode="normal"
            in2="effect1_dropShadow_1266_30154"
            result="effect2_dropShadow_1266_30154"
          />
          <feColorMatrix
            in="SourceAlpha"
            type="matrix"
            values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
            result="hardAlpha"
          />
          <feMorphology
            radius="4"
            operator="erode"
            in="SourceAlpha"
            result="effect3_dropShadow_1266_30154"
          />
          <feOffset dy="20" />
          <feGaussianBlur stdDeviation="12" />
          <feColorMatrix
            type="matrix"
            values="0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.08 0"
          />
          <feBlend
            mode="normal"
            in2="effect2_dropShadow_1266_30154"
            result="effect3_dropShadow_1266_30154"
          />
          <feBlend
            mode="normal"
            in="SourceGraphic"
            in2="effect3_dropShadow_1266_30154"
            result="shape"
          />
        </filter>
        <clipPath
          id="bgblur_0_1266_30154_clip_path"
          transform="translate(-45 -54)"
        >
          <path d="M53 86C53 72.7452 63.7452 62 77 62C90.2548 62 101 72.7452 101 86C101 99.2548 90.2548 110 77 110C63.7452 110 53 99.2548 53 86Z" />
        </clipPath>
        <linearGradient
          id="paint0_linear_1266_30154"
          x1="26.9429"
          y1="37.4855"
          x2="72.2"
          y2="79.9998"
          gradientUnits="userSpaceOnUse"
        >
          <stop stopColor="#E9EAEB" />
          <stop offset="0.350715" stopColor="#FAFAFA" />
        </linearGradient>
        <linearGradient
          id="paint1_linear_1266_30154"
          x1="54.0286"
          y1="26.8571"
          x2="110.6"
          y2="80"
          gradientUnits="userSpaceOnUse"
        >
          <stop stopColor="#E9EAEB" />
          <stop offset="0.350715" stopColor="#FAFAFA" />
        </linearGradient>
        <linearGradient
          id="paint2_linear_1266_30154"
          x1="93.4"
          y1="42.8002"
          x2="133"
          y2="80.0002"
          gradientUnits="userSpaceOnUse"
        >
          <stop stopColor="#E9EAEB" />
          <stop offset="0.350715" stopColor="#FAFAFA" />
        </linearGradient>
      </defs>
    </svg>
  );
}
```


### icon-set/key-rounded.tsx

```tsx
import type { SVGProps } from "react";

import { cn } from "cn";

export default function KeyRounded({
  className,
  ...props
}: SVGProps<SVGSVGElement>) {
  return (
    <svg
      aria-hidden="true"
      viewBox="0 0 60 60"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      className={cn("size-15", className)}
      {...props}
    >
      <g filter="url(#filter0_dii_5023_372977)">
        <path
          d="M2 13C2 6.37258 7.37258 1 14 1H46C52.6274 1 58 6.37258 58 13V45C58 51.6274 52.6274 57 46 57H14C7.37258 57 2 51.6274 2 45V13Z"
          fill="white"
        />
        <path
          d="M14 1.5H46C52.3513 1.5 57.5 6.64873 57.5 13V45C57.5 51.3513 52.3513 56.5 46 56.5H14C7.64873 56.5 2.5 51.3513 2.5 45V13C2.5 6.64873 7.64873 1.5 14 1.5Z"
          stroke="#D5D7DA"
        />
        <path
          d="M35.8333 25.4999C35.8333 24.9028 35.6055 24.3057 35.1499 23.8501C34.6943 23.3945 34.0972 23.1667 33.5 23.1667M33.5 32.5C37.366 32.5 40.5 29.366 40.5 25.5C40.5 21.634 37.366 18.5 33.5 18.5C29.634 18.5 26.5 21.634 26.5 25.5C26.5 25.8193 26.5214 26.1336 26.5628 26.4415C26.6309 26.948 26.6649 27.2013 26.642 27.3615C26.6181 27.5284 26.5877 27.6184 26.5055 27.7655C26.4265 27.9068 26.2873 28.046 26.009 28.3243L20.0467 34.2866C19.845 34.4884 19.7441 34.5893 19.6719 34.707C19.608 34.8114 19.5608 34.9252 19.5322 35.0442C19.5 35.1785 19.5 35.3212 19.5 35.6065V37.6333C19.5 38.2867 19.5 38.6134 19.6272 38.863C19.739 39.0825 19.9175 39.261 20.137 39.3728C20.3866 39.5 20.7133 39.5 21.3667 39.5H24.1667V37.1667H26.5V34.8333H28.8333L30.6757 32.991C30.954 32.7127 31.0932 32.5735 31.2345 32.4945C31.3816 32.4123 31.4716 32.3819 31.6385 32.358C31.7987 32.3351 32.052 32.3691 32.5585 32.4372C32.8664 32.4786 33.1807 32.5 33.5 32.5Z"
          stroke="#414651"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        />
      </g>
      <defs>
        <filter
          id="filter0_dii_5023_372977"
          x="0"
          y="0"
          width="60"
          height="60"
          filterUnits="userSpaceOnUse"
          colorInterpolationFilters="sRGB"
        >
          <feFlood floodOpacity="0" result="BackgroundImageFix" />
          <feColorMatrix
            in="SourceAlpha"
            type="matrix"
            values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
            result="hardAlpha"
          />
          <feOffset dy="1" />
          <feGaussianBlur stdDeviation="1" />
          <feColorMatrix
            type="matrix"
            values="0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.05 0"
          />
          <feBlend
            mode="normal"
            in2="BackgroundImageFix"
            result="effect1_dropShadow_5023_372977"
          />
          <feBlend
            mode="normal"
            in="SourceGraphic"
            in2="effect1_dropShadow_5023_372977"
            result="shape"
          />
          <feColorMatrix
            in="SourceAlpha"
            type="matrix"
            values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
            result="hardAlpha"
          />
          <feOffset dy="-2" />
          <feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
          <feColorMatrix
            type="matrix"
            values="0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.05 0"
          />
          <feBlend
            mode="normal"
            in2="shape"
            result="effect2_innerShadow_5023_372977"
          />
          <feColorMatrix
            in="SourceAlpha"
            type="matrix"
            values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
            result="hardAlpha"
          />
          <feMorphology
            radius="1"
            operator="erode"
            in="SourceAlpha"
            result="effect3_innerShadow_5023_372977"
          />
          <feOffset />
          <feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
          <feColorMatrix
            type="matrix"
            values="0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.18 0"
          />
          <feBlend
            mode="normal"
            in2="effect2_innerShadow_5023_372977"
            result="effect3_innerShadow_5023_372977"
          />
        </filter>
      </defs>
    </svg>
  );
}
```


### icon-set/mail-rounded.tsx

```tsx
import type { SVGProps } from "react";

import { cn } from "cn";

export default function MailRounded({
  className,
  ...props
}: SVGProps<SVGSVGElement>) {
  return (
    <svg
      aria-hidden="true"
      viewBox="0 0 60 60"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      className={cn("size-15", className)}
      {...props}
    >
      <g filter="url(#filter0_dii_5023_372979)">
        <path
          d="M2 13C2 6.37258 7.37258 1 14 1H46C52.6274 1 58 6.37258 58 13V45C58 51.6274 52.6274 57 46 57H14C7.37258 57 2 51.6274 2 45V13Z"
          fill="white"
        />
        <path
          d="M14 1.5H46C52.3513 1.5 57.5 6.64873 57.5 13V45C57.5 51.3513 52.3513 56.5 46 56.5H14C7.64873 56.5 2.5 51.3513 2.5 45V13C2.5 6.64873 7.64873 1.5 14 1.5Z"
          stroke="#D5D7DA"
        />
        <path
          d="M18.3335 23.1666L27.8592 29.8346C28.6306 30.3746 29.0163 30.6446 29.4358 30.7492C29.8064 30.8415 30.194 30.8415 30.5645 30.7492C30.984 30.6446 31.3697 30.3746 32.1411 29.8346L41.6668 23.1666M23.9335 38.3333H36.0668C38.027 38.3333 39.0071 38.3333 39.7558 37.9518C40.4144 37.6163 40.9498 37.0808 41.2854 36.4223C41.6668 35.6736 41.6668 34.6935 41.6668 32.7333V25.2666C41.6668 23.3064 41.6668 22.3264 41.2854 21.5777C40.9498 20.9191 40.4144 20.3837 39.7558 20.0481C39.0071 19.6666 38.027 19.6666 36.0668 19.6666H23.9335C21.9733 19.6666 20.9932 19.6666 20.2445 20.0481C19.586 20.3837 19.0505 20.9191 18.715 21.5777C18.3335 22.3264 18.3335 23.3064 18.3335 25.2666V32.7333C18.3335 34.6935 18.3335 35.6736 18.715 36.4223C19.0505 37.0808 19.586 37.6163 20.2445 37.9518C20.9932 38.3333 21.9733 38.3333 23.9335 38.3333Z"
          stroke="#414651"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        />
      </g>
      <defs>
        <filter
          id="filter0_dii_5023_372979"
          x="0"
          y="0"
          width="60"
          height="60"
          filterUnits="userSpaceOnUse"
          colorInterpolationFilters="sRGB"
        >
          <feFlood floodOpacity="0" result="BackgroundImageFix" />
          <feColorMatrix
            in="SourceAlpha"
            type="matrix"
            values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
            result="hardAlpha"
          />
          <feOffset dy="1" />
          <feGaussianBlur stdDeviation="1" />
          <feColorMatrix
            type="matrix"
            values="0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.05 0"
          />
          <feBlend
            mode="normal"
            in2="BackgroundImageFix"
            result="effect1_dropShadow_5023_372979"
          />
          <feBlend
            mode="normal"
            in="SourceGraphic"
            in2="effect1_dropShadow_5023_372979"
            result="shape"
          />
          <feColorMatrix
            in="SourceAlpha"
            type="matrix"
            values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
            result="hardAlpha"
          />
          <feOffset dy="-2" />
          <feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
          <feColorMatrix
            type="matrix"
            values="0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.05 0"
          />
          <feBlend
            mode="normal"
            in2="shape"
            result="effect2_innerShadow_5023_372979"
          />
          <feColorMatrix
            in="SourceAlpha"
            type="matrix"
            values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
            result="hardAlpha"
          />
          <feMorphology
            radius="1"
            operator="erode"
            in="SourceAlpha"
            result="effect3_innerShadow_5023_372979"
          />
          <feOffset />
          <feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
          <feColorMatrix
            type="matrix"
            values="0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.18 0"
          />
          <feBlend
            mode="normal"
            in2="effect2_innerShadow_5023_372979"
            result="effect3_innerShadow_5023_372979"
          />
        </filter>
      </defs>
    </svg>
  );
}
```


### icon-set/nav-arrow.tsx

```tsx
import { cn } from "cn";

export default function NavArrow({
  className,
  ...props
}: React.ComponentProps<"svg">) {
  return (
    <svg
      aria-hidden="true"
      className={cn(className)}
      viewBox="0 0 13 13"
      width="10"
      height="10"
      {...props}
    >
      <path
        d="M1 12L12.5 0.499965"
        stroke="currentColor"
        strokeWidth="1"
        fill="none"
        // className="vector-effect-non-scaling-stroke"
      />
      <path
        d="M1 0.5H12.5V12"
        stroke="currentColor"
        strokeWidth="1"
        fill="none"
        // className="vector-effect-non-scaling-stroke"
      />
    </svg>
  );
}
```


### icon-set/x-cirlcle-solid.tsx

```tsx
import { cn } from "cn";

import type { BaseIconProps } from "../icon/icon.types";

export default function XCircleSolid({ className, ...props }: BaseIconProps) {
  return (
    <svg
      aria-hidden="true"
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 24 24"
      fill="currentColor"
      className={cn("size-6", className)}
      {...props}
    >
      <path
        fillRule="evenodd"
        d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25Zm-1.72 6.97a.75.75 0 1 0-1.06 1.06L10.94 12l-1.72 1.72a.75.75 0 1 0 1.06 1.06L12 13.06l1.72 1.72a.75.75 0 1 0 1.06-1.06L13.06 12l1.72-1.72a.75.75 0 1 0-1.06-1.06L12 10.94l-1.72-1.72Z"
        clipRule="evenodd"
      />
    </svg>
  );
}
```



## Usage

Use `Icon` with a typed `icon` key and optional `size`. Browse the set with `IconGallery`, or import
individual SVGs from `icon-set`.

```tsx
import Icon from "@/components/icons/icon/icon";

export function Example() {
  return <Icon icon="nav-arrow" size="md" />;
}
```

