Javascript
freelance
MTG addict
Aurélie VIOLETTE
Better performance
Easy deployment
Shallow learning curve
Bad projects teach you a lot
Aurélie.V, Jan 2019
Documentation
Devtools
Mocks
Unit tests
Design system
CI/CD
Living documentation
Visually driven developement
Main UX
=
React
Preview
=
Iframe
Channel
=
Events
import Accordion from './Accordion'
export default {
title: 'Components/Utils/Accordion',
component: Accordion,
}
export const BasicExample = () => ({
components: { Accordion },
data() {
return {
items: Array(5)
.fill(0)
.map((_, index) => index),
}
},
template: `
<Accordion :items="items">
<template v-slot:button="{ index, isExpanded }">Item {{ index }} ({{ isExpanded ? 'Opened' : 'Closed' }})</template>
<template v-slot:content="{ index }">Content of item {{ index }}</template>
</Accordion>
`,
})
Bring "Nuxt" logic
Bring business logic
Easy to do
Wrap
story
Inside
preview
Locally
or
Globally
import { addDecorator } from '@storybook/vue'
import AccessibilityWrapper from '~/components/AccessibilityWrapper'
addDecorator(storyFn => ({
components: { AccessibilityWrapper },
template: `<AccessibilityWrapper><story /></AccessibilityWrapper>`,
}))
import addons, { makeDecorator } from '@storybook/addons'
import { STORY_CHANGED } from '@storybook/core-events'
export const withStore = makeDecorator({
name: 'withStore',
parameterName: 'store',
skipIfNoParametersOrOptions: false,
wrapper: (getStory, context, { parameters = {} }) => {
const { modules = {} } = parameters
return {
created() {
for (name in modules) {
this.$store.registerModule(name, modules[name])
}
const channel = addons.getChannel()
channel.on(STORY_CHANGED, () => {
for (name in modules) {
this.$store.unregisterModule(name)
}
})
},
template: '<story></story>',
}
},
})
// preview.js
import { addDecorator } from '@storybook/vue'
import { withStore } from './addons/store'
addDecorator(withStore)
// Inside story
export const FrenchFooter = () => ({
components: { Footer },
template: '<Footer />',
})
FrenchFooter.story = {
parameters: {
store: {
modules: {
footer: footerStoreMock({ lang: 'fra-fr' }),
},
},
},
}
React components
Specific slot
Many components and hooks available
import { IconButton } from '@storybook/components'
import { styled } from '@storybook/theming'
import { useChannel, useAddonState } from '@storybook/api'
const ButtonLabel = styled.div(({ theme }) => ({
fontSize: theme.typography.size.s2 - 1,
}))
export const TextDirectionTool = () => {
const [state, setState] = useAddonState(`${ADDON_ID}-text-direction`, 'ltr')
const emit = useChannel()
function toggleTextDirection() {
const newState = state === 'ltr' ? 'rtl' : 'ltr'
setState(newState)
emit(TEXT_DIRECTION_CHANGED, newState)
}
return (
<IconButton onClick={toggleTextDirection}>
<ButtonLabel>{state.toUpperCase()}</ButtonLabel>
</IconButton>
)
}
// register.js
addons.register(`${ADDON_ID}`, api => {
addons.add(`${ADDON_ID}-text-direction`, {
title: 'text-direction switch',
type: types.TOOL,
match: ({ viewMode }) => viewMode === 'story',
render: () => <TextDirectionTool />,
})
})
// preview.js
const channel = addons.getChannel()
channel.on(TEXT_DIRECTION_CHANGED, direction => {
store.commit('setLocaleContext', { direction })
document.dir = direction
})
Different
pieces of UI
(tab, panel, ...)
Community addons
Rich API
Duplicate
build
Nuxt
pages
Third
parties
Process
Involves
everyone
Feedback earlier
Bringing joy to your dev is a sure path to success
Aurélie.V, Fév 2020
@purple_orwel
If you want more information