Components

Dropdowns

A simple dropdown menu used for selecting actions or options. It typically appears when the user clicks a button or an icon, revealing a list of choices. This type is useful for navigation menus and contextual actions.

Standard

A simple dropdown menu used for selecting actions or options. It typically appears when the user clicks a button or an icon, revealing a list of choices. This type is useful for navigation menus and contextual actions.

View Mode
                          
HTML
<div class="dropdown"> <button class="btn btn-square dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" data-boundary="viewport"> <span class="tticon-dots-horizontal-bold btn-icon"></span> </button> <ul class="dropdown-menu dropdown-start"> <li class="dropdown-header"> <span>اختر عملية</span> </li> <li> <a class="dropdown-item" href="#!"> <span class="tticon-eye dropdown-icon"></span> التفاصيل </a> </li> <li> <a class="dropdown-item" href="#!"> <span class="tticon-link dropdown-icon"></span> الخدمة </a> </li> <li> <a class="dropdown-item" href="#!"> <span class="tticon-pen dropdown-icon"></span> تحرير </a> </li> <li> <a class="dropdown-item" href="#!"> <span class="tticon-download dropdown-icon"></span> تحميل </a> </li> </ul> </div>
<!-- Usage Example -->
<StandardDropdown header="اختر عملية" :items="standardList" />
<script setup>
import { ref } from 'vue'
const standardList = ref([
  { label: 'التفاصيل', icon: 'tticon-eye', link: '/details' },
  { label: 'الخدمة', icon: 'tticon-link', link: '/service' },
  { label: 'تحرير', icon: 'tticon-pen', link: '/edit' },
  { label: 'تحميل', icon: 'tticon-download', link: '/download' },
])
</script>
<!-- Vue Component Code Block -->
<template>
  <div class="dropdown">
    <button
      class="btn btn-square dropdown-toggle"
      type="button"
      data-bs-toggle="dropdown"
      aria-expanded="false"
      data-boundary="viewport"
    >
      <span class="tticon-dots-horizontal-bold btn-icon"></span>
    </button>
 
    <ul class="dropdown-menu dropdown-start">
      <li class="dropdown-header" v-if="header">
        <span>{{ header }}</span>
      </li>
 
      <li v-for="(item, index) in items" :key="index">
        <a
          class="dropdown-item"
          :href="item.link || '#!'"
          @click.prevent="item.onClick && item.onClick()"
        >
          <span :class="[item.icon, 'dropdown-icon']" v-if="item.icon"></span>
          {{ item.label }}
        </a>
      </li>
    </ul>
  </div>
</template>
<script setup>
defineProps({
  items: {
    type: Array,
    default: () => [],
  },
  header: {
    type: String,
    default: '',
  },
})
</script>

Nested Dropdown

A hierarchical dropdown where selecting an option reveals a secondary dropdown with more specific filters. Examples include Range Price and Select List.

View Mode
                          
