Skip to content

Icon

Sakana Element bundles all 486 icons from pixelarticons — a pixel-art style icon library on a 24×24 grid. Every icon is available out of the box with no extra installation.

NameCategoryDescriptionTypeDefault
flip? StyleFlip direction'horizontal' | 'vertical' | 'both'
rotation? StyleRotation angle90 | 180 | 270
size? SizeIcon size'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '1x' | '2x' | '3x''md'
type? ColorIcon type color'primary' | 'success' | 'warning' | 'danger' | 'info'
color? ColorCustom colorstring
spin? BehaviorSpin animation (step-based)booleanfalse
pulse? BehaviorPulse animation (spin + scale)booleanfalse
bounce? BehaviorBounce animation (vertical)booleanfalse
shake? BehaviorShake animation (horizontal)booleanfalse
beat? BehaviorBeat animation (scale pulse)booleanfalse
fade? BehaviorFade animation (opacity blink)booleanfalse
icon? ContentIcon name (pixelarticons name or mapped alias)string

Basic Usage

Use the icon property to specify the icon name. Icon names follow pixelarticons naming conventions. Common aliases are also supported — for example, spinner resolves to loader, and x resolves to close.

<template>
  <div class="demo-icon">
    <px-icon icon="home" />
    <px-icon icon="user" />
    <px-icon icon="search" />
    <px-icon icon="bookmark" />
    <px-icon icon="heart" />
    <px-icon icon="sliders" />
  </div>
</template>

<style scoped>
.demo-icon {
  display: flex;
  gap: 20px;
  font-size: 24px;
}
</style>

Different Sizes

Use the size property to set the icon size. All sizes are multiples of the 24px grid to ensure crisp pixel rendering:

SizePixelsDescription
xs12pxExtra small
sm18pxSmall
md24pxDefault
lg36pxLarge
xl48pxExtra large
2xl72px2× extra large
1x / 2x / 3x24 / 48 / 72pxFontAwesome-compatible aliases
<template>
  <div class="demo-icon">
    <px-icon icon="bookmark" size="xs" />
    <px-icon icon="bookmark" size="sm" />
    <px-icon icon="bookmark" size="lg" />
    <px-icon icon="bookmark" size="xl" />
    <px-icon icon="bookmark" size="2xl" />
    <px-icon icon="bookmark" size="3x" />
  </div>
</template>

<style scoped>
.demo-icon {
  display: flex;
  align-items: center;
  gap: 20px;
}
</style>

Icon Colors

Use the type property for semantic colors (primary, success, warning, danger, info), or the color property for any custom color value. The color prop overrides type when both are set.

<template>
  <div class="demo-icon">
    <px-icon icon="check" type="primary" size="2x" />
    <px-icon icon="check" type="success" size="2x" />
    <px-icon icon="warning-box" type="warning" size="2x" />
    <px-icon icon="close-box" type="danger" size="2x" />
    <px-icon icon="info-box" type="info" size="2x" />
    <px-icon icon="heart" color="#e91e63" size="2x" />
  </div>
</template>

<style scoped>
.demo-icon {
  display: flex;
  align-items: center;
  gap: 20px;
}
</style>

Flip & Rotation

Use flip to mirror the icon (horizontal, vertical, or both). Use rotation to rotate by 90, 180, or 270 degrees. These can be combined.

<template>
  <div class="demo-icon-flip">
    <h4>Flip / 翻转</h4>
    <div class="demo-row">
      <div class="icon-item">
        <px-icon icon="arrow-right" size="2x" />
        <span>original</span>
      </div>
      <div class="icon-item">
        <px-icon icon="arrow-right" size="2x" flip="horizontal" />
        <span>horizontal</span>
      </div>
      <div class="icon-item">
        <px-icon icon="arrow-right" size="2x" flip="vertical" />
        <span>vertical</span>
      </div>
      <div class="icon-item">
        <px-icon icon="arrow-right" size="2x" flip="both" />
        <span>both</span>
      </div>
    </div>

    <h4>Rotation / 旋转</h4>
    <div class="demo-row">
      <div class="icon-item">
        <px-icon icon="arrow-right" size="2x" />
        <span>0°</span>
      </div>
      <div class="icon-item">
        <px-icon icon="arrow-right" size="2x" :rotation="90" />
        <span>90°</span>
      </div>
      <div class="icon-item">
        <px-icon icon="arrow-right" size="2x" :rotation="180" />
        <span>180°</span>
      </div>
      <div class="icon-item">
        <px-icon icon="arrow-right" size="2x" :rotation="270" />
        <span>270°</span>
      </div>
    </div>
  </div>
</template>

<style scoped>
.demo-icon-flip h4 {
  margin: 0 0 12px;
  font-size: 14px;
  color: #888;
}
.demo-icon-flip h4:not(:first-child) {
  margin-top: 20px;
}
.demo-row {
  display: flex;
  align-items: center;
  gap: 30px;
}
.icon-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.icon-item span {
  font-size: 12px;
  color: #666;
}
</style>

Icon Animations

All animations use CSS steps() for a discrete frame-by-frame look that matches the pixel-art aesthetic:

