Display Multiple Variants in Storybook Without Multiple Stories? - storybook

I am building a Storybook and would like to display multiple variants of the same component in the 'Docs' tab, without creating new stories under the component in the left nav. Is this possible?
For example, I have the following component:
export const Template = (args) => (
<Alert {...args}></Alert>
)
<Canvas>
<Story
name="Filled Alert"
args={{
children: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
severity: 'info',
variant: 'filled'
}}>
{Template.bind({})}
</Story>
</Canvas>
This component has multiple severity values that I would like to show ('info', 'success', 'warning', 'error'). If I create another <Story> to show that variant in the documentation:
<Story
name="Filled Alert - Success"
args={{
children: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
severity: 'success',
variant: 'filled'
}}>
{Template.bind({})}
</Story>
In this case, I'll get two entries under 'Alert' for each of the stories above. What I'd like though is only a single 'Filled Alert' entry. The Canvas showing a single component that can be played with and the Docs showing my MDX documentation.
But (to make it more tricky), I am trying to get a unique entry for each variant property. So:
Alert
Filled Alert
Standard Alert
Outline Alert
Each of the sub-bullets showing different severity, but not creating new children.

Have you tried using #addon-knobs as referenced on this SO post?
The #addon-knobs has been deprecated in favor of #addon-controls.

Related

How do I import a Google Font with a space in the title in Next.js with #next/font/google?

The Next.js documentation on importing Google Fonts shows this recommended method of importing Google fonts:
import { Inter } from '#next/font/google'
const inter = Inter({ subsets: ['latin'] })
export default function MyComponent() {
return (
<main className={inter.className}>
Lorem ipsum dolar set amut
</main>
)
}
This method works for the Inter font and other fonts with single word titles. I'm trying to import a font called Redacted Script which has a space in the title.
I tried just TitleCasing it:
import { RedactedScript } from '#next/font/google'
const redactedScript = RedactedScript({ subsets: ['latin'] })
export default function MyComponent() {
return (
<main className={redactedScript.className}>
Lorem ipsum dolar set amut
</main>
)
}
However this code gives me the error:
`#next/font` error:
Unknown font `RedactedScript`
How do I use #next/font/google to import a Google font with a space in it like Redacted Script?
Thanks to a really cool guy at Vercel helping me debug this I've got the answer: Capital_Snake_Case!
Here's the working code:
import { Redacted_Script } from '#next/font/google'
const redactedScript = Redacted_Script({ subsets: ['latin'] })
export default function MyComponent() {
return (
<main className={redactedScript.className}>
Lorem ipsum dolar set amut
</main>
)
}

djangocms-text-ckeditor how to stop it removing HTML tags and attributes

