initial: bootstrap from BukidBountyApp base
This commit is contained in:
80
resources/js/Components/Core/TableDensityToggle.vue
Normal file
80
resources/js/Components/Core/TableDensityToggle.vue
Normal file
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div class="dropdown table-density-toggle" ref="dropdownRef">
|
||||
<button
|
||||
class="btn btn-theme border dropdown-toggle rounded-12 px-3 shadow-sm d-flex align-items-center"
|
||||
type="button"
|
||||
@click="toggleDropdown"
|
||||
@blur="closeDropdown"
|
||||
style="padding-top: 12px; padding-bottom: 12px;"
|
||||
>
|
||||
<i class="fas fa-expand-alt me-2 opacity-50" style="font-size: 0.9rem;"></i>
|
||||
<span class="fw_6" style="font-size: 0.95rem;">{{ currentLabel }}</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow border-0 rounded-12 mt-2 py-2" :class="{ show: isOpen }">
|
||||
<li v-for="option in options" :key="option.value">
|
||||
<a class="dropdown-item py-2 px-3 d-flex align-items-center"
|
||||
:class="{ active: modelValue === option.value }"
|
||||
href="javascript:void(0);"
|
||||
@mousedown.prevent="selectOption(option.value)">
|
||||
<div class="icon-box me-3 rounded-circle d-flex align-items-center justify-content-center" :class="modelValue === option.value ? 'bg-primary text-white' : 'bg-light text-muted'">
|
||||
<i :class="[option.icon, 'smallest']"></i>
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<div class="small fw_7 d-block">{{ option.label }}</div>
|
||||
<div class="smallest text-muted d-block opacity-75">{{ option.description }}</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: { type: String, default: 'comfortable' }
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const isOpen = ref(false);
|
||||
const dropdownRef = ref(null);
|
||||
|
||||
const options = [
|
||||
{ value: 'comfortable', label: 'Comfortable', description: 'Standard row spacing', icon: 'fas fa-grip-lines' },
|
||||
{ value: 'compact', label: 'Compact', description: 'Reduced row padding', icon: 'fas fa-grip-lines-vertical' },
|
||||
{ value: 'ultra-compact', label: 'Ultra', description: 'Maximum density', icon: 'fas fa-list' }
|
||||
];
|
||||
|
||||
const currentLabel = computed(() => {
|
||||
return options.find(o => o.value === props.modelValue)?.label || 'Comfortable';
|
||||
});
|
||||
|
||||
const toggleDropdown = () => {
|
||||
isOpen.value = !isOpen.value;
|
||||
};
|
||||
|
||||
const closeDropdown = () => {
|
||||
// Small delay to allow click events to fire first
|
||||
setTimeout(() => {
|
||||
isOpen.value = false;
|
||||
}, 150);
|
||||
};
|
||||
|
||||
const selectOption = (value) => {
|
||||
emit('update:modelValue', value);
|
||||
isOpen.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.rounded-12 { border-radius: 12px; }
|
||||
.dropdown-item { transition: all 0.2s; cursor: pointer; }
|
||||
.dropdown-item.active { background-color: rgba(66, 185, 131, 0.1) !important; color: #42b983 !important; }
|
||||
:global(.dark-mode) .dropdown-item.active { background-color: rgba(66, 185, 131, 0.2) !important; }
|
||||
.smallest { font-size: 0.75rem; }
|
||||
.icon-box { width: 28px; height: 28px; flex-shrink: 0; }
|
||||
.btn-theme { background: var(--bg-card); color: var(--text-primary); border-color: var(--border-color) !important; }
|
||||
.dropdown-menu { background: var(--bg-card); min-width: 200px; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user