fix color
This commit is contained in:
@@ -6,6 +6,7 @@ import Video from "@/components/icons/Video.vue";
|
||||
import Credit from "@/components/icons/Credit.vue";
|
||||
import Upload from "./icons/Upload.vue";
|
||||
import NotificationDrawer from "./NotificationDrawer.vue";
|
||||
import GlobalUploadIndicator from "./GlobalUploadIndicator.vue";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { createStaticVNode, ref } from "vue";
|
||||
|
||||
@@ -38,14 +39,9 @@ const links = [
|
||||
<header
|
||||
class=":uno: fixed left-0 w-18 flex flex-col items-center pt-4 gap-6 z-41 max-h-screen h-screen border-r border-gray-200 bg-white">
|
||||
<template v-for="i in links" :key="i.label">
|
||||
<component
|
||||
:name="i.label"
|
||||
:is="i.type === 'a' ? 'router-link' : 'div'"
|
||||
v-bind="i.type === 'a' ? { to: i.href } : {}"
|
||||
v-tooltip="i.label"
|
||||
@click="i.action && i.action($event)"
|
||||
:class="cn(i.className, ($route.path === i.href || i.isActive?.value) && 'bg-primary/15')"
|
||||
>
|
||||
<component :name="i.label" :is="i.type === 'a' ? 'router-link' : 'div'"
|
||||
v-bind="i.type === 'a' ? { to: i.href } : {}" v-tooltip="i.label" @click="i.action && i.action($event)"
|
||||
:class="cn(i.className, ($route.path === i.href || i.isActive?.value) && 'bg-primary/15')">
|
||||
<component :is="i.icon" class="w-6 h-6" :filled="$route.path === i.href || i.isActive?.value" />
|
||||
</component>
|
||||
</template>
|
||||
@@ -53,11 +49,11 @@ const links = [
|
||||
<NotificationDrawer ref="notificationPopover" @change="(val) => isNotificationOpen = val" />
|
||||
</ClientOnly>
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<main class="flex flex-1 overflow-hidden md:ps-18">
|
||||
<div class="flex-1 overflow-auto p-4 bg-white rounded-lg md:(mr-2 mb-2) min-h-[calc(100vh-8rem)]">
|
||||
<div class=":uno: flex-1 overflow-auto p-4 bg-[#FAF8F8] rounded-lg md:(mr-2 mb-2) min-h-[calc(100vh-8rem)]">
|
||||
<router-view v-slot="{ Component }">
|
||||
<Transition enter-active-class="transition-all duration-300 ease-in-out"
|
||||
enter-from-class="opacity-0 transform translate-y-4"
|
||||
@@ -69,6 +65,6 @@ const links = [
|
||||
</Transition>
|
||||
</router-view>
|
||||
</div>
|
||||
<GlobalUploadIndicator />
|
||||
</main>
|
||||
</template>
|
||||
|
||||
|
||||
103
src/components/GlobalUploadIndicator.vue
Normal file
103
src/components/GlobalUploadIndicator.vue
Normal file
@@ -0,0 +1,103 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import { useUploadQueue } from '@/composables/useUploadQueue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import UploadQueueItem from '@/routes/upload/components/UploadQueueItem.vue';
|
||||
|
||||
const { items, totalSize, completeCount, pendingCount } = useUploadQueue();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const isOpen = ref(false);
|
||||
|
||||
const isVisible = computed(() => {
|
||||
// Show if there are items AND we are NOT on the upload page
|
||||
return items.value.length > 0 && route.path !== '/upload';
|
||||
});
|
||||
|
||||
const progress = computed(() => {
|
||||
if (items.value.length === 0) return 0;
|
||||
const totalProgress = items.value.reduce((acc, item) => acc + (item.progress || 0), 0);
|
||||
return Math.round(totalProgress / items.value.length);
|
||||
});
|
||||
|
||||
const isUploading = computed(() => {
|
||||
return items.value.some(i => i.status === 'uploading' || i.status === 'fetching');
|
||||
});
|
||||
|
||||
const toggleOpen = () => {
|
||||
isOpen.value = !isOpen.value;
|
||||
};
|
||||
|
||||
const goToUploadPage = () => {
|
||||
router.push('/upload');
|
||||
isOpen.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="isVisible" class="fixed bottom-6 right-6 z-50 flex flex-col items-end gap-2">
|
||||
|
||||
<!-- Mini Queue Popover -->
|
||||
<Transition enter-active-class="transition duration-200 ease-out"
|
||||
enter-from-class="opacity-0 translate-y-2 scale-95" enter-to-class="opacity-100 translate-y-0 scale-100"
|
||||
leave-active-class="transition duration-150 ease-in" leave-from-class="opacity-100 translate-y-0 scale-100"
|
||||
leave-to-class="opacity-0 translate-y-2 scale-95">
|
||||
<div v-if="isOpen"
|
||||
class="bg-white rounded-2xl shadow-xl border border-gray-100 p-4 mb-2 w-80 max-h-[60vh] flex flex-col">
|
||||
<div class="flex items-center justify-between mb-3 pb-3 border-b border-gray-100">
|
||||
<h3 class="font-bold text-slate-800">Uploads</h3>
|
||||
<button @click="goToUploadPage" class="text-xs font-bold text-accent hover:underline">
|
||||
View All
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex-1 overflow-y-auto min-h-0 space-y-3 [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-slate-300 [&::-webkit-scrollbar-thumb]:rounded">
|
||||
<UploadQueueItem v-for="item in items" :key="item.id" :item="item" :minimal="true"
|
||||
class="border-b border-slate-100 last:border-0 !rounded-none" />
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
|
||||
<!-- Floating Button -->
|
||||
<button @click="toggleOpen"
|
||||
class="relative flex items-center gap-3 bg-white pl-4 pr-5 py-3 rounded-full shadow-[0_8px_30px_rgba(0,0,0,0.12)] border border-slate-100 hover:-translate-y-1 transition-all duration-300 group">
|
||||
<!-- Progress Ring -->
|
||||
<div class="relative w-10 h-10 flex items-center justify-center">
|
||||
<svg class="w-full h-full -rotate-90 text-slate-100" viewBox="0 0 36 36">
|
||||
<path class="stroke-current" fill="none" stroke-width="3"
|
||||
d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
|
||||
</svg>
|
||||
<svg class="absolute inset-0 w-full h-full -rotate-90 text-accent transition-all duration-500"
|
||||
viewBox="0 0 36 36" :style="{ strokeDasharray: `${progress}, 100` }">
|
||||
<path class="stroke-current" fill="none" stroke-width="3" stroke-linecap="round"
|
||||
d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
|
||||
</svg>
|
||||
|
||||
<div class="absolute inset-0 flex items-center justify-center text-accent">
|
||||
<svg v-if="!isUploading && completeCount === items.length" xmlns="http://www.w3.org/2000/svg"
|
||||
class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M20 6 9 17l-5-5" />
|
||||
</svg>
|
||||
<span v-else class="text-[10px] font-bold">{{ progress }}%</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-left">
|
||||
<div class="text-sm font-bold text-slate-800 group-hover:text-accent transition-colors">
|
||||
{{ isUploading ? 'Uploading...' : (completeCount === items.length ? 'Completed' : 'Pending') }}
|
||||
</div>
|
||||
<div class="text-xs text-slate-500">
|
||||
{{ completeCount }} / {{ items.length }} files
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="pendingCount"
|
||||
class="absolute -top-1 -right-1 w-5 h-5 bg-red-500 rounded-full flex items-center justify-center text-[10px] font-bold text-white shadow-sm border-2 border-white">
|
||||
{{ pendingCount }}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import NotificationItem from '@/routes/notification/components/NotificationItem.vue';
|
||||
import { onClickOutside } from '@vueuse/core';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
// Emit event when visibility changes
|
||||
const emit = defineEmits(['change']);
|
||||
@@ -97,7 +97,7 @@ onClickOutside(drawerRef, (event) => {
|
||||
visible.value = false;
|
||||
}
|
||||
}, {
|
||||
ignore: ['.press-animated', '[name="Notification"]'] // Assuming the trigger button has this class or we can suggest adding a class to the trigger
|
||||
ignore: ['[name="Notification"]'] // Assuming the trigger button has this class or we can suggest adding a class to the trigger
|
||||
});
|
||||
|
||||
const handleMarkRead = (id: string) => {
|
||||
@@ -122,35 +122,23 @@ defineExpose({ toggle });
|
||||
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<Transition
|
||||
enter-active-class="transition-all duration-300 ease-out"
|
||||
enter-from-class="opacity-0 -translate-x-4"
|
||||
enter-to-class="opacity-100 translate-x-0"
|
||||
leave-active-class="transition-all duration-200 ease-in"
|
||||
leave-from-class="opacity-100 translate-x-0"
|
||||
leave-to-class="opacity-0 -translate-x-4"
|
||||
>
|
||||
<div
|
||||
v-if="visible"
|
||||
ref="drawerRef"
|
||||
class="fixed top-0 left-[80px] bottom-0 w-[380px] bg-white rounded-2xl border border-gray-300 p-3 z-50 flex flex-col shadow-lg my-3"
|
||||
>
|
||||
<Transition enter-active-class="transition-all duration-300 ease-out"
|
||||
enter-from-class="opacity-0 -translate-x-4" enter-to-class="opacity-100 translate-x-0"
|
||||
leave-active-class="transition-all duration-200 ease-in" leave-from-class="opacity-100 translate-x-0"
|
||||
leave-to-class="opacity-0 -translate-x-4">
|
||||
<div v-if="visible" ref="drawerRef"
|
||||
class="fixed top-0 left-[80px] bottom-0 w-[380px] bg-white rounded-2xl border border-gray-300 p-3 z-50 flex flex-col shadow-lg my-3">
|
||||
<!-- Header -->
|
||||
<div class="flex items-center justify-between p-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="font-semibold text-gray-900">Notifications</h3>
|
||||
<span
|
||||
v-if="unreadCount > 0"
|
||||
class="px-2 py-0.5 text-xs font-medium bg-primary text-white rounded-full"
|
||||
>
|
||||
<span v-if="unreadCount > 0"
|
||||
class="px-2 py-0.5 text-xs font-medium bg-primary text-white rounded-full">
|
||||
{{ unreadCount }}
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
v-if="unreadCount > 0"
|
||||
@click="handleMarkAllRead"
|
||||
class="text-sm text-primary hover:underline font-medium"
|
||||
>
|
||||
<button v-if="unreadCount > 0" @click="handleMarkAllRead"
|
||||
class="text-sm text-primary hover:underline font-medium">
|
||||
Mark all read
|
||||
</button>
|
||||
</div>
|
||||
@@ -158,16 +146,10 @@ defineExpose({ toggle });
|
||||
<!-- Notification List -->
|
||||
<div class="flex flex-col flex-1 overflow-y-auto gap-2">
|
||||
<template v-if="notifications.length > 0">
|
||||
<div
|
||||
v-for="notification in notifications"
|
||||
:key="notification.id"
|
||||
class="border-b border-gray-50 last:border-0"
|
||||
>
|
||||
<NotificationItem
|
||||
:notification="notification"
|
||||
@mark-read="handleMarkRead"
|
||||
@delete="handleDelete"
|
||||
/>
|
||||
<div v-for="notification in notifications" :key="notification.id"
|
||||
class="border-b border-gray-50 last:border-0">
|
||||
<NotificationItem :notification="notification" @mark-read="handleMarkRead"
|
||||
@delete="handleDelete" isDrawer />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -180,11 +162,9 @@ defineExpose({ toggle });
|
||||
|
||||
<!-- Footer -->
|
||||
<div v-if="notifications.length > 0" class="p-3 border-t border-gray-100 bg-gray-50/50">
|
||||
<router-link
|
||||
to="/notification"
|
||||
<router-link to="/notification"
|
||||
class="block w-full text-center text-sm text-primary font-medium hover:underline"
|
||||
@click="visible = false"
|
||||
>
|
||||
@click="visible = false">
|
||||
View all notifications
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
@@ -14,17 +14,17 @@ interface Props {
|
||||
color?: 'primary' | 'success' | 'warning' | 'danger' | 'info';
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
withDefaults(defineProps<Props>(), {
|
||||
color: 'primary'
|
||||
});
|
||||
|
||||
const gradients = {
|
||||
primary: 'from-primary/20 to-primary/5',
|
||||
success: 'from-success/20 to-success/5',
|
||||
warning: 'from-yellow-100 to-yellow-50',
|
||||
danger: 'from-danger/20 to-danger/5',
|
||||
info: 'from-info/20 to-info/5',
|
||||
};
|
||||
// const gradients = {
|
||||
// primary: 'from-primary/20 to-primary/5',
|
||||
// success: 'from-success/20 to-success/5',
|
||||
// warning: 'from-yellow-100 to-yellow-50',
|
||||
// danger: 'from-danger/20 to-danger/5',
|
||||
// info: 'from-info/20 to-info/5',
|
||||
// };
|
||||
|
||||
const iconColors = {
|
||||
primary: 'text-primary',
|
||||
@@ -37,10 +37,10 @@ const iconColors = {
|
||||
|
||||
<template>
|
||||
<div :class="[
|
||||
'stats-card relative overflow-hidden rounded-2xl p-6 bg-gradient-to-br',
|
||||
gradients[color],
|
||||
'border border-white/50 shadow-sm hover:shadow-md transition-all duration-300',
|
||||
'group cursor-pointer'
|
||||
'transform translate-y-0 relative overflow-hidden rounded-2xl p-6 bg-white',
|
||||
// gradients[color],
|
||||
'border border-gray-300 transition-all duration-300',
|
||||
// 'group cursor-pointer'
|
||||
]">
|
||||
<!-- Content -->
|
||||
<div class="relative z-10">
|
||||
@@ -65,10 +65,15 @@ const iconColors = {
|
||||
'flex items-center gap-1 font-medium',
|
||||
trend.isPositive ? 'text-success' : 'text-danger'
|
||||
]">
|
||||
<span :class="[
|
||||
<!-- <span :class="[
|
||||
'w-4 h-4',
|
||||
trend.isPositive ? 'i-heroicons-arrow-trending-up' : 'i-heroicons-arrow-trending-down'
|
||||
]" />
|
||||
]" /> -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path v-if="trend.isPositive" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M3 17l6-6 4 4 8-8" />
|
||||
<path v-else stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 7l-6 6-4-4-8 8" />
|
||||
</svg>
|
||||
{{ Math.abs(trend.value) }}%
|
||||
</span>
|
||||
<span class="text-gray-500">vs last month</span>
|
||||
@@ -76,13 +81,3 @@ const iconColors = {
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.stats-card {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.stats-card:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
</style>
|
||||
|
||||
16
src/components/icons/AlertTriangleIcon.vue
Normal file
16
src/components/icons/AlertTriangleIcon.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<svg v-if="filled" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
|
||||
stroke="none">
|
||||
<path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" />
|
||||
</svg>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>
|
||||
<line x1="12" y1="9" x2="12" y2="13"></line>
|
||||
<line x1="12" y1="17" x2="12.01" y2="17"></line>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{ filled?: boolean }>();
|
||||
</script>
|
||||
15
src/components/icons/ArrowRightIcon.vue
Normal file
15
src/components/icons/ArrowRightIcon.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<svg v-if="filled" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
|
||||
stroke="none">
|
||||
<path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z" />
|
||||
</svg>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
||||
<polyline points="12 5 19 12 12 19"></polyline>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{ filled?: boolean }>();
|
||||
</script>
|
||||
16
src/components/icons/CheckCircleIcon.vue
Normal file
16
src/components/icons/CheckCircleIcon.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<svg v-if="filled" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
|
||||
stroke="none">
|
||||
<path
|
||||
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
|
||||
</svg>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
|
||||
<polyline points="22 4 12 14.01 9 11.01"></polyline>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{ filled?: boolean }>();
|
||||
</script>
|
||||
14
src/components/icons/CheckMarkIcon.vue
Normal file
14
src/components/icons/CheckMarkIcon.vue
Normal file
@@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<svg v-if="filled" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
|
||||
stroke="none">
|
||||
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
|
||||
</svg>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="20 6 9 17 4 12"></polyline>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{ filled?: boolean }>();
|
||||
</script>
|
||||
16
src/components/icons/CreditCardIcon.vue
Normal file
16
src/components/icons/CreditCardIcon.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<svg v-if="filled" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
|
||||
stroke="none">
|
||||
<path
|
||||
d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z" />
|
||||
</svg>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="1" y="4" width="22" height="16" rx="2" ry="2"></rect>
|
||||
<line x1="1" y1="10" x2="23" y2="10"></line>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{ filled?: boolean }>();
|
||||
</script>
|
||||
16
src/components/icons/InfoIcon.vue
Normal file
16
src/components/icons/InfoIcon.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<svg v-if="filled" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
|
||||
stroke="none">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z" />
|
||||
</svg>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<line x1="12" y1="16" x2="12" y2="12"></line>
|
||||
<line x1="12" y1="8" x2="12.01" y2="8"></line>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{ filled?: boolean }>();
|
||||
</script>
|
||||
18
src/components/icons/SettingsIcon.vue
Normal file
18
src/components/icons/SettingsIcon.vue
Normal file
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<svg v-if="filled" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
|
||||
stroke="none">
|
||||
<path
|
||||
d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58a.49.49 0 0 0 .12-.61l-1.92-3.32a.488.488 0 0 0-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54a.484.484 0 0 0-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96a.48.48 0 0 0-.59.22L5.09 8.87a.484.484 0 0 0 .12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58a.48.48 0 0 0-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.21.08.47 0 .59-.22l1.92-3.32a.48.48 0 0 0-.12-.61l-2.03-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z" />
|
||||
</svg>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path
|
||||
d="M12.22 2h-.44a2 2 0 0 1-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.38a2 2 0 0 0-.73-2.73l-.15-.1a2 2 0 0 1-1-1.72v-.51a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z">
|
||||
</path>
|
||||
<circle cx="12" cy="12" r="3"></circle>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{ filled?: boolean }>();
|
||||
</script>
|
||||
17
src/components/icons/TrashIcon.vue
Normal file
17
src/components/icons/TrashIcon.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<svg v-if="filled" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
|
||||
stroke="none">
|
||||
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" />
|
||||
</svg>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="3 6 5 6 21 6"></polyline>
|
||||
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
|
||||
<line x1="10" y1="11" x2="10" y2="17"></line>
|
||||
<line x1="14" y1="11" x2="14" y2="17"></line>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{ filled?: boolean }>();
|
||||
</script>
|
||||
16
src/components/icons/VideoIcon.vue
Normal file
16
src/components/icons/VideoIcon.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<svg v-if="filled" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
|
||||
stroke="none">
|
||||
<path
|
||||
d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z" />
|
||||
</svg>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polygon points="23 7 16 12 23 17 23 7"></polygon>
|
||||
<rect x="1" y="5" width="15" height="14" rx="2" ry="2"></rect>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{ filled?: boolean }>();
|
||||
</script>
|
||||
17
src/components/icons/XCircleIcon.vue
Normal file
17
src/components/icons/XCircleIcon.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<svg v-if="filled" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
|
||||
stroke="none">
|
||||
<path
|
||||
d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z" />
|
||||
</svg>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<line x1="15" y1="9" x2="9" y2="15"></line>
|
||||
<line x1="9" y1="9" x2="15" y2="15"></line>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{ filled?: boolean }>();
|
||||
</script>
|
||||
Reference in New Issue
Block a user