๐ŸŸข Separator


Basic

NSeparator - used to separate the content.

<template>
  <NSeparator label="OR" class="mx-2" />
</template>

Variant

separator="{variant}" - change the variant of the separator.

TypeDescription
solidThe default variant.
dashedThe dashed variant.
dottedThe dotted variant.
<template>
  <div>
    <NSeparator separator="solid" label="Solid" />
    <NSeparator separator="dashed" label="Dashed" />
    <NSeparator separator="dotted" label="Dotted" />
  </div>
</template>

Color

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

You can use any color provided by the Tailwind CSS color palette, the default is gray. You can also add your own colors to the palette through the Configuration section.
<template>
  <NSeparator
    separator="solid-error"
    label="Warning Area"
  />
  <NSeparator
    separator="dashed-success"
    label="Success Green"
  />
  <NSeparator
    separator="dotted-warning"
    label="Dotted Yellow"
  />
</template>

Orientation

orientation="{value}" - change the orientation of the separator's direction.

ValueDescription
horizontalThe default direction.
verticalThe vertical direction.
<script setup lang="ts">
const icons1 = ref([
  { _id: '0', name: 'i-heroicons-bold-solid', value: true },
  { _id: '1', name: 'i-heroicons-italic-solid', value: false },
  { _id: '2', name: 'i-heroicons:underline-20-solid', value: true },
  { _id: '3', name: 'i-heroicons-strikethrough-20-solid', value: false },
])
const icons2 = ref([
  { _id: '0', name: 'i-heroicons-list-bullet-16-solid', value: true },
  { _id: '1', name: 'i-heroicons-numbered-list', value: false },
])
const icons3 = ref([
  { _id: '0', name: 'i-heroicons-link-solid', value: true },
  { _id: '1', name: 'i-heroicons-code-bracket-16-solid', value: false },
])

const textarea = ref('')
</script>

<template>
  <div class="mb-6 h-5 flex items-center gap-1">
    <NButton
      v-for="icon in icons1"
      :key="icon._id"
      :btn="`${icon.value ? 'soft-gray' : 'text-gray'} square`"
      icon
      :label="icon.name"
      @click="icon.value = !icon.value"
    />

    <NSeparator orientation="vertical" class="mx-2" />

    <NButton
      v-for="icon in icons2"
      :key="icon._id"
      :btn="`${icon.value ? 'soft-gray' : 'text-gray'} square`"
      icon
      :label="icon.name"
      @click="icon.value = !icon.value"
    />

    <NSeparator orientation="vertical" class="mx-2" />

    <NButton
      v-for="icon in icons3"
      :key="icon._id"
      :btn="`${icon.value ? 'soft-gray' : 'text-gray'} square`"
      icon
      :label="icon.name"
      @click="icon.value = !icon.value"
    />
  </div>
  <div class="flex flex-col">
    <NInput
      v-model="textarea"
      type="textarea"
      placeholder="Type something..."
    />

    <NSeparator class="my-10">
      <NAvatar src="/images/avatar.png" alt="Phojie Rengel" />
    </NSeparator>
  </div>
</template>

Position

separator-position="{value}" - change the position of the label content.

PositionOrientationDescription
centerhorizontal verticalThe default position.
lefthorizontalThe left position.
rightverticalThe right position.
tophorizontalThe top position.
bottomverticalThe bottom position.
<template>
  <div class="py-10 space-y-10">
    <NSeparator separator-position="right">
      <NAvatar
        size="lg"
        src="https://avatars.githubusercontent.com/u/28706372?v=4"
      />
    </NSeparator>
    <NSeparator separator-position="center">
      <NAvatar
        size="lg"
        src="https://avatars.githubusercontent.com/u/499550?v=4"
      />
    </NSeparator>
    <NSeparator separator-position="left">
      <NAvatar
        size="lg"
        src="https://avatars.githubusercontent.com/u/11247099?v=4"
      />
    </NSeparator>
  </div>
</template>

Size

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

