Liquid UI Elements

  <div class="grid">

    <label class="radio">
        <input type="radio" name="r" value="1" checked />
        <svg viewBox="0 0 24 24" filter="url(#goo-light)">
            <circle class="top" cx="12" cy="-12" r="8" />
            <circle class="dot" cx="12" cy="12" r="5" />
            <circle class="drop" cx="12" cy="12" r="2" />
        </svg>
    </label>

    <label class="radio">
        <input type="radio" name="r" value="2" />
        <svg viewBox="0 0 24 24" filter="url(#goo-light)">
            <circle class="top" cx="12" cy="-12" r="8" />
            <circle class="dot" cx="12" cy="12" r="5" />
            <circle class="drop" cx="12" cy="12" r="2" />
        </svg>
    </label>

    <label class="switch">
        <input type="checkbox" checked />
        <svg viewBox="0 0 38 24" filter="url(#goo)">
            <circle class="default" cx="12" cy="12" r="8" />
            <circle class="dot" cx="26" cy="12" r="8" />
            <circle class="drop" cx="25" cy="-1" r="2" />
        </svg>
    </label>

    <label class="switch">
        <input type="checkbox" />
        <svg viewBox="0 0 38 24" filter="url(#goo)">
            <circle class="default" cx="12" cy="12" r="8" />
            <circle class="dot" cx="26" cy="12" r="8" />
        </svg>
    </label>

    <label class="checkbox">
        <input type="checkbox" checked />
        <svg viewBox="0 0 24 24" filter="url(#goo-light)">
            <path class="tick" d="M4.5 10L10.5 16L24.5 1" />
            <circle class="dot" cx="10.5" cy="15.5" r="1.5" />
        </svg>
    </label>

    <label class="checkbox">
        <input type="checkbox" />
        <svg viewBox="0 0 24 24" filter="url(#goo-light)">
            <path class="tick" d="M4.5 10L10.5 16L24.5 1" />
            <circle class="dot" cx="10.5" cy="15.5" r="1.5" />
            <circle class="drop" cx="25" cy="-1" r="2" />
        </svg>
    </label>

    <div class="last">

        <button class="btn">
            <span>Submit</span>
            <svg preserveAspectRatio="none" viewBox="0 0 132 45">
                <g clip-path="url(#clip)" filter="url(#goo-big)">
                    <circle class="top-left" cx="49.5" cy="-0.5" r="26.5" />
                    <circle class="middle-bottom" cx="70.5" cy="40.5" r="26.5" />
                    <circle class="top-right" cx="104" cy="6.5" r="27" />
                    <circle class="right-bottom" cx="123.5" cy="36.5" r="26.5" />
                    <circle class="left-bottom" cx="16.5" cy="28" r="30" />
                </g>
                <defs>
                    <clipPath id="clip">
                        <rect width="132" height="45" rx="7" />
                    </clipPath>
                </defs>
            </svg>
        </button>

    </div>
</div>
<svg width="0" height="0">
    <defs>
        <filter id="goo" x="-50%" width="200%" y="-50%" height="200%" color-interpolation-filters="sRGB">
            <feGaussianBlur in="SourceGraphic" stdDeviation="3" result="blur" />
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 21 -7" result="cm" />
        </filter>
        <filter id="goo-light" x="-50%" width="200%" y="-50%" height="200%" color-interpolation-filters="sRGB">
            <feGaussianBlur in="SourceGraphic" stdDeviation="1.25" result="blur" />
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 21 -7" result="cm" />
        </filter>
        <filter id="goo-big" x="-50%" width="200%" y="-50%" height="200%" color-interpolation-filters="sRGB">
            <feGaussianBlur in="SourceGraphic" stdDeviation="7" result="blur" />
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 21 -7" result="cm" />
        </filter>
    </defs>
</svg>

