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-iconsbuild script injectsassets/icons/*.svgfiles into the component, usingv-if="name === 'icon-name'"to decide which SVG to render, then passes it toSwIconvia slot. - SwIcon (framework layer): Uses
:deep()to override allfillandstrokeattributes inside the SVG withcurrentColor, 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
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | — | 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 | |
width | number | 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 | |
height | number | string | '1em' | Icon height — number means px, string is a CSS value | |
color | string | — (CSS fallback currentColor) | Icon color — any valid CSS color value. Same as above: omitting it writes no inline style |
Slots
| Name | Description |
|---|---|
default | SVG 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):
| Variable | Default | Description |
|---|---|---|
--sw-icon-color | currentcolor | Icon color. Inherits the text color by default — see "Color inheritance" |
--sw-icon-height | 1em | Icon height. Follows the font size by default |
--sw-icon-width | 1em | Icon 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'sAppIconwraps 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(exceptnone) tocurrentColor. That's convenient for monochrome icons, but a multi-color brand logo will lose its palette. UseSwImage(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), addaria-labelon the surrounding interactive element rather than removingaria-hidden.- Renders a
<span>, not an<i>— avoids clashing with iconfont / Font Awesome and other libraries that claim<i>. Targetspan.sw-iconin CSS selectors. - The
1emdefault is the sole exemption from the stylelintemban —emunits 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 useemelsewhere.