From f12b84e59070504d433340eb7d0ae4c11d6ca2cf Mon Sep 17 00:00:00 2001 From: Renata Motta Date: Tue, 7 Jun 2022 16:55:18 -0300 Subject: [PATCH] Feat: Adds tokens to `Radio` (#89) * Feat: Adds tokens to `Radio` (#87) * Creates Input Radio * Styles Radio * Adds Radio to Storybook * Adds tokens tables * Fixes Storybook table width * Fixes Checkbox hovers * Updates Changelog * Fix typo Co-authored-by: Fanny Chien * Updates Checkbox Story to use TokenTable Co-authored-by: Fanny Chien * Updates Changelog * Updates RadioProps to add FSUI props Co-authored-by: Eduardo Formiga * Tweaks `Radio` token list order Co-authored-by: Fanny Chien Co-authored-by: Eduardo Formiga --- .storybook/storybook.css | 5 + CHANGELOG.md | 2 + .../ui/Checkbox/Checkbox.stories.mdx | 337 ++++++------------ .../ui/Checkbox/checkbox.module.scss | 30 +- src/components/ui/Radio/Radio.stories.mdx | 237 ++++++++++++ src/components/ui/Radio/Radio.tsx | 36 ++ src/components/ui/Radio/index.tsx | 2 + src/components/ui/Radio/radio.module.scss | 122 +++++++ 8 files changed, 528 insertions(+), 243 deletions(-) create mode 100644 src/components/ui/Radio/Radio.stories.mdx create mode 100644 src/components/ui/Radio/Radio.tsx create mode 100644 src/components/ui/Radio/index.tsx create mode 100644 src/components/ui/Radio/radio.module.scss diff --git a/.storybook/storybook.css b/.storybook/storybook.css index 7ed8dd0b..15ec9174 100644 --- a/.storybook/storybook.css +++ b/.storybook/storybook.css @@ -48,6 +48,11 @@ width: 50%; } +.sbdocs-table td code { + line-height: 1.3; + white-space: break-spaces; +} + .sbdocs-table td > div { float: left; width: 1.5rem; diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e54bd7e..6d45b0f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Creates `Radio` component ([#89](https://github.com/vtex-sites/gatsby.store/pull/89)) - Applies new local tokens to `Price` ([#83](https://github.com/vtex-sites/gatsby.store/pull/83)) - Applies new local tokens to `Alert` ([#77](https://github.com/vtex-sites/gatsby.store/pull/77)) - Refactors `Button` component and adds Storybook doc ([#52](https://github.com/vtex-sites/gatsby.store/pull/52)) @@ -22,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Updates `Checkbox` tokens ([#89](https://github.com/vtex-sites/gatsby.store/pull/89)) - Uses `Hero` component from FSUI ([#92](https://github.com/vtex-sites/gatsby.store/pull/92)) - Uses CSS Modules on `Checkbox` component ([#81](https://github.com/vtex-sites/gatsby.store/pull/81)) - Uses CSS Modules on `QuantitySelector` component ([#75](https://github.com/vtex-sites/gatsby.store/pull/75)) diff --git a/src/components/ui/Checkbox/Checkbox.stories.mdx b/src/components/ui/Checkbox/Checkbox.stories.mdx index 57c10eda..fe2978a4 100644 --- a/src/components/ui/Checkbox/Checkbox.stories.mdx +++ b/src/components/ui/Checkbox/Checkbox.stories.mdx @@ -2,6 +2,12 @@ import { Meta, Canvas, Story, ArgsTable } from '@storybook/addon-docs' import Checkbox from '.' +import { + TokenTable, + TokenRow, + TokenDivider, +} from 'src/../.storybook/components' + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Local tokenDefault value/Global token linked
- --fs-checkbox-width - - 1.25rem -
- --fs-checkbox-height - - var(--fs-checkbox-width) -
- --fs-checkbox-border-width - - var(--fs-border-width) -
- --fs-checkbox-border-radius - - var(--fs-border-radius) -
- --fs-checkbox-border-color - -
- var(--fs-border-color) -
- --fs-checkbox-border-color-hover - -
- var(--fs-color-text) -
- --fs-checkbox-transition - -
-          border var(--fs-transition-timing) var(--fs-transition-function),
-          background-color var(--fs-transition-timing)
-          var(--fs-transition-function), box-shadow var(--fs-transition-timing)
-          var(--fs-transition-function)
-        
-
- --fs-checkbox-bkg-color-hover - -
- var(--fs-color-primary-bkg-light) -
- --fs-checkbox-shadow-hover - - - 0 0 0 var(--fs-checkbox-border-width) var(--fs-border-color-active) - -
+ + + + + + + + + + + + + + --- @@ -232,43 +168,28 @@ The `Checkbox` component uses [FastStore UI Checkbox](https://www.faststore.dev/ - - - - - - - - - - - - - - - - - - - - - -
Local tokenDefault value/Global token linked
- --fs-checkbox-checked-bkg-color - -
- var(--fs-color-primary-bkg) -
- --fs-checkbox-checked-bkg-color-hover - -
- var(--fs-color-primary-bkg-hover) -
- --fs-checkbox-checked-border-color - -
- var(--fs-border-color-active) -
+ + + + + + ### Disabled @@ -286,51 +207,27 @@ The `Checkbox` component uses [FastStore UI Checkbox](https://www.faststore.dev/ - - - - - - - - - - - - - - - - - - - - - - - - - -
Local tokenDefault value/Global token linked
- --fs-checkbox-disabled-bkg-color - -
- var(--fs-color-disabled-bkg) -
- --fs-checkbox-disabled-border-width - - var(--fs-checkbox-border-width) -
- --fs-checkbox-disabled-border-color - -
- var(--fs-border-color-disabled) -
- --fs-checkbox-disabled-text-color - -
- var(--fs-color-disabled-text) -
+ + + + + + ### Partial @@ -348,48 +245,24 @@ The `Checkbox` component uses [FastStore UI Checkbox](https://www.faststore.dev/ - - - - - - - - - - - - - - - - - - - - - - - - - -
Local tokenDefault value/Global token linked
- --fs-checkbox-partial-bkg-color - -
- var(--fs-color-neutral-0) -
- --fs-checkbox-partial-border-width - - var(--fs-checkbox-border-width) -
- --fs-checkbox-partial-border-color - -
- var(--fs-color-primary-bkg) -
- --fs-checkbox-partial-hover - -
- var(--fs-color-primary-bkg-light) -
+ + + + + + diff --git a/src/components/ui/Checkbox/checkbox.module.scss b/src/components/ui/Checkbox/checkbox.module.scss index 2d4e8f95..d62cc706 100644 --- a/src/components/ui/Checkbox/checkbox.module.scss +++ b/src/components/ui/Checkbox/checkbox.module.scss @@ -12,7 +12,7 @@ --fs-checkbox-border-width : var(--fs-border-width); --fs-checkbox-border-radius : var(--fs-border-radius); --fs-checkbox-border-color : var(--fs-border-color); - --fs-checkbox-border-color-hover : var(--fs-color-text); + --fs-checkbox-border-color-hover : var(--fs-border-color-active); --fs-checkbox-transition : border var(--fs-transition-timing) var(--fs-transition-function), background-color var(--fs-transition-timing) var(--fs-transition-function), box-shadow var(--fs-transition-timing) var(--fs-transition-function); @@ -22,7 +22,8 @@ // Checked --fs-checkbox-checked-bkg-color : var(--fs-color-primary-bkg); --fs-checkbox-checked-bkg-color-hover : var(--fs-color-primary-bkg-hover); - --fs-checkbox-checked-border-color : var(--fs-border-color-active); + --fs-checkbox-checked-border-color-hover : var(--fs-border-color-hover); + --fs-checkbox-checked-shadow-hover : 0 0 0 var(--fs-checkbox-border-width) var(--fs-checkbox-checked-border-color-hover); // Disabled --fs-checkbox-disabled-bkg-color : var(--fs-color-disabled-bkg); @@ -31,10 +32,10 @@ --fs-checkbox-disabled-text-color : var(--fs-color-disabled-text); // Partial - --fs-checkbox-partial-bkg-color : var(--fs-color-neutral-0); + --fs-checkbox-partial-bkg-color : var(--fs-color-body-bkg); + --fs-checkbox-partial-bkg-color-hover : var(--fs-color-primary-bkg-light); --fs-checkbox-partial-border-width : var(--fs-checkbox-border-width); --fs-checkbox-partial-border-color : var(--fs-color-primary-bkg); - --fs-checkbox-partial-hover : var(--fs-color-primary-bkg-light); // -------------------------------------------------------- // Structural Styles @@ -69,24 +70,30 @@ transform: rotate(45deg); } - &:hover { + &:hover:not(:disabled) { background-color: var(--fs-checkbox-bkg-color-hover); + } + + &:hover:not(:disabled):not(:focus-visible):not(:focus) { border-color: var(--fs-checkbox-border-color-hover); box-shadow: var(--fs-checkbox-shadow-hover); } &:checked { background-color: var(--fs-checkbox-checked-bkg-color); - border-color: var(--fs-checkbox-checked-border-color); - border-width: 0; + border: none; &::before { opacity: 1; } - &:hover { + &:hover:not(:disabled) { background-color: var(--fs-checkbox-checked-bkg-color-hover); - box-shadow: none; + } + + &:hover:not(:disabled):not(:focus-visible):not(:focus) { + border-color: var(--fs-checkbox-checked-border-color-hover); + box-shadow: var(--fs-checkbox-checked-shadow-hover); } } @@ -133,12 +140,13 @@ &:checked { &:hover:not(:disabled) { - background-color: var(--fs-checkbox-partial-hover); + background-color: var(--fs-checkbox-partial-bkg-color-hover); } } &:hover { - background-color: var(--fs-checkbox-partial-hover); + background-color: var(--fs-checkbox-partial-bkg-color-hover); + box-shadow: var(--fs-checkbox-shadow-hover); } &:disabled { diff --git a/src/components/ui/Radio/Radio.stories.mdx b/src/components/ui/Radio/Radio.stories.mdx new file mode 100644 index 00000000..1f86d2cf --- /dev/null +++ b/src/components/ui/Radio/Radio.stories.mdx @@ -0,0 +1,237 @@ +import { Meta, Canvas, Story, ArgsTable } from '@storybook/addon-docs' + +import Radio from '.' +import { + TokenTable, + TokenRow, + TokenDivider, +} from 'src/../.storybook/components' + + `boolean`', + defaultValue: false, + }, + }} +/> + +export const Template = (args) => + +
+ +# Radio + +Radios allow users to select one option from a set. + +
+ +## Overview + +The `Radio` component uses [FastStore UI Radio](https://www.faststore.dev/reference/ui/atoms/Radio) as base. + + + + {Template.bind({})} + + + {Template.bind({})} + + + {Template.bind({})} + + + {Template.bind({})} + + + +--- + +## Usage + +`import Radio from '../components/ui/Radio'` + + + + {Template.bind({})} + + + + + + + + + + + + + + + + + + + + +--- + +## Nested Elements + +### Knob + + + + + + + + +--- + +## Variants + +### Checked + + + + {Template.bind({})} + + + + + + + + +### Disabled + + + + {Template.bind({})} + + + {Template.bind({})} + + + + + + + + + diff --git a/src/components/ui/Radio/Radio.tsx b/src/components/ui/Radio/Radio.tsx new file mode 100644 index 00000000..1ec5de60 --- /dev/null +++ b/src/components/ui/Radio/Radio.tsx @@ -0,0 +1,36 @@ +import { Radio as UIRadio, Label as UILabel } from '@faststore/ui' +import type { RadioProps as UIRadioProps } from '@faststore/ui' + +import styles from './radio.module.scss' + +export type RadioProps = { + /** + * ID to identify input and corresponding label. + */ + id: string + /** + * The text displayed to identify the input. + */ + label: string + /** + * The value to identify the input. + */ + value?: string + /** + * Identify radio in the same group. + */ + name?: string +} & UIRadioProps + +function Radio({ id, label, value, name, ...otherProps }: RadioProps) { + return ( +
+ + + {label} + +
+ ) +} + +export default Radio diff --git a/src/components/ui/Radio/index.tsx b/src/components/ui/Radio/index.tsx new file mode 100644 index 00000000..6241b6a1 --- /dev/null +++ b/src/components/ui/Radio/index.tsx @@ -0,0 +1,2 @@ +export { default } from './Radio' +export type { RadioProps } from './Radio' diff --git a/src/components/ui/Radio/radio.module.scss b/src/components/ui/Radio/radio.module.scss new file mode 100644 index 00000000..cafc8148 --- /dev/null +++ b/src/components/ui/Radio/radio.module.scss @@ -0,0 +1,122 @@ +@import "src/styles/scaffold"; + +.fs-radio { + // -------------------------------------------------------- + // Design Tokens for radio + // -------------------------------------------------------- + + // Default properties + --fs-radio-width : 1.25rem; + --fs-radio-height : var(--fs-radio-width); + + --fs-radio-border-width : var(--fs-border-width); + --fs-radio-border-radius : var(--fs-border-radius-circle); + --fs-radio-border-color : var(--fs-border-color); + --fs-radio-border-color-hover : var(--fs-border-color-hover); + + --fs-radio-transition : border var(--fs-transition-timing) var(--fs-transition-function), background-color var(--fs-transition-timing) var(--fs-transition-function), box-shadow var(--fs-transition-timing) var(--fs-transition-function); + + --fs-radio-bkg-color-hover : var(--fs-color-primary-bkg-light); + --fs-radio-shadow-hover : 0 0 0 var(--fs-radio-border-width) var(--fs-border-color-active); + + // Knob + --fs-radio-knob-width : var(--fs-spacing-1); + --fs-radio-knob-height : var(--fs-radio-knob-width); + --fs-radio-knob-bkg-color : var(--fs-color-body-bkg); + --fs-radio-knob-disabled-bkg-color : var(--fs-color-neutral-5); + + // Checked + --fs-radio-checked-bkg-color : var(--fs-color-primary-bkg); + --fs-radio-checked-bkg-color-hover : var(--fs-color-primary-bkg-hover); + + // Disabled + --fs-radio-disabled-bkg-color : var(--fs-color-disabled-bkg); + --fs-radio-disabled-border-width : var(--fs-radio-border-width); + --fs-radio-disabled-border-color : var(--fs-border-color-disabled); + --fs-radio-disabled-text-color : var(--fs-color-disabled-text); + + // -------------------------------------------------------- + // Structural Styles + // -------------------------------------------------------- + + display: flex; + column-gap: var(--fs-spacing-1); + align-items: center; + + label { width: 100%; } + + input { + position: relative; + display: flex; + flex-shrink: 0; + align-items: center; + justify-content: center; + width: var(--fs-radio-width); + height: var(--fs-radio-height); + cursor: pointer; + border: var(--fs-radio-border-width) solid var(--fs-radio-border-color); + border-radius: var(--fs-radio-border-radius); + outline: none; + transition: var(--fs-radio-transition); + appearance: none; + + @include input-focus-ring; + + &::before { + width: var(--fs-radio-knob-width); + height: var(--fs-radio-knob-height); + pointer-events: none; + content: ""; + background-color: var(--fs-radio-knob-bkg-color); + border-radius: var(--fs-radio-border-radius); + opacity: 0; + } + + &:hover:not(:disabled) { + background-color: var(--fs-radio-bkg-color-hover); + } + + &:hover:not(:disabled):not(:focus-visible):not(:focus) { + border-color: var(--fs-radio-border-color-hover); + box-shadow: var(--fs-radio-shadow-hover); + } + + &:checked { + background-color: var(--fs-radio-checked-bkg-color); + border: none; + + &::before { + opacity: 1; + } + + &:hover:not(:disabled) { + background-color: var(--fs-radio-checked-bkg-color-hover); + } + + &:hover:not(:disabled):not(:focus-visible):not(:focus) { + box-shadow: none; + } + } + + &:disabled { + cursor: not-allowed; + background-color: var(--fs-radio-disabled-bkg-color); + border: var(--fs-radio-disabled-border-width) solid var(--fs-radio-disabled-border-color); + + &::before { + background-color: var(--fs-radio-knob-disabled-bkg-color); + } + + &:checked { + &::before { + background-color: var(--fs-radio-knob-disabled-bkg-color); + } + } + + + label { + color: var(--fs-radio-disabled-text-color); + cursor: not-allowed; + } + } + } +}