SwIcon

SwIcon is a pure size-and-color container (<span class="sw-icon">). It does not embed any specific icon — the actual SVG content is passed via the default slot. In practice it is used together with AppIcon:

  • AppIcon (business layer): The inject-icons build script injects assets/icons/*.svg files into the component, using v-if="name === 'icon-name'" to decide which SVG to render, then passes it to SwIcon via slot.
  • SwIcon (framework layer): Uses :deep() to override all fill and stroke attributes inside the SVG with currentColor, enabling CSS color inheritance.

Basic Usage

<!-- Recommended: use AppIcon with inject-icons -->
<AppIcon name="home" />
<AppIcon name="user" :width="24" color="#3b82f6" />

<!-- Advanced: pass a one-off inline SVG directly to SwIcon -->
<SwIcon name="custom" :width="32" color="#f59e0b">
  <svg viewBox="0 0 24 24"><path d="..." /></svg>
</SwIcon>

inject-icons Build Process

Run pnpm inject-icons at the project root — the script reads all *.svg files from app/assets/icons/ and injects them into AppIcon.vue between the ICONS:START / ICONS:END markers.

# Inject app/assets/icons/home.svg as <AppIcon name="home" />
pnpm inject-icons

# Then use anywhere
<AppIcon name="home" />
<AppIcon name="settings" :width="20" color="var(--primary)" />

Size and Color

Size and Color

Demonstrates various uses of the width, height, and color props, including auto-scaling with parent font size.

加载中...

Color: currentColor inherit + explicit tokens

加载中...

1em scales with parent font-size

加载中...

Default width and height are both 1em, scaling automatically with the parent element's font size. Color defaults to inheriting the parent's color CSS property.

Props

NameTypeRequiredDefaultDescription
namestring—Icon identifier, emitted verbatim as the data-icon attribute so the DOM can be traced back to the icon. Not used for rendering — the icon itself comes from the default slot
widthnumber | string— (CSS fallback 1em)Icon width — number means px, string is a CSS value. Omit it and no inline style is written; the size comes from the --sw-icon-width CSS fallback
heightnumber | string'1em'Icon height — number means px, string is a CSS value
colorstring— (CSS fallback currentColor)Icon color — any valid CSS color value. Same as above: omitting it writes no inline style

Slots

NameDescription
defaultSVG content, usually passed by AppIcon

Color Inheritance

SwIcon uses :deep() to set all fill and stroke attributes inside the SVG to currentColor — except fill="none" and stroke="none" (transparent paths), which are left unchanged. Just set the color prop or set the parent element's CSS color property to control the entire icon.

<!-- Inherit color from parent element -->
<p style="color: #ef4444;">
  <AppIcon name="warning" />  <!-- automatically red -->
  Warning text
</p>

<!-- Override color with prop -->
<AppIcon name="star" color="#f59e0b" />

Style Tokens

These CSS variables can be overridden on your side (the fallback is the default):

VariableDefaultDescription
--sw-icon-colorcurrentcolorIcon color. Inherits the text color by default — see "Color inheritance"
--sw-icon-height1emIcon height. Follows the font size by default
--sw-icon-width1emIcon width. Follows the font size by default

Caveats

  • SwIcon is an icon container, not an icon library — it only manages size (1em, scales with font size) and color (currentColor); the icon itself comes from the slot. Application code usually doesn't use SwIcon directly: for project-owned SVGs write <AppIcon name="x" /> (starter's AppIcon wraps SwIcon internally), and for UI glyphs use an icon library component directly (starter uses @phosphor-icons/vue, e.g. <PhX />) — icon-library components already expose their own size/color props and should not be wrapped in SwIcon.
  • Multi-color SVGs get flattened to a single color — the color-inheritance rule rewrites every fill / stroke (except none) to currentColor. That's convenient for monochrome icons, but a multi-color brand logo will lose its palette. Use SwImage (fit="contain") or an inline <svg> for multi-color assets.
  • aria-hidden="true" by default — icons are treated as decorative and skipped by screen readers. When an icon carries the meaning on its own (icon-only buttons), add aria-label on the surrounding interactive element rather than removing aria-hidden.
  • Renders a <span>, not an <i> — avoids clashing with iconfont / Font Awesome and other libraries that claim <i>. Target span.sw-icon in CSS selectors.
  • The 1em default is the sole exemption from the stylelint em ban — em units are banned framework-wide (nested compounding is hard to trace); SwIcon's font-size-relative mode is an explicit carve-out. Don't cite it to use em elsewhere.