@import url("https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@100;400;700&display=swap");
$primary: #8661c1;
$default: #ced4da;
* {
box-sizing: border-box;
}
html {
font-size: 16px;
}
body {
display: flex;
padding: 0;
margin: 0;
align-items: center;
flex-direction: column;
min-height: 100vh;
font-family: "Roboto Slab", serif;
position: relative;
}
.background {
position: absolute;
top: 0;
left: 0;
width: 100%;
min-height: 100%;
background-color: #eeeef9;
opacity: 0.3;
background-image: repeating-radial-gradient(
circle at 0 0,
transparent 0,
#eeeef9 20px
),
repeating-linear-gradient(#aa90d355, #aa90d3);
}
.challenge-title {
text-align: center;
padding: 0;
margin: 1rem 0 0;
color: $primary;
font-size: 2rem;
font-weight: bold;
}
.challenge-subtitle {
text-align: center;
margin: 0;
font-size: 1.125rem;
font-weight: normal;
color: lighten($primary, 10%);
}
.challenge-part-of {
text-align: center;
margin: 1rem 0 0;
font-size: 0.875rem;
color: lighten($primary, 10%);
position: fixed;
bottom: 1rem;
right: 1rem;
z-index: 2;
a,
a:visited {
color: lighten($primary, 10%);
text-decoration-style: wavy;
&:hover,
&:active {
color: lighten(lighten($primary, 10%), 10%);
}
}
}
div[contenteditable]:focus {
outline: 0;
}
.btn {
display: flex;
align-items: center;
background-color: transparent;
border: 0;
color: darken($default, 70%);
padding: 0.5rem 1rem;
font-size: 1rem;
border-radius: 0.25rem;
border: 1px solid transparent;
transition: background-color 0.2s ease-in;
cursor: pointer;
&:hover {
background-color: lighten($default, 13%);
}
&:active {
background-color: darken($default, 5%);
}
&:focus {
outline: 1px dotted darken($default, 20%);
}
&.btn-sm.btn-circle {
width: 2rem;
height: 2rem;
font-size: 1rem;
}
&.btn-circle {
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
width: 2.5rem;
height: 2.5rem;
font-size: 1.25rem;
}
}
.hidden {
display: none;
}
.hold {
border: 1px solid $default;
width: 600px;
max-width: 100%;
height: 48px;
margin: 2rem;
border-radius: 0.5rem;
padding: 0.5rem 1rem;
display: flex;
align-items: center;
background-color: white;
box-shadow: rgba(0, 0, 0, 0.1) 0px 10px 15px -3px,
rgba(0, 0, 0, 0.05) 0px 4px 6px -2px;
.start-note {
width: 200px;
margin-right: auto;
}
position: relative;
z-index: 2;
&.hidden {
display: none;
}
}
.hold-note {
box-shadow: rgba(0, 0, 0, 0.1) 0px 20px 25px -5px,
rgba(0, 0, 0, 0.04) 0px 10px 10px -5px;
width: 600px;
max-width: 100%;
min-height: 200px;
margin: 2rem;
border: 1px solid $default;
background-color: white;
position: relative;
z-index: 2;
border-radius: 0.5rem;
pointer-events: none;
display: none;
flex-direction: column;
&.open {
pointer-events: initial;
display: flex;
}
&__title {
display: flex;
padding: 0.875rem 1rem;
min-height: 30px;
align-items: center;
word-break: break-all;
&::before {
top: 0.875rem;
}
}
&__note {
padding: 0.5rem 1rem;
&::before {
top: 0.5rem;
}
}
&__title,
&__note {
position: relative;
&::before {
position: absolute;
left: 1rem;
content: attr(data-placeholder);
color: darken($default, 10%);
}
&:focus,
&.not-empty {
&::before {
display: none;
}
}
}
&__note,
&__todo {
flex: 1;
}
&__todo {
.add-todo-item {
cursor: pointer;
color: darken($default, 20%);
font-size: 0.875rem;
position: relative;
.plus {
position: absolute;
left: 2rem;
top: 50%;
transform: translateY(-50%);
}
}
.todo-item,
.add-todo-item {
position: relative;
padding: 0.5rem 0.5rem 0.5rem 3.5rem;
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
}
.todo-item {
position: relative;
display: flex;
align-items: center;
&:hover {
.btn,
.drag {
visibility: visible;
}
}
&-ghost {
background-color: lighten($primary, 35%);
}
&.focus {
border-color: $default;
}
.content {
flex: 1 0 auto;
}
&.checked {
.content {
text-decoration: line-through;
}
}
.btn {
right: 1rem;
}
.btn,
.drag,
.check {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.drag {
left: 1rem;
cursor: grab;
&:active {
cursor: grabbing;
}
}
.check {
left: 2rem;
cursor: pointer;
}
.btn,
.drag {
visibility: hidden;
}
}
}
&__footer {
margin: auto 0 0;
display: flex;
align-items: center;
justify-content: flex-end;
padding: 0.5rem 1rem;
}
}
View Compiled
const createNote = document.querySelector(".start-note");
const createTodo = document.querySelector(".start-todo");
const closeKeep = document.querySelector(".close-keep");
const hold = document.querySelector(".hold");
const holdNote = document.querySelector(".hold-note");
const holdNoteTitle = document.querySelector('.hold-note__title');
const holdNoteNote = document.querySelector('.hold-note__note');
const holdNoteTodo = document.querySelector('.hold-note__todo');
const addTodoItem = document.querySelector('.add-todo-item');
function showHoldNote(type) {
return function (e) {
e.preventDefault();
holdNote.classList.add("open");
if(type === 'note'){
hold.classList.add('hidden');
holdNoteNote.classList.remove('hidden');
holdNoteNote.focus();
!holdNoteTodo.classList.contains('hidden') && holdNoteTodo.classList.add('hidden')
} else {
hold.classList.add('hidden');
holdNoteTodo.classList.remove('hidden');
!holdNoteNote.classList.contains('hidden') && holdNoteNote.classList.add('hidden')
}
};
}
createNote.addEventListener("click", showHoldNote('note'));
createTodo.addEventListener("click", showHoldNote('todo'));
function closeHoldNote(e) {
e.preventDefault();
hold.classList.remove("hidden");
holdNote.classList.remove("open");
}
closeKeep.addEventListener('click', closeHoldNote);
function handlePlaceholder(e) {
e.preventDefault();
if(this.innerHTML.length > 0) {
this.classList.add('not-empty');
} else {
this.classList.remove('not-empty')
}
}
holdNoteTitle.addEventListener('focusout', handlePlaceholder);
holdNoteNote.addEventListener('focusout', handlePlaceholder);
holdNoteTodo.addEventListener('focusin', function(e) {
if(e.target.classList.contains('content') && !e.target.parentNode.classList.contains('focus')){
e.target.parentNode.classList.add('focus')
}
});
holdNoteTodo.addEventListener('focusout', function(e) {
if(e.target.classList.contains('content')){
e.target.parentNode.classList.remove('focus')
}
});
holdNoteTodo.addEventListener('click', function(e) {
if(e.target.classList.contains('remove')){
console.log(e.target)
e.target.parentNode.remove()
} else if (e.target.classList.contains('fa-times')) {
e.target.parentNode.click()
}
})
holdNoteTodo.addEventListener('click', function(e) {
if(e.target.classList.contains('fa-square')){
e.target.classList.remove('fa-square');
e.target.classList.add('fa-check-square');
e.target.parentNode.classList.add('checked');
} else if (e.target.classList.contains('fa-check-square')) {
e.target.classList.add('fa-square');
e.target.classList.remove('fa-check-square');
e.target.parentNode.classList.remove('checked');
}
});
addTodoItem.addEventListener('click', function(e) {
e.preventDefault();
const todoItem = document.createElement('div');
todoItem.classList.add('todo-item');
todoItem.draggable = true;
const content = document.createElement('div');
content.classList.add('content');
content.contentEditable = true;
const drag = document.createElement('i');
drag.classList.add('fa', 'fa-grip-vertical', 'drag');
const check = document.createElement('i');
check.classList.add('far', 'fa-square', 'check');
const removeButton = document.createElement('button');
removeButton.classList.add('btn', 'btn-sm', 'btn-circle', 'remove');
const times = document.createElement('i');
times.classList.add('fa', 'fa-times');
removeButton.appendChild(times);
todoItem.appendChild(content);
todoItem.appendChild(drag);
todoItem.appendChild(check);
todoItem.appendChild(removeButton);
holdNoteTodo.insertBefore(todoItem, this);
});
Sortable.create(holdNoteTodo, {
handle: '.drag',
draggable: '.todo-item',
ghostClass: 'todo-item-ghost'
})
View Compiled