Name and sizes
Choose a name and compare sizes. SVG uses viewBox 0 0 24 24; currentColor comes from its nearest container.
Selected: folder · 24 px
SVG inherits currentColor. Set color on the container or action; pass the pixel size as a number.
Vue SFC · interactive icon selection
<script setup lang="ts">
const name = defineModel<WlIconName>("name", { default: "folder" });
const size = defineModel<number>("size", { default: 24 });
import { WL_ICON_NAMES, WlIcon, type WlIconName, WlSelect } from "gavia-ui";
const comparisonSizes = [16, 20, 24, 32, 48];
function chooseName(value: unknown): void {
if (typeof value === "string" && (WL_ICON_NAMES as readonly string[]).includes(value)) name.value = value as WlIconName;
}
function chooseSize(value: unknown): void {
if (typeof value === "number" && comparisonSizes.includes(value)) size.value = value;
}
</script>
<template>
<section class="icon-playground wl-stack" data-space="lg">
<div class="wl-grid" data-space="md">
<div class="wl-stack" data-space="xs">
<label for="asset-icon-name" class="wl-text-label">{{ "Icon name" }}</label>
<WlSelect
id="asset-icon-name"
:model-value="name"
:options="[...WL_ICON_NAMES]"
aria-label="Icon name"
@update:model-value="chooseName"
/>
</div>
<div class="wl-stack" data-space="xs">
<label for="asset-icon-size" class="wl-text-label">{{ "Icon size" }}</label>
<WlSelect
id="asset-icon-size"
:model-value="size"
:options="comparisonSizes"
aria-label="Icon size"
@update:model-value="chooseSize"
/>
</div>
</div>
<div class="icon-playground-selected wl-inline" data-space="md">
<span role="img" :aria-label="'Icon ' + name + ', ' + size + ' px'"><WlIcon :name="name" :size="size" /></span>
<p class="wl-text-body" role="status">{{ "Selected:" }} {{ name }} · {{ size }} px</p>
</div>
<div class="icon-playground-comparison" aria-label="Size comparison">
<figure
v-for="comparisonSize in comparisonSizes"
:key="comparisonSize"
class="icon-playground-sample"
:data-icon-comparison-size="comparisonSize"
>
<WlIcon :name="name" :size="comparisonSize" /><figcaption class="wl-text-small">{{ comparisonSize }} px</figcaption>
</figure>
</div>
<p class="wl-text-small wl-text-muted">{{ "SVG inherits currentColor. Set color on the container or action; pass the pixel size as a number." }}</p>
</section>
</template>
<style scoped>
.icon-playground { min-width: 0; }
.icon-playground-selected {
min-height: 80px;
padding: var(--wl-space-lg);
background: var(--wl-bg-soft);
border-radius: var(--wl-corner-control);
color: var(--wl-text-accent);
}
.icon-playground-selected p { color: var(--wl-text); }
.icon-playground-comparison {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 80px), 1fr));
gap: var(--wl-space-sm);
}
.icon-playground-sample {
margin: 0;
min-width: 0;
min-height: 110px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: var(--wl-space-md);
border: 1px solid var(--wl-border);
border-radius: var(--wl-corner-control);
color: var(--wl-text);
}
</style>Icon catalogue
Shown: 113 / 113 · Selected: folder · Catalogue size: 24 px
Icons and accessibility
- WlIcon is decorative by default: its SVG has aria-hidden="true". The visible label of an action or object conveys its meaning.
- Give a standalone image an accessible name on its role="img" container. If you name the SVG itself, explicitly pass aria-hidden="false".
- An icon-only button needs an accessible name. WlIconButton accepts aria-label; a text button uses its visible label.
Meaning and action
Text names the object. The adjacent icon is decorative and hidden from assistive technology.
The container name describes a standalone image.
Materials added: 0. Notifications have not been opened yet.
Vue SFC · application example
<script setup lang="ts">
import { WlButton, WlIcon, WlIconButton } from "gavia-ui";
import { ref } from "vue";
const count = ref(0);
const message = ref("Notifications have not been opened yet.");
</script>
<template>
<section class="wl-stack" data-space="lg">
<div class="wl-inline" data-space="sm">
<WlIcon name="folder" :size="20" /><span class="wl-text-body">{{ "Materials" }}</span>
</div>
<p class="wl-text-small wl-text-muted">{{ "Text names the object. The adjacent icon is decorative and hidden from assistive technology." }}</p>
<div class="wl-inline" data-space="md">
<span role="img" aria-label="Secure connection"><WlIcon name="shield" :size="24" /></span>
<p class="wl-text-small">{{ "The container name describes a standalone image." }}</p>
</div>
<div class="wl-inline" data-space="sm">
<WlButton variant="primary" @click="count++">
<template #icon><WlIcon name="plus" :size="18" /></template>{{ "Add material" }}
</WlButton>
<WlIconButton
icon="bell"
aria-label="Open notifications"
@click="message = 'Notifications opened.'"
/>
</div>
<p class="wl-text-small" role="status">{{ "Materials added:" }} {{ count }}. {{ message }}</p>
</section>
</template>CSS size, aliases and fallback
Size accepts a number in pixels or a CSS string. The resolver accepts a canonical name or alias, including legacy pi-name and pi pi-name. For an unknown name, WlIcon renders its default slot.
Compatible names and fallback icon
CSS size: size="1.25rem".
pi pi-pencil → edit. The application changes the stored value separately.
An unknown name preserves the default slot. You can show a custom fallback symbol.
Vue SFC · application example
<script setup lang="ts">
import { resolveWlIconName, WlIcon } from "gavia-ui";
const legacyName = "pi pi-pencil";
const missingName = "my-missing-icon";
</script>
<template>
<section class="wl-stack" data-space="lg">
<div class="wl-inline" data-space="md">
<WlIcon name="folder" size="1.25rem" />
<p class="wl-text-small">{{ "CSS size:" }} <code>size="1.25rem"</code>.</p>
</div>
<div class="wl-inline" data-space="md">
<WlIcon :name="legacyName" :size="20" />
<p class="wl-text-small">
<code>{{ legacyName }}</code> → <code>{{ resolveWlIconName(legacyName) }}</code>{{
". The application changes the stored value separately."
}}
</p>
</div>
<div class="wl-inline" data-space="md">
<span role="img" aria-label="Fallback symbol">
<WlIcon :name="missingName" :size="24"><span class="icon-compatibility-fallback" aria-hidden="true">?</span></WlIcon>
</span>
<p class="wl-text-small">{{ "An unknown name preserves the default slot. You can show a custom fallback symbol." }}</p>
</div>
</section>
</template>
<style scoped>
.icon-compatibility-fallback {
display: inline-flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
border: 1px solid var(--wl-border);
border-radius: var(--wl-corner-control);
font: var(--wl-type-label-weight) var(--wl-type-small-size)/1 var(--wl-font);
}
</style>Adding an SVG
Sources are in packages/ui-kit/icons/<name>.svg. Prepare new icons in the shared style; pnpm icons:sync validates SVG and updates the registry, pnpm icons:check checks that it is up to date.
Check legibility at 16, 20 and 24 px in every theme. The component sets size and colour; SVG files use no external resources or handlers.
Preparing and adding an SVG