index.vue 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. <script setup lang="ts">
  2. import { nextTick, ref, useTemplateRef, watch } from 'vue'
  3. import Logo from '@/components/AppLogo.vue'
  4. import { toRefsPreferencesStore, DEFAULT_PREFERENCES_OPTIONS } from '@/stores'
  5. defineOptions({
  6. name: 'Logo',
  7. })
  8. const APP_NAME = import.meta.env.VITE_APP_NAME
  9. const { navigationMode, sidebarMenu, showLogo } = toRefsPreferencesStore()
  10. const logoWrapperRef = useTemplateRef<HTMLElement>('logoWrapper')
  11. const collapseWidth = ref(0)
  12. watch(
  13. [() => navigationMode.value, () => sidebarMenu.value.collapsed],
  14. ([navigationMode, isCollapsed]) => {
  15. if (navigationMode === 'horizontal') {
  16. nextTick(() => {
  17. collapseWidth.value = logoWrapperRef.value?.clientWidth ?? 0
  18. })
  19. } else {
  20. const { width, maxWidth } = sidebarMenu.value
  21. const { width: defaultWidth, maxWidth: defaultMaxWidth } =
  22. DEFAULT_PREFERENCES_OPTIONS.sidebarMenu
  23. collapseWidth.value = isCollapsed ? width || defaultWidth : maxWidth || defaultMaxWidth
  24. }
  25. },
  26. {
  27. immediate: true,
  28. },
  29. )
  30. </script>
  31. <template>
  32. <div
  33. class="shrink-0 transition-[width]"
  34. :style="
  35. collapseWidth > 0 && {
  36. width: `${collapseWidth}px`,
  37. }
  38. "
  39. >
  40. <div
  41. ref="logoWrapper"
  42. class="flex h-full items-center transition-[opacity,padding]"
  43. :class="[
  44. sidebarMenu.collapsed ? 'px-3' : 'px-4',
  45. {
  46. 'opacity-0': !showLogo,
  47. 'w-fit': navigationMode === 'horizontal',
  48. },
  49. ]"
  50. >
  51. <div class="size-10">
  52. <Logo />
  53. </div>
  54. <div
  55. class="flex flex-1 overflow-hidden transition-[margin-left,max-width]"
  56. :class="sidebarMenu.collapsed ? 'ml-0 max-w-0' : 'ml-4 max-w-44'"
  57. >
  58. <h1 class="shrink-0 text-xl">
  59. {{ APP_NAME }}
  60. </h1>
  61. </div>
  62. </div>
  63. </div>
  64. </template>