#app
View Compiled
@use "sass:math";

@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700");

$background-color: #2f2f2f;
$button-size: 4rem;
$transition-time: 96ms;

@mixin button() {
	font-family: inherit;
	width: 100%;
	height: 100%;
	border: 0;
	position: absolute;
	top: 0;
	left: 0;
	border-radius: 50%;
	box-sizing: border-box;
	user-select: none;
}

#app {
	font-family: "Open Sans", sans-serif;
	background-color: $background-color;
	width: 100vw;
	height: 100vh;
	padding: 2rem;
	display: flex;
	flex-wrap: nowrap;
	overflow: auto;
	box-sizing: border-box;
	& > div {
		margin: auto;
		flex-shrink: 0;
	}
}

.main-button {
	width: $button-size;
	height: $button-size;
	position: relative;
}

.main-button-icon {
	@include button();
	background-color: #ff406f;
	box-shadow: 0 0.3rem 1rem rgba(#000000, 0.4);
	transition: background-color $transition-time ease-out;
	&:before, &:after {
		$width: $button-size * 0.55;
		$height: $button-size * 0.1;
		content: "";
		background-color: #ffffff;
		width: $width;
		height: $height;
		position: absolute;
		top: ($button-size / 2) - ($height / 2);
		left: ($button-size / 2) - ($width / 2);
		border-radius: 10% / 50%;
		transition:
			background-color $transition-time ease-out,
			border-radius $transition-time ease-out,
			transform $transition-time ease-out;
	}
	&:after {
		transform: rotate(90deg);
	}
}

.main-button-active > .main-button-icon {
	background-color: #dadada;
	&:before, &:after {
		background-color: $background-color;
		border-radius: 0;
	}
	&:before {
		transform: rotate(45deg);
	}
	&:after {
		transform: rotate(135deg);
	}
}

.sub-button {
	--background-color: #000000;
	@include button();
	color: #ffffff;
	background-color: var(--background-color);
	display: flex;
	justify-content: center;
	align-items: center;
}

@for $i from 0 to 6 {
	$distance: 150%;
	$angle: (360 / 6) * $i;
	$distance-x: $distance * math.cos($angle * math.$pi / 180);
	$distance-y: $distance * math.sin($angle * math.$pi / 180);

	.main-button-active > .sub-button:nth-child(#{$i + 1}):not(.sub-button-fading) {
		$animation-time: 192ms;
		animation:
			show-sub-buttons-#{$i}
			$animation-time
			ease-out
			(($animation-time / 6) * $i)
			forwards;
		@keyframes show-sub-buttons-#{$i} {
			0% {
				opacity: 0;
				transform: translateX(0%) translateY(0%);
				filter: blur(2px);
			}
			100% {
				opacity: 1;
				box-shadow: 0 0.3rem 1rem rgba(#000000, 0.4);
				transform: translateX($distance-x) translateY($distance-y);
				filter: blur(0);
			}
		}
	}
	
	.main-button-active > .sub-button.sub-button-fading:nth-child(#{$i + 1}) {
		$animation-time: 192ms;
		transform: translateX($distance-x) translateY($distance-y);
		animation: fade-sub-buttons $animation-time ease-out forwards;
		@keyframes fade-sub-buttons {
			0% {
				opacity: 1;
				filter: blur(0);
			}
			100% {
				opacity: 0;
				filter: blur(2px);
			}
		}
	}
}

.sub-button-text {
	font-family: inherit;
	font-size: 0.8rem;
	position: absolute;
	bottom: 0;
	transform: translateY(125%);
}

.sub-button-icon {
	color: $background-color;
}
View Compiled
import React, { useState, useEffect } from "https://cdn.skypack.dev/react@17.0.1";
import ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1";

function MultiPurposeButton() {
	const [activeState, setActiveState] = useState(false);
	const [fadingState, setFadingState] = useState(false);
	
	let SubButton = props => {
		let icon = props.icon;
		let text = props.text;
		let backgroundColor = props.backgroundColor;

		if (!activeState) {
			return null;
		}
		
		let subButtonClassName = "sub-button";
		
		if (fadingState) {
			subButtonClassName += " sub-button-fading";
		}
		
		icon = "sub-button-icon " + icon;

		return (
			<button
				className={subButtonClassName}
				style={{"--background-color": backgroundColor}}
				onAnimationEnd={evt => {
					if (evt.animationName === "fade-sub-buttons") {
						setActiveState(false);
						setFadingState(false);
					}
				}}
			>
				<i className={icon}></i>
				<span className="sub-button-text">{text}</span>
			</button>
		);
	};
	
	let buttonClassName = "main-button";
	
	if (activeState) {
		buttonClassName += " main-button-active";
	}
	
	return (
		<div className={buttonClassName}>
			<SubButton icon="far fa-file-audio fa-2x" text="AUDIO" backgroundColor="#b211c1" />
			<SubButton icon="far fa-file-image fa-2x" text="IMAGE" backgroundColor="#ece82f" />
			<SubButton icon="far fa-file-video fa-2x" text="VIDEO" backgroundColor="#1ccc3a" />
			<SubButton icon="far fa-file-archive fa-2x" text="ARCHIVE" backgroundColor="#f87131" />
			<SubButton icon="far fa-file-code fa-2x" text="CODE" backgroundColor="#e11117" />
			<SubButton icon="far fa-file-alt fa-2x" text="FILE" backgroundColor="#045ee4" />
			<div
				className="main-button-icon"
				onClick={evt => {
					if (activeState) {
						setFadingState(true);
					} else {
						setActiveState(true);
					}
				}}></div>
		</div>
	);
}

ReactDOM.render(
	<MultiPurposeButton />,
	document.querySelector("#app")
);
View Compiled

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css

External JavaScript

This Pen doesn't use any external JavaScript resources.