๐ŸŸข Alert


Basic

NAlert - display a short, important message in a way that attracts the user's attention without interrupting the user's task.

PropDescription
titleTitle of the alert
descriptionDescription of the alert
WARNING

This documentation is still a work in progress. The package itself is not yet officially released and some sections of this documentation may be incomplete or missing entirely until the first release. We are working hard to complete the documentation as soon as possible.

<template>
  <NAlert
    title="WARNING"
    description="This documentation is still a work in progress. The package itself is not yet officially released and some sections of this documentation may be incomplete or missing entirely until the first release. We are working hard to complete the documentation as soon as possible."
  />
</template>

Variants

alert="{variant}" - change the alert variant.

VariantDescription
outlineThe default variant.
softThe soft variant.
~The unstyle or base variant
If you want to change the default variant or add new variant, you can do so through the Configuration section.
Outline variant (default)

Lorem ipsum dolor sit amet consectetur adipisicing elit. aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Soft variant

Lorem ipsum dolor sit amet consectetur adipisicing elit. aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Border variant

Lorem ipsum dolor sit amet consectetur adipisicing elit. aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

<template>
  <div flex="~ col" space-y-4>
    <NAlert
      alert="outline"
      title="Outline variant (default)"
      description="Lorem ipsum dolor sit amet consectetur adipisicing elit. aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum."
    />

    <NAlert
      alert="soft"
      title="Soft variant"
      description="Lorem ipsum dolor sit amet consectetur adipisicing elit. aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum."
    />

    <NAlert
      alert="border"
      title="Border variant"
      description="Lorem ipsum dolor sit amet consectetur adipisicing elit. aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum."
    />
  </div>
</template>

Color

alert="{variant}-{color}" - change the color of the alert.

You can use any color provided by the Tailwind CSS color palette, the default is primary. You can also add your own colors to the palette through the Configuration section.
Info color

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Success color

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Warning color

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Error color

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Purple color

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Lime color

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Pink color

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Sky color

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

<script setup lang="ts">
const description = 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.'
</script>

<template>
  <div flex="~ col" space-y-4>
    <NAlert alert="outline-info" title="Info color" :description="description" />

    <NAlert alert="border-success" title="Success color" :description="description" />

    <NAlert alert="outline-warning" title="Warning color" :description="description" />

    <NAlert alert="border-error" title="Error color" :description="description" />

    <NAlert alert="soft-purple" title="Purple color" :description="description" />

    <NAlert alert="outline-lime" title="Lime color" :description="description" />

    <NAlert alert="border-pink" title="Pink color" :description="description" />

    <NAlert alert="outline-sky" title="Sky color" :description="description" />
  </div>
</template>

Icon

icon - Automatically add icon to the alert based on the color.

Supported colors are success, error, warning, info eg. icon="outline-success".

icon="{icon}" - Customize the icon of the alert.

You can customize the default icon status through the Configuration section.
Customize icon

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Info icon

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Success icon

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Warning icon

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Error icon

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

<template>
  <div flex="~ col" space-y-4>
    <NAlert
      title="Customize icon"
      description="Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum."
      icon="i-heroicons-beaker-20-solid"
    />

    <NAlert
      alert="outline-info"
      title="Info icon"
      description="Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum."
      icon
    />

    <NAlert
      alert="outline-success"
      title="Success icon"
      description="Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum."
      icon
    />

    <NAlert
      alert="outline-warning"
      title="Warning icon"
      description="Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum."
      icon
    />

    <NAlert
      alert="outline-error"
      title="Error icon"
      description="Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum."
      icon
    />
  </div>
</template>

Size

size="{size}" - change the size of the alert.

๐Ÿš€ You can freely adjust the size of the input using any size imaginable. No limits exist, and you can use breakpoints such as sm:sm, xs:lg to change size based on screen size or states such as hover:lg, focus:3xl to change size based on input state and more.

The padding, icons, and text-size of the input scale depends on the size. If you want to change the text-size and padding simultaneously, you can always customize it using utility classes.
Attention needed

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Attention needed

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Attention needed

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

Attention needed

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

<script setup lang="ts">
const alerts = {
  title: 'Attention needed',
  description: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.',
  icon: true,
}
</script>

<template>
  <div flex="~ col" space-y-4>
    <NAlert size="xs" alert="outline-info" v-bind="alerts" />

    <NAlert size="sm" alert="outline-success" v-bind="alerts" />

    <NAlert size="24px" alert="outline-warning" v-bind="alerts" />

    <NAlert size="2rem" alert="outline-error" v-bind="alerts" />
  </div>
</template>

Closable

closable - add a close button to the alert.

Closable alert 1
Closable alert 2

Lorem ipsum dolor sit amet consectetur adipisicing elit. aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.

<script setup lang="ts">
const close1 = ref(false)
const close2 = ref(false)

