$albumUrl: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/1468070/odesza-in-return.jpg';
$mainColor: rgb(63, 42, 58);
$accentColor1: rgb(221, 174, 121);
$accentColor2: rgb(200, 148, 124);
body, html{
background-color: $gray30;
height: 100%;
margin: 0px;
overflow: hidden;
padding: 0px;
width: 100%;
h1{
font-family: 'Roboto', sans-serif;
}
h1, i{
pointer-events: none;
}
}
#hint{
margin: 10px;
h1{
color: $blue;
font-size: 0.8em;
font-weight: 400;
margin: 0px;
text-align: center;
}
}
#notification{
box-shadow: $shadow2;
height: 90px;
left: 50%;
overflow: hidden;
position: absolute;
top: 50%;
transform: translateX(-50%) translateY(-50%);
user-select: none;
width: 300px;
#info, #image{
height: 90px;
position: absolute;
}
#info{
background-color: $mainColor;
width: 210px;
z-index: 2;
&:after{
background: linear-gradient(to right, $mainColor, transparent);
content: '';
height: 90px;
position: absolute;
right: 0px;
top: 0px;
transform: translateX(100%);
width: 90px;
}
#specifics{
margin: 8px 12px;
margin-top: 0px;
h1{
font-size: 0.6em;
font-weight: 400;
margin: 0px;
&.song{
color: $accentColor1;
}
&.artist{
color: $accentColor2;
}
}
}
#controls{
margin: 8px 12px;
margin-top: 0px;
i{
color: $accentColor1;
display: inline-block;
font-size: 0.8em;
margin: 0px 10px;
&:first-child{
margin-left: 0px;
}
}
}
}
#image{
background-image: url($albumUrl);
background-position: center;
background-size: cover;
right: 0px;
top: 0px;
width: 90px;
}
#settings{
background-color: white;
border-radius: 1000px;
height: 20px;
opacity: 0;
position: absolute;
transform: translateX(-50%) translateY(-50%);
transition: all 0.5s, border-radius .75s;
width: 20px;
z-index: 11;
#settings-contents{
background-color: $gray230;
height: 90px;
opacity: 0;
position: relative;
transition: all 0.25s;
.service{
i, h1{
color: $gray40;
}
}
#details{
margin: 8px 12px;
margin-top: 2px;
h1{
font-weight: 400;
margin: 0px;
}
.main{
color: $gray40;
font-size: 0.7em;
}
.sub{
color: $gray120;
font-size: 0.6em;
margin-top: 2px;
}
}
#done{
border-radius: 2px;
bottom: 0px;
cursor: pointer;
margin: 12px 8px;
padding: 4px 6px;
position: absolute;
right: 0px;
&:hover{
background-color: $gray220;
}
h1{
color: $blue;
font-size: 0.7em;
font-weight: 400;
margin: 0px;
}
}
}
}
.service{
display: inline-block;
margin: 8px 12px;
height: 12px;
i, h1{
color: $accentColor1;
display: inline-block;
font-size: 0.6em;
height: 12px;
line-height: 12px;
margin: 0px;
vertical-align: top;
}
h1{
font-weight: 400;
&.details{
color: $accentColor2;
}
}
}
}
View Compiled
const STATE = {
holdLength: 0,
isToggled: false
}
const NOTIFICATION = getEl('notification'),
SETTINGS = getEl('settings'),
SETTINGS_CONTENTS = getEl('settings-contents'),
DONE = getEl('done')
let holdInterval = null
const toggleNotificationSettings = (mouseX, mouseY, isToggling) => {
const left = mouseX - NOTIFICATION.getBoundingClientRect().left,
right = Math.abs(mouseX - NOTIFICATION.getBoundingClientRect().right),
top = mouseY - NOTIFICATION.getBoundingClientRect().top,
distance = right > left ? right : left,
size = Math.max(300, distance * 2)
if(isToggling){
setElPos(SETTINGS, left, top)
setTimeout(() => {
setStyle(SETTINGS, 'transition', 'all 0.5s, border-radius .75s')
setStyle(SETTINGS, 'border-radius', '0px')
setStyle(SETTINGS, 'opacity', '1')
setStyle(SETTINGS, 'height', `${size}px`)
setStyle(SETTINGS, 'width', `${size}px`)
setTimeout(() => {
setStyle(SETTINGS, 'height', '90px')
setStyle(SETTINGS, 'width', '300px')
setStyle(SETTINGS, 'left', '0px')
setStyle(SETTINGS, 'top', '0px')
setStyle(SETTINGS, 'transition', 'none')
setStyle(SETTINGS, 'transform', 'none')
setStyle(SETTINGS_CONTENTS, 'opacity', 1)
}, 500)
}, 100)
}
else{
setTimeout(() => {
setStyle(SETTINGS, 'left', '50%')
setStyle(SETTINGS, 'top', '50%')
setStyle(SETTINGS, 'height', '300px')
setStyle(SETTINGS, 'width', '300px')
setStyle(SETTINGS, 'transform', 'translateX(-50%) translateY(-50%)')
setStyle(SETTINGS_CONTENTS, 'opacity', 0)
setTimeout(() => {
setElPos(SETTINGS, left, top)
setStyle(SETTINGS, 'opacity', '0')
setStyle(SETTINGS, 'height', '20px')
setStyle(SETTINGS, 'width', '20px')
setStyle(SETTINGS, 'border-radius', '1000px')
setStyle(SETTINGS, 'transition', 'all 0.5s, border-radius 0s')
resetSettings(500)
}, 100)
}, 100)
}
}
const resetSettings = time => {
setTimeout(() => {
STATE.isToggled = false
SETTINGS.removeAttribute('style')
SETTINGS_CONTENTS.removeAttribute('style')
}, time)
}
const doOnMouseDown = e => {
clearInterval(holdInterval)
STATE.holdLength = 0
STATE.isToggled = !STATE.isToggled
toggleNotificationSettings(e.clientX, e.clientY, STATE.isToggled)
}
const handleMouseHold = (e, isInstant = false) => {
if(isInstant){
doOnMouseDown(e)
}
else{
holdInterval = setInterval(() => {
STATE.holdLength += 100
if(STATE.holdLength >= 500){
doOnMouseDown(e)
}
}, 100)
}
}
NOTIFICATION.onmousedown = e => {
const element = e.target.id || e.target.className
if(element !== 'done'){
handleMouseHold(e)
}
}
NOTIFICATION.onmouseup = () => clearInterval(holdInterval)
NOTIFICATION.onmouseleave = () => clearInterval(holdInterval)
DONE.onmousedown = e => handleMouseHold(e, false)
DONE.onmouseup = e => handleMouseHold(e, true)