@uzum-tech/icons
@uzum-tech/icons
Корпоративная библиотека иконок Uzum Tech для Vue 3. Иконки сгруппированы по packs и категориям, поддерживают
currentColorи градиенты, типобезопасны и полностью tree-shakeable.
Возможности
- Vue 3, ESM + CJS, TypeScript-типы из коробки
- Иконки разделены на packs (
b2b, …) и категории (general,arrows,flags, …) - Sync-рендер —
renderIcon(name)мгновенно возвращаетVNodeиз встроенного реестра - Async-рендер —
renderAsyncIcon(name)возвращаетVNodeчерезdefineAsyncComponent+ dynamicimport(), каждая иконка в отдельном chunk-е - Async-only pack (
IconsB2BAsync) — реестр не встроен, initial bundle ~100 KB - Типобезопасные имена иконок: автодополнение и проверка на этапе компиляции
sideEffects: false— корректный tree-shaking- Никаких runtime-зависимостей кроме
vue - Интеграция с
u-config-providerиз@uzum-tech/ui
Установка
pnpm add @uzum-tech/icons
# или
npm i @uzum-tech/icons
# или
yarn add @uzum-tech/icons
Требуется
vue@^3.0.0(peer-зависимость).
Быстрый старт с @uzum-tech/ui
Самый удобный способ использования — через u-config-provider и u-icon:
<script setup lang="ts">
import { IconsB2B } from '@uzum-tech/icons'
const iconPacks = {
packs: [IconsB2B],
defaultPackName: 'b2b'
}
</script>
<template>
<u-config-provider :icon-packs="iconPacks">
<u-icon name="general/home-line" :size="24" />
<u-icon name="arrows/chevron-down-line" color="#666" />
<u-icon name="finance-ecommerce/wallet-solid" pack="b2b" />
</u-config-provider>
</template>
Пропс pack опционален — при отсутствии используется defaultPackName.
Sync vs Async
Sync (по умолчанию)
Весь реестр иконок встроен в пак-файл. Иконки рендерятся мгновенно, без сетевых запросов. Оптимально для большинства приложений.
import { IconsB2B } from '@uzum-tech/icons'
// IconsB2B: IconPack<B2BIconName>
// Имеет renderIcon (sync) и renderAsyncIcon (с dynamic import)
Async-only pack
Реестр не встроен. Каждая иконка — отдельный chunk, загружается по требованию. Подходит, если критичен начальный размер бандла и иконок используется немного.
import { IconsB2BAsync } from '@uzum-tech/icons'
// IconsB2BAsync: AsyncIconPack<B2BIconName>
// Только renderAsyncIcon — renderIcon недоступен
<script setup lang="ts">
import { IconsB2BAsync } from '@uzum-tech/icons'
const iconPacks = {
packs: [IconsB2BAsync],
defaultPackName: 'b2b',
async: true
}
</script>
<template>
<u-config-provider :icon-packs="iconPacks">
<Suspense>
<u-icon name="general/home-line" />
</Suspense>
</u-config-provider>
</template>
Сравнение размеров
IconsB2B (sync) |
IconsB2BAsync (async-only) |
|
|---|---|---|
| Пак-файл | ~1.2 MB | ~100 KB |
| Per-icon chunks | — | 872 × ~1 KB |
| Initial bundle при 20 иконках | 1.2 MB | ~120 KB |
Использование без @uzum-tech/ui
<script setup lang="ts">
import { IconsB2B, type B2BIconName } from '@uzum-tech/icons'
defineProps<{ name: B2BIconName }>()
</script>
<template>
<component :is="IconsB2B.renderIcon(name)" />
</template>
API
IconsB2B: IconPack<B2BIconName>
Sync-пак. Содержит встроенный реестр всех иконок b2b.
interface IconPack<Name extends string = string> extends IconPackBase<Name> {
renderIcon: (name: Name) => VNode
renderAsyncIcon: (name: Name) => VNode
}
IconsB2BAsync: AsyncIconPack<B2BIconName>
Async-only пак. Реестра нет — только loaders для dynamic import.
interface AsyncIconPack<Name extends string = string> extends IconPackBase<Name> {
renderAsyncIcon: (name: Name) => VNode
}
IconPackBase<Name>
Общий супертип для обоих видов паков.
interface IconPackBase<Name extends string = string> {
name: string
iconNames: readonly Name[]
}
B2BIconName
Union строковых литералов вида '<category>/<icon>':
import type { B2BIconName } from '@uzum-tech/icons'
const icon: B2BIconName = 'general/home-line' // ✅
const wrong: B2BIconName = 'general/does-not-exist' // ❌ ts error
createPack(options)
Фабрика sync-пака из своего SVG-реестра.
import { createPack, type IconRegistry } from '@uzum-tech/icons'
const registry: IconRegistry<'brand/logo'> = {
'brand/logo': {
attrs: { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
nodes: [{ tag: 'path', attrs: { d: 'M12 2 L22 22 L2 22 Z', fill: 'currentColor' } }]
}
}
export const IconsBrand = createPack({
name: 'brand',
registry,
loaders: { 'brand/logo': () => import('./chunks/brand/logo.es.js') }
})
createAsyncPack(options)
Фабрика async-only пака без реестра.
import { createAsyncPack } from '@uzum-tech/icons'
export const IconsBrandAsync = createAsyncPack({
name: 'brand',
iconNames: ['brand/logo'] as const,
loaders: { 'brand/logo': () => import('./chunks/brand/logo.es.js') }
})
IconPackRegistry — module augmentation
При импорте IconsB2B TypeScript автоматически регистрирует пак. Это даёт автодополнение pack и name в u-icon.
// встроено в dist/packs/b2b.d.ts:
declare module '@uzum-tech/icons' {
interface IconPackRegistry {
'b2b': typeof IconsB2B
}
}
Все публичные типы
import type {
AnyIconPack,
AsyncIconPack,
CreateAsyncPackOptions,
CreatePackOptions,
IconDefinition,
IconLoader,
IconPack,
IconPackBase,
IconPackRegistry,
IconRegistry,
SvgNode
} from '@uzum-tech/icons'
Содержимое pack b2b
872 иконки в 15 категориях:
| Категория | Кол-во |
|---|---|
general |
244 |
finance-ecommerce |
94 |
arrows |
81 |
media-devices |
81 |
files |
79 |
maps-travel |
42 |
communication |
38 |
time |
38 |
weather |
38 |
users |
32 |
others |
28 |
alerts-feedback |
24 |
charts |
23 |
security |
22 |
flags |
8 |
Имя иконки: <category>/<name>, например general/home-line, arrows/chevron-down-line.
Большинство иконок в двух стилях: *-line (контурная) и *-solid (заливная).
Полный список в рантайме: IconsB2B.iconNames.
Содержимое pack point
819 иконок в 15 категориях:
| Категория | Кол-во |
|---|---|
general |
227 |
files |
90 |
finance-ecommerce |
84 |
media-devices |
77 |
arrows |
74 |
maps-travel |
41 |
weather |
38 |
users |
34 |
time |
34 |
communication |
34 |
alerts-feedback |
29 |
security |
23 |
charts |
22 |
editor |
10 |
brand |
2 |
Имя иконки: <category>/<name>, например general/home-line, editor/format-align-left-line.
Большинство иконок в двух стилях: *-line (контурная) и *-solid (заливная). Категории editor и brand — расширение поверх набора b2b.
Полный список в рантайме: IconsPoint.iconNames.
Содержимое pack mainsite
53 иконки в 11 категориях:
| Категория | Кол-во |
|---|---|
general |
13 |
arrows |
13 |
finance-ecommerce |
5 |
files |
5 |
communication |
4 |
alerts-feedback |
3 |
time |
3 |
media-devices |
2 |
security |
2 |
users |
2 |
weather |
1 |
Имя иконки: <category>/<name>, например general/check-line, arrows/arrow-up-line.
Большинство иконок в двух стилях: *-line (контурная) и *-solid (заливная). Используется stroke-width="1.67" (в b2b / point — 2), поэтому визуально набор тоньше.
Исключения из currentColor. Три иконки — files/file-doc-badge, files/file-pdf-badge, files/file-xls-badge — это двухцветные плашки типов файлов (бренд-цвет фона + белый текст), viewBox="0 0 22 28". Они не наследуют CSS color и всегда рендерятся в своих фирменных цветах (#155EEF, #F9B225, #079455). Остальные 50 иконок — currentColor, как в b2b / point.
Полный список в рантайме: IconsMainsite.iconNames.
Структура dist/
dist/
├── index.es.js # ESM barrel
├── index.cjs # CJS barrel
├── index.d.ts
├── shared/
│ ├── types/types.d.ts # все типы
│ └── utils/ # createPack, createAsyncPack
└── packs/
├── b2b.es.js # sync pack (~1.2 MB)
├── b2b.async.es.js # async-only pack (~100 KB)
├── b2b.d.ts
├── b2b.async.d.ts
├── b2b/ # 872 per-icon chunks
│ ├── general/home-line.es.js
│ └── ...
├── point.es.js
├── point.async.es.js
├── point.d.ts
├── point.async.d.ts
├── point/ # 819 per-icon chunks
├── mainsite.es.js
├── mainsite.async.es.js
├── mainsite.d.ts
├── mainsite.async.d.ts
└── mainsite/ # 53 per-icon chunks
Контрибьютинг
Иконки хранятся в src/packs/<pack>/<category>/<name>.svg.
pnpm build # vite + tsc + build:registry
pnpm build:registry # перегенерировать только dist/packs/*
pnpm clean # удалить dist вручную
При добавлении SVG:
- корневой тег —
<svg>сviewBox - допустимые узлы:
- фигуры —
path,rect,circle,ellipse,line,polyline,polygon,use - контейнеры —
g,defs,clipPath,mask,pattern,symbol - градиенты —
linearGradient,radialGradient,stop
- фигуры —
- цвет
#101010автоматически заменяется наcurrentColorпри сборке — только в «красящих» атрибутах (fill,stroke,color,stop-color, …), так чтоd,idи прочее остаются нетронутыми
Градиенты, clip-path и маски
<defs> переносится в реестр целиком, поэтому иконка может сочетать
currentColor с фиксированными бренд-цветами — например others/humo-card:
подложка карты красится в currentColor, а логотип Humo остаётся золотым
градиентом.
Два нюанса сборки:
- id namespace.
idвнутри<defs>глобальны для документа, а Figma выдаёт их видаpaint0_linear_909_727— легко получить коллизию между иконками. При сборке каждыйid(и все ссылкиurl(#…)/href="#…"на него) получает префикс<pack>-<category>-<name>__. - Пустые
<clipPath>/<mask>. Figma нередко экспортирует их телом<rect fill="white"/>— безwidth/height. Такое определение ничего не рисует и спрятало бы иконку целиком, поэтому оно отбрасывается вместе с атрибутомclip-path/mask, который на него ссылался.
Ссылки
Related Packages
Vue library for Iconoir, the biggest open source icon library with tons of free...
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 1.2.8 | ^3.0.0 | ||
| 1.2.7 | ^3.0.0 | ||
| 1.2.6 | ^3.0.0 | ||
| 1.2.5 | ^3.0.0 | ||
| 1.2.4 | ^3.0.0 | ||
| 1.2.3 | ^3.0.0 | ||
| 1.2.2 | ^3.0.0 | ||
| 1.2.1 | ^3.0.0 | ||
| 1.2.0 | ^3.0.0 | ||
| 1.1.0 | ^3.0.0 | ||
| 1.0.0 | ^3.0.0 | ||
| 0.0.3 | MIT | ||
| 0.0.2 | MIT | ||
| 0.0.1 | MIT |