stories/atoms/components/button/Button.stories.mdx
import { ArgsTable, Meta, Story, Canvas } from '@storybook/addon-docs'
import { useState } from 'react'
import { useTheme } from 'hook/useTheme'
import { Button } from 'ui/atoms/button/Button'
import { ThemeProvider } from 'ui/atoms/theme/ThemeProvider'
import { ThemeSwitcher } from 'ui/atoms/theme/ThemeSwitcher'
import { Icon } from 'ui/atoms/icon/Icon'
import { Toast } from 'ui/atoms/toast/Toast'
import { Typography } from 'ui/atoms/typography/Typography'
import '../component.scss'
<Meta
title="Atoms/Button"
component={Button}
decorators={[
Story => (
<ThemeProvider>
<div className="story-theme-switcher">
<ThemeSwitcher />
</div>
<div className="component-story-main">
<Story />
</div>
</ThemeProvider>
)
]}
/>
# Button
> Communicates actions that users can take.
[![stability-unstable](https://img.shields.io/badge/stability-unstable-yellow.svg)](https://github.com/emersion/stability-badges#unstable)
## Description
Buttons are mainly used to give the user options to act. They help users to find
the most important actions through the UI and enable them to perform these actions.
By using one or more of the button properties, it's possible to create appealing and intuitive buttons
that will help users to find the action they're looking for.
## Overview
<Story
name="Overview"
argTypes={{
icon: { control: false, table: { type: { summary: 'Node' } } },
leftIcon: { control: false, table: { type: { summary: 'Node' } } },
rightIcon: { control: false, table: { type: { summary: 'Node' } } }
}}
args={{
label: 'Connect wallet',
variant: 'primary',
size: 'medium',
backgroundColor: 'primary',
disabled: false
}}
>
{args => {
const { theme } = useTheme()
const isLightTheme = theme === 'light'
return (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '25px'
}}
>
<Button {...args} icon={<Icon name="wallet" size={22} invertColor={isLightTheme} />} />
</div>
)
}}
</Story>
## Properties
<ArgsTable story="Overview" />
## Label
The `label` is the text description of Button that helps communicate what happens after the click.
If Button is an **icon** `variant`, the `label` is not shown, however it is still there as a title
attribut used for the [tooltip](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Tooltip_Role)
(as you can see by hovering your mouse over the icon button below).
The `label` can have any length however Button width will never exceed 273px.
<Canvas>
<Story name="Label">
{() => {
const { theme } = useTheme()
const isLightTheme = theme === 'light'
return (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexWrap: 'wrap',
gap: '50px'
}}
>
<Button label="Short label" />
<Button label="Here is how the button acts when it has a long label" />
<Button
label="I'm the label of the icon button"
variant="icon"
icon={<Icon name="profile" size={22} invertColor={isLightTheme} />}
/>
</div>
)
}}
</Story>
</Canvas>
## Icon
`Icon` turns the button into a more concise, unlabeled element. For that, you can pass the icon of your choice as a value.
Requires Button to be an **icon** `variant`. Without it, the button content will remain `label`.
<Canvas>
<Story name="Icon">
{() => {
const { theme } = useTheme()
const isLightTheme = theme === 'light'
return (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexWrap: 'wrap',
gap: '50px'
}}
>
<Button
label="icon button"
icon={<Icon name="calendar" size={22} invertColor={isLightTheme} />}
variant="icon"
/>
<Button
label="Icon passed without the icon variant"
icon={<Icon name="calendar" size={22} />}
/>
</div>
)
}}
</Story>
</Canvas>
## Variants
Button is available in three styled versions:
- **primary** (default): A rectangular version, symbol of the brand and which reinforces the cosmic atmosphere.
- **secondary**: A rounded version, softer, allowing to adapt in particular to smaller screens.
- **icon**: Sets the button to be an icon button, requires you to supply an `icon` property.
<Canvas>
<Story name="Variants">
{() => {
const { theme } = useTheme()
const isLightTheme = theme === 'light'
return (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexWrap: 'wrap',
gap: '50px'
}}
>
<Button backgroundColor="primary" variant="primary" label="Primary" size="medium" />
<Button backgroundColor="primary" variant="secondary" label="Secondary" size="medium" />
<Button
backgroundColor="primary"
variant="icon"
label="Icon"
size="medium"
icon={<Icon name="alert" size={22} invertColor={isLightTheme} />}
/>
</div>
)
}}
</Story>
</Canvas>
## Sizes
There are three different sizes to allow Button to be used according to its location within the interface.
- **small**: Suitable for small screens and must not saturate the space. This size should also be used for integrations in content spaces such as cards, footers, etc.
- **medium** (default): Makes it possible to adapt to a greater number of uses.
- **large**: Appropriate for large screens or in conjonction with `leftIcon` / `rightIcon` properties.
<Canvas>
<Story name="Sizes">
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexWrap: 'wrap',
gap: '50px'
}}
>
<Button backgroundColor="primary" variant="primary" label="Small" size="small" />
<Button backgroundColor="primary" variant="primary" label="Medium" size="medium" />
<Button backgroundColor="primary" variant="primary" label="Large" size="large" />
</div>
</Story>
</Canvas>
## Background colors
Button has a palette of background colors to choose from and allows to better mark a user action.
The background color can be a visual aid as to what type of action the button executes.
By default `backgroundColor` is **primary**.
<Canvas>
<Story name="Background colors">
<div
style={{
display: 'flex',
justifyContent: 'center',
gap: '25px',
flexWrap: 'wrap'
}}
>
<Button backgroundColor="primary" variant="primary" label="Primary" size="medium" />
<Button backgroundColor="secondary" variant="primary" label="Secondary" size="medium" />
<Button backgroundColor="success" variant="primary" label="Success" size="medium" />
<Button backgroundColor="error" variant="primary" label="Error" size="medium" />
<Button backgroundColor="warning" variant="primary" label="Warning" size="medium" />
<Button backgroundColor="info" variant="primary" label="Info" size="medium" />
</div>
</Story>
</Canvas>
## Disabled
Button can be `disabled` at any time, thus preventing any user interaction. This is indicated by a change in background color
and cursor.
<Canvas>
<Story name="Disabled">
<div
style={{
display: 'flex',
justifyContent: 'center'
}}
>
<Button disabled variant="primary" label="I'm disabled" size="medium" />
</div>
</Story>
</Canvas>
## Left / Right Icon
`leftIcon` and `rightIcon` are auxilliary elements giving great freedom to embellish the button
together with the `label`.
<Canvas>
<Story name="Left / right Icon">
{() => {
const { theme } = useTheme()
const isLightTheme = theme === 'light'
return (
<div
style={{
display: 'flex',
justifyContent: 'center',
flexWrap: 'wrap',
gap: '50px'
}}
>
<Button
leftIcon={<Icon name="wallet" size={22} invertColor={isLightTheme} />}
label="Get wallet address"
/>
<Button
label="Add wallet"
rightIcon={<Icon name="add" size={22} invertColor={isLightTheme} />}
/>
</div>
)
}}
</Story>
</Canvas>
## OnClick
`onClick` is what makes the magic happen, without it the button has no corresponding action.
It is triggered when a click is registered on the button.
<Canvas>
<Story name="OnClick">
{() => {
const [isOpened, setIsOpened] = useState(false)
const handleOpen = () => {
setIsOpened(prevState => !prevState)
}
return (
<div>
<div
style={{
display: 'flex',
justifyContent: 'center'
}}
>
<Button label="Click me!" onClick={handleOpen} />
</div>
<Toast
description={
<div style={{ display: 'flex', flexDirection: 'column' }}>
<Typography color="inverted-text" fontSize="small" fontWeight="light">
{`Like this component? See `}
<Typography color="inverted-text" fontSize="small" fontWeight="bold">
<a
href="/?path=/docs/atoms-toast--overview"
rel="author noreferrer"
target="_blank"
style={{ color: 'inherit' }}
>
Toast
</a>
</Typography>
</Typography>
</div>
}
isOpened={isOpened}
onOpenChange={handleOpen}
title={
<Typography color="inverted-text" fontSize="small" fontWeight="bold">
Button clicked!
</Typography>
}
severityLevel="info"
/>
</div>
)
}}
</Story>
</Canvas>
## Prerequisites
It is mandatory to wrap the component in a `<ThemeProvider />` for the thematisation to work.
See <a href="?path=/docs/atoms-brand-identity-theming--theming">Theming</a> for more information.
##### **`app.tsx`**
```tsx
import React from 'react'
import { Button, ThemeProvider } from '@okp4/ui'
export const App: React.FC = () => (
<React.StrictMode>
<ThemeProvider>
<Button label="Super label" />
</ThemeProvider>
</React.StrictMode>
)
```