1 | # Vue-Awesome
|
2 |
|
3 | > Awesome SVG icon component for Vue.js, with built-in Font Awesome icons.
|
4 |
|
5 | > [🇨🇳 中文版](./README.zh_CN.md)
|
6 |
|
7 | Vue-Awesome an SVG icon component for [Vue.js](https://vuejs.org/), with built-in icons courtesy of [Font Awesome](https://fontawesome.com/).
|
8 |
|
9 | Check out the demo [here](https://justineo.github.io/vue-awesome/demo/).
|
10 |
|
11 | ## Installation
|
12 |
|
13 | ### npm (Recommended)
|
14 |
|
15 | ```bash
|
16 | $ npm install vue-awesome
|
17 | ```
|
18 |
|
19 | ### bower
|
20 |
|
21 | ```bash
|
22 | $ bower install vue-awesome
|
23 | ```
|
24 |
|
25 | ### Manual
|
26 |
|
27 | Just download `dist/vue-awesome.js` and include it in your HTML file:
|
28 |
|
29 | ```html
|
30 | <script src="path/to/vue-awesome/dist/vue-awesome.js"></script>
|
31 | ```
|
32 |
|
33 | ## Usage
|
34 |
|
35 | ```html
|
36 | <!-- basic -->
|
37 | <v-icon name="beer"/>
|
38 |
|
39 | <!-- with options -->
|
40 | <v-icon name="sync" scale="2" spin/>
|
41 | <v-icon name="comment" flip="horizontal"/>
|
42 | <v-icon name="code-branch" label="Forked Repository"/>
|
43 |
|
44 | <!-- stacked icons -->
|
45 | <v-icon label="No Photos">
|
46 | <v-icon name="camera"/>
|
47 | <v-icon name="ban" scale="2" class="alert"/>
|
48 | </v-icon>
|
49 | ```
|
50 |
|
51 | Font Awesome 5 has separated all icons into several packs. Vue-Awesome is built upon its all free icons, which includes all free icons from 3 icon packs: `regular`, `solid` and `brands`. Since the `solid` pack has the most number of icons, we organize all Vue-Awesome icons as follows:
|
52 |
|
53 | * All icons from `solid` pack are located in `vue-awesome/icons` directory and have unprefixed `name` prop values.
|
54 |
|
55 | * Icons from `regular` and `brands` are located in `vue-awesome/icons/regular` and `vue-awesome/icons/brands`, which have prefixed `name` prop values like `regular/flag` or `brands/reddit`.
|
56 |
|
57 | You can find all available `name` values from [Font Awesome's website](https://fontawesome.com/icons) like `beer`, `file` and `camera`.
|
58 |
|
59 | ### ES Modules with NPM & vue-loader (Recommended)
|
60 |
|
61 | ```js
|
62 | import Vue from 'vue'
|
63 |
|
64 | /* Pick one way between the 2 following ways */
|
65 |
|
66 | // only import the icons you use to reduce bundle size
|
67 | import 'vue-awesome/icons/flag'
|
68 |
|
69 | // or import all icons if you don't care about bundle size
|
70 | import 'vue-awesome/icons'
|
71 |
|
72 | /* Register component with one of 2 methods */
|
73 |
|
74 | import Icon from 'vue-awesome/components/Icon'
|
75 |
|
76 | // globally (in your main .js file)
|
77 | Vue.component('v-icon', Icon)
|
78 |
|
79 | // or locally (in your component file)
|
80 | export default {
|
81 | components: {
|
82 | 'v-icon': Icon
|
83 | }
|
84 | }
|
85 | ```
|
86 |
|
87 | #### ⚠️ Heads up
|
88 |
|
89 | ##### Importing the souce version
|
90 |
|
91 | If you are using official Vue CLI to create your project and you want to use the untranspiled component (import `vue-awesome/components/Icon` rather than import `vue-awesome` directly, to optimize bundle size, which is recommended), you'll encounter the problem that the default configuration will exclude `node_modules` from files to be transpiled by Babel.
|
92 |
|
93 | For **Vue CLI 3+**, add `vue-awesome` into `transpileDependencies` in `vue.config.js` like this:
|
94 |
|
95 | ```js
|
96 | // vue.config.js
|
97 | module.exports = {
|
98 | transpileDependencies: [
|
99 | /\bvue-awesome\b/
|
100 | ]
|
101 | }
|
102 | ```
|
103 |
|
104 | For **Vue CLI 2** with the `webpack` template, modify `build/webpack.base.conf.js` like this:
|
105 |
|
106 | ```diff
|
107 | {
|
108 | test: /\.js$/,
|
109 | loader: 'babel-loader',
|
110 | - include: [resolve('src'), resolve('test')]
|
111 | + include: [
|
112 | + resolve('src'),
|
113 | + resolve('test'),
|
114 | + resolve('node_modules/vue-awesome')
|
115 | + ]
|
116 | }
|
117 | ```
|
118 |
|
119 | If you are using bare webpack config, just do similar modifications make it work.
|
120 |
|
121 | #### Using with Nuxt.js
|
122 |
|
123 | When using Vue-Awesome on the server side with Nuxt.js, it may prompt `Unexpected token import` because Nuxt.js has configured an `external` option by default, which prevent files under `node_modules` from being bundled into the server bundle with only a few exceptions. We need to whitelist `vue-awesome` in `nuxt.config.js` as follows:
|
124 |
|
125 | For **Nuxt.js 2**:
|
126 |
|
127 | ```js
|
128 |
|
129 | module.exports = {
|
130 | // ...
|
131 | build: {
|
132 | transpile: [/^vue-awesome/]
|
133 | }
|
134 | }
|
135 | ```
|
136 |
|
137 | For **Nuxt.js 1**:
|
138 |
|
139 | ```js
|
140 | // Don't forget to
|
141 | // npm i --save-dev webpack-node-externals
|
142 | const nodeExternals = require('webpack-node-externals')
|
143 |
|
144 | module.exports = {
|
145 | // ...
|
146 | build: {
|
147 | extend (config, { isServer }) {
|
148 | // ...
|
149 | if (isServer) {
|
150 | config.externals = [
|
151 | nodeExternals({
|
152 | // default value for `whitelist` is
|
153 | // [/es6-promise|\.(?!(?:js|json)$).{1,5}$/i]
|
154 | whitelist: [/es6-promise|\.(?!(?:js|json)$).{1,5}$/i, /^vue-awesome/]
|
155 | })
|
156 | ]
|
157 | }
|
158 | }
|
159 | }
|
160 | }
|
161 | ```
|
162 |
|
163 | ##### Unit Testing with Jest
|
164 |
|
165 | Make sure to whitelist `vue-awesome` from the `transformIgnorePattern`. Add following configuation in `test/unit/jest.conf.js`:
|
166 |
|
167 | ```diff
|
168 | + transformIgnorePatterns: [
|
169 | + '/node_modules(?![\\\\/]vue-awesome[\\\\/])/'
|
170 | + ],
|
171 | ```
|
172 |
|
173 | *Don't import all icons if you don't want to make unit testing slow because this will transform all icons from ES module and thus slow down the test process.*
|
174 |
|
175 | ### CommonJS with NPM without ES Next support
|
176 |
|
177 | ```js
|
178 | var Vue = require('vue')
|
179 |
|
180 | // requiring the UMD module
|
181 | var Icon = require('vue-awesome')
|
182 |
|
183 | // or with vue-loader you can require the src directly
|
184 | var Icon = require('vue-awesome/components/Icon')
|
185 |
|
186 | // register component to use
|
187 | ```
|
188 |
|
189 | ### AMD
|
190 |
|
191 | ```js
|
192 | require.config({
|
193 | paths: {
|
194 | 'vue-awesome': 'path/to/vue-awesome'
|
195 | }
|
196 | })
|
197 |
|
198 | require(['vue-awesome'], function (Icon) {
|
199 | // register component to use
|
200 | Vue.component('v-icon', Icon)
|
201 | })
|
202 | ```
|
203 |
|
204 | ### Global variable
|
205 |
|
206 | The component class is exposed as `window.VueAwesome`.
|
207 |
|
208 | ```js
|
209 | // register component to use
|
210 | Vue.component('v-icon', VueAwesome)
|
211 | ```
|
212 |
|
213 | ### Props
|
214 |
|
215 | * `name: string`
|
216 |
|
217 | The name of the icon. It's necessary if the component isn't used as the wrapper of an icon stack. All valid names correspond to the file path relative to the `icons` directory. Notice that you may have to check the name of the icon pack after you search on FontAwesome's website. For example, you'll see a URL argument of `style=brands` on the [detail page for `500px`](https://fontawesome.com/icons/500px?style=brands) and the icon name will be `brands/500px`.
|
218 |
|
219 | Only free icons for FontAwesome are available by default and because the `solid` style has the most icons, we've made it the default pack so the path prefixes can be omitted.
|
220 |
|
221 | If you pass `null` to this prop, the whole component will not be rendered.
|
222 |
|
223 | * `scale: number|string`
|
224 |
|
225 | Used to adjust the size of the icon. Default to `1`.
|
226 |
|
227 | * `spin: boolean`
|
228 |
|
229 | Used to specify whether the icon is spining. Default to `false`.
|
230 |
|
231 | * `inverse: boolean`
|
232 |
|
233 | If set to `true`, the color of the icon will become `#fff`. Default to `false`.
|
234 |
|
235 | * `pulse: boolean`
|
236 |
|
237 | Set the pulse effect to the icon. Default to `false`.
|
238 |
|
239 | * `flip: 'vertical'|'horizontal'|null`
|
240 |
|
241 | Used to flip the icon.
|
242 |
|
243 | * `label: string`
|
244 |
|
245 | Set the `aria-label` for the icon if provided.
|
246 |
|
247 | * `title: string`
|
248 |
|
249 | Set the title for the icon.
|
250 |
|
251 | > The icon will have `role="presentation"` thus not accessible when neither `label` nor `title` exists.
|
252 |
|
253 | ### Misc
|
254 |
|
255 | If you are using `vue-awesome/components/Icon` (instead of the whole bundled version), Vue-Awesome won't import a single icon by default. Do not forget to import icons you want to use.
|
256 |
|
257 | If these caveats don't help and there are no proper workarounds in [earlier issues](https://github.com/Justineo/vue-awesome/issues?utf8=%E2%9C%93&q=is%3Aissue), please feel free to [file a new one](https://github.com/Justineo/vue-awesome/issues/new).
|
258 |
|
259 | ## Styling
|
260 |
|
261 | ### Dynamic sizing
|
262 |
|
263 | You can make the icons scale dynamically according to your `font-size` by adding the following CSS:
|
264 |
|
265 | ```css
|
266 | .fa-icon {
|
267 | width: auto;
|
268 | height: 1em; /* or any other relative font sizes */
|
269 |
|
270 | /* You would have to include the following two lines to make this work in Safari */
|
271 | max-width: 100%;
|
272 | max-height: 100%;
|
273 | }
|
274 | ```
|
275 |
|
276 | ### Colors
|
277 |
|
278 | The icon color is inherited from the font color of the parent element by default. You can easily change it to any other color by specifying the `color` property.
|
279 |
|
280 | ## Local development
|
281 |
|
282 | ```bash
|
283 | $ npm i
|
284 | $ npm run dev
|
285 | ```
|
286 |
|
287 | Open `http://localhost:8080/demo` to see the demo.
|
288 |
|
289 | ### Updating icons
|
290 |
|
291 | Don't touch files in `src/icons` but update `assets/svg/*` instead and run `npm run icons` to re-generate icon module files.
|
292 |
|
293 | ## Registering custom icons
|
294 |
|
295 | ### Simple case
|
296 |
|
297 | You can register custom icons like this:
|
298 |
|
299 | ```js
|
300 | import Icon from 'vue-awesome/components/Icon'
|
301 |
|
302 | Icon.register({
|
303 | baidu: {
|
304 | width: 23.868,
|
305 | height: 26,
|
306 | d: 'M3.613 13.701c2.827-.608 2.442-3.986 2.357-4.725-.138-1.139-1.477-3.128-3.296-2.971C.386 6.21.052 9.515.052 9.515c-.309 1.528.74 4.793 3.561 4.186zm3.002 5.875c-.083.238-.268.846-.107 1.375.315 1.187 1.346 1.24 1.346 1.24h1.48v-3.619H7.749c-.713.213-1.057.767-1.134 1.004zM8.86 8.035c1.562 0 2.823-1.797 2.823-4.019C11.683 1.796 10.421 0 8.86 0 7.301 0 6.036 1.796 6.036 4.016c0 2.222 1.265 4.019 2.824 4.019zm6.724.265c2.087.271 3.429-1.956 3.695-3.644.272-1.686-1.074-3.644-2.552-3.98-1.48-.339-3.329 2.032-3.497 3.578-.2 1.89.271 3.778 2.354 4.046zm5.114 9.923s-3.229-2.498-5.113-5.198c-2.555-3.981-6.185-2.361-7.399-.337-1.209 2.024-3.093 3.305-3.36 3.644-.271.334-3.9 2.293-3.095 5.871.806 3.576 3.635 3.508 3.635 3.508s2.085.205 4.504-.336c2.42-.537 4.503.134 4.503.134s5.652 1.893 7.199-1.751c1.545-3.645-.874-5.535-.874-5.535zm-9.671 5.423H7.352c-1.587-.316-2.219-1.4-2.299-1.584-.078-.188-.528-1.059-.29-2.539.686-2.219 2.642-2.379 2.642-2.379h1.956V14.74l1.666.025v8.881zm6.844-.025h-4.229c-1.639-.423-1.716-1.587-1.716-1.587v-4.677l1.716-.027v4.203c.104.447.661.529.661.529h1.742v-4.705h1.825v6.264zm5.986-12.486c0-.808-.671-3.239-3.159-3.239-2.492 0-2.825 2.295-2.825 3.917 0 1.548.131 3.71 3.227 3.641 3.096-.068 2.757-3.507 2.757-4.319z'
|
307 | }
|
308 | })
|
309 | ```
|
310 |
|
311 | ### More advanced cases
|
312 |
|
313 | If your SVG file has more than one path or polygon, and/or you want to have a predefined style, you can register like this:
|
314 |
|
315 | #### Paths
|
316 |
|
317 | ```js
|
318 | import Icon from 'vue-awesome/components/Icon'
|
319 |
|
320 | Icon.register({
|
321 | webpack: {
|
322 | width: 1200,
|
323 | height: 1200,
|
324 | paths: [
|
325 | {
|
326 | style: 'fill:#8ED6FB',
|
327 | d: 'M1035.6 879.3l-418.1 236.5V931.6L878 788.3l157.6 91zm28.6-25.9V358.8l-153 88.3V765l153 88.4zm-901.5 25.9l418.1 236.5V931.6L320.3 788.3l-157.6 91zm-28.6-25.9V358.8l153 88.3V765l-153 88.4zM152 326.8L580.8 84.2v178.1L306.1 413.4l-2.1 1.2-152-87.8zm894.3 0L617.5 84.2v178.1l274.7 151.1 2.1 1.2 152-87.8z'
|
328 | },
|
329 | {
|
330 | style: 'fill:#1C78C0',
|
331 | d: 'M580.8 889.7l-257-141.3v-280l257 148.4v272.9zm36.7 0l257-141.3v-280l-257 148.4v272.9zm-18.3-283.6zM341.2 436l258-141.9 258 141.9-258 149-258-149z'
|
332 | }
|
333 | ]
|
334 | }
|
335 | })
|
336 | ```
|
337 |
|
338 | #### Polygons
|
339 |
|
340 | ```js
|
341 | import Icon from 'vue-awesome/components/Icon'
|
342 |
|
343 | Icon.register({
|
344 | vue: {
|
345 | width: 256,
|
346 | height: 221,
|
347 | polygons: [
|
348 | {
|
349 | style: 'fill:#41B883',
|
350 | points: '0,0 128,220.8 256,0 204.8,0 128,132.48 50.56,0 0,0'
|
351 | },
|
352 | {
|
353 | style: 'fill:#35495E',
|
354 | points: '50.56,0 128,133.12 204.8,0 157.44,0 128,51.2 97.92,0 50.56,0'
|
355 | }
|
356 | ]
|
357 | }
|
358 | })
|
359 | ```
|
360 |
|
361 | #### Raw SVG
|
362 |
|
363 | **If you are using Vue.js version prior to `2.6.0`, you need to include [innersvg-polyfill](https://www.npmjs.com/package/svg-innerhtml) before you use this feature.**
|
364 |
|
365 | ```js
|
366 | import Icon from 'vue-awesome/components/Icon'
|
367 |
|
368 | Icon.register({
|
369 | 'html5-c': {
|
370 | width: 512,
|
371 | height: 512,
|
372 | raw: '<path fill="#E34F26" d="M71,460 L30,0 481,0 440,460 255,512"/><path fill="#EF652A" d="M256,472 L405,431 440,37 256,37"/><path fill="#EBEBEB" d="M256,208 L181,208 176,150 256,150 256,94 255,94 114,94 115,109 129,265 256,265zM256,355 L255,355 192,338 188,293 158,293 132,293 139,382 255,414 256,414z"/><path fill="#FFF" d="M255,208 L255,265 325,265 318,338 255,355 255,414 371,382 372,372 385,223 387,208 371,208zM255,94 L255,129 255,150 255,150 392,150 392,150 392,150 393,138 396,109 397,94z"/>'
|
373 | }
|
374 | })
|
375 | ```
|