# Icon Guides

## Patterns

### Inline Control Icon

When to use:

- a button or trigger needs one decorative glyph

Composition notes:

- keep icon size aligned with the control density
- let `currentColor` inherit from the parent control

Trade-offs:

- consistent and compact
- easy to overuse decorative glyphs

```tsx
import { Button, Icon } from '@vega-ui/react';
import { ChevronDownIcon, DownloadIcon, PlusIcon } from '@vega-ui/icons';

export default function IconInsideAButton() {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 'var(--spacing-4)' }}>
      <Button type='button'>
        <Icon size='sm'><PlusIcon /></Icon>
        Add member
      </Button>
      <Button type='button' variant='secondary' appearance='ghost'>
        Export
        <Icon size='sm'><ChevronDownIcon /></Icon>
      </Button>
      <Button type='button' size='sm' variant='secondary' appearance='ghost'>
        <Icon size='xs'><DownloadIcon /></Icon>
        Invoice.pdf
      </Button>
    </div>
  );
}
```

### Status Row Icon

When to use:

- text needs a small adjacent symbol

Composition notes:

- keep the icon secondary to the text
- do not rely on the icon as the only status signal

Trade-offs:

- fast visual scanning
- still needs text for clarity

```tsx
import { Icon, Text } from '@vega-ui/react';
import { CircleCheckIcon, ShieldIcon, TriangleAlertIcon } from '@vega-ui/icons';

export default function InfoRow() {
  return (
    <ul style={{ display: 'flex', flexDirection: 'column', gap: 'var(--spacing-4)', margin: 0, padding: 0, listStyle: 'none', width: '100%' }}>
      <li style={{ display: 'flex', alignItems: 'flex-start', gap: 'var(--spacing-4)' }}>
        <Icon size='sm' style={{ flexShrink: 0, marginBlockStart: 'var(--spacing-3)', color: 'var(--color-green-accent-500)' }}><CircleCheckIcon /></Icon>
        <Text size={3}>SSO is enabled for this workspace</Text>
      </li>
      <li style={{ display: 'flex', alignItems: 'flex-start', gap: 'var(--spacing-4)' }}>
        <Icon size='sm' style={{ flexShrink: 0, marginBlockStart: 'var(--spacing-3)', color: 'var(--color-primary-500)' }}><ShieldIcon /></Icon>
        <Text size={3}>Two-factor authentication is required for admins</Text>
      </li>
      <li style={{ display: 'flex', alignItems: 'flex-start', gap: 'var(--spacing-4)' }}>
        <Icon size='sm' style={{ flexShrink: 0, marginBlockStart: 'var(--spacing-3)', color: 'var(--color-error)' }}><TriangleAlertIcon /></Icon>
        <Text size={3}>2 members have not verified their email</Text>
      </li>
    </ul>
  );
}
```

### Custom SVG Wrapper

When to use:

- a custom or third-party SVG should use the same VegaUI sizing contract

Composition notes:

- keep the child SVG compatible with forwarded SVG props
- use explicit dimensions only when token sizing is not enough

Trade-offs:

- consistent icon integration
- easier to produce drift if every icon is explicitly sized

```tsx
import type { SVGProps } from 'react';
import { Icon } from '@vega-ui/react';

function OrbitMark(props: SVGProps<SVGSVGElement>) {
  return (
    <svg viewBox='0 0 24 24' fill='none' strokeWidth={2} strokeLinecap='round' {...props}>
      <circle cx='12' cy='12' r='3' />
      <ellipse cx='12' cy='12' rx='10' ry='4.5' transform='rotate(-30 12 12)' />
    </svg>
  );
}

export default function CustomSvgWrapper() {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--spacing-8)' }}>
      <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--spacing-3)', fontWeight: 600 }}>
        <Icon size='lg' style={{ color: 'var(--color-primary-500)' }}><OrbitMark /></Icon>
        Orbit
      </span>
      <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--spacing-3)', color: 'var(--label-secondary)' }}>
        <Icon size='sm'><OrbitMark /></Icon>
        Synced with Orbit
      </span>
    </div>
  );
}
```

## Comparison

### Quick Decision Rule

Use `Icon` to render SVGs with VegaUI sizing and color behavior. Use text or labels when the meaning should be explicit rather than purely visual.

### `Icon` vs raw SVG

- Use `Icon` for consistent sizing and color inheritance.
- Use raw SVG only when you intentionally want to bypass the shared icon contract.

### `Icon` vs `Avatar`

- Use `Icon` for symbolic graphics.
- Use `Avatar` for people or entity identity.

### Choose This Component When

- you need one scalable SVG glyph
- sizing should follow VegaUI icon tokens

### Do Not Choose This Component When

- the UI needs a full labeled status on its own
- the content is not really an SVG icon

## Troubleshooting

### The Icon Ignores The `size` Prop

#### Symptom

Changing `size` does not affect the rendered icon dimensions.

#### Likely Cause

Explicit `width` or `height` props are already set.

#### How To Verify

- inspect the rendered props
- check whether `width` or `height` is present

#### Fix

Remove explicit dimensions if you want token sizing to apply.

### The Icon Is Invisible Or Wrongly Colored

#### Symptom

The icon renders but its color is unexpected.

#### Likely Cause

The icon uses `currentColor`, so the surrounding text or control color is driving it.

#### How To Verify

- inspect the computed `color` of the parent context

#### Fix

Set the desired text color on the parent or pass an explicit `color` prop.

### A Standalone Icon Is Not Announced

#### Symptom

The icon has meaning visually, but assistive technology does not announce it.

#### Likely Cause

`Icon` defaults to `aria-hidden='true'`.

#### How To Verify

- inspect the rendered element attributes

#### Fix

Provide meaning through adjacent text or a labeled parent control rather than relying on the raw icon alone.
