---
title: Icon
description: Renders an icon from a UnoCSS icon class, JSX element, or render function.
sidebar:
  order: 2
search:
  tags: [Iconify, Lucide, symbol, SVG]
---

# Icon

> Renders an icon from a UnoCSS icon class, JSX element, or render function.

## Import

```tsx
import { Icon } from 'moraine'
```

## Slot Structure

Icon element with no slot.

## Examples

### Icon Sizes

Numeric pixel sizes from 12 to 48.

```tsx
function IconSizes() {
  const ICON_SIZES = [12, 16, 20, 24, 32, 48]

  return (
    <div class="flex flex-wrap gap-6 items-end">
      <For each={ICON_SIZES}>
        {(size) => (
          <div class="flex flex-col gap-1 items-center">
            <Icon name="i-lucide-star" size={size} />
            <span class="text-[10px] text-muted-foreground">{size}px</span>
          </div>
        )}
      </For>
    </div>
  )
}
```

### Icon Gallery

Common Lucide icons rendered via UnoCSS classes.

```tsx
function IconGallery() {
  const ICON_NAMES = [
    'i-lucide-search',
    'i-lucide-home',
    'i-lucide-settings',
    'i-lucide-user',
    'i-lucide-star',
    'i-lucide-heart',
    'i-lucide-bell',
    'i-lucide-mail',
    'i-lucide-calendar',
    'i-lucide-folder',
    'i-lucide-file',
    'i-lucide-trash',
  ]

  return (
    <div class="gap-4 grid grid-cols-4 sm:grid-cols-6">
      <For each={ICON_NAMES}>
        {(name) => (
          <div class="p-3 b-1 b-border border-border rounded-lg flex flex-col gap-2 items-center">
            <Icon name={name} size={24} />
            <span class="text-[10px] text-muted-foreground truncate">
              {name.replace('i-lucide-', '')}
            </span>
          </div>
        )}
      </For>
    </div>
  )
}
```

### Icon as JSX

Pass a JSX element or render function instead of a string name.

```tsx
function IconAsJSX() {
  return (
    <div class="flex flex-wrap gap-6 items-center">
      <div class="flex flex-col gap-1 items-center">
        <Icon
          name={
            <svg
              viewBox="0 0 24 24"
              width="24"
              height="24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
            >
              <circle cx="12" cy="12" r="10" />
              <path d="M8 14s1.5 2 4 2 4-2 4-2" />
              <line x1="9" y1="9" x2="9.01" y2="9" />
              <line x1="15" y1="9" x2="15.01" y2="9" />
            </svg>
          }
        />
        <span class="text-[10px] text-muted-foreground">JSX element</span>
      </div>
      <div class="flex flex-col gap-1 items-center">
        <Icon name={() => <div class="i-lucide-zap size-6" />} />
        <span class="text-[10px] text-muted-foreground">Render function</span>
      </div>
    </div>
  )
}
```

## API Reference

### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| class | ClassValue | — | Class applied to the component root or trigger element. |
| classes | IconT.Classes \| undefined | — | — |
| name | IconT.Name | — | Icon source. Strings should be Uno icon classes such as `i-lucide-search`<br>or app-config aliases such as `icon-search`.<br>Non-string values can be JSX nodes or render functions. |
| ref | JSX.HTMLElementTags["div"] extends { ref?: infer Ref; } ? Ref : never \| undefined | — | — |
| size | string \| number \| undefined | — | Icon size. Numbers are interpreted as px. |
| slotName | string \| undefined | icon | Data slot for styling. |
| style | JSX.CSSProperties \| undefined | — | — |
| styles | IconT.Styles \| undefined | — | — |

### ARIA

Accessibility attributes and roles emitted by the component markup.

| Attribute | Type | Description |
| --- | --- | --- |
| aria-hidden | boolean \| string \| undefined | Hides decorative content from assistive technology. |

### Data Attributes

State and slot attributes exposed for styling hooks and selectors.

| Attribute | Type | Description |
| --- | --- | --- |
| data-slot | string | Identifies the rendered slot for styling hooks and selectors. |
