From 45fe157aae844d5e1dbcd38c9b0a2e51627dca2e Mon Sep 17 00:00:00 2001 From: benaxse Date: Sat, 10 Aug 2024 13:07:10 +0300 Subject: [PATCH 1/5] feat(RadioButton): redesign to increase contrast in component --- src/components/RadioButton/RadioButton.scss | 134 ++++++++++++------ src/components/RadioButton/RadioButton.tsx | 61 +------- .../RadioButton/RadioButtonOption.tsx | 3 +- 3 files changed, 99 insertions(+), 99 deletions(-) diff --git a/src/components/RadioButton/RadioButton.scss b/src/components/RadioButton/RadioButton.scss index 77b7f35138..32f8086e7c 100644 --- a/src/components/RadioButton/RadioButton.scss +++ b/src/components/RadioButton/RadioButton.scss @@ -3,45 +3,88 @@ $block: '.#{variables.$ns}radio-button'; #{$block} { + --_--border-width: 1px; + --_--negative-border-width: calc(-1 * var(--_--border-width)); + box-sizing: border-box; display: inline-flex; flex-direction: row; font-family: var(--g-text-body-font-family); font-weight: var(--g-text-body-font-weight); + border: var(--_--border-width) solid var(--g-color-line-generic); border-radius: var(--_--border-radius); - background-color: var(--g-color-base-generic); position: relative; - --_--border-radius-inner: calc(var(--_--border-radius) - 3px); - - &__plate { - position: absolute; - inset-block: 0; - transition: - left 0.2s, - width 0.2s; - - &[hidden] { - display: none; - } - } - &__option { + position: relative; flex: 1 1 auto; user-select: none; font-size: var(--g-text-body-1-font-size); text-align: center; - border-radius: var(--_--border-radius-inner); + + margin: var(--_--negative-border-width) var(--_--negative-border-width) + var(--_--negative-border-width) 0; + cursor: pointer; transform: scale(1); transition: color 0.15s linear; - &-outline { + &::before { + position: absolute; + inset-inline-start: 0; + inset-block: var(--_--border-width); + content: ''; + width: var(--_--border-width); + background-color: var(--g-color-line-generic); + } + + &::after { content: ''; position: absolute; - z-index: -1; - inset: 3px; - border-radius: var(--_--border-radius-inner); + z-index: -2; + inset: 0; + border: var(--_--border-width) solid transparent; + border-radius: 0; + } + + &:first-child { + margin-inline-start: var(--_--negative-border-width); + border-start-start-radius: var(--_--border-radius); + border-end-start-radius: var(--_--border-radius); + + &::before { + display: none; + } + + &::after { + border-start-start-radius: var(--_--border-radius); + border-end-start-radius: var(--_--border-radius); + } + } + + &:last-child { + border-start-end-radius: var(--_--border-radius); + border-end-end-radius: var(--_--border-radius); + + &::after { + border-start-end-radius: var(--_--border-radius); + border-end-end-radius: var(--_--border-radius); + } + } + + &:not(&_checked):hover { + &::after { + background-color: var(--g-color-base-simple-hover); + } + + #{$block}__option-text { + color: var(--g-color-text-primary); + } + } + + &:has(#{&}-control:focus-visible) { + outline: 2px solid var(--g-color-line-misc); + outline-offset: calc(-1 * var(--_--border-width)); } &-control { @@ -56,16 +99,13 @@ $block: '.#{variables.$ns}radio-button'; outline: none; opacity: 0; cursor: inherit; - - &:focus-visible + #{$block}__option-outline { - outline: 2px solid var(--g-color-line-focus); - } } &-text { display: inline-block; white-space: nowrap; color: var(--g-color-text-complementary); + overflow: hidden; &_icon { height: 100%; @@ -74,45 +114,55 @@ $block: '.#{variables.$ns}radio-button'; } } - &:hover, &_checked { + cursor: default; + pointer-events: none; + border-color: var(--g-color-line-brand); + #{$block}__option-text { - color: var(--g-color-text-primary); + color: var(--g-color-text-brand-heavy); } - } - &_checked { - cursor: default; + &::after { + background-color: var(--g-color-base-selection); + border-color: var(--g-color-line-brand); + } + + &::before, + & + #{$block}__option::before { + background-color: transparent; + } } &_disabled { cursor: default; pointer-events: none; + &::after { + background-color: var(--g-color-base-generic); + } + #{$block}__option-text { color: var(--g-color-text-hint); } } - } - &__plate::before, - &__option::before { - position: absolute; - inset: 3px; - border-radius: var(--_--border-radius-inner); + &_disabled#{&}_checked { + &::after { + background-color: var(--g-color-base-generic-accent); + border-color: var(--g-color-line-generic-accent); + } + + #{$block}__option-text { + color: var(--g-color-text-secondary); + } + } } &__option::before { z-index: -1; } - &__plate::before, - &__plate[hidden] ~ &__option_checked::before { - content: ''; - - background-color: var(--g-color-base-background); - } - &_size { &_s { #{$block}__option { diff --git a/src/components/RadioButton/RadioButton.tsx b/src/components/RadioButton/RadioButton.tsx index c236c8b5d9..573e9ca053 100644 --- a/src/components/RadioButton/RadioButton.tsx +++ b/src/components/RadioButton/RadioButton.tsx @@ -43,53 +43,14 @@ export const RadioButton = React.forwardRef(function RadioButton>[] - ).map(({props}) => ({ - value: props.value, - content: props.content || props.children, - disabled: props.disabled, - title: props.title, + ).map(({props: optionProps}) => ({ + value: optionProps.value, + content: optionProps.content || optionProps.children, + disabled: optionProps.disabled, + title: optionProps.title, })); } - const plateRef = React.useRef(null); - const optionRef = React.useRef(); - - const handleCheckedOptionMount: React.Ref = React.useCallback( - (checkedOptionNode: HTMLLabelElement | null) => { - if (!checkedOptionNode) { - return; - } - - const plateNode = plateRef.current; - - if (!plateNode) { - return; - } - - const uncheckedOptionNode = optionRef.current; - - if (uncheckedOptionNode && uncheckedOptionNode !== checkedOptionNode) { - const setPlateStyle = (node: HTMLElement) => { - plateNode.style.left = `${node.offsetLeft}px`; - plateNode.style.width = `${node.offsetWidth}px`; - }; - - setPlateStyle(uncheckedOptionNode); - - plateNode.hidden = false; - - setPlateStyle(checkedOptionNode); - } - - optionRef.current = checkedOptionNode; - }, - [], - ); - - const handlePlateTransitionEnd: React.TransitionEventHandler = (event) => { - event.currentTarget.hidden = true; - }; - const {containerProps, optionsProps} = useRadioGroup({...props, options}); return ( @@ -100,18 +61,8 @@ export const RadioButton = React.forwardRef(function RadioButton - ); diff --git a/src/components/RadioButton/RadioButtonOption.tsx b/src/components/RadioButton/RadioButtonOption.tsx index 8c5915c8e2..52019d1562 100644 --- a/src/components/RadioButton/RadioButtonOption.tsx +++ b/src/components/RadioButton/RadioButtonOption.tsx @@ -17,7 +17,7 @@ export interface RadioButtonOptionProps extends Contro } type RadioButtonOptionComponentType = ( - props: RadioButtonOptionProps & {ref?: React.ForwardedRef}, + props: RadioButtonOptionProps, ) => React.JSX.Element; export const RadioButtonOption = React.forwardRef(function RadioButtonOption( @@ -39,7 +39,6 @@ export const RadioButtonOption = React.forwardRef(function RadioButtonOption - {inner && {inner}} ); From 2ee7a3c9a8c2040fb0eabf44928c9298c49e5565 Mon Sep 17 00:00:00 2001 From: benaxse Date: Sat, 10 Aug 2024 14:00:04 +0300 Subject: [PATCH 2/5] refactor(RadioButton): refactor styles --- src/components/RadioButton/RadioButton.scss | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/RadioButton/RadioButton.scss b/src/components/RadioButton/RadioButton.scss index 32f8086e7c..9229a1b3d0 100644 --- a/src/components/RadioButton/RadioButton.scss +++ b/src/components/RadioButton/RadioButton.scss @@ -4,15 +4,12 @@ $block: '.#{variables.$ns}radio-button'; #{$block} { --_--border-width: 1px; - --_--negative-border-width: calc(-1 * var(--_--border-width)); box-sizing: border-box; display: inline-flex; flex-direction: row; font-family: var(--g-text-body-font-family); font-weight: var(--g-text-body-font-weight); - border: var(--_--border-width) solid var(--g-color-line-generic); - border-radius: var(--_--border-radius); position: relative; &__option { @@ -22,9 +19,6 @@ $block: '.#{variables.$ns}radio-button'; font-size: var(--g-text-body-1-font-size); text-align: center; - margin: var(--_--negative-border-width) var(--_--negative-border-width) - var(--_--negative-border-width) 0; - cursor: pointer; transform: scale(1); transition: color 0.15s linear; @@ -43,12 +37,19 @@ $block: '.#{variables.$ns}radio-button'; position: absolute; z-index: -2; inset: 0; - border: var(--_--border-width) solid transparent; + border: var(--_--border-width) solid var(--g-color-line-generic); border-radius: 0; } + &:not(:first-child):not(&_checked)::after { + border-inline-start-width: 0; + } + + &:not(:last-child):not(&_checked):after { + border-inline-end-width: 0; + } + &:first-child { - margin-inline-start: var(--_--negative-border-width); border-start-start-radius: var(--_--border-radius); border-end-start-radius: var(--_--border-radius); From e4229bad092b1ebe47e8fd23ab96b3ac5eac4638 Mon Sep 17 00:00:00 2001 From: benaxse Date: Sat, 10 Aug 2024 21:44:50 +0300 Subject: [PATCH 3/5] feat(RadioButton): add transitions --- src/components/RadioButton/RadioButton.scss | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/RadioButton/RadioButton.scss b/src/components/RadioButton/RadioButton.scss index 9229a1b3d0..99d9446a0b 100644 --- a/src/components/RadioButton/RadioButton.scss +++ b/src/components/RadioButton/RadioButton.scss @@ -4,6 +4,7 @@ $block: '.#{variables.$ns}radio-button'; #{$block} { --_--border-width: 1px; + --_--transition-time: 0.15s; box-sizing: border-box; display: inline-flex; @@ -21,7 +22,7 @@ $block: '.#{variables.$ns}radio-button'; cursor: pointer; transform: scale(1); - transition: color 0.15s linear; + transition: color var(--_--transition-time) linear; &::before { position: absolute; @@ -39,6 +40,10 @@ $block: '.#{variables.$ns}radio-button'; inset: 0; border: var(--_--border-width) solid var(--g-color-line-generic); border-radius: 0; + + transition: + background-color var(--_--transition-time) linear, + border-color var(--_--transition-time) linear; } &:not(:first-child):not(&_checked)::after { From 2c3848e9ff1d7b2f902da60dfacf3c6fb5273b5c Mon Sep 17 00:00:00 2001 From: benaxse Date: Wed, 21 Aug 2024 18:09:16 +0300 Subject: [PATCH 4/5] fix: lower z-index; add icon + text support; add pointer events to checked option --- src/components/RadioButton/RadioButton.scss | 8 +++++--- .../RadioButton/__stories__/RadioButtonShowcase.tsx | 11 ++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/components/RadioButton/RadioButton.scss b/src/components/RadioButton/RadioButton.scss index 99d9446a0b..ef7c8f490d 100644 --- a/src/components/RadioButton/RadioButton.scss +++ b/src/components/RadioButton/RadioButton.scss @@ -36,7 +36,7 @@ $block: '.#{variables.$ns}radio-button'; &::after { content: ''; position: absolute; - z-index: -2; + z-index: -1; inset: 0; border: var(--_--border-width) solid var(--g-color-line-generic); border-radius: 0; @@ -108,7 +108,10 @@ $block: '.#{variables.$ns}radio-button'; } &-text { - display: inline-block; + display: inline-flex; + justify-content: center; + align-items: center; + gap: 8px; white-space: nowrap; color: var(--g-color-text-complementary); overflow: hidden; @@ -122,7 +125,6 @@ $block: '.#{variables.$ns}radio-button'; &_checked { cursor: default; - pointer-events: none; border-color: var(--g-color-line-brand); #{$block}__option-text { diff --git a/src/components/RadioButton/__stories__/RadioButtonShowcase.tsx b/src/components/RadioButton/__stories__/RadioButtonShowcase.tsx index 04cbd93ffc..310e377cd0 100644 --- a/src/components/RadioButton/__stories__/RadioButtonShowcase.tsx +++ b/src/components/RadioButton/__stories__/RadioButtonShowcase.tsx @@ -16,7 +16,16 @@ export function RadioButtonShowcase() { ]; const iconOptions: RadioButtonOption[] = [ - {value: 'Value 1', content: , title: 'Warning'}, + { + value: 'Value 1', + content: ( + + + Warning + + ), + title: 'Warning', + }, {value: 'Value 2', content: , title: 'Info'}, ]; From 58383125548e3302f9989bc9381caf3c381b4432 Mon Sep 17 00:00:00 2001 From: benaxse Date: Thu, 22 Aug 2024 14:24:37 +0300 Subject: [PATCH 5/5] fix: remove pointer-events none from disabled --- src/components/RadioButton/RadioButton.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/RadioButton/RadioButton.scss b/src/components/RadioButton/RadioButton.scss index ef7c8f490d..75461de372 100644 --- a/src/components/RadioButton/RadioButton.scss +++ b/src/components/RadioButton/RadioButton.scss @@ -78,7 +78,7 @@ $block: '.#{variables.$ns}radio-button'; } } - &:not(&_checked):hover { + &:not(&_checked):not(&_disabled):hover { &::after { background-color: var(--g-color-base-simple-hover); } @@ -144,7 +144,6 @@ $block: '.#{variables.$ns}radio-button'; &_disabled { cursor: default; - pointer-events: none; &::after { background-color: var(--g-color-base-generic);