Describe the bug
Previously I was dynamically adding stories, in CSF this I don't think is longer possible but I also noticed that knobs stopped working if I nested them.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Have knobs work when nested in a component.
Screenshots
If applicable, add screenshots to help explain your problem.
Code snippets
previous code:
import React from 'react';
import { storiesOf } from '@storybook/react';
import { withKnobs, select, boolean } from '@storybook/addon-knobs';
import { FontAwesomeIcon, library } from '..';
import startCase from 'lodash/startCase';
export const useKnobs = ({ prefix }) => {
const iconsArray = Object.keys(library.definitions[prefix]);
const border = boolean('Border', false);
const fixedWidth = boolean('Fixed Width', false);
const flip = select(
'Flip',
{
Horizontal: 'horizontal',
Vertical: 'vertical',
Both: 'both',
None: null,
},
null
);
const iconName = select(
'Name',
iconsArray.reduce(
(prefixes, prefix) => ({ ...prefixes, [startCase(prefix)]: prefix }),
{}
),
iconsArray[0]
);
const inverse = boolean('Inverse', false);
const listItem = boolean('List Item', false);
const pull = select(
'Pull',
{
Left: 'left',
Right: 'right',
None: null,
},
null
);
const pulse = boolean('Pulse', false);
const rotation = select(
'Rotation',
{ 90: 90, 180: 180, 270: 270, None: null },
null
);
const size = select(
'Size',
{
'1x': '1x',
'2x': '2x',
'3x': '3x',
'4x': '4x',
'5x': '5x',
'6x': '6x',
'7x': '7x',
'8x': '8x',
'9x': '9x',
'10x': '10x',
xs: 'xs',
sm: 'sm',
lg: 'lg',
},
'1x'
);
const spin = boolean('Spin', false);
return {
border,
fixedWidth,
flip,
iconName,
inverse,
listItem,
pull,
pulse,
rotation,
size,
spin,
};
};
const stories = storiesOf('UI|FontAwesomeIcon', module).addDecorator(withKnobs);
Object.keys(library.definitions).forEach(prefix => {
stories.add(prefix, () => {
const {
border,
fixedWidth,
flip,
iconName,
inverse,
listItem,
pull,
pulse,
rotation,
size,
spin,
} = useKnobs({ prefix });
return (
<FontAwesomeIcon
border={border}
fixedWidth={fixedWidth}
flip={flip}
icon={[prefix, iconName]}
inverse={inverse}
listItem={listItem}
pull={pull}
pulse={pulse}
rotation={rotation}
size={size}
spin={spin}
/>
);
});
});
Updated Code (which breaks knobs):
import React from 'react';
import PropTypes from 'prop-types';
import { withKnobs, select, boolean } from '@storybook/addon-knobs';
import { FontAwesomeIcon, library } from '..';
import startCase from 'lodash/startCase';
export const useKnobs = ({ prefix }) => {
const iconsArray = Object.keys(library.definitions[prefix]);
const border = boolean('Border', false);
const fixedWidth = boolean('Fixed Width', false);
const flip = select(
'Flip',
{
Horizontal: 'horizontal',
Vertical: 'vertical',
Both: 'both',
None: null,
},
null
);
const iconName = select(
'Name',
iconsArray.reduce(
(prefixes, prefix) => ({ ...prefixes, [startCase(prefix)]: prefix }),
{}
),
iconsArray[0]
);
const inverse = boolean('Inverse', false);
const listItem = boolean('List Item', false);
const pull = select(
'Pull',
{
Left: 'left',
Right: 'right',
None: null,
},
null
);
const pulse = boolean('Pulse', false);
const rotation = select(
'Rotation',
{ 90: 90, 180: 180, 270: 270, None: null },
null
);
const size = select(
'Size',
{
'1x': '1x',
'2x': '2x',
'3x': '3x',
'4x': '4x',
'5x': '5x',
'6x': '6x',
'7x': '7x',
'8x': '8x',
'9x': '9x',
'10x': '10x',
xs: 'xs',
sm: 'sm',
lg: 'lg',
},
'1x'
);
const spin = boolean('Spin', false);
return {
border,
fixedWidth,
flip,
iconName,
inverse,
listItem,
pull,
pulse,
rotation,
size,
spin,
};
};
export default {
title: 'UI|FontAwesomeIcon',
decorators: [withKnobs],
excludeStories: ['useKnobs'],
};
const Fai = ({ prefix }) => {
const {
border,
fixedWidth,
flip,
iconName,
inverse,
listItem,
pull,
pulse,
rotation,
size,
spin,
} = useKnobs({ prefix });
return (
<FontAwesomeIcon
border={border}
fixedWidth={fixedWidth}
flip={flip}
icon={[prefix, iconName]}
inverse={inverse}
listItem={listItem}
pull={pull}
pulse={pulse}
rotation={rotation}
size={size}
spin={spin}
/>
);
};
Fai.propTypes = {
prefix: PropTypes.oneOf(['fal', 'far', 'fas']).isRequired,
};
export const fal = () => <Fai prefix="fal" />;
export const far = () => <Fai prefix="far" />;
export const fas = () => <Fai prefix="fas" />;
System:
Please paste the results of npx -p @storybook/cli@next sb info here.
Environment Info:
System:
OS: macOS 10.15.2
CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
Binaries:
Node: 12.14.0 - ~/n/bin/node
Yarn: 1.21.1 - ~/.yarn/bin/yarn
npm: 6.13.4 - ~/n/bin/npm
Browsers:
Firefox: 70.0
Safari: 13.0.4
npmPackages:
@storybook/addon-actions: 5.3.2 => 5.3.2
@storybook/addon-knobs: 5.3.2 => 5.3.2
@storybook/addon-links: 5.3.2 => 5.3.2
@storybook/addon-viewport: 5.3.2 => 5.3.2
@storybook/addons: 5.3.2 => 5.3.2
@storybook/cli: 5.3.2 => 5.3.2
@storybook/react: 5.3.2 => 5.3.2
Additional context
Add any other context about the problem here.
for anyone running into the same issues, this is how I solved it:
import React from 'react';
import { withKnobs, select, boolean } from '@storybook/addon-knobs';
import { FontAwesomeIcon, library } from '..';
import startCase from 'lodash/startCase';
export default {
title: 'UI|FontAwesomeIcon',
decorators: [withKnobs],
};
export const fal = () => {
const border = boolean('Border', false);
const fixedWidth = boolean('Fixed Width', false);
const flip = flipSelect();
const icon = iconSelect('fal');
const inverse = boolean('Inverse', false);
const listItem = boolean('List Item', false);
const pull = pullSelect();
const pulse = boolean('Pulse', false);
const rotation = rotationSelect();
const size = sizeSelect();
const spin = boolean('Spin', false);
return (
<FontAwesomeIcon
border={border}
fixedWidth={fixedWidth}
flip={flip}
icon={icon}
inverse={inverse}
listItem={listItem}
pull={pull}
pulse={pulse}
rotation={rotation}
size={size}
spin={spin}
/>
);
};
export const far = () => {
const border = boolean('Border', false);
const fixedWidth = boolean('Fixed Width', false);
const flip = flipSelect();
const icon = iconSelect('far');
const inverse = boolean('Inverse', false);
const listItem = boolean('List Item', false);
const pull = pullSelect();
const pulse = boolean('Pulse', false);
const rotation = rotationSelect();
const size = sizeSelect();
const spin = boolean('Spin', false);
return (
<FontAwesomeIcon
border={border}
fixedWidth={fixedWidth}
flip={flip}
icon={icon}
inverse={inverse}
listItem={listItem}
pull={pull}
pulse={pulse}
rotation={rotation}
size={size}
spin={spin}
/>
);
};
export const fas = () => {
const border = boolean('Border', false);
const fixedWidth = boolean('Fixed Width', false);
const flip = flipSelect();
const icon = iconSelect('fas');
const inverse = boolean('Inverse', false);
const listItem = boolean('List Item', false);
const pull = pullSelect();
const pulse = boolean('Pulse', false);
const rotation = rotationSelect();
const size = sizeSelect();
const spin = boolean('Spin', false);
return (
<FontAwesomeIcon
border={border}
fixedWidth={fixedWidth}
flip={flip}
icon={icon}
inverse={inverse}
listItem={listItem}
pull={pull}
pulse={pulse}
rotation={rotation}
size={size}
spin={spin}
/>
);
};
function iconSelect(prefix) {
const iconsArray = Object.keys(library.definitions[prefix]);
return [
prefix,
select(
'Name',
iconsArray.reduce(
(prefixes, prefix) => ({
...prefixes,
[startCase(prefix)]: prefix,
}),
{}
),
iconsArray[0]
),
];
}
function sizeSelect() {
return select(
'Size',
{
'1x': '1x',
'2x': '2x',
'3x': '3x',
'4x': '4x',
'5x': '5x',
'6x': '6x',
'7x': '7x',
'8x': '8x',
'9x': '9x',
'10x': '10x',
xs: 'xs',
sm: 'sm',
lg: 'lg',
},
'1x'
);
}
function flipSelect() {
return select(
'Flip',
{
Horizontal: 'horizontal',
Vertical: 'vertical',
Both: 'both',
None: null,
},
null
);
}
function pullSelect() {
return select(
'Pull',
{
Left: 'left',
Right: 'right',
None: null,
},
null
);
}
function rotationSelect() {
return select('Rotation', { 90: 90, 180: 180, 270: 270, None: null }, null);
}
there's a bit of duplication, but I think its a decent implementation :)
Do you have a working example of this? I cannot seem to get font awesome icons showing in storybook.
@imcodingideas the example I provided is a working solution please follow the directions on creating an icon library using font-awesome.
https://www.npmjs.com/package/@fortawesome/react-fontawesome#build-a-library-to-reference-icons-throughout-your-app-more-conveniently
You're awesome. Thanks for replying. I converted my stories to CSF.
But I get:
Cannot convert undefined or null to object
TypeError: Cannot convert undefined or null to object
at keys (<anonymous>)
at Function.keys (http://localhost:6006/vendors~main.3d4df032770bbc1d0664.bundle.js:60949:24)
at iconSelect (http://localhost:6006/main.3d4df032770bbc1d0664.bundle.js:3090:27)
at push../src/app/library/components/Icons/icons.story.js.addSourceDecorator.__STORY__ (http://localhost:6006/main.3d4df032770bbc1d0664.bundle.js:3234:14)
at decorated (http://localhost:6006/vendors~main.3d4df032770bbc1d0664.bundle.js:32753:14)
at http://localhost:6006/vendors~main.3d4df032770bbc1d0664.bundle.js:20384:21
at http://localhost:6006/vendors~main.3d4df032770bbc1d0664.bundle.js:21687:16
at wrapper (http://localhost:6006/vendors~main.3d4df032770bbc1d0664.bundle.js:19956:12)
at http://localhost:6006/vendors~main.3d4df032770bbc1d0664.bundle.js:20860:14
at http://localhost:6006/vendors~main.3d4df032770bbc1d0664.bundle.js:20874:26
Font Awesome Works for me by itself
<FontAwesomeIcon icon={faPlusCircle} />
In your pull issue here I see you do something like import { FontAwesomeIcon, library } from '..'; but that doesn't work for me. This is what I have now:
import React from 'react';
import { withKnobs, select, boolean } from '@storybook/addon-knobs';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { library } from '@fortawesome/fontawesome-svg-core';
import { faPlusCircle } from '@fortawesome/free-solid-svg-icons';
import startCase from 'lodash/startCase';
export default {
title: 'UI|FontAwesome Icon',
decorators: [
withKnobs,
story => <div style={{ padding: '3rem' }}>{story()}</div>,
],
};
export const SimpleWorks = () => <FontAwesomeIcon icon={faPlusCircle} />;
export const CampaignFlagDoesNotWork = () => (
<FontAwesomeIcon icon={['fal', 'browser']} size="lg" />
);
CampaignFlagDoesNotWork.story = {
name: 'CampaignFlag (Does not work)',
};
function iconSelect(prefix) {
const iconsArray = Object.keys(library.definitions[prefix]);
return [
prefix,
select(
'Name',
iconsArray.reduce(
(prefixes, prefix) => ({
...prefixes,
[startCase(prefix)]: prefix,
}),
{}
),
iconsArray[0]
),
];
}
function sizeSelect() {
return select(
'Size',
{
'1x': '1x',
'2x': '2x',
'3x': '3x',
'4x': '4x',
'5x': '5x',
'6x': '6x',
'7x': '7x',
'8x': '8x',
'9x': '9x',
'10x': '10x',
xs: 'xs',
sm: 'sm',
lg: 'lg',
},
'1x'
);
}
function flipSelect() {
return select(
'Flip',
{
Horizontal: 'horizontal',
Vertical: 'vertical',
Both: 'both',
None: null,
},
null
);
}
function pullSelect() {
return select(
'Pull',
{
Left: 'left',
Right: 'right',
None: null,
},
null
);
}
function rotationSelect() {
return select('Rotation', { 90: 90, 180: 180, 270: 270, None: null }, null);
}
export const fal = () => {
const border = boolean('Border', false);
const fixedWidth = boolean('Fixed Width', false);
const flip = flipSelect();
const icon = iconSelect('fal');
const inverse = boolean('Inverse', false);
const listItem = boolean('List Item', false);
const pull = pullSelect();
const pulse = boolean('Pulse', false);
const rotation = rotationSelect();
const size = sizeSelect();
const spin = boolean('Spin', false);
return (
<FontAwesomeIcon
border={border}
fixedWidth={fixedWidth}
flip={flip}
icon={icon}
inverse={inverse}
listItem={listItem}
pull={pull}
pulse={pulse}
rotation={rotation}
size={size}
spin={spin}
/>
);
};
export const far = () => {
const border = boolean('Border', false);
const fixedWidth = boolean('Fixed Width', false);
const flip = flipSelect();
const icon = iconSelect('far');
const inverse = boolean('Inverse', false);
const listItem = boolean('List Item', false);
const pull = pullSelect();
const pulse = boolean('Pulse', false);
const rotation = rotationSelect();
const size = sizeSelect();
const spin = boolean('Spin', false);
return (
<FontAwesomeIcon
border={border}
fixedWidth={fixedWidth}
flip={flip}
icon={icon}
inverse={inverse}
listItem={listItem}
pull={pull}
pulse={pulse}
rotation={rotation}
size={size}
spin={spin}
/>
);
};
export const fas = () => {
const border = boolean('Border', false);
const fixedWidth = boolean('Fixed Width', false);
const flip = flipSelect();
const icon = iconSelect('fas');
const inverse = boolean('Inverse', false);
const listItem = boolean('List Item', false);
const pull = pullSelect();
const pulse = boolean('Pulse', false);
const rotation = rotationSelect();
const size = sizeSelect();
const spin = boolean('Spin', false);
return (
<FontAwesomeIcon
border={border}
fixedWidth={fixedWidth}
flip={flip}
icon={icon}
inverse={inverse}
listItem={listItem}
pull={pull}
pulse={pulse}
rotation={rotation}
size={size}
spin={spin}
/>
);
};
Maybe Im missing something, key here?