initial: bootstrap from BukidBountyApp base
This commit is contained in:
66
resources/js/Components/Core/Skeleton/HomeSkeleton.vue
Normal file
66
resources/js/Components/Core/Skeleton/HomeSkeleton.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div class="home-skeleton pb-5">
|
||||
<!-- BalanceBox Skeleton -->
|
||||
<div class="tf-container">
|
||||
<SkeletonStats />
|
||||
</div>
|
||||
|
||||
<!-- Grid Services Skeleton -->
|
||||
<div class="mt-4 px-2">
|
||||
<div class="tf-container">
|
||||
<div class="row g-3 justify-content-center">
|
||||
<div v-for="i in 12" :key="i" class="col-3 text-center mb-4">
|
||||
<SkeletonBlock width="52px" height="52px" borderRadius="14px" margin="0 auto 10px" />
|
||||
<SkeletonBlock width="40px" height="10px" margin="0 auto" borderRadius="2px" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Announcements Skeleton -->
|
||||
<div class="mt-4">
|
||||
<div class="tf-container">
|
||||
<SkeletonBlock width="100%" height="110px" borderRadius="20px" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Management Tools Skeleton -->
|
||||
<div class="tf-container mt-5">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3 px-1">
|
||||
<SkeletonBlock width="160px" height="22px" borderRadius="4px" />
|
||||
</div>
|
||||
|
||||
<div v-for="i in 5" :key="i" class="d-flex align-items-center mb-3 p-3 glass-card rounded-xl border border-light-5">
|
||||
<SkeletonBlock width="44px" height="44px" borderRadius="12px" margin="0 16px 0 0" />
|
||||
<div class="flex-grow-1">
|
||||
<SkeletonBlock width="60%" height="16px" borderRadius="4px" />
|
||||
</div>
|
||||
<SkeletonBlock width="24px" height="24px" borderRadius="6px" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import SkeletonBlock from './SkeletonBlock.vue';
|
||||
import SkeletonStats from './SkeletonStats.vue';
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.glass-card {
|
||||
background: white;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.rounded-xl {
|
||||
border-radius: 20px;
|
||||
}
|
||||
.border-light-5 {
|
||||
border-color: rgba(0, 0, 0, 0.03) !important;
|
||||
}
|
||||
:global(.dark-mode) .glass-card {
|
||||
background: #1f2228 !important;
|
||||
}
|
||||
:global(.dark-mode) .border-light-5 {
|
||||
border-color: rgba(255, 255, 255, 0.05) !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="product-list-skeleton px-2 pt-3">
|
||||
<div class="row g-3 justify-content-center">
|
||||
<div v-for="i in parseInt(count)" :key="i" class="col-6 col-sm-4 col-md-3">
|
||||
<div class="glass-card rounded-xl overflow-hidden mb-3 border border-light-5 text-start">
|
||||
<SkeletonBlock width="100%" height="140px" borderRadius="0" :noShimmer="false" />
|
||||
<div class="p-3">
|
||||
<SkeletonBlock width="85%" height="14px" margin="0 0 8px 0" borderRadius="3px" />
|
||||
<SkeletonBlock width="60%" height="10px" margin="0 0 16px 0" borderRadius="2px" />
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<SkeletonBlock width="50px" height="12px" borderRadius="3px" />
|
||||
<SkeletonBlock width="36px" height="36px" borderRadius="12px" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import SkeletonBlock from './SkeletonBlock.vue';
|
||||
|
||||
defineProps({
|
||||
count: { type: [Number, String], default: 8 }
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.glass-card {
|
||||
background: white;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.rounded-xl {
|
||||
border-radius: 20px;
|
||||
}
|
||||
.border-light-5 {
|
||||
border-color: rgba(0, 0, 0, 0.03) !important;
|
||||
}
|
||||
:global(.dark-mode) .glass-card {
|
||||
background: #1f2228 !important;
|
||||
}
|
||||
</style>
|
||||
17
resources/js/Components/Core/Skeleton/SkeletonAvatar.vue
Normal file
17
resources/js/Components/Core/Skeleton/SkeletonAvatar.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<SkeletonBlock
|
||||
:width="size"
|
||||
:height="size"
|
||||
borderRadius="50%"
|
||||
:margin="margin"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import SkeletonBlock from './SkeletonBlock.vue';
|
||||
|
||||
defineProps({
|
||||
size: { type: String, default: '48px' },
|
||||
margin: { type: String, default: '0' }
|
||||
})
|
||||
</script>
|
||||
68
resources/js/Components/Core/Skeleton/SkeletonBlock.vue
Normal file
68
resources/js/Components/Core/Skeleton/SkeletonBlock.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<div
|
||||
class="skeleton-block"
|
||||
:style="{
|
||||
width: width,
|
||||
height: height,
|
||||
borderRadius: borderRadius,
|
||||
margin: margin
|
||||
}"
|
||||
:class="{ 'shimmer': !noShimmer }"
|
||||
></div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineProps({
|
||||
width: { type: String, default: '100%' },
|
||||
height: { type: String, default: '1rem' },
|
||||
borderRadius: { type: String, default: '4px' },
|
||||
margin: { type: String, default: '0' },
|
||||
noShimmer: { type: Boolean, default: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.skeleton-block {
|
||||
background: #f0f2f5;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.shimmer::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
transform: translateX(-100%);
|
||||
background-image: linear-gradient(
|
||||
90deg,
|
||||
rgba(255, 255, 255, 0) 0,
|
||||
rgba(255, 255, 255, 0.2) 20%,
|
||||
rgba(255, 255, 255, 0.5) 60%,
|
||||
rgba(255, 255, 255, 0)
|
||||
);
|
||||
animation: shimmer 2s infinite;
|
||||
}
|
||||
|
||||
:global(.dark-mode) .skeleton-block {
|
||||
background: #2d3138 !important;
|
||||
}
|
||||
:global(.dark-mode) .shimmer::after {
|
||||
background-image: linear-gradient(
|
||||
90deg,
|
||||
rgba(255, 255, 255, 0) 0,
|
||||
rgba(255, 255, 255, 0.05) 20%,
|
||||
rgba(255, 255, 255, 0.1) 60%,
|
||||
rgba(255, 255, 255, 0)
|
||||
);
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
38
resources/js/Components/Core/Skeleton/SkeletonCard.vue
Normal file
38
resources/js/Components/Core/Skeleton/SkeletonCard.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="skeleton-card glass-card p-4 rounded-xl mb-4 text-start">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<SkeletonAvatar size="56px" margin="0 16px 0 0" />
|
||||
<div class="flex-grow-1">
|
||||
<SkeletonBlock width="140px" height="20px" margin="0 0 8px 0" borderRadius="6px" />
|
||||
<SkeletonBlock width="80px" height="14px" borderRadius="4px" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="divider border-bottom border-light opacity-10 mb-3"></div>
|
||||
<SkeletonBlock width="100%" height="12px" margin="0 0 8px 0" borderRadius="4px" />
|
||||
<SkeletonBlock width="100%" height="12px" margin="0 0 8px 0" borderRadius="4px" />
|
||||
<SkeletonBlock width="60%" height="12px" borderRadius="4px" />
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mt-4 pt-2">
|
||||
<SkeletonBlock width="100px" height="10px" borderRadius="4px" />
|
||||
<SkeletonBlock width="90px" height="36px" borderRadius="18px" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import SkeletonBlock from './SkeletonBlock.vue';
|
||||
import SkeletonAvatar from './SkeletonAvatar.vue';
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.rounded-xl {
|
||||
border-radius: 24px;
|
||||
}
|
||||
.glass-card {
|
||||
background: white;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
:global(.dark-mode) .glass-card {
|
||||
background: #1f2228 !important;
|
||||
}
|
||||
</style>
|
||||
44
resources/js/Components/Core/Skeleton/SkeletonStats.vue
Normal file
44
resources/js/Components/Core/Skeleton/SkeletonStats.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div class="skeleton-stats glass-card p-4 rounded-xl mb-4 border text-center">
|
||||
<div class="row align-items-center mb-3">
|
||||
<div class="col-6 border-right">
|
||||
<SkeletonBlock width="60px" height="10px" margin="0 auto 8px" borderRadius="3px" />
|
||||
<SkeletonBlock width="100px" height="28px" margin="0 auto" borderRadius="6px" />
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<SkeletonBlock width="60px" height="10px" margin="0 auto 8px" borderRadius="3px" />
|
||||
<SkeletonBlock width="130px" height="28px" margin="0 auto" borderRadius="6px" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center gap-4 mt-4 pt-3 border-top-dashed">
|
||||
<SkeletonBlock v-for="i in 4" :key="i" width="44px" height="44px" borderRadius="12px" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import SkeletonBlock from './SkeletonBlock.vue';
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.skeleton-stats {
|
||||
background: white;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.rounded-xl {
|
||||
border-radius: 24px;
|
||||
}
|
||||
.border-right {
|
||||
border-right: 1px solid #e9ecef;
|
||||
}
|
||||
.border-top-dashed {
|
||||
border-top: 1px dashed #e9ecef;
|
||||
}
|
||||
:global(.dark-mode) .skeleton-stats {
|
||||
background: #1f2228 !important;
|
||||
}
|
||||
:global(.dark-mode) .border-right,
|
||||
:global(.dark-mode) .border-top-dashed {
|
||||
border-color: rgba(255, 255, 255, 0.05) !important;
|
||||
}
|
||||
</style>
|
||||
35
resources/js/Components/Core/Skeleton/SkeletonTable.vue
Normal file
35
resources/js/Components/Core/Skeleton/SkeletonTable.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div class="skeleton-table rounded-3 overflow-hidden border text-start bg-white">
|
||||
<div class="table-header bg-light p-3 border-bottom d-flex align-items-center">
|
||||
<SkeletonBlock v-for="n in parseInt(columns)" :key="n" :width="colWidth" height="16px" margin="0 15px 0 0" borderRadius="4px" />
|
||||
</div>
|
||||
<div v-for="row in parseInt(rows)" :key="row" class="table-row p-3 border-bottom d-flex align-items-center">
|
||||
<SkeletonBlock v-for="n in parseInt(columns)" :key="n" :width="colWidth" height="12px" margin="0 15px 0 0" borderRadius="4px" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import SkeletonBlock from './SkeletonBlock.vue';
|
||||
|
||||
defineProps({
|
||||
rows: { type: [Number, String], default: 6 },
|
||||
columns: { type: [Number, String], default: 4 },
|
||||
colWidth: { type: String, default: '18%' }
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.skeleton-table {
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.table-row:last-child {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
:global(.dark-mode) .skeleton-table {
|
||||
background: #1f2228 !important;
|
||||
}
|
||||
:global(.dark-mode) .table-header {
|
||||
background: #2d3138 !important;
|
||||
}
|
||||
</style>
|
||||
28
resources/js/Components/Core/Skeleton/SkeletonText.vue
Normal file
28
resources/js/Components/Core/Skeleton/SkeletonText.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<div class="skeleton-text-container">
|
||||
<SkeletonBlock
|
||||
v-for="line in parseInt(lines)"
|
||||
:key="line"
|
||||
:width="getWidth(line)"
|
||||
height="14px"
|
||||
margin="0 0 8px 0"
|
||||
borderRadius="4px"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import SkeletonBlock from './SkeletonBlock.vue';
|
||||
|
||||
const props = defineProps({
|
||||
lines: { type: [Number, String], default: 1 },
|
||||
lastWidth: { type: String, default: '70%' }
|
||||
})
|
||||
|
||||
const getWidth = (line) => {
|
||||
if (parseInt(props.lines) > 1 && line === parseInt(props.lines)) {
|
||||
return props.lastWidth;
|
||||
}
|
||||
return '100%';
|
||||
}
|
||||
</script>
|
||||
15
resources/js/Components/Core/Skeleton/StoreListSkeleton.vue
Normal file
15
resources/js/Components/Core/Skeleton/StoreListSkeleton.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div class="store-list-skeleton tf-container pt-3">
|
||||
<div v-for="i in parseInt(count)" :key="i">
|
||||
<SkeletonCard />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import SkeletonCard from './SkeletonCard.vue';
|
||||
|
||||
defineProps({
|
||||
count: { type: [Number, String], default: 4 }
|
||||
})
|
||||
</script>
|
||||
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div class="transaction-list-skeleton tf-container pt-3">
|
||||
<div v-for="i in parseInt(count)" :key="i" class="d-flex align-items-center mb-3 p-3 glass-card rounded-xl border border-light-5 text-start">
|
||||
<SkeletonBlock width="44px" height="44px" borderRadius="12px" margin="0 16px 0 0" />
|
||||
<div class="flex-grow-1">
|
||||
<SkeletonBlock width="160px" height="16px" margin="0 0 6px 0" borderRadius="4px" />
|
||||
<SkeletonBlock width="100px" height="12px" borderRadius="3px" />
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<SkeletonBlock width="80px" height="18px" margin="0 0 4px auto" borderRadius="4px" />
|
||||
<SkeletonBlock width="50px" height="10px" margin="0 0 0 auto" borderRadius="2px" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import SkeletonBlock from './SkeletonBlock.vue';
|
||||
|
||||
defineProps({
|
||||
count: { type: [Number, String], default: 10 }
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.glass-card {
|
||||
background: white;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.rounded-xl {
|
||||
border-radius: 20px;
|
||||
}
|
||||
.border-light-5 {
|
||||
border-color: rgba(0, 0, 0, 0.03) !important;
|
||||
}
|
||||
:global(.dark-mode) .glass-card {
|
||||
background: #1f2228 !important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user