CollapseButton.vue 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { computed } from 'vue'
  4. import { useTouchDevice } from '#shared/composables/useTouchDevice.ts'
  5. import { EnumTextDirection } from '#shared/graphql/types.ts'
  6. import { i18n } from '#shared/i18n/index.ts'
  7. import { useLocaleStore } from '#shared/stores/locale.ts'
  8. import CommonButton from '#desktop/components/CommonButton/CommonButton.vue'
  9. const { isTouchDevice } = useTouchDevice()
  10. interface Props {
  11. ownerId: string
  12. collapsed?: boolean
  13. orientation?: 'horizontal' | 'vertical'
  14. expandLabel?: string
  15. collapseLabel?: string
  16. inverse?: boolean
  17. variant?: 'none' | 'tertiary-gray'
  18. noPadded?: boolean
  19. buttonClass?: string
  20. }
  21. const props = withDefaults(defineProps<Props>(), {
  22. orientation: 'horizontal',
  23. collapsed: false,
  24. })
  25. defineEmits<{
  26. 'toggle-collapse': [MouseEvent]
  27. }>()
  28. const locale = useLocaleStore()
  29. const collapseButtonIcon = computed(() => {
  30. if (props.orientation === 'vertical')
  31. return props.collapsed ? 'arrows-expand' : 'arrows-collapse'
  32. if (
  33. (props.inverse && locale.localeData?.dir !== EnumTextDirection.Rtl) ||
  34. (!props.inverse && locale.localeData?.dir === EnumTextDirection.Rtl)
  35. )
  36. return props.collapsed ? 'arrow-bar-left' : 'arrow-bar-right'
  37. return props.collapsed ? 'arrow-bar-right' : 'arrow-bar-left'
  38. })
  39. // :TODO think if we add this variant as a Variant of CommonButton
  40. const variantClass = computed(() => {
  41. if (props.variant === 'tertiary-gray')
  42. return 'bg-neutral-500 focus-visible:bg-blue-800 active:dark:bg-blue-800 focus:dark:bg-blue-800 active:bg-blue-800 focus:bg-blue-800 hover:bg-blue-600 hover:dark:bg-blue-900 text-black dark:bg-gray-200 dark:text-white'
  43. return ''
  44. })
  45. const labels = computed(() => ({
  46. expand: props.expandLabel || i18n.t('Expand this element'),
  47. collapse: props.collapseLabel || i18n.t('Collapse this element'),
  48. }))
  49. </script>
  50. <template>
  51. <div
  52. class="flex items-center justify-center focus-within:opacity-100 hover:opacity-100"
  53. :class="{
  54. 'opacity-0': !isTouchDevice,
  55. 'p-2': !noPadded,
  56. }"
  57. >
  58. <CommonButton
  59. v-tooltip="collapsed ? labels.expand : labels.collapse"
  60. class="hover:outline-transparent focus:outline-transparent focus-visible:outline-transparent dark:hover:outline-transparent dark:focus:outline-transparent"
  61. :class="[variantClass, buttonClass]"
  62. :icon="collapseButtonIcon"
  63. :aria-expanded="!collapsed"
  64. variant="none"
  65. :aria-controls="ownerId"
  66. :aria-label="
  67. collapsed ? $t('Expand this element') : $t('Collapse this element')
  68. "
  69. size="small"
  70. @click="$emit('toggle-collapse', $event)"
  71. />
  72. </div>
  73. </template>