storybook: Addon-knobs not working unless applied directly in story props

Describe the bug Hard to describe, but the knobs are not working unless the options are directly defined in the props of the story. I normally define a props variable I can share between stories for common data. If I put any knob options in this props variable it will not display in the knobs tab in Storybook. Occasionally if I refresh the page I can see both select knobs, but if I change the width one it will just disappear completely. The widthThatWorks has no issue and does update in Storybook properly.

To Reproduce Run the story file code below.

Expected behavior The code below should display two select knob options. Occasionally displays both, but only one ever works.

Screenshots Here’s how it looks when they both finally display. Screenshot from 2019-06-27 08-26-40

What it looks like if you make a change to width. Screenshot from 2019-06-27 08-21-04

Code snippets

import { select, withKnobs } from '@storybook/addon-knobs';
import { moduleMetadata, storiesOf } from '@storybook/angular';

const props = {
  width: select('width', ['full', 'auto', 200, 320, 400, 600], 320)
};

storiesOf('Knob Test', module)
  .addDecorator(
    moduleMetadata({
      imports: []
    })
  )
  .addDecorator(withKnobs)
  .add('Basic', () => ({
    template: `
      width: {{ width }}<br>
      widthThatWorks: {{ widthThatWorks }}
    `,
    props: {
      ...props,
      widthThatWorks: select('widthThatWorks', ['full', 'auto', 200, 320, 400, 600], 320)
    }
  }));

System:

  • OS: Linux Ubuntu 18.04
  • Device: [e.g. iPhoneX, Macbook Pro 2018]
  • Browser: Chromium 75, Firefox 67
  • Framework: Angular
  • Addons: Knobs
  • Version: 5.1.8

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 2
  • Comments: 19 (3 by maintainers)

Commits related to this issue

Most upvoted comments

@matthewmorek Updated the title.

TBH, knobs is legacy code at this point and in need of a major cleanup. We’re hoping to rearchitect it for 6.0 to address these issues and more.

@nunoleong

import React from "react";
import { storiesOf } from "@storybook/react-native";
import { CardColorSquare, ICardColorSquare } from "./index";
import { select, text } from "@storybook/addon-knobs";

type TCardColorSquareArgs = (
  color?: string,
  groupID?: string,
) => ICardColorSquare;

export const CardColorSquareArgs: TCardColorSquareArgs = (
  color = 'pink',
  groupID= 'CardColorSquareArgs'
) => {
  return {
    color: select('color',['blue','red'], 'red', groupID),
  }
}

storiesOf("CardColorSquare", module).add("Basic", () => (
  <CardColorSquare {...CardColorSquareArgs()} />
  ));

Works fine for me!

@KoltonG, I’ve been using this pattern but it doesn’t seem to work for the select knob. From what I’m observing, that one still has to be defined as a prop to the component. Can you confirm on your end if that’s the case? Trying to figure out if it’s just a problem on my end.

👋 This is late to the convo since Storybook V6 is already out 🙈 but for those that are still facing this issue I found a workaround that is not too bad 😛

When defining your props, create a function similar to the one below

const componentProps = () => ({
  name: text("name", "Bob"),
  isAvailable: boolean("isAvailable", false),
  // You get the drift!
})

Then spread the function as your would with object props and call the function. Note that this is using the new Component Story Format (CSF).

export function isNotAvaiable() {
  return <Component {...componentProps()}/>
}

TLDR 🦄

export function isNotAvaiable() {
  return <Component {...componentProps()}/>
}

const componentProps = () => ({
  name: text("name", "Bob"),
  isAvailable: boolean("isAvailable", false),
  // You get the drift!
})

@chriscarpenter12 While we wait for this to be fixed, you can change your props to be inline functions.

const props = {
  width: () => select('width', ['full', 'auto', 200, 320, 400, 600], 320)
};

And then just invoke the function like width():

storiesOf('Knob Test', module)
  .addDecorator(
    moduleMetadata({
      imports: []
    })
  )
  .addDecorator(withKnobs)
  .add('Basic', () => ({
    template: `
      width: {{ width() }}<br>
    `,
    props: {
      ...props,
    }
  }));

I know it’s annoying, but it works.