Dùng 3.504 icon, 4 kiểu với framework của bạn, qua CDN, hoặc dưới dạng SVG thuần.
Healing Icons có 3.504 icon, 4 kiểu. Chọn gói hợp với dự án của bạn: gói nào cũng có cùng bộ icon, cùng tên và cùng tùy chọn.
Tên icon là tiếng Anh dạng kebab-case, ví dụ arrow-left. Tên component là PascalCase thêm hậu tố Icon: ArrowLeftIcon (tên bắt đầu bằng số thì thêm tiền tố: Icon2fa). Tìm tên icon bằng ô tìm kiếm ở thư viện icon, hoặc bấm Ctrl K.
Mỗi gói chia theo kiểu: …/outline (mặc định), …/outline-duo, …/fill và …/glyph-duo. Icon được vẽ trên lưới 18 × 18; icon outline có nét 1.5.
Icon một màu dùng currentColor, nên tự theo màu chữ nếu bạn không đặt color. Kiểu duo có thêm một lớp phụ, đổi màu riêng bằng secondaryColor.
import { HeartIcon } from "@healing-icons/react"; // outline (default)
import { HeartIcon as HeartFill } from "@healing-icons/react/fill";
export function Like({ liked }) {
return liked ? <HeartFill color="tomato" title="Liked" /> : <HeartIcon size={20} />;
}Mỗi icon là một module riêng nên bundler chỉ đóng gói icon bạn import. Có thể import từng file: import HeartIcon from "@healing-icons/react/outline/HeartIcon". Component chuyển tiếp ref và truyền các prop khác (className, onClick, aria-*) xuống <svg>. Dùng được trong Server Components.
<script setup>
import { HeartIcon } from "@healing-icons/vue";
import { HeartIcon as HeartFill } from "@healing-icons/vue/fill";
defineProps(["liked"]);
</script>
<template>
<HeartFill v-if="liked" color="tomato" title="Liked" />
<HeartIcon v-else :size="20" :stroke-width="2" />
</template>Cần Vue 3.3 trở lên. Prop viết được dạng kebab-case (secondary-color, stroke-width). class, style và sự kiện như @click được chuyển xuống <svg>.
<script>
import HeartIcon from "@healing-icons/svelte/outline/HeartIcon";
import HeartFill from "@healing-icons/svelte/fill/HeartIcon";
let { liked } = $props();
</script>
{#if liked}
<HeartFill color="tomato" title="Liked" />
{:else}
<HeartIcon size={20} />
{/if}Cần Svelte 5. Import từng icon (…/<style>/<Component>) là nhanh nhất, cả lúc dev lẫn lúc build. Import có tên như import { HeartIcon } from "@healing-icons/svelte/fill" vẫn dùng được và được tree-shake, nhưng dev server của Vite sẽ phải xử lý cả kiểu đó một lần.
import { Component, input } from "@angular/core";
import { HealingIcon, HeartIcon } from "@healing-icons/angular";
import { HeartIcon as HeartFill } from "@healing-icons/angular/fill";
@Component({
selector: "app-like",
imports: [HealingIcon],
template: `
@if (liked()) {
<healing-icon [icon]="HeartFill" color="tomato" title="Liked" />
} @else {
<healing-icon [icon]="HeartIcon" [size]="20" />
}
`,
})
export class LikeComponent {
readonly liked = input(false);
protected readonly HeartIcon = HeartIcon;
protected readonly HeartFill = HeartFill;
}Cần Angular 17 trở lên. <healing-icon> là standalone component; icon chỉ là dữ liệu nên bản build chỉ chứa icon bạn import. Hỗ trợ server rendering (hydration bỏ qua icon và vẽ lại ở client).
Với Expo, cài renderer bằng npx expo install react-native-svg.
import HeartIcon from "@healing-icons/react-native/outline/HeartIcon";
import HeartFill from "@healing-icons/react-native/fill/HeartIcon";
export function Like({ liked }: { liked: boolean }) {
return liked ? <HeartFill color="tomato" title="Liked" /> : <HeartIcon size={20} color="#14201b" />;
}React Native không có màu chữ kế thừa nên color mặc định là đen. Metro không tree-shake, nên hãy import từng icon như trên. title trở thành nhãn trợ năng; các prop khác của react-native-svg (style, onPress, testID) được truyền xuống <Svg>.
<healing-icon> dùng được trong HTML thuần và mọi framework. Cách nhanh nhất là qua CDN: bản lazy tự tải từng icon khi được dùng lần đầu.
<script type="module" src="https://cdn.jsdelivr.net/npm/@healing-icons/elements/dist/lazy.js"></script> <healing-icon name="heart"></healing-icon> <healing-icon name="heart" variant="fill" size="32" color="tomato" label="Liked"></healing-icon>
Khi dùng bundler, cài gói rồi import các icon bạn cần:
import "@healing-icons/elements"; import "@healing-icons/elements/outline/heart"; // registers <healing-icon name="heart"> import "@healing-icons/elements/fill/star"; // registers <healing-icon name="star" variant="fill">
Thuộc tính giống prop của component nhưng viết kebab-case (secondary-color, stroke-width, absolute-stroke-width); dùng label để đặt tên cho trình đọc màn hình. Icon nằm trong shadow root; chỉnh style bằng healing-icon::part(svg). Với Vue, khai báo là custom element (compilerOptions.isCustomElement); với Angular, thêm CUSTOM_ELEMENTS_SCHEMA.
Gói healing-icons chứa các file SVG đã tối ưu, ở healing-icons/svg/<style>/<name>.svg.
import heartUrl from "healing-icons/svg/outline/heart.svg";
<img src={heartUrl} width="24" height="24" alt="" />Mọi file đều có trên jsDelivr và unpkg. Khi chạy thật nên ghim phiên bản. <img> không theo được màu chữ; muốn vậy thì dùng icon làm CSS mask:
<img src="https://cdn.jsdelivr.net/npm/healing-icons@0.7/svg/outline/heart.svg" width="24" height="24" alt="">
<style>
.icon-heart {
width: 24px; height: 24px;
background: currentColor;
mask: url(https://cdn.jsdelivr.net/npm/healing-icons@0.7/svg/outline/heart.svg) center / contain no-repeat;
}
</style>Sprite gom nhiều icon vào một file. Tạo sprite chỉ với các icon bạn cần, rồi dùng bằng <use>:
npx healing-icons sprite heart star arrow-left --style outline --out public/icons.svg
<svg width="24" height="24"><use href="/icons.svg#heart"/></svg>
Trên thư viện icon, bấm Chọn để tải các icon đã chọn dưới dạng ZIP file SVG hoặc sprite.
Tìm icon có ảnh xem trước và chèn code đúng với file đang mở (Ctrl Alt I), tự thêm dòng import. Rê chuột lên tên icon để xem icon.
code --install-extension hoanghuilinh.healing-icons-vscode
Gói nào cũng có cùng các tùy chọn. React Native chỉ nhận số cho size; web component nhận chúng dưới dạng thuộc tính kebab-case.
| Thuộc tính | Mặc định | Mô tả |
|---|---|---|
| size | 24 | Chiều rộng và cao (số hoặc độ dài CSS) |
| color | currentColor | Màu icon; icon một màu tự theo màu chữ |
| secondaryColor | color | Màu lớp phụ của icon duo |
| strokeWidth | 1.5 | Độ dày nét của icon outline, theo đơn vị lưới (18 mỗi icon) |
| absoluteStrokeWidth | false | Tính strokeWidth theo pixel, giữ nguyên ở mọi cỡ |
| title | Tên cho trình đọc màn hình; không có thì icon bị ẩn với trình đọc |
Gói nào cũng export kiểu IconName (hợp của mọi tên icon) và IconStyle. Khi chỉ biết icon lúc chạy (CMS, cấu hình), DynamicIcon sẽ tải icon khi cần:
import { DynamicIcon, type IconName } from "@healing-icons/react/dynamic";
function MenuItem({ icon, label }: { icon: IconName; label: string }) {
return (
<li>
<DynamicIcon name={icon} variant="fill" fallback={<span className="size-6" />} />
{label}
</li>
);
}Vue và Svelte: DynamicIcon từ …/dynamic (có slot / snippet fallback). Angular: <healing-dynamic-icon [name]="…"> từ @healing-icons/angular/dynamic. Web component: bản lazy luôn tải theo tên.
Nên import tĩnh khi có thể. Với DynamicIcon, mỗi icon trở thành một chunk tải lười trong bản build (Metro của React Native thì gói tất cả vào), và hiện icon tốn thêm một request.
Mặc định icon chỉ để trang trí: trình đọc màn hình bỏ qua (aria-hidden). Khi icon tự mang ý nghĩa, hãy đặt title (label với web component), icon sẽ thành hình ảnh có tên đó.
// Icon-only button: name the button, keep the icon decorative. <button aria-label="Delete"><TrashIcon /></button> // Icon that stands alone <WarningIcon title="Warning" color="#b45309" />