Skip to content

Commit

Permalink
feat(react-ui-kit): add focus for switch button
Browse files Browse the repository at this point in the history
  • Loading branch information
przemvs committed Oct 10, 2024
1 parent b5c261e commit 18781ed
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 93 deletions.
115 changes: 115 additions & 0 deletions packages/react-ui-kit/src/Form/Switch.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Wire
* Copyright (C) 2022 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
*/

import {CSSObject} from '@emotion/react';

import {COLOR, COLOR_V2} from '../Identity';

export const wrapperStyles: CSSObject = {
display: 'grid',
position: 'relative',
textAlign: 'left',
userSelect: 'none',
verticalAlign: 'middle',
width: '42px',
};

export const inputStyles: CSSObject = {
height: '0',
width: '0',
opacity: '0',
'&:focus + label': {
outline: `1px solid ${COLOR_V2.BLUE_LIGHT_700}`,
},
};

export const labelStyles = (disabled: boolean, showLoading: boolean): CSSObject => ({
borderRadius: '20px',
cursor: disabled || showLoading ? '' : 'pointer',
display: 'block',
margin: 0,
overflow: 'hidden',
});

type SwitchStylesProps = {
disabled: boolean;
showLoading: boolean;
checked: boolean;
activatedColor: string;
deactivatedColor: string;
};

export const switchStyles = ({
disabled,
showLoading,
checked,
activatedColor,
deactivatedColor,
}: SwitchStylesProps): CSSObject => ({
'&:after': {
content: '" "',
paddingRight: '10px',
textAlign: 'right',
},
'&:before': {
content: '" "',
paddingLeft: '10px',
},
'&:before, &:after': {
backgroundColor:
disabled || showLoading
? COLOR.tint(checked ? activatedColor : deactivatedColor, 0.4)
: checked
? activatedColor
: deactivatedColor,
boxSizing: 'border-box',
display: 'block',
float: 'left',
height: '25px',
lineHeight: '1.5625rem',
padding: 0,
width: '50%',
},
display: 'block',
marginLeft: checked ? 0 : '-100%',
transition: 'margin 0.1s ease-in 0s',
width: '200%',
});

export const loadingStyles: CSSObject = {
display: 'block',
margin: '2px',
position: 'absolute',
};

export const switchDotStyles = (disabled: boolean, checked: boolean): CSSObject => ({
background: COLOR.WHITE,
borderRadius: '100%',
bottom: 0,
boxShadow: '0px 0px 2px -1px gray',
display: 'block',
height: '23px',
margin: '1px',
opacity: disabled ? 0.7 : undefined,
position: 'absolute',
right: checked ? '0px' : '17px',
top: 0,
transition: 'all 0.15s ease-in 0s',
width: '23px',
});
133 changes: 40 additions & 93 deletions packages/react-ui-kit/src/Form/Switch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
*
*/

import {Fragment} from 'react';
import {forwardRef} from 'react';

import {InputProps} from './Input';
import {inputStyles, labelStyles, loadingStyles, switchDotStyles, switchStyles, wrapperStyles} from './Switch.styles';

import {COLOR} from '../Identity';
import {Loading} from '../Misc';
Expand All @@ -38,111 +39,57 @@ export interface SwitchProps<T = HTMLInputElement> extends InputProps<T> {
dataUieName?: string;
}

export const Switch = ({
id = Math.random().toString(),
checked,
onToggle = () => {},
showLoading,
disabled,
loadingColor = COLOR.BLUE,
activatedColor = COLOR.BLUE,
deactivatedColor = '#d2d2d2',
name,
dataUieName,
}: SwitchProps) => (
<div
css={{
display: 'inline-block',
position: 'relative',
textAlign: 'left',
userSelect: 'none',
verticalAlign: 'middle',
width: '42px',
}}
>
<Fragment>
export const Switch = forwardRef<HTMLInputElement, SwitchProps>(
(
{
id = Math.random().toString(),
checked,
onToggle = () => {},
showLoading,
disabled,
loadingColor = COLOR.BLUE,
activatedColor = COLOR.BLUE,
deactivatedColor = '#d2d2d2',
name,
dataUieName,
},
ref,
) => (
<div css={wrapperStyles}>
<input
ref={ref}
id={id}
checked={checked}
disabled={disabled}
name={name}
onChange={event => onToggle(event.target.checked)}
onKeyDown={event => {
if (event.key == 'Enter') {
onToggle(!(event.target as HTMLInputElement).checked);
}
}}
type="checkbox"
css={{display: 'none'}}
css={inputStyles}
data-uie-name={dataUieName}
/>
<label
htmlFor={id}
css={{
borderRadius: '20px',
cursor: disabled || showLoading ? '' : 'pointer',
display: 'block',
margin: 0,
overflow: 'hidden',
}}
>
<label htmlFor={id} css={labelStyles(disabled, showLoading)}>
<span
css={{
['&:after']: {
content: '" "',
paddingRight: '10px',
textAlign: 'right',
},
['&:before']: {
content: '" "',
paddingLeft: '10px',
},
['&:before, &:after']: {
backgroundColor:
disabled || showLoading
? COLOR.tint(checked ? activatedColor : deactivatedColor, 0.4)
: checked
? activatedColor
: deactivatedColor,
boxSizing: 'border-box',
display: 'block',
float: 'left',
height: '25px',
lineHeight: '1.5625rem',
padding: 0,
width: '50%',
},
display: 'block',
marginLeft: checked ? 0 : '-100%',
transition: 'margin 0.1s ease-in 0s',
width: '200%',
}}
css={switchStyles({
disabled,
showLoading,
checked,
activatedColor,
deactivatedColor,
})}
/>
{showLoading ? (
<Loading
size={21}
color={loadingColor}
style={{
display: 'block',
margin: '2px',
position: 'absolute',
}}
/>
<Loading size={21} color={loadingColor} css={loadingStyles} />
) : (
<span
css={{
background: COLOR.WHITE,
borderRadius: '100%',
bottom: 0,
boxShadow: '0px 0px 2px -1px gray',
display: 'block',
height: '23px',
margin: '1px',
opacity: disabled ? 0.7 : undefined,
position: 'absolute',
right: checked ? '0px' : '17px',
top: 0,
transition: 'all 0.15s ease-in 0s',
width: '23px',
}}
/>
<span css={switchDotStyles(disabled, checked)} />
)}
</label>
</Fragment>
</div>
</div>
),
);

Switch.displayName = 'Switch';

0 comments on commit 18781ed

Please sign in to comment.