Skip to content

Commit

Permalink
feat: add stories for @nuxtjs/storybook (#20)
Browse files Browse the repository at this point in the history
* feat: add stories for `@nuxtjs/storybook`

* chore: rename story scope

* docs: add storybook integration

* improve story UI
  • Loading branch information
farnabaz authored Jan 28, 2021
1 parent 20b009c commit e56498c
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 1 deletion.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,13 @@ export default {
</script>
```
## Integrations
### Storybook
If you are fan of storybook this might be interesting for you, This module provides a story to list and search available icons of your project. You can see stories under `stories` directory.
If you are using [`@nuxtjs/storybook`](https://storybook.nuxtjs.org) you can see the fontawesome stories under `Modules` section in your storybook. By default Font Awesome story will shows in your storybook, you disable/hide the story using [Storybook's `modules` option](/options#modules)



## License

[MIT License](./LICENSE)
Expand Down
4 changes: 4 additions & 0 deletions lib/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,8 @@ export default function fontawesomeModule (moduleOptions) {
fileName: 'fontawesome.js',
options
})

this.nuxt.hook('storybook:config', ({ stories }) => {
stories.push('@nuxtjs/fontawesome/stories/*.stories.js')
})
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"fontawesome"
],
"files": [
"lib"
"lib",
"stories"
],
"scripts": {
"dev": "nuxt example",
Expand Down
135 changes: 135 additions & 0 deletions stories/Iconslist.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<template>
<div class="ficon-container">
<div class="ficon-search-wrapper">
<input v-model="query" class="ficon-search" placeholder="Search Icons">
</div>
<div class="ficon-preview-wrapper">
<div v-for="icon in filteredIcons" :key="icon[1]" class="ficon-preview">
<div class="ficon-card">
<font-awesome-icon :icon="icon[1]" :class="size" />
<span class="ficon-name">{{ icon[1] }}</span>
<input
class="ficon-name-input"
type="text"
readonly
:value="`<font-awesome-icon icon='${icon[1]}' class='${size}' />`"
@click="copy"
>
</div>
</div>
</div>
</div>
</template>

<script>
export default {
props: {
size: {
type: String,
default: 'fa-2x'
},
onClick: {
type: Function,
default: () => () => {}
},
icons: {
type: Array,
default: () => ([])
}
},
data () {
return {
query: ''
}
},
computed: {
filteredIcons () {
return this.icons.filter(([_, name]) => name.match(this.query))
}
},
methods: {
copy (e) {
const el = e.target
el.select()
el.setSelectionRange(0, 99999)
document.execCommand('copy')
this.onClick(`Icon "${e.target.value}" copied to clipboard`)
}
}
}
</script>

<style scoped>
.ficon-container {
padding: 25px;
max-width: 1050px;
margin: 0 auto;
box-sizing: border-box;
}
.ficon-container * {
box-sizing: inherit
}
.ficon-search-wrapper {
margin: 10px 25px;
}
.ficon-sprite-title {
width: 100%;
text-align: center;
text-transform: uppercase;
font-family: monospace;
letter-spacing: 0.1em;
}
.ficon-search {
width: 100%;
height: 50px;
font-size: 20px;
text-indent: 10px;
}
.ficon-preview-wrapper {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.ficon-preview {
width: 200px;
height: 200px;
padding: 10px;
text-align: center;
}
.ficon-card {
width: 100%;
height: 100%;
border-radius: 5px;
padding: 5px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
position: relative;
}
.ficon-card:hover {
box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
}
.ficon-name {
margin-top: 10px;
font-family: monospace;
width: 100%;
color: #333;
background: #fff;
overflow: hidden;
padding: 2px;
border-radius: 3px;
}
.ficon-name-input {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
bottom: 0;
right: 0;
opacity: 0;
cursor: copy;
}
</style>
54 changes: 54 additions & 0 deletions stories/fontawesome.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { library } from '@fortawesome/fontawesome-svg-core'
import IconsList from './Iconslist.vue'
/**
* Gets icons from library with ["fas", "edit", "fasEdit"] shape
*
* @return array
*/
const getLibIcons = (library) => {
const data = library.definitions

const toPascalCase = (str) => {
const camelCase = str.replace(/-([a-z])/g, val => val[1].toUpperCase())
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1)
}

return (Object.keys(data).map(key =>
Object.keys(data[key]).map(value => [key, value, key + toPascalCase(value)])
)).reduce((current, next) => current.concat(next), [])
}

export default {
title: 'Modules/Font Awesome',
argTypes: {
size: {
name: 'Icons Size',
control: { type: 'select', options: ['fa-1x', 'fa-2x', 'fa-3x', 'fa-4x', 'fa-5x'] }
},
onClick: { action: 'clicked' }
}
}

export const Icons = () => ({
props: {
size: {
type: String,
default: 'fa-2x'
},
onClick: {
type: Function,
default: () => () => {}
}
},
components: { IconsList },
data () {
return {
icons: getLibIcons(library)
}
},
template: '<IconsList :icons="icons" :size="size" :onClick="onClick" />'
})

Icons.args = {
size: 'fa-2x'
}

0 comments on commit e56498c

Please sign in to comment.