MoreOptions.vue 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. <template>
  2. <div class="relative flex justify-end items-center" @keydown.escape="isOpen = false">
  3. <button
  4. ref="openOptions"
  5. @click="isOpen = !isOpen"
  6. :aria-expanded="isOpen"
  7. id="project-options-menu-0"
  8. aria-has-popup="true"
  9. type="button"
  10. class="w-8 h-8 bg-white inline-flex items-center justify-center text-grey-400 rounded-full hover:text-grey-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"
  11. >
  12. <span class="sr-only">Open options</span>
  13. <icon
  14. name="more"
  15. class="block w-6 h-6 text-grey-300 fill-current cursor-pointer outline-none"
  16. aria-hidden="true"
  17. />
  18. </button>
  19. <transition
  20. enter-active-class="transition ease-out duration-100"
  21. enter-class="transform opacity-0 scale-95"
  22. enter-to-class="transform opacity-100 scale-100"
  23. leave-active-class="transition ease-in duration-75"
  24. leave-class="transform opacity-100 scale-100"
  25. leave-to-class="transform opacity-0 scale-95"
  26. >
  27. <div
  28. v-show="isOpen"
  29. class="mx-3 origin-top-right absolute right-7 top-0 w-48 mt-1 rounded-md shadow-lg z-10 bg-white ring-1 ring-black ring-opacity-5 divide-y divide-grey-200"
  30. role="menu"
  31. aria-orientation="vertical"
  32. aria-labelledby="project-options-menu-0"
  33. >
  34. <slot></slot>
  35. </div>
  36. </transition>
  37. </div>
  38. </template>
  39. <script>
  40. export default {
  41. data() {
  42. return {
  43. isOpen: false,
  44. }
  45. },
  46. created() {
  47. window.addEventListener('click', this.close)
  48. },
  49. beforeDestroy() {
  50. window.removeEventListener('click', this.close)
  51. },
  52. methods: {
  53. close(e) {
  54. if (!this.$refs.openOptions.contains(e.target)) {
  55. this.isOpen = false
  56. }
  57. },
  58. },
  59. }
  60. </script>