(1) Using the docker image of django cms obtained from
django cms install docker image
(2) The version of CKEditor being used (taken from requirement.txt) is:
djangocms-text-ckeditor==5.1.1
(3) The directory structure is
(4) cms_plugin.py has
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
from cms.models.pluginmodel import CMSPlugin
from django.utils.translation import gettext_lazy as _
from .models import AvilonLayout3Column
#plugin_pool.register_plugin
class AvilonLayout3ColumnPlugin(CMSPluginBase):
model = AvilonLayout3Column
render_template = "AvilonLayout3Column.html"
cache = False
(5) models.py
from cms.models.pluginmodel import CMSPlugin
from django.db import models
from djangocms_text_ckeditor.fields import HTMLField
class AvilonLayout3Column(CMSPlugin):
title = models.CharField(max_length=50, default='Pricing')
column_1_featureColumn=models.BooleanField (default=False)
column_1_heading=models.CharField(max_length=50, default='Free')
#----------- HTMLField defined -----------------
column_1_content=HTMLField(blank=True)
#-----------------------------------------------
column_1_button_show=models.BooleanField (default=True)
column_1_button_text=models.CharField(max_length=20, default='Get Started')
(7) CKEditior is removing attributes from HTML tags for example
If this is input:
<ul>
<li>
<i class='bi bi-check-circle'>
</i>
Quam adipiscing vitae proin
</li>
<li>
<i class='bi bi-check-circle'></i>
Nec feugiat nisl pretium
</li>
<li>
<i class='bi bi-check-circle'></i>
Nulla at volutpat diam uteera
</li>
</ul>
It is converted to:
<ul>
<li>Quam adipiscing vitae proin</li>
<li>Nec feugiat nisl pretium</li>
<li>Nulla at volutpat diam uteera</li>
</ul>
namely, the i tags and class attributes are removed.
(8) I know that this is due to CKEditor and when the above behavior is reported elsewhere people are often saying that the config.allowedContent should be set to true and then there is reference in other articles about extraAllowedContent needing to be set
(9) Then elsewhere it is stated that amending your settings.py file could address the situation adding
CKEDITOR_SETTINGS_AvilonLayout3ColumnPricing={
'toolbar_HTMLField':[
[
'Undo',
'Redo',
]
],
'basicEntities': False,
'entities': False,
'TEXT_HTML_SANITIZE': False,
}
but, does this mean i add the above in the backend/settings.py file or somewhere else? If the former then this doesn't work
(10) the CKEditior plugin directory from the docker images looks like this:
(11) So am trying to get the plugin field's CKEditor to over ride it's default behaviour - this plugin field:
Any ideas how I over-ride the default behavior so the i tag and it's attribute of class stay put and are not removed by CKEditor
Useful resource: https://github.com/django-cms/djangocms-text-ckeditor
Just can't get the advice in the above resource to work.
The setting should be added to your settings.py file.
The specific settings can be found here: https://docs-old.ckeditor.com/ckeditor_api/symbols/CKEDITOR.config.html
I can see that the setting you have doesn't match the model, your setting: CKEDITOR_SETTINGS_AvilonLayout3ColumnPricing, I think should be: CKEDITOR_SETTINGS_AvilonLayout3Column
May also be worth adding the htmlEncodeOutput setting: https://docs-old.ckeditor.com/ckeditor_api/symbols/CKEDITOR.config.html#.htmlEncodeOutput
The HTML field does have some limitations for plugins, but I think the configuration should work ok.

React NextJs Add Link as componenet into a string

I need to build nextJs links programatically.
A simple example:
const link = <Link href={'/example'}>ipsum</Link>
const text = 'Lorem ipsum dolor sit amet'
const replaced = text.replaceAll('ipsum', link);
But the result is:
Lorem [object Object] dolor sit amet
How can i replace a string with a link componenet without destroying the react component?
Thank you
Concatenating components in a string will result in displaying [object Object] because eventually that component is an object and will get coerced into a string to fit in.
What would work in react to achieve your goal is to use arrays instead.
const link = <Link href={'/example'}>ipsum</Link>
const text = 'Lorem ipsum dolor sit amet'
const res = text.split(" ").reduce((acc, curr) => {
if (curr === "ipsum") {
return [...acc, link];
}
return [...acc, ` ${curr} `];
}, []);
return <>{res}</>
The fragment would display the array of objects as you expect it to be.

How can hide storybook control per story arg

I have rails engine project using storybook and mdx files to specify the controls
but i need to hide specific control per story
<Meta
title='Label Component'
story='with_tooltip'
args={{
object: 'employee',
field_name: 'name',
text: 'Employee name',
tooltip: 'Lorem ipsum dolor sit amet, consectetur adipiscing eli'
}}
/>
I have two stories [label,with_tooltip]
in case label story i need to hide tooltip control
I'm using view component preview to show components
You can disable controls for individual properties of a story including the prop table documentation, or you can disable only the control and leave the prop table documentation intact.
To disable the control and prop table documentation for the tooltip prop:
<Meta
title='Label Component'
story='with_tooltip'
args={{
object: 'employee',
field_name: 'name',
text: 'Employee name',
tooltip: 'Lorem ipsum dolor sit amet, consectetur adipiscing eli'
}}
argTypes={{
tooltip: {
table: {
disable: true
}
}
}}
/>
To disable the control but leave the prop table documentation intact for the tooltip prop:
<Meta
title='Label Component'
story='with_tooltip'
args={{
object: 'employee',
field_name: 'name',
text: 'Employee name',
tooltip: 'Lorem ipsum dolor sit amet, consectetur adipiscing eli'
}}
argTypes={{
tooltip: {
control: false
}
}}
/>
See the Storybook docs on disabling controls for specific properties.
The best approach is doing this:
export default {
title: 'Pages/Login ',
component: Login,
parameters:{
controls:{
exclude:/.*/g
}
}
} as ComponentMeta<typeof Login>;
For someone searching for a way to remove the control and change the control count, use amir's answer:
parameters:{
controls:{
exclude:/.*/g
}
}
But changing the regex '/.*/g'(used to remove all the controls) for either:
Another regex that works for you.
A string with the name of the control you want to disable.
The following regex, changing the passing the names of the controls you want to disable between pipes(|).
(?:\b|')(string1|string2|string3)(?:\b|')
For anyone that wants the explanation for the regex, you can read this comment.