AnimationEffectFrames
spin360° rotation8 steps
pulseRotation + scale8 steps
bounceVertical hop5 steps
shakeHorizontal shake4 steps
beatScale throb3 steps
fadeOpacity flicker4 steps
<template>
  <div class="demo-icon">
    <div class="icon-item">
      <px-icon icon="loader" spin size="2x" />
      <span>spin</span>
    </div>
    <div class="icon-item">
      <px-icon icon="loader" pulse size="2x" />
      <span>pulse</span>
    </div>
    <div class="icon-item">
      <px-icon icon="notification" shake size="2x" />
      <span>shake</span>
    </div>
    <div class="icon-item">
      <px-icon icon="heart" beat size="2x" type="danger" />
      <span>beat</span>
    </div>
    <div class="icon-item">
      <px-icon icon="zap" bounce size="2x" type="warning" />
      <span>bounce</span>
    </div>
    <div class="icon-item">
      <px-icon icon="circle" fade size="2x" />
      <span>fade</span>
    </div>
  </div>
</template>

<style scoped>
.demo-icon {
  display: flex;
  align-items: center;
  gap: 30px;
}
.icon-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.icon-item span {
  font-size: 12px;
  color: #666;
}
</style>

Icon Collection

Browse and search all 486 bundled icons. Click any icon to copy its name.

<script setup lang="ts">
import { defaultPixelIcons } from 'sakana-element';
import { computed, ref } from 'vue';

const search = ref('');
const copiedName = ref('');

const allIconNames = computed(() => Object.keys(defaultPixelIcons).sort());

const filteredIcons = computed(() => {
  const keyword = search.value.trim().toLowerCase();
  if (!keyword) return allIconNames.value;
  return allIconNames.value.filter((name) => name.toLowerCase().includes(keyword));
});

function copyIconName(name: string) {
  navigator.clipboard.writeText(name).then(() => {
    copiedName.value = name;
    setTimeout(() => {
      copiedName.value = '';
    }, 1500);
  });
}
</script>

<template>
  <div class="icon-collection">
    <div class="icon-search">
      <px-icon icon="search" size="sm" class="search-icon" />
      <input
        v-model="search"
        type="text"
        class="search-input"
        placeholder="Search icon name..."
      />
      <span class="icon-count">{{ filteredIcons.length }} icons</span>
    </div>

    <div v-if="filteredIcons.length" class="icon-grid">
      <div
        v-for="name in filteredIcons"
        :key="name"
        class="icon-card"
        :class="{ 'icon-card--copied': copiedName === name }"
        :title="`Click to copy: ${name}`"
        @click="copyIconName(name)"
      >
        <px-icon :icon="name" size="lg" />
        <span class="icon-name">{{ name }}</span>
        <span v-if="copiedName === name" class="copied-tip">Copied!</span>
      </div>
    </div>

    <div v-else class="icon-empty">
      <px-icon icon="search" size="2x" />
      <p>No icons found for "{{ search }}"</p>
    </div>
  </div>
</template>

<style scoped>
.icon-collection {
  width: 100%;
}

.icon-search {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border: 2px solid var(--px-color-border, #ccc);
  background: var(--px-color-bg, #fff);
  margin-bottom: 16px;
}

.search-icon {
  color: var(--px-color-text-placeholder, #999);
  flex-shrink: 0;
}

.search-input {
  flex: 1;
  border: none;
  outline: none;
  background: transparent;
  font-family: var(--px-font-family, monospace);
  font-size: 14px;
  color: var(--px-color-text, #333);
}

.search-input::placeholder {
  color: var(--px-color-text-placeholder, #999);
}

.icon-count {
  font-size: 12px;
  color: var(--px-color-text-secondary, #888);
  white-space: nowrap;
  flex-shrink: 0;
}

.icon-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 8px;
  max-height: 520px;
  overflow-y: auto;
  padding: 4px;
}

.icon-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 12px 4px 8px;
  border: 2px solid var(--px-color-border-light, #e0e0e0);
  background: var(--px-color-bg, #fff);
  cursor: pointer;
  position: relative;
  transition: border-color 0.15s, background-color 0.15s;
}

.icon-card:hover {
  border-color: var(--px-color-primary, #7287fd);
  background: var(--px-color-primary-light-9, #eef1fe);
}

.icon-card--copied {
  border-color: var(--px-color-success, #40a070);
  background: var(--px-color-success-light-9, #e2f7eb);
}

.icon-name {
  font-size: 10px;
  color: var(--px-color-text-secondary, #888);
  text-align: center;
  word-break: break-all;
  line-height: 1.3;
  max-width: 100%;
}

.copied-tip {
  position: absolute;
  top: 2px;
  right: 4px;
  font-size: 10px;
  color: var(--px-color-success, #40a070);
  font-weight: bold;
}

.icon-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 40px;
  color: var(--px-color-text-placeholder, #999);
}

.icon-empty p {
  margin: 0;
  font-size: 14px;
}
</style>

Custom Icons

Register your own SVG icons and use them alongside the built-in set.

Single Registration

ts
import { registerPixelIcon } from 'sakana-element';

registerPixelIcon('my-icon', '<svg viewBox="0 0 24 24">...</svg>');
vue
<px-icon icon="my-icon" />

Batch Registration

ts
import { registerPixelIcons } from 'sakana-element';

registerPixelIcons({
  'my-icon-a': '<svg viewBox="0 0 24 24">...</svg>',
  'my-icon-b': '<svg viewBox="0 0 24 24">...</svg>',
});

Registry API

FunctionDescription
registerPixelIcon(name, svg)Register a single custom icon
registerPixelIcons(icons)Register multiple icons at once
hasPixelIcon(name)Check if an icon name is registered
getRegisteredIconNames()Get an array of all registered icon names
getPixelIcon(name)Get the SVG string of a registered icon
resolveIconName(name)Resolve an icon name alias to its pixelarticons name
getIconNameMap()Get the full icon name alias mapping

TIP

SVG content is automatically sanitized on registration — dangerous elements like <script> and event handler attributes are stripped for XSS safety.