HTML
<div class="dropdown"> <button class="btn btn-secondary btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"> <span class="tticon-filter-light btn-icon"></span> <span>فلترة</span> </button> <ul class="dropdown-menu dropdown-start"> <li class="dropdown-header"> <span class="dropdown-title">اختر إجراء الفلترة</span> </li> <li> <button class="dropdown-item dropdown-toggle submenu-open" data-bs-toggle="dropdown"> الخدمة <span class="dropdown-end-area"> <span class="dropdown-number">2</span> <span class="dropdown-chevron tticon-chevron-left"></span> </span> </button> <ul class="dropdown-menu submenu" style="min-width: 230px"> <li class="dropdown-header"> <button class="submenu-close dropdown-toggle"> <span class="tticon-chevron-right"></span> رجوع للفلترة </button> </li> <li class="dropdown-search"> <span class="input-group"> <span class="tticon-search input-group-text"></span> <input class="form-control" type="text" placeholder="بحث في الفلتر.."/> </span> </li> <li class="dropdown-checks"> <span class="form-check dropdown-check-item"> <label class="form-label"> <input class="form-check-input" type="checkbox" value=""/> خدمة توفير نقاط البيع </label> </span> <span class="form-check dropdown-check-item"> <label class="form-label"> <input class="form-check-input" type="checkbox" value="" checked/> خدمة صرف العلاج الدوائي </label> </span> </li> <li class="dropdown-footer"> <button class="btn btn-primary btn-sm">اعتماد</button> <button class="btn btn-secondary btn-sm">إعادة تعيين</button> </li> </ul> </li> <li> <button class="dropdown-item dropdown-toggle submenu-open" data-bs-toggle="dropdown"> الحالة <span class="dropdown-end-area"> <span class="dropdown-number">1</span> <span class="dropdown-chevron tticon-chevron-left"></span> </span> </button> <ul class="dropdown-menu submenu" style="min-width: 230px"> <li class="dropdown-header"> <button class="submenu-close dropdown-toggle"> <span class="tticon-chevron-right"></span> رجوع للفلترة </button> </li> <li class="dropdown-search"> <span class="input-group"> <span class="tticon-search input-group-text"></span> <input class="form-control" type="text" placeholder="بحث في الفلتر.."/> </span> </li> <li class="dropdown-checks"> <span class="form-check dropdown-check-item"> <label class="form-label"> <input class="form-check-input" type="checkbox" value=""/> قيد المراجعة </label> </span> <span class="form-check dropdown-check-item"> <label class="form-label"> <input class="form-check-input" type="checkbox" value="" checked/> قيد التنفيذ </label> </span> <span class="form-check dropdown-check-item"> <label class="form-label"> <input class="form-check-input" type="checkbox" value=""/> مكتملة </label> </span> <span class="form-check dropdown-check-item"> <label class="form-label"> <input class="form-check-input" type="checkbox" value=""/> تجربة سريعة </label> </span> </li> <li class="dropdown-footer"> <button class="btn btn-primary btn-sm">اعتماد</button> <button class="btn btn-secondary btn-sm">إعادة تعيين</button> </li> </ul> </li> <li> <button class="dropdown-item dropdown-toggle submenu-open" data-bs-toggle="dropdown"> النطاق الزمني <span class="dropdown-end-area"> <span class="dropdown-number d-none">0</span> <span class="dropdown-chevron tticon-chevron-left"></span> </span> </button> <ul class="dropdown-menu submenu" style="min-width: 230px"> <li class="dropdown-header"> <button class="submenu-close dropdown-toggle"> <span class="tticon-chevron-right"></span> رجوع للفلترة </button> </li> <li class="js-stop-propagation"> <input class="js-datepicker" type="hidden"/> </li> <li class="dropdown-footer"> <button class="btn btn-primary btn-sm">اعتماد</button> <button class="btn btn-secondary btn-sm">إعادة تعيين</button> </li> </ul> </li> </ul> </div>
<!-- Usage Example -->
<NestedDropdown
  label="فلترة"
  label-icon="tticon-filter-light"
  header="اختر عملية"
  :items="nestedList"
  @update="onUpdateFilter"