<script src="https://unpkg.co/gsap@3/dist/gsap.min.js"></script>
:root {
	--c-active: #275EFE;
	--c-active-inner: #FFFFFF;
	--c-default: #D2D6E9;
	--c-default-dark: #C7CBDF;
	--c-black: #1B1B22;
  }
  
  .radio,
  .checkbox,
  .switch {
	display: table;
	border-radius: var(--border-radius, 12px) var(--border-radius-corner, 12px) var(--border-radius, 12px) var(--border-radius, 12px);
	position: relative;
  }
  .radio input,
  .checkbox input,
  .switch input {
	-webkit-appearance: none;
	   -moz-appearance: none;
			appearance: none;
	outline: none;
	border: none;
	background: var(--input-background, none);
	display: block;
	cursor: pointer;
	margin: 0;
	padding: 0;
	border-radius: inherit;
	width: var(--input-width, 24px);
	height: var(--input-height, 24px);
  }
  .radio svg,
  .checkbox svg,
  .switch svg {
	display: block;
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	top: 0;
	pointer-events: none;
	fill: var(--c-active-inner);
	transform: scale(1.01) translateZ(0);
  }
  
  .radio input,
  .checkbox input {
	--border-color: var(--c-default);
	--border-width: 2px;
	box-shadow: inset 0 0 0 var(--border-width) var(--border-color);
  }
  .radio input:checked,
  .checkbox input:checked {
	--border-color: var(--c-active);
  }
  .radio input:not(:checked),
  .checkbox input:not(:checked) {
	transition: box-shadow 0.25s;
  }
  .radio input:not(:checked):hover,
  .checkbox input:not(:checked):hover {
	--border-width: 3px;
	--border-color: var(--c-active);
  }
  
  .radio input:checked {
	--border-width: 6.75px;
  }
  .radio input + svg {
	--top-y: 0;
	--dot-y: -17px;
	--drop-y: -14px;
	--top-s-x: 1.75;
	--top-s-y: 1;
  }
  .radio input + svg .top {
	transform-origin: 12px -12px;
	transform: translateY(var(--top-y)) scale(var(--top-s-x), var(--top-s-y)) translateZ(0);
  }
  .radio input + svg .dot {
	transform: translateY(var(--dot-y)) translateZ(0);
  }
  .radio input + svg .drop {
	transform: translateY(var(--drop-y)) translateZ(0);
  }
  
  .checkbox {
	--border-radius: 5px;
	--border-radius-corner: 5px;
  }
  .checkbox input:checked {
	--border-width: 12px;
  }
  .checkbox input:checked + svg {
	--tick-offset: 46.5px;
  }
  .checkbox input + svg {
	--dot-x: 14px;
	--dot-y: -14px;
	--dot-s: 1;
	--tick-offset: 20.5px;
	--tick-array: 16.5px;
	--tick-s: 1;
	--drop-s: 1;
  }
  .checkbox input + svg .tick {
	fill: none;
	stroke-width: 3px;
	stroke-linecap: round;
	stroke-linejoin: round;
	stroke: var(--c-active-inner);
	stroke-dasharray: var(--tick-array) 33px;
	stroke-dashoffset: var(--tick-offset);
	transform-origin: 10.5px 16px;
	transform: scale(var(--tick-s)) translateZ(0);
  }
  .checkbox input + svg .dot {
	transform-origin: 10.5px 15.5px;
	transform: translate(var(--dot-x), var(--dot-y)) scale(var(--dot-s)) translateZ(0);
  }
  .checkbox input + svg .drop {
	transform-origin: 25px -1px;
	transform: scale(var(--drop-s)) translateZ(0);
  }
  
  .switch {
	--input-width: 38px;
  }
  .switch input {
	--input-background: var(--c-default);
  }
  .switch input:checked {
	--input-background: var(--c-active);
  }
  .switch input:checked + svg {
	--default-s: 0;
	--default-x: 8px;
	--dot-s: 1;
	--dot-x: 0px;
  }
  .switch input + svg {
	--input-background: var(--c-default);
	--default-s: 1;
	--default-x: 0px;
	--dot-s: 0;
	--dot-x: -8px;
  }
  .switch .default {
	transform-origin: 12px 12px;
	transform: translateX(var(--default-x)) scale(var(--default-s)) translateZ(0);
  }
  .switch .dot {
	transform-origin: 26px 12px;
	transform: translateX(var(--dot-x)) scale(var(--dot-s)) translateZ(0);
  }
  
  .btn {
	-webkit-appearance: none;
	   -moz-appearance: none;
			appearance: none;
	border: none;
	position: relative;
	background: var(--c-black);
	color: #fff;
	outline: none;
	cursor: pointer;
	font-size: 14px;
	line-height: 21px;
	font-weight: 600;
	display: block;
	width: 132px;
	text-align: center;
	border-radius: 7px;
	margin: 0 auto;
	padding: 12px 0;
  }
  .btn span {
	position: relative;
	z-index: 1;
  }
  .btn svg {
	display: block;
	width: 100%;
	height: 100%;
	position: absolute;
	left: 0;
	top: 0;
	fill: var(--c-active);
  }
  .btn svg circle {
	transition: transform var(--duration, 0.25s) ease-out;
  }
  .btn svg circle.top-left {
	transform: translate(var(--spacing, -16px), var(--spacing, -40px));
  }
  .btn svg circle.middle-bottom {
	transform: translate(var(--spacing, 8px), var(--spacing, 40px));
  }
  .btn svg circle.top-right {
	transform: translate(var(--spacing, 40px), var(--spacing, -40px));
  }
  .btn svg circle.right-bottom {
	transform: translate(var(--spacing, 4px), var(--spacing, 40px));
  }
  .btn svg circle.left-bottom {
	transform: translate(var(--spacing, -40px), var(--spacing, 40px));
  }
  .btn:hover {
	--spacing: 0;
	--duration: .45s;
  }
  
  .grid {
	display: grid;
	grid-gap: 24px 32px;
	grid-template-columns: repeat(3, auto);
	grid-template-rows: repeat(3, auto);
	grid-auto-flow: column;
  }
  .grid .last {
	grid-column: 1/4;
	grid-row: 3;
  }
  
  html {
	box-sizing: border-box;
	-webkit-font-smoothing: antialiased;
  }
  
  * {
	box-sizing: inherit;
  }
  *:before, *:after {
	box-sizing: inherit;
  }
  
  body {
	min-height: 100vh;
	display: flex;
	font-family: "Poppins", Arial;
	justify-content: center;
	align-items: center;
	background: #fff;
  }
  body .dribbble {
	position: fixed;
	display: block;
	right: 20px;
	bottom: 20px;
  }
  body .dribbble img {
	display: block;
	height: 28px;
  }
  body .twitter {
	position: fixed;
	display: block;
	right: 64px;
	bottom: 14px;
  }
  body .twitter svg {
	width: 32px;
	height: 32px;
	fill: #1da1f2;
  }
