storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
83.49k stars 9.13k forks source link

Addon-controls: Add custom user-defined controls #11486

Open stefanhamburger opened 4 years ago

stefanhamburger commented 4 years ago

We are currently documenting our React components in Storybook, and decided to go straight to version 6.0 to make use of the new Args and Controls addons. During that work, we realised that the choice of controls is very limited.

Here are some examples:

Any chance to allow users to specify custom controls in argTypes that are not built into addon-controls?

Here's how this could look like in React code, where ColorPicker is a custom control we'd build:

const ColorPicker = ({ value, setValue }) => {
  return (
    <select value={value} onChange={setValue}>
      <option>red</option>
      <option>blue</option>
    </select>
  );
}

export default {
  title: "ExampleComponent",
  component: ExampleComponent,
  argTypes: {
    color: {
      control: ColorPicker,
    },
  },
};
ryaninvents commented 3 years ago

I'd be happy to start working on this. I'd like to add a gradient editor and rich text editor to my Storybook's controls without having to modify the core controls package.

Rycochet commented 3 years ago

One generic thing that would be good is nested controls. For arrays and tuples it is relatively simple (a tuple is a fixed length array) - in my use case I'd like to be able to have a [number, number] that can get the normal range options on it. Object types would likely be a bit more complicated - though the current way of pasting some JSON is pretty good for most situations.

I've not looked at the source, but I feel that making the recognition and control both generic, so certain ones can try to identify then including user-defined controls that support it (the aforementioned array type might be useful etc)

hydrosquall commented 3 years ago

Copying @ndelangen 's suggestion from another thread to make these user-defined controls lazy-loaded:

https://github.com/storybookjs/storybook/pull/12685#issuecomment-711761883

ndelangen commented 3 years ago

@stefanhamburger @hydrosquall @Rycochet @ryaninvents super excited to see ya'll helping 🙇

@shilman I'm concerned about:

export default {
  title: "ExampleComponent",
  component: ExampleComponent,
  argTypes: {
    color: {
      control: ColorPicker,
    },
  },
};

If the actual control component is specified in the story (preview), but the control component itself is displayed in an addon (manager) aren't we opening ourselves up to a world of hurt?

Should we not do this instead:

