Skip to content
Snippets Groups Projects
UnderConstruction.vue 1.85 KiB
Newer Older
<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>