diff --git a/index.html b/index.html index 096d31f..242cc30 100644 --- a/index.html +++ b/index.html @@ -27,11 +27,28 @@
- - + + +
-

Tasklist

+

+ My Tasks + + +

+
diff --git a/src/assets/icons/checked-theme.svg b/src/assets/icons/checked-theme.svg new file mode 100644 index 0000000..0aca10d --- /dev/null +++ b/src/assets/icons/checked-theme.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/checked.svg b/src/assets/icons/checked.svg new file mode 100644 index 0000000..422e3b0 --- /dev/null +++ b/src/assets/icons/checked.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/clear-circle-lgt.svg b/src/assets/icons/clear-circle-lgt.svg new file mode 100644 index 0000000..713a6c4 --- /dev/null +++ b/src/assets/icons/clear-circle-lgt.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icons/clear-circle.svg b/src/assets/icons/clear-circle.svg new file mode 100644 index 0000000..ff100f9 --- /dev/null +++ b/src/assets/icons/clear-circle.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icons/delete-lgt.svg b/src/assets/icons/delete-lgt.svg new file mode 100644 index 0000000..d479b37 --- /dev/null +++ b/src/assets/icons/delete-lgt.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/icons/delete.svg b/src/assets/icons/delete.svg new file mode 100644 index 0000000..a0a88cf --- /dev/null +++ b/src/assets/icons/delete.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/icons/edit-lgt.svg b/src/assets/icons/edit-lgt.svg new file mode 100644 index 0000000..1b82253 --- /dev/null +++ b/src/assets/icons/edit-lgt.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/plus-lgt.svg b/src/assets/icons/plus-lgt.svg new file mode 100644 index 0000000..ee1f431 --- /dev/null +++ b/src/assets/icons/plus-lgt.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/plus.svg b/src/assets/icons/plus.svg new file mode 100644 index 0000000..5786232 --- /dev/null +++ b/src/assets/icons/plus.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/unchecked-hover.svg b/src/assets/icons/unchecked-hover.svg new file mode 100644 index 0000000..8978d41 --- /dev/null +++ b/src/assets/icons/unchecked-hover.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/unchecked.svg b/src/assets/icons/unchecked.svg new file mode 100644 index 0000000..3266a16 --- /dev/null +++ b/src/assets/icons/unchecked.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/cactus-1.webp b/src/assets/images/cactus-1.webp new file mode 100644 index 0000000..8c8e46d Binary files /dev/null and b/src/assets/images/cactus-1.webp differ diff --git a/src/assets/images/cactus-2.webp b/src/assets/images/cactus-2.webp new file mode 100644 index 0000000..abb87ad Binary files /dev/null and b/src/assets/images/cactus-2.webp differ diff --git a/src/assets/images/cactus-3.webp b/src/assets/images/cactus-3.webp new file mode 100644 index 0000000..e3b7ba1 Binary files /dev/null and b/src/assets/images/cactus-3.webp differ diff --git a/src/assets/images/cactus-4.webp b/src/assets/images/cactus-4.webp new file mode 100644 index 0000000..16f985c Binary files /dev/null and b/src/assets/images/cactus-4.webp differ diff --git a/src/assets/scss/_base.scss b/src/assets/scss/_base.scss index ff898aa..31a325b 100644 --- a/src/assets/scss/_base.scss +++ b/src/assets/scss/_base.scss @@ -70,71 +70,12 @@ a { } } -button { - border-radius: 50vw; - border: 1.5px solid transparent; - padding: 0.6em 1.2em; - font-size: $font-size-sm; - font-weight: 500; - font-family: inherit; - background-color: $color-gray-drk; - color: $color-white; - cursor: pointer; - transition: - border-color 0.25s, - background-color 0.25s; - - display: inline-flex; - justify-content: center; - flex-direction: row; - align-items: center; - gap: 0.75rem; - - &:disabled { - opacity: 0.5; - } - - &:focus, - &:focus-visible { - outline: 4px auto -webkit-focus-ring-color; - } - - &.btn-primary { - background-color: $color-primary; - color: $color-white; - - &:hover { - background-color: $color-primary; - } - } - - &.btn-large { - width: 100%; - border-radius: $border-radius; - font-size: $font-size-md; - line-height: 1.32; - } -} - @media (prefers-color-scheme: light) { :root { color: $color-body; background-color: $color-bg-lgt; } - button { - background-color: $color-white; - color: $color-gray; - - &:hover { - border-color: $color-gray-lgt; - } - } - - button.btn-primary:hover { - background-color: $color-primary-hover; - } - a:hover { color: $color-primary-hover; } @@ -147,4 +88,5 @@ picture.icon { .text-center { text-align: center; + width: 100%; } diff --git a/src/assets/scss/_button.scss b/src/assets/scss/_button.scss new file mode 100644 index 0000000..2d62443 --- /dev/null +++ b/src/assets/scss/_button.scss @@ -0,0 +1,68 @@ +@use './variables' as *; + +button { + white-space: normal; + border-radius: 50vw; + border: 1.5px solid transparent; + padding: 0.6em 1em; + font-size: $font-size-sm; + font-weight: 500; + font-family: inherit; + background-color: $color-gray-drk; + color: $color-white; + cursor: pointer; + transition: + border-color 0.25s, + background-color 0.25s; + + display: inline-flex; + justify-content: center; + flex-direction: row; + align-items: center; + gap: 0.75rem; + + picture.icon { + margin: -0.5rem; + } + + &:disabled { + opacity: 0.5; + pointer-events: none; + } + + &:focus, + &:focus-visible { + outline: 4px auto -webkit-focus-ring-color; + } + + &.btn-primary { + background-color: $color-primary; + color: $color-white; + + &:hover { + background-color: $color-primary; + } + } + + &.btn-large { + width: 100%; + border-radius: $border-radius; + font-size: $font-size-md; + line-height: 1.32; + } +} + +@media (prefers-color-scheme: light) { + button { + background-color: $color-white; + color: $color-gray; + + &:hover { + border-color: $color-gray-lgt; + } + + &.btn-primary:hover { + background-color: $color-primary-hover; + } + } +} \ No newline at end of file diff --git a/src/assets/scss/_todos.scss b/src/assets/scss/_todos.scss index 5eb950c..eb030b0 100644 --- a/src/assets/scss/_todos.scss +++ b/src/assets/scss/_todos.scss @@ -16,15 +16,39 @@ @media #{$xlarge-up} { margin-top: 4rem; } +} + +#todo-list-heading { + display: flex; + justify-content: space-between; + align-items: flex-end; + text-transform: uppercase; + color: $color-gray-theme; + margin-block: 2.5rem 1rem; - h3 { - margin-block: 2.5rem 1rem; + span { + font-size: $font-size-xs; + letter-spacing: 0.0625rem; + font-family: $font-family-semibold; } } #todo-form { width: 100%; max-width: unset; + display: flex; + flex-direction: row; + align-items: center; + gap: 0.75rem; + + > input { + margin-bottom: 0; + } + + button { + flex: 1 0 auto; + padding-block: 0.625rem; + } } #todo-list { @@ -39,21 +63,105 @@ li { background-color: $color-gray-drk; + border: 1.5px solid transparent; border-radius: $border-radius-lrg; - margin-bottom: 0.5rem; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.75rem; + margin-bottom: 0.75rem; + + transition: border 0.25s; + } + + label { + flex: 1 1 auto; + align-self: stretch; + font-size: $font-size-md; + cursor: pointer; + + input[type="checkbox"] { + display: none; + } + + &:before { + content: ''; + display: block; + width: 24px; + height: 24px; + background-image: url('./src/assets/icons/unchecked.svg'); + margin-left: 0.375rem; + margin-right: 1rem; + } + + &:hover:before { + background-image: url('./src/assets/icons/unchecked-hover.svg'); + } + } + + li.todo-completed { + box-shadow: none; + + label { + text-decoration: line-through; + opacity: 0.5; + } + + .button-group { + opacity: 0.4; + pointer-events: none; + } + + label:before { + background-image: url('./src/assets/icons/checked.svg'); + } + } + + label, .button-group { + display: flex; + align-items: center; + } + + .button-group { + gap: 0.25rem; + button { + width: 40px; + height: 40px; + padding: 0; + } + } + + .delete-todo .icon { + width: 20px; + height: 20px; } } #todo-list li.todo-list-empty { + margin-top: 1rem; + padding: 0; background-color: transparent; box-shadow: none; color: $color-gray-lgt; + flex-direction: column; } @media (prefers-color-scheme: light) { + #todo-list-heading { + color: $color-gray; + + button { + box-shadow: $box-shadow-lgt; + } + } + #todo-list li { background-color: $color-white; box-shadow: $box-shadow-lgt; + + &:not(.todo-completed):hover { + border-color: $color-gray-lgt;; + } } #todo-list li.todo-list-empty { @@ -61,4 +169,18 @@ box-shadow: none; color: $color-gray; } +} + +@media (prefers-color-scheme: dark) { + .button-group button:hover { + border-color: $color-gray-theme; + } + + #todo-list li.todo-list-empty img { + filter: drop-shadow(0px 10px 15px rgba(0, 0, 0, 0.5)); + } + + #todo-list li.todo-completed label:before { + background-image: url('./src/assets/icons/checked-theme.svg'); + } } \ No newline at end of file diff --git a/src/assets/scss/_variables.scss b/src/assets/scss/_variables.scss index 72182ed..247f5a1 100644 --- a/src/assets/scss/_variables.scss +++ b/src/assets/scss/_variables.scss @@ -1,5 +1,5 @@ // color -$color-bg-lgt: #F9FBFE; +$color-bg-lgt: #f6faff; $color-bg-drk: #242424; $color-body: #415a70; @@ -9,8 +9,8 @@ $color-gray-lgt: #dddfe2; $color-gray: #7282a7; $color-gray-theme: #7d869b; $color-gray-drk: #46484B; -$color-primary: #4f58f7; -$color-primary-hover: #424be9; +$color-primary: #5d4ff7; +$color-primary-hover: #4a42e9; $color-contrast: #F303FF; $color-alert: #f0506a; $color-success: #2ab75e; @@ -20,6 +20,7 @@ $color-success-hover: #07aa5e; $font-family-semibold: 'GeneralSans-Semibold', system-ui, Avenir, Helvetica, Arial, sans-serif; $font-family-medium: 'GeneralSans-Medium', system-ui, Avenir, Helvetica, Arial, sans-serif; +$font-size-xs: 0.75rem; $font-size-sm: 0.875rem; $font-size-md: 1rem; diff --git a/src/components/ShowTodoList.ts b/src/components/ShowTodoList.ts index 31b3482..2813913 100644 --- a/src/components/ShowTodoList.ts +++ b/src/components/ShowTodoList.ts @@ -4,13 +4,14 @@ import { handleRenameTodo, handleTodoCompletion } from '../utils/todosService'; export const ShowTodoList = async () => { const main = document.getElementById('todo-list') as HTMLElement; - const clearListBtn = document.getElementById('clear-list-btn') as HTMLButtonElement; + const randomNumber = Math.floor(Math.random() * 4) + 1; + const todoListHeading = document.getElementById('todo-list-heading') as HTMLHeadingElement; const ul = document.createElement("ul"); const fetchedTodos: Todo[] = await getUserTodos(); let hasTodos = fetchedTodos.length > 0; if (hasTodos) { - clearListBtn.classList.remove('hide'); + todoListHeading.classList.remove('hide'); ul.innerHTML = fetchedTodos .sort((a, b) => { @@ -20,10 +21,26 @@ export const ShowTodoList = async () => { }) .map((todo) => `
  • - - ${todo.title} - - + + +
    + + + +
  • `).join(""); @@ -47,9 +64,10 @@ export const ShowTodoList = async () => { } else { ul.innerHTML = `
  • -

    Your list is empty - start by adding a new task!

    + Happy cactus +

    Your list is empty
    - start fresh by adding a new task!

  • `; - clearListBtn.classList.add('hide'); + todoListHeading.classList.add('hide'); } main.innerHTML = ''; diff --git a/src/style.scss b/src/style.scss index 2a1f959..bd6fd41 100644 --- a/src/style.scss +++ b/src/style.scss @@ -4,6 +4,7 @@ @use './assets/scss/base' as *; @use './assets/scss/header' as *; @use './assets/scss/forms' as *; +@use './assets/scss/button' as *; @use './assets/scss/todos' as *; body { diff --git a/src/utils/todosService.ts b/src/utils/todosService.ts index 488ce51..d76426f 100644 --- a/src/utils/todosService.ts +++ b/src/utils/todosService.ts @@ -68,12 +68,12 @@ export const handleRenameTodo = async (btn: HTMLButtonElement, todoId: number, t } if (isDelete) { - const confirmDelete = confirm(`Are you sure you want to remove this Todo?`); + const confirmDelete = confirm(`Are you sure you want to remove this task?`); confirmDelete && await deleteTodo(todoId, userId); } if (isEdit) { - const updatedTodoTitle = prompt('Rename todo: ', todoTitle); + const updatedTodoTitle = prompt('Update task name: ', todoTitle); if (!updatedTodoTitle || updatedTodoTitle.trim() === '') return; editTodoTitle(todoId, userId, updatedTodoTitle.trim()); @@ -100,7 +100,7 @@ export const handleTodoCompletion = async (todoId: number, completed: boolean): // Clear todo list export const handleClearList = async () => { - const confirmClear = confirm(`This will permanently delete all todos. Are you sure you want to continue?`); + const confirmClear = confirm(`This will permanently delete all todos. \n Are you sure you want to continue?`); if (confirmClear) { const { data } = await supabase.auth.getUser();