๐Ÿš€ You can freely adjust the size of the separator 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 and font-size of the separator scale depends on the size. If you want to change the font-size and padding simultaneously, you can always customize it using utility classes.
<template>
  <div>
    <NSeparator
      separator="solid"
      size="4xl"
    />
    <NSeparator
      separator="dashed"
      size="40px"
    />
    <NSeparator
      separator="dotted"
      size="9xl"
    />
  </div>
</template>

Props

import type { SeparatorProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'

type Extensions = SeparatorProps & { class?: HTMLAttributes['class'], label?: string }

export interface NSeparatorProps extends Extensions {
  /**
   * Allows you to add `UnaUI` separator 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/separator.ts
   * @example
   * separator="solid-green"
   */
  separator?: string
  /**
   * Allows you to change the orientation and position of the separator.
   *
   * @default horizontal-center
   */
  separatorPosition?: HTMLAttributes['class']
  /**
   * Allows you to change the size of the separator.
   *
   * @default md
   *
   * @example
   * size="sm" | size="2cm" | size="2rem" | size="2px"
   */
  size?: string
  /**
   * `UnaUI` preset configuration
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/separator.ts
   */
  una?: {
    separator?: HTMLAttributes['class']
    separatorContent?: HTMLAttributes['class']

    separatorDefaultVariant?: HTMLAttributes['class']
  }
}

Presets

type SeparatorPrefix = 'separator'

export const staticSeparator: Record<`${SeparatorPrefix}-${string}` | SeparatorPrefix, string> = {
  // base
  'separator': 'text-md shrink-0 relative',
  'separator-default-variant': 'separator-solid-gray',
  'separator-content': 'text-0.75em text-muted bg-base absolute flex justify-center items-center',

  // orientation states
  'separator-horizontal': 'h-px my-4 w-full border-t-0.0625em',
  'separator-vertical': 'w-px mx-4 h-full border-l-0.0625em',
  'separator-content-horizontal': 'h-1px py-1 px-2',
  'separator-content-vertical': 'w-1px px-1 py-2',

  // horizontal positions
  'separator-position-left': 'left-6 top-1/2 -translate-y-1/2',
  'separator-position-right': 'right-6 top-1/2 -translate-y-1/2',
  'separator-position-center': 'left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2',

  // vertical positions
  'separator-position-bottom': 'bottom-4 left-1/2 -translate-x-1/2',
  'separator-position-top': 'top-4 left-1/2 -translate-x-1/2',

  // static variants
  'separator-solid-gray': 'border-base',
}

export const dynamicSeparator = [
  // dynamic variants
  [/^separator-solid(-(\S+))?$/, ([, , c = 'gray']) => `border-solid border-${c}-200 dark:border-${c}-700/58`],
  [/^separator-dashed(-(\S+))?$/, ([, , c = 'gray']) => `border-dashed border-${c}-200 dark:border-${c}-700/58`],
  [/^separator-dotted(-(\S+))?$/, ([, , c = 'gray']) => `border-dotted border-${c}-200 dark:border-${c}-700/58`],
]

export const separator = [
  ...dynamicSeparator,
  staticSeparator,
]

Component

<script setup lang="ts">
import type { NSeparatorProps } from '../../types'
import { Separator } from 'radix-vue'
import { computed } from 'vue'
import { cn, omitProps } from '../../utils'

const props = withDefaults(defineProps<NSeparatorProps>(), {
  orientation: 'horizontal',
})

const delegatedProps = computed(() => {
  const { class: _, ...delegated } = omitProps(props, ['una'])

  return delegated
})
</script>

<template>
  <Separator
    v-bind="omitProps(delegatedProps, ['una', 'separatorPosition'])"
    :class="
      cn(
        'separator',
        props.una?.separatorDefaultVariant || 'separator-default-variant',
        props.class,
        props.una?.separator,
        props.orientation === 'vertical' ? 'separator-vertical' : 'separator-horizontal',
      )
    "
  >
    <span
      v-if="props.label || $slots.default"
      :separator-position="props.separatorPosition || 'center'"
      :class="cn(
        'separator-content',
        props.una?.separatorContent,
        props.orientation === 'vertical' ? 'separator-content-vertical' : 'separator-content-horizontal',
      )"
    >
      <slot>
        {{ props.label }}
      </slot>
    </span>
  </Separator>
</template>