const { to, set, from, fromTo } = gsap

const getVar = (key, elem = document.documentElement) => getComputedStyle(elem).getPropertyValue(key)

document.querySelectorAll('.radio').forEach(elem => {
    let svg = elem.querySelector('svg'),
        input = elem.querySelector('input')
    input.addEventListener('change', e => {
        fromTo(input, {
            '--border-width': '3px'
        }, {
            '--border-color': getVar('--c-active'),
            '--border-width': '12px',
            duration: .2
        })
        to(svg, {
            keyframes: [{
                '--top-y': '6px',
                '--top-s-x': 1,
                '--top-s-y': 1.25,
                duration: .2,
                delay: .2
            }, {
                '--top-y': '0px',
                '--top-s-x': 1.75,
                '--top-s-y': 1,
                duration: .6
            }]
        })
        to(svg, {
            keyframes: [{
                '--dot-y': '2px',
                duration: .3,
                delay: .2
            }, {
                '--dot-y': '0px',
                duration: .3
            }]
        })
        to(svg, {
            '--drop-y': '0px',
            duration: .6,
            delay: .4,
            clearProps: true,
            onComplete() {
                input.removeAttribute('style')
            }
        })
    })
})

document.querySelectorAll('.checkbox').forEach(elem => {
    let svg = elem.querySelector('svg'),
        input = elem.querySelector('input')
    input.addEventListener('change', e => {
        let checked = input.checked
        if(!checked) {
            return
        }
        fromTo(input, {
            '--border-width': '3px'
        }, {
            '--border-color': getVar('--c-active'),
            '--border-width': '12px',
            duration: .2,
            clearProps: true
        })
        set(svg, {
            '--dot-x': '14px',
            '--dot-y': '-14px',
            '--tick-offset': '20.5px',
            '--tick-array': '16.5px',
            '--drop-s': 1
        })
        to(elem, {
            keyframes: [{
                '--border-radius-corner': '14px',
                duration: .2,
                delay: .2
            }, {
                '--border-radius-corner': '5px',
                duration: .3,
                clearProps: true
            }]
        })
        to(svg, {
            '--dot-x': '0px',
            '--dot-y': '0px',
            '--dot-s': 1,
            duration: .4,
            delay: .4
        })
        to(svg, {
            keyframes: [{
                '--tick-offset': '48px',
                '--tick-array': '14px',
                duration: .3,
                delay: .2
            }, {
                '--tick-offset': '46.5px',
                '--tick-array': '16.5px',
                duration: .35,
                clearProps: true
            }]
        })
    })
})

document.querySelectorAll('.switch').forEach(elem => {
    let svg = elem.querySelector('svg'),
        input = elem.querySelector('input')
    input.addEventListener('pointerenter', e => {
        if(elem.animated || input.checked) {
            return
        }
        to(input, {
            '--input-background': getVar('--c-default-dark'),
            duration: .2
        })
    })
    input.addEventListener('pointerleave', e => {
        if(elem.animated || input.checked) {
            return
        }
        to(input, {
            '--input-background': getVar('--c-default'),
            duration: .2
        })
    })
    input.addEventListener('change', e => {
        let checked = input.checked
        let hide = checked ? 'default' : 'dot',
            show = checked ? 'dot' : 'default'
        fromTo(svg, {
            '--default-s': checked ? 1 : 0,
            '--default-x': checked ? '0px' : '8px',
            '--dot-s': checked ? 0 : 1,
            '--dot-x': checked ? '-8px' : '0px'
        }, {
            ['--' + hide + '-s']: 0,
            ['--' + hide + '-x']: checked ? '8px' : '-8px',
            duration: .25,
            delay: .15
        })
        fromTo(input, {
            '--input-background': getVar(checked ? '--c-default' : '--c-active'),
        }, {
            '--input-background': getVar(checked ? '--c-active' : '--c-default'),
            duration: .35,
            clearProps: true
        })
        to(svg, {
            keyframes: [{
                ['--' + show + '-x']: checked ? '2px' : '-2px',
                ['--' + show + '-s']: 1,
                duration: .25
            }, {
                ['--' + show + '-x']: '0px',
                duration: .2,
                clearProps: true
            }]
        })
    })
})