@whydrf/nava-icon-web-components 0.1.0 → 1.0.1

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.
Files changed (3) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +309 -0
  3. package/package.json +4 -7
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 whydrf
3
+ Copyright (c) 2026 Whydrf
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
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) &copy; [whydrf](https://github.com/whydrf)
package/package.json CHANGED
@@ -1,24 +1,21 @@
1
1
  {
2
2
  "name": "@whydrf/nava-icon-web-components",
3
- "version": "0.1.0",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "./dist/icons/*.js"
7
7
  ],
8
8
  "description": "Web Components for Nava Icons",
9
- "main": "./dist/index.mjs",
10
- "module": "./dist/index.mjs",
9
+ "module": "./dist/index.js",
11
10
  "types": "./dist/index.d.ts",
12
11
  "exports": {
13
12
  ".": {
14
13
  "types": "./dist/index.d.ts",
15
- "import": "./dist/index.mjs",
16
- "require": "./dist/index.cjs"
14
+ "import": "./dist/index.js"
17
15
  },
18
16
  "./icons": {
19
17
  "types": "./dist/index.d.ts",
20
- "import": "./dist/index.mjs",
21
- "require": "./dist/index.cjs"
18
+ "import": "./dist/index.js"
22
19
  },
23
20
  "./package.json": "./package.json"
24
21
  },