Skip to content
Snippets Groups Projects
UnderConstruction.vue 1.85 KiB
Newer Older
  • Learn to ignore specific revisions
  • <template>
      <div class="construction tw-relative" :class="{ 'show-construction-area': showConstructionArea }">
        <component
    
          v-bind="attrs"
    
          :is="link ? 'a' : 'div'"
          :href="link"
          :target="link ? '_blank' : undefined"
          :class="showConstructionArea ? 'tw-bg-amber-200' : 'tw-bg-amber-100'"
          class="tw-group tw-flex tw-items-center tw-gap-2 tw-absolute tw-rounded tw-w-min tw-p-[.35em] tw-px-[.7em] tw-cursor-help tw-select-none tw-transition tw-duration-200"
          tabindex="0"
          @mouseover="mouseOver = true"
          @mouseleave="mouseOver = false"
          @focus="hasFocus = true"
          @blur="hasFocus = false"
        >
          <icon-noto-construction />
          {{ t('construction.label') }}
          <div
            class="construction-info tw-absolute tw-top-full tw-right-0 tw-mt-2 tw-bg-white tw-w-96 tw-text-base tw-p-4 tw-shadow-xl tw-rounded tw-z-50"
            :class="{ 'tw-hidden': !showConstructionArea }"
          >
            <slot name="title">
              <p>{{ title }}</p>
            </slot>
          </div>
        </component>
        <slot />
      </div>
    </template>
    <script setup lang="ts">
    import { computed, ref, useAttrs } from 'vue'
    import { useI18n } from '@/i18n'
    
    defineOptions({ inheritAttrs: false, compatConfig: { MODE: 3 } })
    
    defineProps<{
      title?: string
      link?: string
    }>()
    
    const { t } = useI18n()
    const attrs = useAttrs()
    const mouseOver = ref(false)
    const hasFocus = ref(false)
    const showConstructionArea = computed(() => mouseOver.value || hasFocus.value)
    </script>
    
    <style lang="postcss" scoped>
    .construction::after {
      content: '';
      position: absolute;
      inset: -1rem;
      pointer-events: none;
      border-radius: 6px;
      background-color: theme('colors.amber.100');
      z-index: -1;
      opacity: 0;
      transition: opacity 0.2s;
    }
    
    .construction.show-construction-area::after {
      opacity: 1;
    }
    
    .construction-info :deep(:last-child) {
      margin-bottom: 0;
    }
    </style>