<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
Run Pen

External CSS

  1. https://pro.fontawesome.com/releases/v5.2.0/css/all.css

External JavaScript

This Pen doesn't use any external JavaScript resources.