/>
<script setup>
import { ref } from 'vue'
const nestedList = ref([
  {
    label: 'الخدمة',
    selectedCount: 2,
    type: 'checkboxes',
    options: [
      { label: 'خدمة توفير نقاط البيع', value: 'pos' },
      { label: 'خدمة صرف العلاج الدوائي', value: 'medicine', checked: true },
    ],
  },
  {
    label: 'الحالة',
    selectedCount: 1,
    type: 'checkboxes',
    options: [
      { label: 'قيد المراجعة', value: 'review' },
      { label: 'قيد التنفيذ', value: 'in_progress', checked: true },
      { label: 'مكتملة', value: 'completed' },
      { label: 'تجربة سريعة', value: 'test' },
    ],
  },
  {
    label: 'النطاق الزمني',
    type: 'datepicker',
  },
])
const onUpdateFilter = ({ filter, value, checked }) => {
  console.log(filter, value, checked)
}
</script>
<!-- Vue Component Code Block -->
<template>
  <div class="dropdown">
    <button
      class="btn btn-secondary btn-sm dropdown-toggle"
      type="button"
      data-bs-toggle="dropdown"
      aria-expanded="false"
    >
      <span :class="labelIcon + ' btn-icon'"></span>
      <span>{{ label }}</span>
    </button>
 
    <ul class="dropdown-menu dropdown-start">
      <li class="dropdown-header" v-if="header">
        <span>{{ header }}</span>
      </li>
 
      <li v-for="(item, index) in items" :key="index" class="position-static">
        <button
          class="dropdown-item dropdown-toggle submenu-open"
          data-bs-toggle="dropdown"
          aria-expanded="false"
        >
          {{ item.label }}
          <span class="dropdown-end-area">
            <span class="dropdown-number" v-if="item.selectedCount">{{ item.selectedCount }}</span>
            <span class="dropdown-chevron tticon-chevron-left"></span>
          </span>
        </button>
 
        <ul class="dropdown-menu dropdown-menu-end submenu" style="min-width: 230px">
          <li class="dropdown-header">
            <button class="submenu-close dropdown-toggle" @click="closeFilters($event)">
              <span class="tticon-chevron-right"></span>
              رجوع للفلترة
            </button>
          </li>
 
          <!-- search bar (optional) -->
          <li v-if="item.type === 'checkboxes'" class="dropdown-search">
            <span class="input-group">
              <span class="tticon-search input-group-text"></span>
              <input class="form-control" type="text" placeholder="بحث في الفلتر.." />
            </span>
          </li>
 
          <!-- checkboxes -->
          <li v-if="item.type === 'checkboxes'" class="dropdown-checks">
            <span
              v-for="(opt, idx) in item.options"
              :key="idx"
              class="form-check dropdown-check-item"
            >
              <label class="form-label">
                <input
                  class="form-check-input"
                  type="checkbox"
                  :value="opt.value"
                  :checked="opt.checked"
                  @change="
                    $emit('update', {
                      filter: item.label,
                      value: opt.value,
                      checked: $event.target.checked,
                    })
                  "
                />
                {{ opt.label }}
              </label>
            </span>
          </li>
 
          <!-- datepicker (you can replace with your component) -->
          <li v-if="item.type === 'datepicker'" class="js-stop-propagation">
            <input class="js-datepicker" type="hidden" />
          </li>
 
          <!-- footer actions -->
          <li class="dropdown-footer">
            <button class="btn btn-primary btn-sm" @click="onUpdate">اعتماد</button>
            <button class="btn btn-secondary btn-sm" @click="onReset">إعادة تعيين</button>
          </li>
        </ul>
      </li>
    </ul>
  </div>
</template>
<script setup>
import { onMounted } from 'vue'
import { Dropdown } from 'bootstrap'
 
defineProps({
  items: {
    type: Array,
    default: () => [],
  },
  header: {
    type: String,
    default: '',
  },
  label: {
    type: String,
    default: '',
  },
  labelIcon: {
    type: String,
    default: '',
  },
  onUpdate: {
    type: Function,
    default: () => {},
  },
  onReset: {
    type: Function,
    default: () => {},
  },
})
 
defineEmits(['update'])
 
onMounted(() => {
  document.querySelectorAll('.dropdown .dropdown-toggle').forEach((el) => {
    el.addEventListener('click', (e) => {
      e.stopPropagation()
 
      const parent = el.parentElement
      const submenu = parent.querySelector('.dropdown-menu')
 
      if (submenu) {
        submenu.classList.toggle('show')
      }
 
      parent.parentElement.querySelectorAll('.dropdown-menu.show').forEach((openMenu) => {
        if (openMenu !== submenu) {
          openMenu.classList.remove('show')
        }
      })
    })
  })
 
  document.querySelectorAll('.dropdown > .dropdown-toggle').forEach((el) => {
    new Dropdown(el)
  })
})
 
function closeFilters(event) {
  event.stopPropagation()
 
  const submenu = event.target.closest('.dropdown-menu.submenu.show')
 
  if (submenu) {
    submenu.classList.remove('show')
 
    const parentSubmenuToggle = submenu.parentElement.querySelector(
      '.dropdown-item.dropdown-toggle.submenu-open',
    )
    if (parentSubmenuToggle) {
      parentSubmenuToggle.focus()
    }
  }
}
</script>
Last updated 3 months ago