Icon
Icon
Start with the basic example, then compare related settings before moving to controlled, asynchronous or combined use cases.
Basic examples
Basic Usage
size: Controls the component size.color: Overrides the color.
Appearance and states
Icon size and color
Configuration reference for this comparison
| Configuration | Purpose | Related examples |
|---|---|---|
size | inherit | Icon size and color |
color | Icon color | Icon size and color |
Compare size and color independently of rotation, animation and click handling.
Content and presentation
Rotate Spin
Configuration reference for this comparison
| Configuration | Purpose | Related examples |
|---|---|---|
size | inherit | Rotate Spin |
rotate | Rotation angle | Rotate Spin |
spin | Whether to rotate continuously | Rotate Spin |
size: Controls the component size.
Catalog
Preview configuration: clearable, placeholder="搜索图标名称".
Customization and slots
Custom
Configuration reference for this comparison
| Configuration | Purpose | Related examples |
|---|---|---|
size | inherit | Custom |
color | Icon color | Custom |
size: Controls the component size.color: Overrides the color.
IconPark custom projects
You can use the SVG Symbol JS or Web Component JS generated by an IconPark custom project directly. Exporting individual SVG files or generating a Vue component for every icon is optional. These are SVG resource mechanisms, separate from loading text fonts with @font-face.
The public @icon-park/vue-next component package and your custom project's JS are separate resource sources. Installing the public package does not automatically include your team's uploaded or maintained icons.
| Approach | Resource source | Rendering | Loading unit |
|---|---|---|---|
| SVG Symbol JS | Custom project script | svg / use in the default slot | The icon collection in that file |
| Web Component JS | Custom project script | A custom element in the default slot | Depends on the generated implementation; do not assume individual icon loading |
| Individual SVG Vue components | Local files or a component package | Vue components in the default slot | Imported modules, subject to build configuration |
SVG Symbol is a suitable starting point: it reuses the Icon container without configuring Vue custom element recognition.
Current API: CIcon does not have a symbol prop and does not download, register or inject IconPark resources. The examples below use the existing default slot. name only resolves icon components registered in the current Vue application; it does not resolve Symbol IDs or Web Component icon names. Default slot content takes precedence over name.
SVG Symbol: load the project script
Copy the SVG Symbol script URL from your custom project and load it once in the application's HTML entry, such as index.html in a Vite application:
<!-- Example path: replace with your project URL or a locally deployed copy -->
<script src="/icons/project-symbol.js" defer></script>
After execution, the script should inject an SVG collection containing symbol nodes into the page. The application owns the resource URL and decides whether to use a remote URL or a deployed static file. The component library does not embed business project URLs. Load the script type you chose; using the same collection does not require loading both script variants.
SVG Symbol: reference an icon
Suppose the script injects <symbol id="project-home" viewBox="0 0 48 48">. You can render it as follows. Paths and IDs in these examples are placeholders; use the values in your generated output.
<script setup lang="ts">
import { Icon as CIcon } from '@cedar-design/ui'
import '@cedar-design/ui/icon/style'
</script>
<template>
<c-icon :size="24" color="#1677ff">
<svg width="1em" height="1em" aria-hidden="true">
<use href="#project-home" />
</svg>
</c-icon>
</template>
href uses the complete Symbol ID with a leading #. Display names, the library's name prop and IconPark icon names may differ from the Symbol ID. Do not invent or strip prefixes; inspect symbol[id] in developer tools. This references resources injected into the current page: do not use href="project.js#project-home".
size sets the container's font size, and the inner SVG follows it through 1em. rotate and spin affect the entire container. Without an explicit size, normal Icon size inheritance applies. Preserve the generated Symbol's viewBox to avoid clipping or incorrect scaling.
An application wrapper for shorter usage
Create an application component named ProjectIcon.vue if you want to pass an ID as a prop. This requires neither a library API change nor a generated Vue file for each icon:
<script setup lang="ts">
import { Icon as CIcon } from '@cedar-design/ui'
import '@cedar-design/ui/icon/style'
defineProps<{ symbol: string }>()
</script>
<template>
<c-icon>
<svg width="1em" height="1em" aria-hidden="true">
<use :href="`#${symbol}`" />
</svg>
</c-icon>
</template>
Use it in the application:
<script setup lang="ts">
import ProjectIcon from './ProjectIcon.vue'
</script>
<template>
<ProjectIcon symbol="project-home" :size="24" color="#1677ff" />
</template>
Here, symbol belongs to the application wrapper and excludes #. Undeclared attributes such as size, color, rotate and spin fall through to the single CIcon root. Forward $attrs explicitly if you add multiple roots or disable inheritAttrs. The existing transition prop only animates CIcon's name changes; it does not animate Symbol reference changes inside the slot.
Web Component: script and compiler configuration
Alternatively, load your project's Web Component JS and place its registered element in the slot. The following assumes the generated element is named iconpark-icon and uses a name attribute. Confirm element names, attributes and theme support against your project's generated usage instructions.
<!-- Application HTML entry; use the Web Component variant here -->
<script src="/icons/project-web-component.js" defer></script>
Configure the build that compiles Vue SFCs containing this tag to recognize the custom element. For Vite:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag === 'iconpark-icon',
},
},
}),
],
})
Merge this into the existing Vue plugin configuration instead of adding a duplicate plugin. isCustomElement is a compile-time setting; setting only app.config.compilerOptions does not replace this configuration when using a build tool. Configure the library build when the tag is wrapped inside library source, or the application build when application source uses the tag directly.
<template>
<c-icon :size="24" color="#1677ff">
<iconpark-icon name="project-home" size="1em"></iconpark-icon>
</c-icon>
</template>
This example uses the application's existing c-icon import or registration. The outer CIcon does not automatically forward theme, stroke width or other attributes to slot content. Set supported attributes directly on the custom element. If it uses Shadow DOM, external .c-icon svg rules cannot directly style its inner SVG; use the element's supported attributes, inherited styles or CSS variables.
Size, color and multicolor icons
| Setting | Behavior and limitations |
|---|---|
size | Symbol examples inherit through 1em; check the Web Component's own sizing API |
color | Works only when the graphic uses currentColor or supports corresponding inheritance |
Fixed fill / stroke | Colors embedded in the graphic are not automatically overridden by the container's color |
| Multicolor icons | Preserve their colors; avoid forcing a single fill or stroke across all paths |
| Themes and stroke width | Depend on generated output; public Vue icon package props do not automatically apply to project scripts |
On-demand loading and bundle size
Importing components on demand and loading icon resources are independent. Slot usage does not make CIcon depend on the entire IconPark package, and existing Resolver imports still work. The Resolver does not load resources based on a use ID.
A Symbol script that injects a collection loads that entire file. If it contains 200 icons and a page references three, all 200 are still downloaded and injected. href="#project-home" selects a graphic; it does not request an individual icon. A static script is outside the application's module tree-shaking analysis, and string IDs do not automatically remove unused Symbols.
| Goal | Approach |
|---|---|
| Small collection reused across pages | Load once at application entry and reuse the browser cache by file version |
| Large collection with distinct business modules | Split resources into shared and module collections; load each when its route or module needs it |
| Render the page before loading icons | Manage loading, failure and placeholder states in the application; show icons when resources are ready |
| Require individual icons to participate in tree shaking | Use separate SVG modules or Vue components and verify package exports and actual build output |
Remote JS is outside the library's npm package but still contributes to application download size. Updating the project requires updating generated resources and their cache versions. The component library's build size alone does not describe page cost.
Loading order, SSR and accessibility
- Make static resources available when icons are needed. For dynamic loading, wait for successful script execution. For Web Components,
customElements.whenDefined('iconpark-icon')can additionally wait for registration; it neither downloads the script nor automatically settles on a resource loading failure. - Load each resource once per application instead of inserting a script on every component mount. Keep Symbol IDs unique across collections to avoid conflicting references.
- Do not execute scripts requiring
window,documentorcustomElementson the server. Use HTML scripts or client lifecycle loading. When rendering conditionally, keep server and initial client placeholders consistent. Icons remain invisible until their resources exist; strict first-paint requirements need server-inlined Symbols or individual SVGs. - Use
aria-hidden="true"for decorative SVGs. Give standalone informative SVGsrole="img"and an accessible name. Give icon-only buttons anaria-labelon the button itself.
Troubleshooting
| Symptom | Check |
|---|---|
| Blank icon | Successful script execution, correct script variant, exact ID and nonzero container size |
Failed to resolve component: iconpark-icon | Compile-time isCustomElement configuration for the source containing the tag |
| Color does not change | Fixed graphic colors or the Web Component's supported color interface |
Size does not follow CIcon | Inner SVG / element sizing through 1em and any fixed pixel dimensions |
| Old icon after a project update | Current script version and browser / CDN caching |
| Works locally but fails after deployment | Resource base paths, network requests, CSP script-src and script execution errors |
| Wrong icon with multiple collections | Symbol ID collisions, duplicate scripts and the unique IDs in actual output |
References: Vue and Web Components, SVG use element.
Interaction and control
Click
Configuration reference for this comparison
| Configuration | Purpose | Related examples |
|---|---|---|
size | inherit | Click, Dynamic Name |
color | Icon color | Click |
name | Explicitly registered icon name | Dynamic Name |
transition | Name-change animation duration in ms | Dynamic Name |
size: Controls the component size.color: Overrides the color.
Dynamic Name
size: Controls the component size.
Lifecycle and edge cases
Lifecycle
Configuration reference for this comparison
| Configuration | Purpose | Related examples |
|---|---|---|
name | Explicitly registered icon name | Lifecycle |
transition | Name-change animation duration in ms | Lifecycle |
size | inherit | Lifecycle |
size: Controls the component size.
API
Icon Props
| Prop | Description | Type | Default |
|---|---|---|---|
| name | Explicitly registered icon name | string | - |
| size | inherit | number | string | - |
| color | Icon color | string | - |
| rotate | Rotation angle | number | - |
| spin | Whether to rotate continuously | boolean | false |
| transition | Name-change animation duration in ms | number | string | 0 |
| animation-class | Custom transition animation class | string | - |
Icon-xxx Props
| Prop | Description | Type | Default |
|---|---|---|---|
| size | inherit | number | string | - |
| color | Icon color | string | - |
| rotate | Rotation angle | number | - |
| spin | Whether to rotate | boolean | false |
| title | Accessible title | string | - |
| stroke-width | Stroke width | number | 4 |
| stroke-linecap | Stroke line cap | 'butt' | 'round' | 'square' | 'butt' |
| stroke-linejoin | Stroke line join | 'bevel' | 'inherit' | 'miter' | 'round' | 'miter' |
Icon Events
| Event | Description | Arguments |
|---|---|---|
| click | Click event | (event: MouseEvent) => void |
Icon Slots
| Slot | Description |
|---|---|
| default | Custom default content |
Type definitions
The component exports the following types
import type { IconProps } from "@cedar-design/ui";
Shared implementation and platform boundaries
Each platform maintains a complete local implementation. They do not import a common core or share component instances or reactive state. Changes must update both implementations. Component bodies, props, key styles and paired tests have read-only source consistency checks; theme tokens and installation entries remain local to each library.
Only icons registered in the current application are resolved. Repeated name changes cancel stale timers; no changes run after unmount. Each library locally adapts its registration prefix and legacy spin class; icon resources are not imported across libraries.
Icons inherit the host font size on both platforms. For a fixed 20px icon, set size="20" or icon-size explicitly. The size prop overrides the variable; color inherits from the host by default.
Motion variables
| Token | Default |
|---|---|
--c-icon-spin-duration | 1s |
Built-in motion follows prefers-reduced-motion: reduce: content and state feedback remain, while decorative spinning, shimmer and ripples stop. Icon name changes display the latest value immediately and cancel unfinished phases, keeping CSS and JS durations aligned. Callers must adapt custom animation classes. Ripple duration/cleanup follows Ripple documentation; its historical 250ms rule is not an Icon duration limit.