fix(dashboard-v2): migrate Switch to styled-components

This commit is contained in:
Michał Leszczyk 2022-03-13 10:43:39 +01:00
parent a00d4f8db9
commit cb5a162fe4
No known key found for this signature in database
GPG Key ID: FA123CA8BAA2FBF4
3 changed files with 72 additions and 63 deletions

View File

@ -1,40 +0,0 @@
.react-switch-checkbox {
height: 0;
width: 0;
visibility: hidden;
}
.react-switch-label {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
width: 44px;
height: 22px;
background: white;
border-radius: 11px;
@apply border-palette-200;
border-width: 1px;
position: relative;
transition: background-color 0.2s;
}
.react-switch-label .react-switch-button {
content: "";
position: absolute;
top: 2px;
left: 2px;
width: 16px;
height: 16px;
border-radius: 8px;
transition: 0.2s;
}
.react-switch-checkbox:checked + .react-switch-label .react-switch-button {
left: calc(100% - 2px);
transform: translateX(-100%);
}
.react-switch-label:active .react-switch-button {
width: 20px;
}

View File

@ -1,37 +1,86 @@
import PropTypes from "prop-types";
import "./Switch.css";
import { useEffect, useMemo, useState } from "react";
import styled from "styled-components";
import { nanoid } from "nanoid";
const Container = styled.div.attrs({
className: "inline-flex items-center gap-1 cursor-pointer select-none",
})``;
const Checkbox = styled.input.attrs({
type: "checkbox",
className: `h-0 w-0 hidden`,
})``;
const Label = styled.label.attrs({
className: "cursor-pointer inline-flex items-center gap-2",
})`
&:active .toggle-pin {
width: 20px;
}
`;
const Toggle = styled.span.attrs({
className: `flex flex-row items-center justify-between
w-[44px] h-[22px] bg-white rounded-full
border border-palette-200 relative cursor-pointer`,
})`
&:active .toggle-pin {
width: 20px;
}
`;
const TogglePin = styled.span.attrs(({ $checked }) => ({
className: `toggle-pin
absolute top-[2px] w-4 h-4 rounded-full
transition-[width_left] active:w-5
${$checked ? "checked bg-primary" : "bg-palette-200"}`,
}))`
left: 2px;
&.checked {
left: calc(100% - 2px);
transform: translateX(-100%);
}
`;
export const Switch = ({ children, defaultChecked, onChange, ...props }) => {
const id = useMemo(nanoid, [onChange]);
const [checked, setChecked] = useState(defaultChecked);
useEffect(() => {
onChange(checked);
}, [checked, onChange]);
/**
* Primary UI component for user interaction
*/
export const Switch = ({ isOn, handleToggle }) => {
return (
<>
<input
checked={isOn}
onChange={handleToggle}
className="react-switch-checkbox"
id={`react-switch-new`}
type="checkbox"
/>
<label className={"react-switch-label"} htmlFor={`react-switch-new`}>
<span className={`react-switch-button ${isOn ? "bg-primary" : "bg-palette-200"}`} />
</label>
</>
<Container {...props}>
<Checkbox checked={checked} onChange={(ev) => setChecked(ev.target.checked)} id={id} />
<Label htmlFor={id}>
<Toggle>
<TogglePin $checked={checked} />
</Toggle>
{children}
</Label>
</Container>
);
};
Switch.propTypes = {
/**
* Switch's current value
* Should the checkbox be checked by default?
*/
isOn: PropTypes.bool,
defaultChecked: PropTypes.bool,
/**
* Element to be rendered as the switch label
*/
children: PropTypes.element,
/**
* Function to execute on change
*/
handleToggle: PropTypes.func,
onChange: PropTypes.func.isRequired,
};
Switch.defaultProps = {
isOn: false,
defaultChecked: false,
};

View File

@ -13,10 +13,10 @@ const Template = (args) => <Switch {...args} />;
export const SwitchTrue = Template.bind({});
// More on args: https://storybook.js.org/docs/react/writing-stories/args
SwitchTrue.args = {
isOn: true,
defaultChecked: true,
};
export const SwitchFalse = Template.bind({});
// More on args: https://storybook.js.org/docs/react/writing-stories/args
SwitchFalse.args = {
isOn: false,
defaultChecked: false,
};