fix(dashboard-v2): migrate Switch to styled-components
This commit is contained in:
parent
a00d4f8db9
commit
cb5a162fe4
|
@ -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;
|
||||
}
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
Reference in New Issue