Is it possible to use css in .js file in a react app?

I want to map .js file. I need to apply some CSS too. Is it possible to place CSS in a .js file?
I have a constant file at src > Constant > AboutMyselftProgressCount.js and it's code is as below:
const AboutMyselfProgressCount = [
{
ProgressCountTitle: "USER REACHERS",
},
{
ProgressCountTitle: "WEB DESIGN",
},
{
ProgressCountTitle: "UI DESIGN",
},
{
ProgressCountTitle: "ILLUSTRATION",
},
]
export default AboutMyselfProgressCount;
Now I've another .js file at src > Routes > Home > Components > AboutMyself > Components > SkillsContent
The code is as below:
import React from 'react'
import { Row, Col } from 'react-bootstrap'
const Skills = (props) => {
return (
<>
{props.ProgressCountTitle}
</>
)
}
export default Skills;
Basically in this section I've some stuff that I'm using with props
Now, I've one another .js file at src > Routes > Home > Components > AboutMyself > index.js in which I'm mapping data from No. 1 and No. 2
The code is as:
import React from 'react'
import './style.scss';
import Skills from '../AboutMyself/Components/SkillsContent/index'
import AboutMyselfProgressCount from '../../../../Constant/AboutMyselfProgressCount'
const AboutMyself = () => {
return (
<>
<div className='AboutMyselfBackground'>
<div className='AboutMyselfContent'>
<div className='content'>
<p>ABOUT MYSELF</p>
<h4>
I’m a Creative director based on New York, who loves clean, simple & unique design. I also enjoy crafting..
</h4>
<a href=''>DOWNLOAD RESUME</a>
<div className='borderTop'></div>
{
AboutMyselfProgressCount.map((val, ind) => {
return (
<Skills
key={ind}
ProgressCountTitle={val.ProgressCountTitle}
/>
)
})
}
<div className='skillsPara'>
<p>
Proin laoreet elementum ligula, ac tincidunt lorem accumsan nec. Fusce eget urna ante. Donec massa velit, varius a accumsan ac, tempor iaculis massa. Sed placerat justo sed libero varius vulputate.
</p>
</div>
</div>
</div>
</div>
</>
);
}
export default AboutMyself;
All I want to show a progress bar of skills under ProgressCountTitle which is being done using css. So is this possible to place that css of progress bar(s) in file No. 1 using array of objects, array of object(s) as a key value of an object, etc. etc.
I hope I'm clear to all of you with my question.
A CSS component for React is Styled-Component. You can specifically design out your element within the same JS file and assign them by unique element name. https://styled-components.com/
This example was taken direct from their documentation
// Create a Title component that'll render an <h1> tag with some styles
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
// Create a Wrapper component that'll render a <section> tag with some styles
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
// Use Title and Wrapper like any other React component – except they're styled!
render(
<Wrapper>
<Title>
Hello World!
</Title>
</Wrapper>
);
Yes ofcourse you can
just create any .css file and import in react component.
import './App.css'
and then you can simply add your classNames to your JSX as follows.
<div className='myclass'>
hello world
</div>
if you want mode advance feature like preventing the global styles and using component bases local styles you can also use css modules in reactjs.
you need to name the css file as anyfilename.module.css
then you need to import like:
import classes from './anyfilename.module.css'
then you can add your style classes to jsx as follows:
<div className='myclass'>
hello world
</div>
to learn more click here

Resources