// auto reset if all alerts are closed
watchEffect(() => {
  if (close1.value && close2.value) {
    setTimeout(() => {
      close1.value = false
      close2.value = false
    }, 1000)
  }
})
</script>

<template>
  <div flex="~ col" space-y-4>
    <NAlert
      v-if="!close1"
      title="Closable alert 1"
      closable
      @close="close1 = true"
    />

    <NAlert
      v-if="!close2"
      title="Closable alert 2"
      closable
      description="Lorem ipsum dolor sit amet consectetur adipisicing elit. aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum."
      @close="close2 = true"
    />
  </div>
</template>

Events

Event NameDescription
@closeemit an event when the close icon is clicked. Use in conjunction with closable.

Slots

SlotDescription
defaultCover the title and description slots.
titleThe title of the alert.
descriptionThe description of the alert.
iconThe icon of the alert.
closeIconThe close icon of the alert.

Example 1

Lorem ipsum dolor sit amet consectetur adipisicing elit. Ducimus vel optio aliquam autem dolorem enim! Quo, nesciunt deleniti. Natus quisquam quae quis quam ipsa reiciendis at alias molestiae voluptate repudiandae.

<template>
  <NAlert
    alert="outline-info"
    icon
  >
    <template #title>
      <div class="flex-1 md:flex md:justify-between space-y-3 md:space-y-0">
        <p class="text-brand">
          Lorem ipsum dolor sit amet consectetur adipisicing elit. Ducimus vel optio aliquam autem dolorem enim! Quo, nesciunt deleniti. Natus quisquam quae quis quam ipsa reiciendis at alias molestiae voluptate repudiandae.
        </p>
        <NButton
          btn="text-info"
          to="#"
          label="i-heroicons-chevron-double-right"
          icon
          class="animate-pulse p-0 md:ml-4"
        />
      </div>
    </template>
  </NAlert>
</template>

Example 2

There were some errors with your submission
  • The team name must be a string.
  • The team name must be at least 1 character.
<template>
  <NAlert alert="soft-error" icon>
    <template #title>
      There were some errors with your submission
    </template>
    <template #description>
      <ul role="list" class="list-disc pl-4.5 space-y-1">
        <li>The team name must be a string.</li>
        <li>The team name must be at least 1 character.</li>
      </ul>
    </template>
  </NAlert>
</template>

Example 3

Payment completed

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam.

<template>
  <NAlert alert="border-success" icon>
    <template #title>
      Payment completed
    </template>
    <template #description>
      <div class="text-sm text-success-700 dark:text-success-200">
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid pariatur, ipsum similique veniam.</p>
      </div>
      <div class="mt-4">
        <div class="flex -mx-2.5 -my-1.5">
          <NButton leading="i-heroicons-document-text-20-solid" btn="ghost-success" class="text-success-800 dark:text-success-100">
            View receipt
          </NButton>
          <NButton btn="ghost-success" class="text-success-800 dark:text-success-100">
            Dismiss
          </NButton>
        </div>
      </div>
    </template>
  </NAlert>
</template>

Props

export interface NAlertProps {
  /**
   * Allows you to add `UnaUI` alert preset properties,
   * Think of it as a shortcut for adding options or variants to the preset if available.
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/alert.ts
   * @example
   * alert="outline-pink"
   */
  alert?: string
  /**
   * Add icon to the alert,
   * If this is true, the icon will be automatically generated based on the color.
   * Supported colors are `info`, `success`, `warning`, and `error`
   *
   * You can customize the icon by providing the icon that you want.
   *
   * @example
   * icon="i-heroicons-information-circle"
   */
  icon?: string | boolean
  /**
   * Add a close button to the alert.
   *
   * @default false
   */
  closable?: boolean
  /**
   * Add a title to the alert.
   */
  title?: string
  /**
   * Add a description to the alert.
   */
  description?: string

  /**
   * `UnaUI` preset configuration
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/alert.ts
   */
  una?: {
    // base
    alert?: string
    alertTitle?: string
    alertDescription?: string
    alertIconBase?: string
    alertClose?: string
    alertCloseIconBase?: string

    // wrappers
    alertInnerWrapper?: string
    alertContentWrapper?: string
    alertIconWrapper?: string
    alertCloseWrapper?: string
    alertCloseInnerWrapper?: string

    // icons
    alertCloseIcon?: string
  }
}

Presets

type AlertPrefix = 'alert'

