@whydrf/nava-icon-web-components 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +309 -0
- package/package.json +1 -1
package/LICENSE
CHANGED
package/README.md
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/whydrf/nava-icon/main/docs/public/favicon.svg" width="60" alt="Nava Icons">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">@whydrf/nava-icon-web-components</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
950+ beautiful, tree-shakeable SVG icons as native Web Components.
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/@whydrf/nava-icon-web-components"><img src="https://img.shields.io/npm/v/@whydrf/nava-icon-web-components?style=flat-square&color=purple" alt="npm version"></a>
|
|
13
|
+
<a href="https://github.com/whydrf/nava-icon/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@whydrf/nava-icon-web-components?style=flat-square" alt="license"></a>
|
|
14
|
+
<a href="https://www.npmjs.com/package/@whydrf/nava-icon-web-components"><img src="https://img.shields.io/npm/dm/@whydrf/nava-icon-web-components?style=flat-square&color=purple" alt="npm downloads"></a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## What is this?
|
|
20
|
+
|
|
21
|
+
`@whydrf/nava-icon-web-components` is the framework-agnostic binding for [Nava Icons](https://github.com/whydrf/nava-icon) — a collection of 950+ handcrafted SVG icons. Each icon is a native Web Component using the Custom Elements API, so it works everywhere: vanilla HTML, React, Vue, Angular, Svelte, Solid, Lit — any framework that can render HTML.
|
|
22
|
+
|
|
23
|
+
Unlike icon fonts or SVG sprites, every icon here is a proper Custom Element with Shadow DOM encapsulation. You use it in your markup exactly like any native HTML element — no framework, no build step, no configuration.
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @whydrf/nava-icon-web-components
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Requirements:** A browser that supports Custom Elements v1 (all modern browsers). No framework dependency.
|
|
32
|
+
|
|
33
|
+
## Getting Started
|
|
34
|
+
|
|
35
|
+
After installation, import the package to register all icon custom elements:
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<script type="module">
|
|
39
|
+
import '@whydrf/nava-icon-web-components'
|
|
40
|
+
</script>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Once imported, every icon becomes available as a custom element. Icons follow the pattern `<nava-icon-{name}>` in kebab-case:
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<nav>
|
|
47
|
+
<nava-icon-home size="24"></nava-icon-home>
|
|
48
|
+
<nava-icon-search size="24" color="gray"></nava-icon-search>
|
|
49
|
+
<nava-icon-settings size="24"></nava-icon-settings>
|
|
50
|
+
</nav>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
That's it — no framework, no components to import, no configuration. Just HTML.
|
|
54
|
+
|
|
55
|
+
## How Tree Shaking Works
|
|
56
|
+
|
|
57
|
+
When you import the package in a `<script type="module">`, only the icons actually used in your HTML are included in the final bundle. The build tool (Vite, Rollup, webpack, esbuild) traces which custom elements are referenced and eliminates the rest.
|
|
58
|
+
|
|
59
|
+
**Important:** Tree shaking only works with **static imports** in a module context. If you dynamically add icon elements at runtime (via `document.createElement`), all icons will be included because the bundler can't trace them.
|
|
60
|
+
|
|
61
|
+
```html
|
|
62
|
+
<!-- ✅ Tree-shakeable — only home and search are bundled -->
|
|
63
|
+
<script type="module">
|
|
64
|
+
import '@whydrf/nava-icon-web-components'
|
|
65
|
+
</script>
|
|
66
|
+
<nava-icon-home size="24"></nava-icon-home>
|
|
67
|
+
<nava-icon-search size="24"></nava-icon-search>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Two Variants: Regular and Filled
|
|
71
|
+
|
|
72
|
+
Every icon ships in two visual styles:
|
|
73
|
+
|
|
74
|
+
- **Regular** — Stroke-based outlines. Clean, minimal, and ideal for most UI contexts like navigation, toolbars, and forms.
|
|
75
|
+
- **Filled** — Solid shapes with filled regions. Great for emphasis, active states, or when you want an icon to stand out.
|
|
76
|
+
|
|
77
|
+
You control which variant to show with the `mode` attribute:
|
|
78
|
+
|
|
79
|
+
```html
|
|
80
|
+
<!-- Outline variant (default) -->
|
|
81
|
+
<nava-icon-heart size="24" mode="regular" color="gray"></nava-icon-heart>
|
|
82
|
+
|
|
83
|
+
<!-- Filled variant -->
|
|
84
|
+
<nava-icon-heart size="24" mode="filled" color="red"></nava-icon-heart>
|
|
85
|
+
|
|
86
|
+
<!-- Toggle with JavaScript -->
|
|
87
|
+
<script type="module">
|
|
88
|
+
import '@whydrf/nava-icon-web-components'
|
|
89
|
+
|
|
90
|
+
const heart = document.querySelector('nava-icon-heart')
|
|
91
|
+
heart.mode = heart.mode === 'filled' ? 'regular' : 'filled'
|
|
92
|
+
</script>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The mode switching is instant — no re-fetching, no lazy loading. Both variants are bundled together.
|
|
96
|
+
|
|
97
|
+
## Customizing Appearance
|
|
98
|
+
|
|
99
|
+
Since icons are standard SVG elements inside a Shadow DOM, you can customize them through their attributes. All attributes are reactive — changing them updates the icon instantly.
|
|
100
|
+
|
|
101
|
+
```html
|
|
102
|
+
<nava-icon-home
|
|
103
|
+
size="32"
|
|
104
|
+
color="#6366f1"
|
|
105
|
+
stroke-width="1"
|
|
106
|
+
style="transition: transform 0.2s; cursor: pointer"
|
|
107
|
+
onclick="handleClick()"
|
|
108
|
+
></nava-icon-home>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Colors
|
|
112
|
+
|
|
113
|
+
You can pass colors in any format the browser understands — hex codes, RGB, HSL, named colors, or CSS variables:
|
|
114
|
+
|
|
115
|
+
```html
|
|
116
|
+
<nava-icon-home color="#1a1a2e"></nava-icon-home> <!-- Hex -->
|
|
117
|
+
<nava-icon-home color="rgb(99, 102, 241)"></nava-icon-home> <!-- RGB -->
|
|
118
|
+
<nava-icon-home color="oklch(65% 0.27 264)"></nava-icon-home> <!-- OKLCH -->
|
|
119
|
+
<nava-icon-home color="var(--primary)"></nava-icon-home> <!-- CSS variable -->
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
With **Tailwind CSS**, the `color` attribute defaults to `currentColor`, so Tailwind's `text-*` utilities work directly:
|
|
123
|
+
|
|
124
|
+
```html
|
|
125
|
+
<!-- Combine color, size, and hover effects -->
|
|
126
|
+
<nava-icon-home class="text-emerald-400 w-8 h-8 hover:text-emerald-300 transition-colors"></nava-icon-home>
|
|
127
|
+
|
|
128
|
+
<!-- Dark mode support -->
|
|
129
|
+
<nava-icon-home class="text-gray-900 dark:text-white"></nava-icon-home>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### CSS Custom Properties
|
|
133
|
+
|
|
134
|
+
You can theme icons using CSS custom properties that inherit through the Shadow DOM:
|
|
135
|
+
|
|
136
|
+
```css
|
|
137
|
+
:root {
|
|
138
|
+
--icon-color: currentColor;
|
|
139
|
+
--icon-size: 24px;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.icon-large {
|
|
143
|
+
--icon-size: 48px;
|
|
144
|
+
--icon-color: #6366f1;
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
```html
|
|
149
|
+
<div class="icon-large">
|
|
150
|
+
<nava-icon-home size="var(--icon-size)" color="var(--icon-color)"></nava-icon-home>
|
|
151
|
+
</div>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Popular Icons
|
|
155
|
+
|
|
156
|
+
| Category | Icons |
|
|
157
|
+
|----------|-------|
|
|
158
|
+
| **Arrows** | `arrow-back`, `arrow-right`, `arrow-from-left`, `arrow-to-top`, `refresh`, `redo`, `undo` |
|
|
159
|
+
| **Interface** | `home`, `search`, `settings`, `menu`, `check-circle`, `x-circle`, `copy`, `trash` |
|
|
160
|
+
| **Communication** | `bell`, `mail`, `phone`, `message-square`, `send`, `at` |
|
|
161
|
+
| **Files** | `file`, `folder`, `download`, `upload`, `archive`, `clipboard` |
|
|
162
|
+
| **Media** | `camera`, `image`, `music`, `video`, `play`, `pause` |
|
|
163
|
+
| **Objects** | `star`, `bookmark`, `lock`, `key`, `award`, `gift` |
|
|
164
|
+
| **Weather** | `sun`, `moon`, `cloud`, `droplet`, `wind`, `umbrella` |
|
|
165
|
+
| **Shopping** | `cart`, `credit-card`, `bag`, `tag`, `badge`, `diamond` |
|
|
166
|
+
|
|
167
|
+
Browse all 950+ icons with live preview at [**nava-icons.dev**](https://nava-icons.dev).
|
|
168
|
+
|
|
169
|
+
## Accessibility
|
|
170
|
+
|
|
171
|
+
Icons include built-in accessibility features:
|
|
172
|
+
|
|
173
|
+
- When you provide a `title` attribute, an invisible `<title>` element is added inside the SVG, which screen readers announce.
|
|
174
|
+
- Decorative icons (no `title`) are implicitly `aria-hidden` since SVGs without titles are ignored by assistive technology.
|
|
175
|
+
|
|
176
|
+
```html
|
|
177
|
+
<!-- Meaningful icon — screen reader announces "Go to homepage" -->
|
|
178
|
+
<nava-icon-home title="Go to homepage"></nava-icon-home>
|
|
179
|
+
|
|
180
|
+
<!-- Decorative icon — screen reader ignores it -->
|
|
181
|
+
<nava-icon-home></nava-icon-home>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Framework Interop
|
|
185
|
+
|
|
186
|
+
Because Web Components are a browser standard, they work everywhere. Here's how to use them in popular frameworks:
|
|
187
|
+
|
|
188
|
+
### React
|
|
189
|
+
|
|
190
|
+
```jsx
|
|
191
|
+
// React needs a small wrapper — use the npm package directly for best DX
|
|
192
|
+
import { HomeIcon } from '@whydrf/nava-icon-react'
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Vue
|
|
196
|
+
|
|
197
|
+
```vue
|
|
198
|
+
<template>
|
|
199
|
+
<!-- Vue supports custom elements natively -->
|
|
200
|
+
<nava-icon-home :size="24" />
|
|
201
|
+
</template>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Angular
|
|
205
|
+
|
|
206
|
+
```html
|
|
207
|
+
<!-- Angular supports custom elements natively -->
|
|
208
|
+
<nav>
|
|
209
|
+
<nava-icon-home [attr.size]="24"></nava-icon-home>
|
|
210
|
+
</nav>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Svelte
|
|
214
|
+
|
|
215
|
+
```svelte
|
|
216
|
+
<script>
|
|
217
|
+
import '@whydrf/nava-icon-web-components'
|
|
218
|
+
</script>
|
|
219
|
+
|
|
220
|
+
<nava-icon-home size="24"></nava-icon-home>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Lit
|
|
224
|
+
|
|
225
|
+
```js
|
|
226
|
+
import '@whydrf/nava-icon-web-components'
|
|
227
|
+
import { html, LitElement } from 'lit'
|
|
228
|
+
|
|
229
|
+
class MyApp extends LitElement {
|
|
230
|
+
render() {
|
|
231
|
+
return html`<nava-icon-home size="24"></nava-icon-home>`
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Plain HTML
|
|
237
|
+
|
|
238
|
+
```html
|
|
239
|
+
<script type="module">
|
|
240
|
+
import '@whydrf/nava-icon-web-components'
|
|
241
|
+
</script>
|
|
242
|
+
|
|
243
|
+
<nava-icon-home size="24"></nava-icon-home>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Dynamic Icons with JavaScript
|
|
247
|
+
|
|
248
|
+
You can create, update, and remove icons dynamically using the standard DOM API:
|
|
249
|
+
|
|
250
|
+
```html
|
|
251
|
+
<script type="module">
|
|
252
|
+
import '@whydrf/nava-icon-web-components'
|
|
253
|
+
|
|
254
|
+
// Create a new icon
|
|
255
|
+
const icon = document.createElement('nava-icon-home')
|
|
256
|
+
icon.setAttribute('size', '24')
|
|
257
|
+
icon.setAttribute('color', 'blue')
|
|
258
|
+
document.body.appendChild(icon)
|
|
259
|
+
|
|
260
|
+
// Update an existing icon
|
|
261
|
+
const existing = document.querySelector('nava-icon-home')
|
|
262
|
+
existing.setAttribute('mode', 'filled')
|
|
263
|
+
existing.setAttribute('color', 'red')
|
|
264
|
+
|
|
265
|
+
// Remove an icon
|
|
266
|
+
existing.remove()
|
|
267
|
+
</script>
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Note:** Dynamically created icons won't benefit from tree shaking — all 950+ icons will be in your bundle.
|
|
271
|
+
|
|
272
|
+
## Server-Side Rendering
|
|
273
|
+
|
|
274
|
+
Web Components don't work during SSR (the Custom Elements API is only available in the browser). For SSR frameworks, use the framework-specific Nava Icons package instead:
|
|
275
|
+
|
|
276
|
+
| Framework | Package |
|
|
277
|
+
|-----------|---------|
|
|
278
|
+
| React / Next.js | `@whydrf/nava-icon-react` |
|
|
279
|
+
| Vue / Nuxt | `@whydrf/nava-icon-vue` |
|
|
280
|
+
| Angular | `@whydrf/nava-icon-angular` |
|
|
281
|
+
|
|
282
|
+
If you're using a framework with partial hydration (like Astro), use the Web Components package in client islands and the framework-specific package for server-rendered content.
|
|
283
|
+
|
|
284
|
+
## Attributes Reference
|
|
285
|
+
|
|
286
|
+
| Attribute | Type | Default | Description |
|
|
287
|
+
|-----------|------|---------|-------------|
|
|
288
|
+
| `size` | `number \| string` | `24` | Width and height in pixels |
|
|
289
|
+
| `color` | `string` | `currentColor` | SVG stroke/fill color. `currentColor` inherits from parent CSS |
|
|
290
|
+
| `stroke-width` | `number \| string` | `0.5` | Controls line thickness for stroke-based icons |
|
|
291
|
+
| `mode` | `"regular" \| "filled"` | `"regular"` | Toggles between outline and solid variants |
|
|
292
|
+
| `title` | `string` | — | Accessible title for screen readers |
|
|
293
|
+
|
|
294
|
+
All standard HTML attributes (`class`, `style`, `onclick`, `onmouseenter`, `data-*`, `aria-*`, etc.) are also supported.
|
|
295
|
+
|
|
296
|
+
## Custom Element Naming
|
|
297
|
+
|
|
298
|
+
Each icon is registered as a custom element with the prefix `nava-icon-` followed by the kebab-case icon name. Examples:
|
|
299
|
+
|
|
300
|
+
| Import Name | Custom Element |
|
|
301
|
+
|-------------|----------------|
|
|
302
|
+
| `HomeIconComponent` | `<nava-icon-home>` |
|
|
303
|
+
| `CheckCircleIconComponent` | `<nava-icon-check-circle>` |
|
|
304
|
+
| `ArrowRightIconComponent` | `<nava-icon-arrow-right>` |
|
|
305
|
+
| `CommandLineIconComponent` | `<nava-icon-command-line>` |
|
|
306
|
+
|
|
307
|
+
## License
|
|
308
|
+
|
|
309
|
+
[MIT](https://github.com/whydrf/nava-icon/blob/main/LICENSE) © [whydrf](https://github.com/whydrf)
|