UIPackage
Menu

Block Ui

block-ui ui
Edit on GitHub

Overlay that blocks interaction during loading. Wraps content and shows a spinner + message overlay. v-model toggles the blocked state with configurable overlay opacity, color, background blur, and custom icon/message slots. Composes the spinner primitive.

Also available for React ->

Installation

$ npx shadcn-vue@latest add https://uipkge.dev/r/vue/block-ui.json
Named registry: npx shadcn-vue@latest add @uipkge/block-ui Installs to: app/components/ui/block-ui/

Examples

Props

Name Type / Values Default Required
modelValue boolean false optional
message string 'Loading...' optional
opacity number 0.6 optional
overlayColor string '' optional
blur boolean false optional
showSpinner boolean true optional
class HTMLAttributes['class'] optional

npm dependencies

Includes

Files installed (3)

  • app/components/ui/block-ui/BlockUi.vue 2.2 kB
    <script setup lang="ts">
    import type { HTMLAttributes } from 'vue'
    import { computed, useSlots } from 'vue'
    import { cn } from '@/lib/utils'
    import { blockUiVariants } from './block-ui.variants'
    import { Spinner } from '@/components/ui/spinner'
    
    interface Props {
      modelValue?: boolean
      message?: string
      opacity?: number
      overlayColor?: string
      blur?: boolean
      showSpinner?: boolean
      class?: HTMLAttributes['class']
    }
    
    const props = withDefaults(defineProps<Props>(), {
      modelValue: false,
      message: 'Loading...',
      opacity: 0.6,
      overlayColor: '',
      blur: false,
      showSpinner: true,
    })
    
    const emit = defineEmits<{
      'update:modelValue': [value: boolean]
    }>()
    
    const slots = useSlots()
    const hasIconSlot = computed(() => !!slots.icon)
    
    const overlayStyle = computed(() => {
      const style: Record<string, string> = {
        opacity: String(props.opacity),
      }
      if (props.overlayColor) style.backgroundColor = props.overlayColor
      return style
    })
    </script>
    
    <template>
      <div
        data-uipkge
        data-slot="block-ui"
        :data-blocked="modelValue ? '' : undefined"
        :class="cn(blockUiVariants(), props.class)"
      >
        <!-- Wrapped content -->
        <div :class="cn('block-ui-content', blur && modelValue && 'pointer-events-none blur-[2px] transition-[filter]')">
          <slot />
        </div>
    
        <!-- Blocking overlay -->
        <Transition name="block-ui-fade">
          <div
            v-if="modelValue"
            class="absolute inset-0 z-50 flex flex-col items-center justify-center gap-3"
            role="status"
            aria-live="polite"
            aria-busy="true"
          >
            <!-- Background layer (opacity only affects this layer) -->
            <div class="absolute inset-0" :style="overlayStyle" :class="!overlayColor && 'bg-background'" />
            <!-- Content layer (spinner + message stay fully opaque) -->
            <slot name="icon">
              <Spinner v-if="showSpinner" size="lg" />
            </slot>
            <p v-if="message || slots.message" class="text-foreground text-sm font-medium">
              <slot name="message">{{ message }}</slot>
            </p>
          </div>
        </Transition>
      </div>
    </template>
    
    <style scoped>
    .block-ui-fade-enter-active,
    .block-ui-fade-leave-active {
      transition: opacity 0.2s ease;
    }
    .block-ui-fade-enter-from,
    .block-ui-fade-leave-to {
      opacity: 0;
    }
    </style>
  • app/components/ui/block-ui/block-ui.variants.ts 0.2 kB
    import type { VariantProps } from 'class-variance-authority'
    import { cva } from 'class-variance-authority'
    
    export const blockUiVariants = cva('relative inline-block')
    
    export type BlockUiVariants = VariantProps<typeof blockUiVariants>
  • app/components/ui/block-ui/index.ts 0.1 kB
    export { default as BlockUi } from './BlockUi.vue'
    export { blockUiVariants, type BlockUiVariants } from './block-ui.variants'

Raw manifest: https://uipkge.dev/r/vue/block-ui.json