export const staticAlert: Record<`${AlertPrefix}-${string}` | AlertPrefix, string> = {
  // config
  'alert-default-variant': 'alert-outline',
  'alert-info-icon': 'i-info',
  'alert-error-icon': 'i-error',
  'alert-success-icon': 'i-success',
  'alert-warning-icon': 'i-warning',
  'alert-close-icon': 'i-close',

  // base
  'alert': 'p-1em',
  'alert-title': 'text-0.875em font-medium text-brand',
  'alert-description': 'text-0.875em leading-1.625em text-brand/90',
  'alert-icon-base': 'h-1.25em w-1.25em',
  'alert-close': 'p-0.5em rounded-md hover:bg-brand/10 active:bg-brand/20 transition-colors duration-200',
  'alert-close-icon-base': 'h-1.2em w-1.2em',

  // wrappers
  'alert-inner-wrapper': 'gap-0.75em flex',
  'alert-content-wrapper': 'flex flex-col w-full space-y-0.5em',
  'alert-icon-wrapper': '-mt-0.2em',
  'alert-close-wrapper': 'ml-auto pl-0.2em',
  'alert-close-inner-wrapper': '-mx-1.1 -my-1.1',
}

export const dynamicAlert: [RegExp, (params: RegExpExecArray) => string][] = [
  // variants
  [/^alert-soft(-(\S+))?$/, ([, , c = 'primary']) => `rounded-md bg-${c}-50 text-${c}-400 dark:text-${c}-300 dark:bg-${c}-950 n-${c}-800 dark:n-${c}-100`],
  [/^alert-outline(-(\S+))?$/, ([, , c = 'primary']) => `rounded-md border border-${c}-600 dark:border-${c}-500 text-brand n-${c}-600 dark:n-${c}-500`],
  [/^alert-border(-(\S+))?$/, ([, , c = 'primary']) => `border-l-4 border-${c}-400 dark:border-${c}-500 bg-${c}-50 dark:bg-${c}-950 text-${c}-400 dark:text-${c}-300 n-${c}-800 dark:n-${c}-100`],
]

export const alert = [
  ...dynamicAlert,
  staticAlert,
]

Component

<script setup lang="ts">
import { computed } from 'vue'
import type { NAlertProps } from '../../types'
import NIcon from '../elements/Icon.vue'
import NButton from '../elements/Button.vue'

defineOptions({
  inheritAttrs: false,
})

const props = withDefaults(defineProps<NAlertProps>(), {
  icon: false,
})

const emit = defineEmits<{ (...args: any): void }>()

const slots = defineSlots<{
  default?: any
  title?: any
  description?: any
  icon?: any
  closeIcon?: any
}>()

const alertVariants = ['soft', 'outline', 'border'] as const
const hasVariant = computed(() => alertVariants.some(alertVariants => props.alert?.includes(alertVariants)))
const isBaseVariant = computed(() => props.alert?.includes('~'))

const alertClassVariants = computed(() => {
  const icon = {
    info: 'alert-info-icon',
    success: 'alert-success-icon',
    warning: 'alert-warning-icon',
    error: 'alert-error-icon',
    default: '',
  }

  // TODO: simplify and optimize this
  const alertType = props.alert ? (props.alert.includes('info') ? 'info' : (props.alert.includes('success') ? 'success' : (props.alert.includes('warning') ? 'warning' : (props.alert.includes('error') ? 'error' : 'default')))) : 'default'

  return {
    icon: icon[alertType],
  }
})

const icon = computed(() => {
  if (props.icon === '' || props.icon === undefined || props.icon === true)
    return alertClassVariants.value.icon

  return props.icon.toString()
})
</script>

<template>
  <div
    v-bind="$attrs"
    :alert="alert"
    class="alert"
    :class="[
      { 'alert-default-variant': !hasVariant && !isBaseVariant },
      una?.alert,
    ]"
  >
    <div
      alert="inner-wrapper"
      :class="una?.alertInnerWrapper"
    >
      <div
        v-if="props.icon !== false"
        alert="icon-wrapper"
        :class="una?.alertIconWrapper"
      >
        <slot name="icon">
          <NIcon
            alert="icon-base"
            :name="icon"
            aria-hidden="true"
          />
        </slot>
      </div>

      <slot>
        <div
          alert="content-wrapper"
          :class="una?.alertContentWrapper"
        >
          <div
            v-if="slots.title || title"
            alert="title"
            :class="una?.alertTitle"
          >
            <slot name="title">
              <div>
                {{ title }}
              </div>
            </slot>
          </div>
          <div
            v-if="slots.description || description"
            alert="description"
            :class="una?.alertDescription"
          >
            <slot name="description">
              <p>
                {{ description }}
              </p>
            </slot>
          </div>
        </div>
      </slot>

      <div
        v-if="slots.closeIcon || closable"
        alert="close-wrapper"
        :class="una?.alertCloseWrapper"
      >
        <div
          alert="close-inner-wrapper"
          :class="una?.alertCloseInnerWrapper"
        >
          <NButton
            alert="close"
            :class="una?.alertClose"
            btn="~ square"
            @click="emit('close')"
          >
            <slot name="closeIcon">
              <NIcon
                :class="`${una?.alertCloseIconBase} alert-close-icon-base`"
                :name="una?.alertCloseIcon ?? 'alert-close-icon'"
                aria-hidden="true"
              />
            </slot>
          </NButton>
        </div>
      </div>
    </div>
  </div>
</template>