I have custom styled checkbox. Is there a way in Storybook to make the checkbox checked so that you dont have to click on it to see this state?
This is a work in progress, not fully functioning yet but it does pass props so I am just getting storybook to cooperate.
the storybook-addon-pseudo-states really should have this built in...
I am using a jsx approach but the difference is negligible.
I just started learning Vue and storybook last night, so this is quite new to me, I will post up a fully functional version later.
Checkbox.stories.js
export const CheckBoxChecked = Template.bind({});
CheckBoxChecked.args = {
label: 'Checked',
checked: true,
};
Checkbox.jsx
import Vue from 'vue';
import { styled, VueEmotion } from '#egoist/vue-emotion';
import './checkbox.css';
Vue.use(VueEmotion);
const Label = styled('label')`
`
const Input = styled('input')`
opacity: 0;
width: 1em;
height: 1em;
`
export default {
name: 'CheckBox',
props: {
label: {
type: String,
required: true,
},
checked: {
type: Boolean,
default: false
},
render (h) {
return (
<Label>
<Input type="checkbox" checked={this.checked} />
</Label>
)
}
}
Related
I have a question regarding Storybook and Vue components with v-models. When writing a story for let's say an input component with a v-model i want a control reflecting the value of this v-model. Setting the modelValue from the control is no problem, but when using the component itself the control value stays the same. I am searching the web for a while now but i can't seem to find a solution for this.
A small example:
// InputComponent.vue
<template>
<input
type="text"
:value="modelValue"
#input="updateValue"
:class="`form-control${readonly ? '-plaintext' : ''}`"
:readonly="readonly"
/>
</template>
<script lang="ts">
export default {
name: "GcInputText"
}
</script>
<script lang="ts" setup>
defineProps({
modelValue: {
type: String,
default: null
},
readonly: {
type: Boolean,
default: false
}
});
const emit = defineEmits(['update:modelValue']);
const updateValue = (event: Event) => {
const target = event.target as HTMLInputElement;
emit('update:modelValue', target.value);
}
</script>
In Storybook:
Does anyone have a solution to make this working?
Thanks in advance!
In my case, I have a custom select input that uses a modelValue prop.
I tried this and worked for me:
at my-component.stories.js:
import { ref } from 'vue'
import MyComponent from './MyComponent.vue'
export default {
title: 'Core/MyComponent',
component: MyComponent,
argTypes: { }
}
const Template = (args) => ({
components: { MyComponent },
setup() {
let model = ref('Javascript')
const updateModel = (event) => model.value = event
return { args, model, updateModel }
},
template: '<my-component v-bind="args" :modelValue="model" #update:modelValue="updateModel" />'
})
export const Default = Template.bind({})
Default.args = {
options: [
'Javascript',
'PHP',
'Java'
]
}
Hi
I just made a website with a darkmode and multilanguage support to test around but I ran into an issue.
the code
I got rid of all things that aren't an issue
portfolio/src/pages/index.tsx
import { useTranslation } from 'react-i18next'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
export default () => {
const { t,i18n } = useTranslation('common')
return <div onClick={()=>i18n.changeLanguage(i18n.language=='fr'?'en':'fr')}>
<div>{i18n.language}</div>
<span>{t('debug')}</span>
</div>
}
export async function getStaticProps({ locale }:any) {
return {
props: {
...(await serverSideTranslations(locale, ['common'])),
// Will be passed to the page component as props
},
};
}
portfolio/src/public/locales/en/common.js
{"debug":"english"}
portfolio/src/public/locales/fr/common.js
{"debug":"français"}
portfolio/next-i18next.config.js
const path = require("path");
module.exports = {
debug: false,
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr'],
},
localePath: path.resolve('./src/public/locales'),
};
portfolio/src/pages/_app.tsx
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import {appWithTranslation} from 'next-i18next'
export default appWithTranslation(({ Component, pageProps }: AppProps) => {
return <Component {...pageProps} />
})
The issue
When I do npm run dev and go to http://localhost:3000/fr, the page defaults to french and works good I can swap between languages without problems but when i go to http://localhost:3000/en the t('debug') doesn't translate when the i18n.language changes as intended.
Found what I wanted
So basicaly I need to use a next Link that will change the local and the link
Code application
index.js
//...
export default () => {
const { t,i18n } = useTranslation('common')
return (
<div>
<Link
href={i18n.language=='fr'?'/en':'/fr'}
locale={i18n.language=='fr'?'en':'fr'}
>{i18n.language}</Link>
<div>{t('debug')}</div>
</div>
)
}
//...
result
Now the text changes as intended both in the /fr and /en because it switches between the 2 however the result is far from smooth. It reloads the page and i'd like to avoid that because I use some animations on it.
Found what i wanted part 2
Browsing through the next-i18next documentation I found what I wanted.
solution
I needed to load the props using getStaticProps and in the serverSideTranslation function i needed to pass as argument the array off ALL the language necessary to load the page ['en','fr'] because i switched between the 2
I'm trying to use the useArgs() hook to update args. Since #storybook/client-api is deprecated, I'm using the #storybook/api library instead. However, it throws a TypeError when I try to use it in a template:
import { useArgs } from "#storybook/api";
import Button from "./Button";
export default {
title: "Button",
component: Button,
} as ComponentMeta<typeof Button>;
const ToggleTemplate: ComponentStory<typeof Button> = (args) => {
const [_, updateArgs] = useArgs();
return <Button {...args} />;
};
export const Toggle: typeof Template = ToggleTemplate.bind({});
Toggle.args = {
children: "Toggle me!",
toggle: {
toggleFunc: () => {},
value: false,
},
};
The above throws TypeError: Cannot read properties of undefined (reading 'getCurrentStoryData'). When I comment out useArgs(), the error disappears. Does anyone know what I'm doing wrong?
You are using the useArgs from the wrong package. The #storybook/api is for creating an addon, not using it in a story (Storybook Docs: Addon API). For inside a story, install #storybook/client-api and change the import to import { useArgs } from '#storybook/client-api';
I've implemented a simple Anime Js text animation into my react app; I have other other Anime Js projects which perform perfectly but I just don't see the issue with this one, and why it doesn't work.
TextColourChangeLoader.js
import React from 'react';
import './styles/TextColourChangeLoader.css';
import anime from 'animejs';
export default class TextColourChangeLoader extends React.Component {
constructor(props) {
super(props);
this.state = {
text: "",
play: false
}
}
componentDidMount() {
this.setState({
text: this.props.textToRender,
play: true
})
}
componentWillUnmount() {
this.setState({
text: '',
play: false
})
}
playAnimeColourChange = () => {
if(this.state.play) {
anime({
targets: '.loader-letter',
delay: anime.stagger(100),
duration: 1000,
scale: anime.stagger(2, {easing: "easeInElastic"}),
color: '#7DE2FC',
direction: 'alternate',
easing: 'easeInOutElastic(1,.8)',
loop: true,
loopComplete: function() {
console.log('done')
}
});
}
}
render() {
this.playAnimeColourChange();
return (
<div id="loader-text-holder">
{this.state.text.split('').map((letter, i) => {
return <span id={letter === " " ? "loader-letter-space" : "loader-letter"+i} key={i} className="loader-letter text">{letter}</span>
})}
{this.playAnimeColourChange()}
</div>
)
}
}
Example.js
import React from 'react';
import './styles/ViewLoaderWithText.css';
import anime from 'animejs';
import TextColourChangeLoader from './TextColourChangeLoader';
export default class ViewLoaderWithText extends React.Component {
constructor(props) {
super(props);
this.state = {
play: false
}
}
componentDidMount() {
this.setState({
play: true
})
}
playAnime = () => {
if(this.state.play) {
let loaderAnime = anime({
targets: '.view-loader-shape',
delay: anime.stagger(100, {start: -100}),
translateY: [{value: -25, easing: 'easeInCubic'}, {value: 0, easing: 'easeOutCirc'}],
background: '#7DE2FC',
direction: 'alternate',
easing: 'easeInOutElastic(1,.8)',
duration: 1000,
loop: true,
autoplay: true
});
}
}
render() {
return (
<div id="view-loader-wrapper">
<div id="loader-shape-holder">
<span className="view-loader-shape" id="view-loader-shape1"></span>
<span className="view-loader-shape" id="view-loader-shape2"></span>
<span className="view-loader-shape" id="view-loader-shape3"></span>
<span className="view-loader-shape" id="view-loader-shape4"></span>
<span className="view-loader-shape" id="view-loader-shape5"></span>
</div>
<TextColourChangeLoader textToRender="Verifying email"/>
{this.playAnime()}
</div>
)
}
}
The anime js instance in the Example.js file works as it should; however the TextColourChangeLoader.js animation doesn't run. I've tried logging to the console each time a loop completes with the loopComplete callback option, and it shows that the loop is running however, the animation doesn't. I've also tried only running the TextColourChangeLoader.js animation, but that still doesn't work. What could be a possible explanation for this? Anything helps.
I think that doesn't work because you are trying to animate a component that had not loaded first. Remember the lifecycle flow in React, I prefer use React Hooks to solve the problem and this is the way: with the useEffect hook you pass in the animate function, in order to first render the component and then execute the function, not in the reverse order. I guess that the equivalent in class components is componentDidMount() so try to refactorize your code in order to connect the anime() with the componentDidMount. Conclusion, the main concept is first render the component and then execute the anime(). Sorry for my english level.
According to this reference https://github.com/airbnb/javascript/tree/master/css-in-javascript, a styled JS component should be written like this:
function MyComponent({ styles }) {
return (
<div {...css(styles.container)}>
Never doubt that a small group of thoughtful, committed citizens can
change the world. Indeed, it’s the only thing that ever has.
</div>
);
}
export default withStyles(() => ({
container: {
display: 'inline-block',
},
}))(MyComponent);
I'm trying to write a simple React component like following, without success (I'm receiving a withStyles is not defined error):
import React from 'react';
const MyComponent = ({styles}) => {
return (
<div {...css(styles.container)}>Hello World</div>
)
}
export default withStyles(() => ({
container: {
color: 'red'
},
}))(MyComponent);
What am I doing wrong? Is it possible to use this convention for a React component?
You can do it like this
const divStyle = {
color: 'blue',
fontSize:10px
};
function HelloWorldComponent() {
return <div style={divStyle}>Hello World!</div>;
}
However you can try other better approaches.Please refer to the link below:
https://medium.com/#aghh1504/4-four-ways-to-style-react-components-ac6f323da822