Skip to content
    Style: Wireframe

    Components · Display

    Icons

    Twenty-four icons on a 16px grid with a 1.5px stroke, decorative unless labelled.

    0.39% of the 2,073 sites in The UI Index have a icon (8 sites).

    Used in UI Pro: Footer, Hero, Features, Pricing, Split, Team, Services, Work, Integrations, Values, Header, Navigation, Breadcrumb, Comparison, Content card, Story card, Collection card, Hover card

    • arrow-right
    • arrow-up-right
    • check
    • x
    • plus
    • minus
    • chevron-down
    • chevron-right
    • chevron-left
    • search
    • menu
    • copy
    • play
    • map-pin
    • calendar
    • settings
    • user
    • mail
    • bell
    • trash
    • edit
    • download
    • info
    • alert

    Both previews render the same markup; the HTML tab below is that markup without a framework.

    Install

    React
    npx shadcn@latest add https://www.themes.dev/ui/r/icon.json
    Astro
    npx shadcn@latest add https://www.themes.dev/ui/r/astro/icon.json

    Or copy the files below into your project. They need clsx, tailwind-merge, and the themes.dev UI theme. The HTML needs only the compiled CSS.

    icon.tsx
    import { cn } from '@/lib/utils';
    import { ICONS, iconClasses, type IconName } from './icon.variants';
    
    export { ICONS, type IconName };
    
    export interface IconProps {
      name: IconName;
      /** Only when the icon means something on its own; otherwise it is hidden from screen readers. */
      label?: string;
      className?: string;
    }
    
    /** One of themes.dev UI's icons: 16px grid, 1.5px stroke, decorative unless it has a label. */
    export function Icon({ name, label, className }: IconProps) {
      return (
        <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" role={label ? 'img' : undefined} aria-label={label} aria-hidden={label ? undefined : 'true'} className={cn(iconClasses, className)}>
          <path d={ICONS[name]} />
        </svg>
      );
    }
    icon.variants.ts
    /** themes.dev UI's icons: drawn on a 16px grid with a 1.5px stroke, round caps and joins, so they sit with the text.
     *  Decorative by default (aria-hidden); give a label when the icon is the only content of a control or carries
     *  meaning. Sizes follow the text: 16px with text-sm, 20px for larger controls. */
    export const ICONS = {
      'arrow-right': 'M3 8h10M9 4l4 4-4 4',
      'arrow-up-right': 'M5 11l6-6M6 5h5v5',
      check: 'M3.5 8.5l3 3 6-7',
      x: 'M4 4l8 8M12 4l-8 8',
      plus: 'M8 3v10M3 8h10',
      minus: 'M3.5 8h9',
      'chevron-down': 'M4 6l4 4 4-4',
      'chevron-right': 'M6 3.5l4.5 4.5L6 12.5',
      'chevron-left': 'M10 3.5L5.5 8l4.5 4.5',
      search: 'M7 12.5a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zM11 11l3.5 3.5',
      menu: 'M2.5 4.5h11M2.5 8h11M2.5 11.5h11',
      copy: 'M5.5 5.5h8v8h-8zM10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H3A1.5 1.5 0 0 0 1.5 3v6A1.5 1.5 0 0 0 3 10.5h.5',
      play: 'M5 3.5v9l7-4.5z',
      'map-pin': 'M8 14.5s4.5-4.2 4.5-8a4.5 4.5 0 0 0-9 0c0 3.8 4.5 8 4.5 8zM8 8a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z',
      calendar: 'M2.5 4h11v9.5h-11zM2.5 7h11M5.5 2.5v3M10.5 2.5v3',
      settings: 'M8 10a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM8 1.5v2M8 12.5v2M1.5 8h2M12.5 8h2M3.4 3.4l1.4 1.4M11.2 11.2l1.4 1.4M3.4 12.6l1.4-1.4M11.2 4.8l1.4-1.4',
      user: 'M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM2.5 14.5a5.5 5.5 0 0 1 11 0',
      mail: 'M2 3.5h12v9H2zM2.5 4l5.5 4.5L13.5 4',
      bell: 'M4 11V7a4 4 0 0 1 8 0v4l1.5 1.5h-11zM6.5 14h3',
      trash: 'M2.5 4h11M6 4V2.5h4V4M4 4l.7 9.5h6.6L12 4',
      edit: 'M10.5 2.5l3 3-8 8h-3v-3z',
      download: 'M8 2.5v8M4.5 7L8 10.5 11.5 7M2.5 13.5h11',
      info: 'M8 14.5a6.5 6.5 0 1 0 0-13 6.5 6.5 0 0 0 0 13zM8 7.5V11M8 5h.01',
      alert: 'M8 2l6.5 11.5h-13zM8 6.5v3M8 11.5h.01',
    } as const;
    
    export type IconName = keyof typeof ICONS;
    export const iconClasses = 'inline-block size-4 shrink-0';