mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 02:57:57 +00:00 
			
		
		
		
	 6ced918549
			
		
	
	6ced918549
	
	
	
		
			
			# Pull Request Template ## Description This PR updates the basic filter UI for conversations. ## Type of change - [x] New feature (non-breaking change which adds functionality) ## How Has This Been Tested? ### Loom video https://www.loom.com/share/df69a023a39c4dfca2c12b1ee42a0b2e?sid=977e802e-2865-46f1-ae8e-f89ab5eabc2a ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules --------- Co-authored-by: Pranav <pranav@chatwoot.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
		
			
				
	
	
		
			86 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <script setup>
 | |
| import { ref, computed } from 'vue';
 | |
| import Button from 'dashboard/components-next/button/Button.vue';
 | |
| 
 | |
| const props = defineProps({
 | |
|   options: {
 | |
|     type: Array,
 | |
|     required: true,
 | |
|   },
 | |
|   modelValue: {
 | |
|     type: String,
 | |
|     required: true,
 | |
|   },
 | |
|   label: {
 | |
|     type: String,
 | |
|     required: true,
 | |
|   },
 | |
|   subMenuPosition: {
 | |
|     type: String,
 | |
|     default: 'right',
 | |
|     validator: value => {
 | |
|       return ['right', 'left', 'bottom'].includes(value);
 | |
|     },
 | |
|   },
 | |
| });
 | |
| 
 | |
| const emit = defineEmits(['update:modelValue']);
 | |
| 
 | |
| const isOpen = ref(false);
 | |
| 
 | |
| const labelValue = computed(() => props.label);
 | |
| 
 | |
| const toggleMenu = () => {
 | |
|   isOpen.value = !isOpen.value;
 | |
| };
 | |
| 
 | |
| const handleSelect = value => {
 | |
|   emit('update:modelValue', value);
 | |
|   isOpen.value = false;
 | |
| };
 | |
| </script>
 | |
| 
 | |
| <template>
 | |
|   <div
 | |
|     v-on-clickaway="() => (isOpen = false)"
 | |
|     class="relative flex flex-col gap-1 w-fit"
 | |
|   >
 | |
|     <Button
 | |
|       icon="i-lucide-chevron-down"
 | |
|       size="sm"
 | |
|       trailing-icon
 | |
|       color="slate"
 | |
|       variant="faded"
 | |
|       class="!w-fit max-w-40"
 | |
|       :class="{ 'dark:!bg-n-alpha-2 !bg-n-slate-9/20': isOpen }"
 | |
|       :label="labelValue"
 | |
|       @click="toggleMenu"
 | |
|     />
 | |
|     <div
 | |
|       v-if="isOpen"
 | |
|       class="absolute select-none max-w-64 flex flex-col gap-1 bg-n-alpha-3 backdrop-blur-[100px] p-1 top-0 shadow-lg z-40 rounded-lg border border-n-weak dark:border-n-strong/50"
 | |
|       :class="{
 | |
|         'ltr:left-full rtl:right-full ltr:ml-1 rtl:mr-1':
 | |
|           subMenuPosition === 'right',
 | |
|         'ltr:right-full rtl:left-full ltr:mr-1 rtl:ml-1':
 | |
|           subMenuPosition === 'left',
 | |
|         'top-full mt-1 ltr:right-0 rtl:left-0': subMenuPosition === 'bottom',
 | |
|       }"
 | |
|     >
 | |
|       <Button
 | |
|         v-for="option in options"
 | |
|         :key="option.value"
 | |
|         :label="option.label"
 | |
|         :icon="option.value === modelValue ? 'i-lucide-check' : ''"
 | |
|         size="sm"
 | |
|         variant="ghost"
 | |
|         color="slate"
 | |
|         trailing-icon
 | |
|         class="!justify-end !px-2.5 !h-7"
 | |
|         :class="{ '!bg-n-alpha-2': option.value === modelValue }"
 | |
|         @click="handleSelect(option.value)"
 | |
|       />
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 |