New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Addon-controls: configuring argTypes globally on preview.js #11697
Comments
To add another use-case: I showcase different themes for my components (the third party themes addon doesn't work in my case, because of how the classes are applied vs how I need them, and I'd prefer users be able to tinker with components all in one place). The theming is done as a value passed in via a property, which I've set controls up to display the arg as an enum (because only certain values will work). This arg is the same across all components and will contain the same selection options. The ideal way to set this up would be a global setting that provides that information without needing to add it to every single component. |
Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks! |
I'm happy to help someone get a PR over the line adding this. |
Hey! I'd love to try and tackle this. --- a/addons/controls/src/components/ControlsPanel.tsx
+++ b/addons/controls/src/components/ControlsPanel.tsx
@@ -1,30 +1,45 @@
import React, { FC } from 'react';
import { ArgsTable, NoControlsWarning } from '@storybook/components';
-import { useArgs, useArgTypes, useParameter } from '@storybook/api';
+import { ArgTypes, useArgs, useArgTypes, useParameter } from '@storybook/api';
import { PARAM_KEY } from '../constants';
interface ControlsParameters {
expanded?: boolean;
hideNoControlsWarning?: boolean;
+ argTypes?: ArgTypes;
}
export const ControlsPanel: FC = () => {
const [args, updateArgs, resetArgs] = useArgs();
const rows = useArgTypes();
const isArgsStory = useParameter<boolean>('__isArgsStory', false);
- const { expanded, hideNoControlsWarning = false } = useParameter<ControlsParameters>(
+ const { expanded, hideNoControlsWarning = false, argTypes } = useParameter<ControlsParameters>(
PARAM_KEY,
{}
);
const hasControls = Object.values(rows).filter((argType) => !!argType?.control).length > 0;
+
+ const rowsWithDefaults = Object
+ .entries(rows)
+ .reduce((sum , [key, value]) => {
+ const defaultControls = argTypes[key] ?? {};
+ return {
+ ...sum,
+ [key]: {
+ ...defaultControls,
+ ...value
+ }
+ }
+ }, {} as ArgTypes);
+
return (
<>
{(hasControls && isArgsStory) || hideNoControlsWarning ? null : <NoControlsWarning />}
<ArgsTable
{...{
compact: !expanded && hasControls,
- rows,
+ rows: rowsWithDefaults,
args,
updateArgs,
resetArgs, however, I'm a bit lost on how to test / experiment with this? Is there any guide i missed? |
Hi @PupoSDC -- I'm not quite sure what that snippet does but that's not what I had in mind. I was thinking we'd add a concept of "global" args/argTypes, similar to global parameters and decorators. We would wire it up so it made its way from the So basically we'd need to add:
|
Thank you for the extra information! This is my first time contributing here, so im not fully aware of the ecosystem. My idea, would have the Im just a bit lost, on how to test / develop this. is there any "development environment" i can quickly set up? Also, is it worth it for me to pick this up? Or is it already a WIP? |
This would be a simple way to prototype it for sure! We wouldn't want to leave them there long term as we'd reserve the right to use a different mechanism to store arg[Types] but it would be a simple way to try it out. I think right now we have a warning/error if you try and put them in there so a start could just be to drop the warning and try it out in some stories in official storybook. The instructions are here but my TLDR is:
Then I would add some more stories to the official storybook that use global args/arg types and see what happens.
Nope (not a WIP)! |
i was missing step 4. Thanks! I will try to work on this in the coming weekend! |
Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks! |
This would be lovely....what else does it need? |
I am also interested in this feature, except I would like to configure global custom props, rather than disable Here was my attempt to edit
Should I open a different feature request for this? |
@mancristiana I think you are looking for this feature (although it would be I am happy to help if you want to work on it. I think the comments I made above are still relevant. |
@tmeasday thanks for clarifying! You are correct, I meant |
@tmeasday could you update these steps since
I really appreciate your guidance, especially since this is my first time contributing to a popular open-source library ❤️ ! |
@mancristiana - good pickup! - I'll update the comment to be more accurate, but in short:
I'm not sure why it is a JS file, probably a webpack thing.
This file is actually where we transform the exported |
@mancristiana if you are still looking at this, this PR does a lot of similar things to the above and could be a useful reference: #14901 |
Thanks for the reference. I am still looking into this |
I made a bit of progress on this issue and added a draft pull request here #14934. How would you suggest implementing global |
The interesting thing about argTypes is that they don't need to relate to a property that exists in a component. If the argTypes are now only applied to components which expose the property, this would be a breaking change 🤔 |
Looks good so far, nice job.
Hmm, I'm not sure I agree with the semantics here. I think if you have: // in preview.js
export const argTypes = {
icon: { control: 'icon' },
}; Then you are saying "the arg type Maybe for the more subtle case of "if the arg type // in preview.js
export const argTypeEnhancers = [
({ argTypes }) => ({ ...argTypes, ...(argTypes.icon && { icon: { ...argTypes.icon, control: 'icon' } }),
]; WDYT @shilman? It's both harder to write and maybe more work for the store to process. Hmmm. An alternative would be not to treat an argType as "set" unless it has an actual |
@tmeasday I agree with your proposal. The semantics of args ArgTypes should be consistent with the other metadata we support: parameters & decorators both cascade, and ArgTypes should too. We have another mechanism for enriching the types of existing ArgTypes: matchers. I think this is a better user-facing API for augmenting ArgTypes, and we should reserve the "enhancer" API for addons and possibly not even expose this as a public API. |
@shilman Does your last comment mean that this is not going to be done at the end? Do you recommend then using the matchers approach? I have a similar use case, I have a theme property that I would like to control globally with a custom toolbar and a custom ThemeProvider, and then hide the Do you think some global matcher could help? Like
Thanks! |
@sauldeleon No, I agree with the basic premise of this issue. There's an internal API that @tmeasday was suggesting we might expose, and I was disagreeing with that. If you want a global theme, I would use |
matchers are great, but is there a way of disabling controls using them?
This would match the story defined version:
|
FYI this was implemented in 6.4, currently only for |
Olé!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.5.0-alpha.9 containing PR #17043 that references this issue. Upgrade today to the
Closing this issue. Please re-open if you think there's still more to do. |
..So in conclusion, if we want a conditional global argType (In order to hide if if there's no corresponding arg, as there's no reason to ever display a global argType if there's no arg for that component) we should do this? (Matchers obviously won't work because we can't assign categories, subcategories, disable, or name to them.) // in preview.js
export const argTypeEnhancers = [
({ argTypes }) => ({ ...argTypes, ...(argTypes.icon && { icon: { ...argTypes.icon, control: 'icon' } }),
]; Edit: // in preview.js
export const argTypes = {
text: { table: { category: "Global"}, if:{ arg: "text", exists: true }},
isDisabled: { table: { category: "Global"}, if:{ arg :"isDisabled", exists: true }},
}; Essentially, if your code has (Of course, this won't help at all if you've also defined a default arg inside |
@EliezerB123 thank your for this example, this is exactly what I need too. Our current 'workaround' is to have a global options, but we only want to show the control if it really exists in the args. We now do it like this: // .storybook/images.ts
type Image = {
name: string;
url: string;
}
const IMAGES = [
{ name: 'Awesome image', url: '/assets/img/awesome-image.jpg', },
// ..
];
const getImageArgType = (controlName: string, images: Image[]) => {
return {
control: {
type: 'select',
labels: images.reduce((a, b) => {
...a,
[b.url]: b.name,
}, {}),
},
options: images.map(image => image.url),
if: {
arg: controlName,
exists: true,
},
}
} // .storybook/preview.ts
export const argTypes = {
image: getImageArgType('image', IMAGES),
}; |
I don't think it should be based on whether an arg is provided or not. There is no need for a globally defined argType to render if the component doesn't even have that prop in its definitions. I want to display all the component's props without showing extra globally defined argTypes that don't apply to this specific component, currently there is no straight forward way to do it. Having to add a default prop for all props that i don't want to add to the args table isn't always reasonable. The other solution is to not use global arg types at all, which would be unfortunate because global argTypes are very convenient. |
Would be nice to have a way to configure some controls globally.
Example: imagine that all components contain one prop called
ComponentId
and we don't want this to be showing in the controls table.How we do now:
On each component.stories.tsx you have to configure it manually within the default export:
Proposal
Add this as configuration inside the preview.js
preview.js
And then it will be applied for all stories.
The text was updated successfully, but these errors were encountered: