<div id="example"></div>
.switch {
transition: all 0.3s;
&.background {
height: 100%;
width: 100%;
display: grid;
align-items: center;
justify-items: center;
}
.switch-container {
margin: 25px 0;
height: 40px;
width: 100px;
background-image: radial-gradient(
circle farthest-corner at 10% 20%,
rgba(253, 203, 50, 1) 0%,
rgba(244, 56, 98, 1) 100.2%
);
border-radius: 25px;
display: flex;
align-items: center;
box-sizing: border-box;
padding: 0 5px;
cursor: pointer;
}
.handle {
height: 30px;
width: 30px;
border-radius: 50%;
display: grid;
align-items: center;
justify-items: center;
background-color: #fff;
overflow: hidden;
}
.icon {
color: #f88748;
font-size: 16px;
}
&[data-darkmode="true"] {
background-color: #52527a;
.switch-container {
background-image: linear-gradient(
109.8deg,
rgba(62, 5, 116, 1) -5.2%,
rgba(41, 14, 151, 1) -5.2%,
rgba(216, 68, 148, 1) 103.3%
);
}
.icon {
color: #501a96;
}
}
}
View Compiled
import React, { useState } from "https://cdn.skypack.dev/react@17.0.1";
import * as ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1";
import {
motion,
AnimatePresence
} from "https://cdn.skypack.dev/framer-motion@5.5.5";
const Switch = () => {
const [isOn, setIsOn] = useState(false);
return (
<div className="switch background" data-darkmode={isOn}>
<div
className="switch-container"
onClick={() => setIsOn(!isOn)}
style={{ justifyContent: isOn ? "flex-end" : "flex-start" }}
>
<motion.div layout className="handle">
<AnimatePresence exitBeforeEnter initial={false}>
<motion.i
className={`icon far fa-${isOn ? "moon" : "sun"}`}
key={isOn ? "moon" : "sun"}
initial={{ y: -30, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: 30, opacity: 0 }}
transition={{ duration: 0.2 }}
/>
</AnimatePresence>
</motion.div>
</div>
</div>
);
};
ReactDOM.render(<Switch />, document.getElementById("example"));
View Compiled
This Pen doesn't use any external JavaScript resources.