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.