// story
export default {
  title: "ExampleComponent",
  component: ExampleComponent,
  argTypes: {
    color: {
      control: 'ControlColorPicker',
    },
  },
};
// some addon
addons.register('AddonControlsColorPicker', api => {
  addons.add('AddonControlsColorPicker', {
    type: addons.types.CONTROL,
    render: ColorPicker,
  }
})
Rycochet commented 3 years ago

@ndelangen I'm with you there - it's not so much a security thing, but being able to keep the definition and usage separate makes it easier to debug things. I do feel that it might be a little bit much for simple uses - but given a suitably "powerful" api for registering and using them it could probably reduce the need for actually doing things like that. Definitely needs a nice and simple example however it gets added so that people don't get confused over what to do, and what it can achieve ;-)

shilman commented 3 years ago

@ndelangen Yep, the user/addon needs to register a mapping from string to React component in both the preview and the manager, since the control will be rendered in both the addons panel AND in the docs page. The user would then reference that control by string in the argTypes annotation.

shilman commented 3 years ago

Strawman spec:

ndelangen commented 3 years ago

I'd be happy to assist in the creation of this

savgrace commented 3 years ago

I'd love to see OTB support for this as well.

stubar commented 3 years ago

For objects rather than editing a json string what about some kind of recursive docgen driven form. The UX would be hard to fathom admittedly. My immediate thought is you could click an edit CTA (where the json string is today) and the whole form is replaced by the child object's fields, breadcrumbs could allow for navigating back to parent.

CaptainN commented 3 years ago

There are sophisticated form generation tools, like uniforms. For most of my needs, I'd like to be able to simply pass a configured Schema in for particular properties with deep data structures, and have that form open in a dialog or something similar.

nathanielks commented 3 years ago

One generic thing that would be good is nested controls.

I would also be interested in adding controls for args with nested properties.

ndelangen commented 3 years ago

@nathanielks yes, that has come up a few time in discussions!

In particular in combination with args being composed from other stories!

davidpfahler commented 3 years ago

It would be really great to have custom control types. For example, I'd like to create a color control type for tailwindcss classes, specifically for color classes, so you can use a color-picker-style control type, but use tailwindcss classes.

What is holding this up? How can I help?

lvndry commented 2 years ago

It sounds like a very nice feature to have, I'd love to help make this happen :)

jsduffy commented 2 years ago

We could use this too!

WebTerminator commented 2 years ago

is there any update on this? Thank you

harleyharl commented 2 years ago

I'm keen for this too! Any new update?

markrocks commented 2 years ago

I would love this as well1 +1

gereltod-g commented 2 years ago

I would love to use it.

adamlohner commented 2 years ago

@shilman @ndelangen can y'all confirm if this is anywhere on the roadmap?

shilman commented 2 years ago

@adamlohner we'd love to add this but only after things are a lot more stable -- perhaps 7.x-8.0 timeframe.

franktopel commented 1 year ago

It's been more than two years, and this is a very common need... How long is it gonna take?

Klowes commented 1 year ago

I'd appreciate this feature, I think you should just open this up for us.

just let us straight register components to be used as controls, I'm writing a Vue app, but I'd gladly do some react like it's 2018 if that was supported 😛

cmcnicholas commented 1 year ago

Give me this! We have a big component library now with models of varying complexity and the simple controls just don't cut it.

pseudotsuga-fir commented 1 year ago

I'm surprised it's not yet something you can do in storybook! Definitely worth bumping priority up on.

i-am-the-slime commented 1 year ago

What is it with the entitledness in the comments? If you want this functionality, create a PR that adds it or create your own custom controls addon.

Klowes commented 1 year ago

@i-am-the-slime idk about you but my company is def not paying me to build out storybook

GideonMax commented 1 year ago

@i-am-the-slime with all due respect, some people don't want to have to learn how addons work, then understand how the controls addon works internally, then change it to allow for custom controls, then go through the process of a PR

zb-sj commented 1 year ago

I've gathered a dirty workaround while #21566 is on the way.

This just injects invokable button to the controls.

I might be able to generalize the implementation to add any custom controls and publish proper addon package if there is enough demand.

gotwig commented 9 months ago

I've gathered a dirty workaround while #21566 is on the way.

This just injects invokable button to the controls.

I might be able to generalize the implementation to add any custom controls and publish proper addon package if there is enough demand.

Very nice, thanks. Is there also a solution for Angular? I was thinking about using Angular Material with mat-select and mat-autocomplete (so you can for example add icons or prefix to select input)

zb-sj commented 9 months ago

Very nice, thanks. Is there also a solution for Angular? I was thinking about using Angular Material with mat-select and mat-autocomplete (so you can for example add icons or prefix to select input)

I'm afraid the Storybook UI itself is built with React. It would be difficult and not feasible to use Angular component on React

gotwig commented 9 months ago

Very nice, thanks. Is there also a solution for Angular? I was thinking about using Angular Material with mat-select and mat-autocomplete (so you can for example add icons or prefix to select input)

I'm afraid the Storybook UI itself is built with React. It would be difficult and not feasible to use Angular component on React

Alright. What I am looking for is a control select with html options, so we can for example show icons in front of option names :)

dmamontov commented 9 months ago

@zb-sj Hello, it seems to me that gist is missing constants and InvokerControl. Can I please see them somehow? otherwise I don’t see the full picture. I would like to implement custom controls.

zb-sj commented 9 months ago

Alright. What I am looking for is a control select with html options, so we can for example show icons in front of option names :)

Sounds cool! Please share your implements if possible. 😄

@zb-sj Hello, it seems to me that gist is missing constants and InvokerControl. Can I please see them somehow? otherwise I don’t see the full picture. I would like to implement custom controls.

@dmamontov 😢 I'm sorry for inconvenience. I must have made mistake. I've updated the gist to include missing file. Please let me know if there's something other missing.

Note I'd also note that latest Storybook has small issue with the workaround which I had no spare time to fix. The custom controls won't re-render if panel has changed. Reset Controls button (which looks like: ↩️) should force render. Any suggestion would be welcomed!

samvv commented 7 months ago

If it's feasible I'd like to look into it. I really need this and I have some spare time. I'll try to continue where @dobrinyonkov stopped.

There are sophisticated form generation tools, like uniforms. For most of my needs, I'd like to be able to simply pass a configured Schema in for particular properties with deep data structures, and have that form open in a dialog or something similar.

That's not really related to this issue, I believe. This issue isn't about adding more built-in controls (like the ones you are describing), but about being able to write your own for whatever purpose you want.