Skip to content

Commit 6cb1847

Browse files
committed
feat(ui): add shake effect on error
1 parent 31eb1f5 commit 6cb1847

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

src/App.vue

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import { useToast } from 'vue-toastification'
55
import Todo from './components/TodoItem.vue'
66
import { slugger } from './lib/slugger'
77
8+
const error = ref(false)
89
const todoInput = ref('')
10+
const todoInputComponent = ref<HTMLDivElement>()
911
const todoList: { todos: TodoData[] } = reactive({
1012
todos: []
1113
})
@@ -24,14 +26,15 @@ const toast = useToast()
2426
function addNewTodo() {
2527
// Prevent todo names less than 2 characters
2628
if (todoInput.value.length < 2) {
29+
error.value = true
2730
toast.warning("The to-do name has to be more than 2 characters")
2831
return
2932
}
3033
3134
// Prevent repeated todos
3235
const repeatedList = todoList.todos.filter(todo => slugger(todo.name) === slugger(todoInput.value))
33-
console.log(repeatedList)
3436
if (repeatedList.length > 0) {
37+
error.value = true
3538
toast.warning("There is already a to-do with that name")
3639
return
3740
}
@@ -69,6 +72,12 @@ onMounted(() => {
6972
const parsedTodoList: TodoData[] = JSON.parse(savedTodoList)
7073
todoList.todos.push(...parsedTodoList)
7174
}
75+
76+
todoInputComponent?.value?.addEventListener("animationend", () => {
77+
error.value = false
78+
})
79+
80+
7281
})
7382
</script>
7483

@@ -79,7 +88,8 @@ onMounted(() => {
7988
class='h-full bg-vue-light transition-all rounded-r-full data-[percentage="100"]:rounded-none'
8089
:style="{ width: completedPercentage + '%' }" />
8190
</div>
82-
<div class="content-container fixed bottom-20 space-y-1">
91+
<div :data-error="error" ref="todoInputComponent"
92+
class='content-container fixed bottom-20 space-y-1 data-[error="true"]:animate-shake'>
8393
<div class="flex items-stretch justify-between gap-3">
8494
<input type="text" v-model="todoInput" @keypress.enter="addNewTodo" placeholder="Some task"
8595
class="h-12 w-full rounded-lg border-none bg-neutral-200/80 p-3 text-xl backdrop-blur-[80px] focus:bg-neutral-200/10 focus:ring-2 focus:ring-vue-light" />

tailwind.config.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ module.exports = {
99
'vue-dark': '#35495e'
1010
},
1111
animation: {
12-
'fade-up': 'fade-up .5s 0s'
12+
'fade-up': 'fade-up .5s 0s',
13+
'shake': 'shake 0.82s cubic-bezier(.36,.07,.19,.97) both'
1314
},
1415
keyframes: {
1516
'fade-up': {
@@ -24,6 +25,20 @@ module.exports = {
2425
'translate(var(--tw-translate-x), 0) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))'
2526
}
2627
},
28+
'shake': {
29+
'10%, 90%': {
30+
transform: 'translate3d(-1px, 0, 0)'
31+
},
32+
'20%, 80%': {
33+
transform: 'translate3d(2px, 0, 0)'
34+
},
35+
'30%, 50%, 70%': {
36+
transform: 'translate3d(-4px, 0, 0)'
37+
},
38+
'40%, 60%': {
39+
transform: 'translate3d(4px, 0, 0)'
40+
}
41+
}
2742
}
2843
}
2944
},

0 commit comments

Comments
 (0)