components/ColsPersonal.vue
Rama main · réplica de lectura del repositorio original.
<script setup lang="ts">
import Notes from '../assets/svg/notes.svg?component';
import Tag from '../assets/svg/tag.svg?component';
import Trash from '../assets/svg/trash-2.svg?component';
import Settings from '../assets/svg/settings.svg?component';
import Refresh from '../assets/svg/refresh.svg?component';
import ArrowLeftToLine from '../assets/svg/arrow-left-to-line.svg?component';
import ArrowRightToLine from '../assets/svg/arrow-right-to-line.svg?component';
import { hasNewVersion } from '~/utils/check-app-version';
const props = defineProps([
'activeFolderId',
'isCollapseFolder',
'isSyncing',
]);
const refreshRef = ref<HTMLElement | null>(null);
watch(() => props.isSyncing, (value) => {
if (value) {
refreshRef.value?.classList.add('spin');
} else {
refreshRef.value?.classList.remove('spin');
}
});
const emit = defineEmits([
'clickNotes',
'clickTags',
'clickTrash',
'clickSetting',
'clickUpdateData',
'clickCollapseFolder'
]);
const handleClickSetting = () => {
emit('clickSetting');
}
const handleClickUpdateData = () => {
emit('clickUpdateData');
}
const handleClickNotes = () => {
emit('clickNotes');
}
const handleClickTags = () => {
emit('clickTags');
}
const handleClickTrash = () => {
emit('clickTrash');
}
const handleClickCollapseFolder = () => {
emit('clickCollapseFolder');
}
</script>
<template>
<div class="h-screen flex flex-col bg-base-300">
<!-- Logo -->
<div class="flex items-center justify-center h-20">
<img src="/logo.png" alt="Logo" class="w-10 h-10" />
</div>
<!-- Menu -->
<div class="flex-1 flex flex-col items-center gap-4 mt-4">
<div class="menu-item flex flex-col items-center gap-2 relative !text-base-content"
:class="{ active: props.activeFolderId !== 'bottombar-trash' && props.activeFolderId !== 'bottombar-tags' }"
@click="handleClickNotes">
<Notes />
<span class="text-sm">Notes</span>
</div>
<div class="menu-item flex flex-col items-center gap-2 relative !text-base-content"
:class="{ active: props.activeFolderId === 'bottombar-tags' }" @click="handleClickTags">
<Tag />
<span class="text-sm">Tags</span>
</div>
<div class="menu-item flex flex-col items-center gap-2 relative !text-base-content"
:class="{ active: props.activeFolderId === 'bottombar-trash' }" @click="handleClickTrash">
<Trash />
<span class="text-sm">Trash</span>
</div>
</div>
<!-- Bottom Actions -->
<div class="p-4 flex flex-col gap-4">
<button class="btn btn-ghost btn-sm w-full" @click="handleClickCollapseFolder">
<div class="arrow-wrapper" :class="{ 'is-collapsed': props.isCollapseFolder }">
<ArrowLeftToLine class="arrow-icon" />
</div>
</button>
<button class="btn btn-ghost btn-sm w-full" @click="handleClickUpdateData">
<span ref="refreshRef">
<Refresh />
</span>
</button>
<button class="btn btn-ghost btn-sm w-full relative" @click="handleClickSetting">
<Settings />
<span v-if="hasNewVersion"
class="absolute top-1 right-2 w-2 h-2 bg-error rounded-full ring-2 ring-base-100"></span>
</button>
<div class="avatar placeholder flex items-center justify-center">
<div class="bg-primary text-primary-content rounded-full w-10 h-10 cursor-pointer" @click="handleClickSetting">
<span>O</span>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.menu-item {
position: relative;
padding: 8px 16px;
cursor: pointer;
}
.menu-item.active {
color: white;
}
.menu-item.active::before {
content: '';
position: absolute;
left: -2px;
top: 50%;
transform: translateY(-50%);
width: 5px;
height: 20px;
background-color: oklch(var(--p));
border-radius: 0 4px 4px 0;
}
.arrow-wrapper {
display: inline-flex;
transition: transform 0.3s ease;
}
.arrow-wrapper.is-collapsed {
transform: rotate(180deg);
}
.arrow-icon {
width: 20px;
height: 20px;
}
button:hover .arrow-wrapper {
transform: translateX(0px) rotate(0deg);
}
button:hover .arrow-wrapper.is-collapsed {
transform: translateX(0px) rotate(180deg);
}
</style>