LayoutHeader.vue 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { computed, useTemplateRef, useSlots } from 'vue'
  4. import CommonBackButton from '#mobile/components/CommonBackButton/CommonBackButton.vue'
  5. import CommonButton from '#mobile/components/CommonButton/CommonButton.vue'
  6. import type { CommonButtonProps } from '#mobile/components/CommonButton/types.ts'
  7. import CommonRefetch from '#mobile/components/CommonRefetch/CommonRefetch.vue'
  8. import type { RouteLocationRaw } from 'vue-router'
  9. export interface Props {
  10. containerTag?: 'header' | 'div'
  11. title?: string
  12. titleClass?: string
  13. backTitle?: string
  14. backIgnore?: string[]
  15. backUrl?: RouteLocationRaw
  16. backAvoidHomeButton?: boolean
  17. defaultAttrs?: Record<string, unknown>
  18. refetch?: boolean
  19. actionTitle?: string
  20. actionHidden?: boolean
  21. actionButtonProps?: CommonButtonProps
  22. onAction?(): void
  23. }
  24. const headerElement = useTemplateRef<HTMLElement>('header')
  25. defineExpose({
  26. headerElement,
  27. })
  28. const props = withDefaults(defineProps<Props>(), {
  29. refetch: false,
  30. containerTag: 'header',
  31. })
  32. const slots = useSlots()
  33. const hasSlots = computed(() => Object.keys(slots).length > 0)
  34. const headerClass = computed(() => {
  35. return [
  36. 'flex items-center justify-center text-center text-lg font-bold',
  37. props.titleClass,
  38. ]
  39. })
  40. </script>
  41. <template>
  42. <component
  43. :is="containerTag"
  44. v-if="title || backUrl || (onAction && actionTitle) || hasSlots"
  45. ref="header"
  46. class="grid h-[64px] shrink-0 grid-cols-[75px_auto_75px] border-b-[0.5px] border-white/10 bg-black px-4"
  47. data-test-id="appHeader"
  48. >
  49. <div class="flex items-center justify-self-start text-base">
  50. <slot
  51. name="before"
  52. :data="{ backUrl, backTitle, backIgnore, backAvoidHomeButton }"
  53. >
  54. <CommonBackButton
  55. v-if="backUrl"
  56. :fallback="backUrl"
  57. :label="backTitle"
  58. :ignore="backIgnore"
  59. :avoid-home-button="backAvoidHomeButton"
  60. />
  61. </slot>
  62. </div>
  63. <div class="flex flex-1 items-center justify-center">
  64. <CommonRefetch v-bind="defaultAttrs" :refetch="refetch">
  65. <slot :data="{ defaultAttrs, refetch }">
  66. <h1 :class="headerClass">
  67. {{ $t(title) }}
  68. </h1>
  69. </slot>
  70. </CommonRefetch>
  71. </div>
  72. <div
  73. v-if="((onAction || actionTitle) && !actionHidden) || slots.after"
  74. class="flex items-center justify-self-end text-base"
  75. >
  76. <slot name="after" :data="{ actionButtonProps }">
  77. <CommonButton
  78. v-bind="{
  79. variant: 'primary',
  80. transparentBackground: true,
  81. ...actionButtonProps,
  82. }"
  83. @click="onAction?.()"
  84. >
  85. {{ $t(actionTitle) }}
  86. </CommonButton>
  87. </slot>
  88. </div>
  89. </component>
  90. </template>