Back to list
matthewharwood

ux-iconography

by matthewharwood

A fantasy-themed phonics game where kids turn spelling words into creatures, places, and spells through imagination, drawing, and storytelling.

0🍴 0📅 Dec 9, 2025

SKILL.md


name: ux-iconography description: Icon usage patterns using Material Symbols v3. Use when adding icons to buttons, navigation, or status indicators. Covers sizing, accessibility, animations, and color integration with project tokens. allowed-tools:

  • Read
  • Write
  • Edit
  • Glob
  • Grep

UX Iconography Skill

Icon implementation patterns for UI components. This project uses Material Symbols v3 as the primary icon system.

  • material-symbols-v3: Complete icon API reference, variable font axes, icon names
  • ux-accessibility: ARIA requirements for icon buttons
  • ux-animation-motion: Anime.js patterns for icon animations

Icon System

Location: css/styles/icons.css

This project uses Material Symbols Outlined (variable font) from Google Fonts:

<span class="icon">home</span>
<span class="icon">settings</span>
<span class="icon">favorite</span>

See material-symbols-v3 skill for complete icon name reference.

Icon Sizing

Size Classes

<span class="icon icon--sm">info</span>   <!-- 20px -->
<span class="icon icon--md">info</span>   <!-- 24px (default) -->
<span class="icon icon--lg">info</span>   <!-- 40px -->
<span class="icon icon--xl">info</span>   <!-- 48px -->

Fluid Sizing with Utopia

Scale icons with typography tokens:

.icon-fluid {
  font-size: var(--step-1);
}

.icon-small {
  font-size: var(--step--1);
}

Fixed Container

.icon-fixed {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
}

Icon + Text Patterns

Inline with Label

<button class="btn-icon-text">
  <span class="icon" aria-hidden="true">menu_book</span>
  <span class="label">Word Phase</span>
</button>
.btn-icon-text {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
}

.btn-icon-text .icon {
  flex-shrink: 0;
}

Icon-Only Button

<button class="btn-icon" aria-label="Settings">
  <span class="icon" aria-hidden="true">settings</span>
</button>
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--min-touch-target);
  min-height: var(--min-touch-target);
  padding: var(--space-xs);
}

Trailing Icon

<a href="/next" class="link-arrow">
  Next Phase
  <span class="icon" aria-hidden="true">arrow_forward</span>
</a>

Accessibility

Always Hide Decorative Icons

<!-- Decorative: has visible label -->
<button>
  <span class="icon" aria-hidden="true">settings</span>
  Settings
</button>

<!-- Meaningful: icon-only needs label -->
<button aria-label="Settings">
  <span class="icon" aria-hidden="true">settings</span>
</button>

Screen Reader Text

<button class="btn-icon">
  <span class="icon" aria-hidden="true">settings</span>
  <span class="sr-only">Settings</span>
</button>
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  clip: rect(0, 0, 0, 0);
}

Status Icons with Text

<span class="status status-complete">
  <span class="icon" aria-hidden="true">check_circle</span>
  <span>Complete</span>
</span>

Icon Variants

Fill Style

<span class="icon icon--outlined">favorite</span>  <!-- Outline (default) -->
<span class="icon icon--filled">favorite</span>    <!-- Solid fill -->

Weight

<span class="icon icon--thin">home</span>     <!-- 100 -->
<span class="icon icon--light">home</span>    <!-- 300 -->
<span class="icon icon--regular">home</span>  <!-- 400 -->
<span class="icon icon--medium">home</span>   <!-- 500 -->
<span class="icon icon--bold">home</span>     <!-- 700 -->

Icon Color

Inherit from Parent

.icon {
  color: inherit;
}

.btn-primary .icon {
  color: var(--theme-on-primary);
}

Semantic Colors

.icon-success { color: var(--color-success); }
.icon-error { color: var(--color-error); }
.icon-warning { color: var(--color-warning); }

Phase Colors

[data-phase="word"] .icon { color: var(--color-word); }
[data-phase="collision"] .icon { color: var(--color-collision); }
[data-phase="mutation"] .icon { color: var(--color-mutation); }
[data-phase="story"] .icon { color: var(--color-story); }

Animation

CSS Transitions

.icon {
  transition: transform 0.15s ease;
}

.btn:hover .icon {
  transform: scale(1.1);
}

.btn:active .icon {
  transform: scale(0.95);
}

Wiggle Animation (Anime.js)

import { animate } from 'animejs';
import { DURATION, EASE } from '../../utils/animations.js';

animate(this._iconEl, {
  rotate: [0, -10, 10, -10, 10, 0],
  duration: DURATION.normal,
  ease: EASE.smooth
});

Celebration Bounce

import { successBounce } from '../../utils/animations.js';

successBounce(this._iconEl);
// Scale: 1 → 1.2 → 1

Status Indicators

Phase Status

.phase-icon {
  font-size: var(--step-0);
}

[data-status="complete"] .phase-icon {
  color: var(--color-success);
}

[data-status="current"] .phase-icon {
  color: var(--theme-primary);
  animation: pulse 1.5s ease-in-out infinite;
}

[data-status="locked"] .phase-icon {
  opacity: 0.5;
  filter: grayscale(0.5);
}

Progress Dots

.progress-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--theme-outline-variant);
}

.progress-dot[data-completed] {
  background: var(--color-success);
}

.progress-dot[data-current] {
  background: var(--theme-primary);
}

Loading Icons

Spinner

<span class="spinner" role="status">
  <span class="sr-only">Loading...</span>
</span>
.spinner {
  display: inline-block;
  width: 1em;
  height: 1em;
  border: 2px solid var(--theme-outline);
  border-top-color: var(--theme-primary);
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

@keyframes spin {
  to { rotate: 360deg; }
}

Common Game Icons

PurposeIcon NameUsage
Word phasemenu_bookPhase indicator
Collision phaseswordsPhase indicator
Mutation phasegeneticsPhase indicator
Story phaseauto_storiesPhase indicator
Completecheck_circleStatus indicator
LockedlockUnavailable item
Star/achievementstarRewards
SettingssettingsConfiguration
HomehomeNavigation
Sound onvolume_upAudio toggle
Sound offvolume_offAudio toggle

High Contrast Mode

@media (forced-colors: active) {
  .icon {
    forced-color-adjust: auto;
  }
}

Best Practices

Do

  • Use aria-hidden="true" on decorative icons
  • Provide aria-label for icon-only buttons
  • Use semantic colors for status icons
  • Ensure touch targets are 44x44px minimum
  • Use .icon--filled for selected/active states

Don't

  • Use icons as the only indicator of meaning
  • Forget to hide icons from screen readers
  • Use fixed pixel sizes that don't scale
  • Animate icons excessively
  • Mix icon systems inconsistently

Score

Total Score

75/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新

+5
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon