Skip to content

Separator

A dividing line between two groups of content, announced as one.

View source View as Markdown

Separator is the line you draw between two groups of content, rendered as a role="separator" so a screen reader announces the division too. Useful between the sections of a settings page, or between the actions in a toolbar, where a bare border would show the division to sighted readers only.

A separator takes no space of its own, so give it a size on the axis it divides.

A vertical one needs a height as well, which in a flex row is usually self-stretch.

App.vue
<template>
  <div class="flex w-full max-w-md flex-col gap-6">
    <div class="flex items-center gap-2" role="group" aria-label="Document">
      <Button v-for="action in actions" :key="action" :class="button">
        {{ action }}
      </Button>

      <Separator orientation="vertical" :class="vertical" />

      <Button :class="button">Delete</Button>
    </div>

    <div class="flex flex-col gap-4">
      <p class="type-surface-body-sm text-surface-muted">
        A separator takes no space of its own, so give it a size on the axis it
        divides.
      </p>

      <Separator :class="horizontal" />

      <p class="type-surface-body-sm text-surface-muted">
        A vertical one needs a height as well, which in a flex row is usually
        <code>self-stretch</code>.
      </p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { Button, Separator } from '@maas/mirror/vue'

const actions = ['Edit', 'Duplicate', 'Share']

const button = [
  'rounded-component-md border-surface border px-2.5 py-1',
  'type-component-xs text-surface-muted hover:text-surface',
  'transition-all duration-100 ease-linear',
  'outline-4 outline-transparent focus-visible:focus-ring',
].join(' ')

const vertical = 'bg-surface-higher w-px self-stretch'

const horizontal = 'bg-surface-higher h-px w-full'
</script>

Usage guidelines

  • Separator ships no CSS at all, so it is invisible until you give it a size and a colour. A one-pixel background on the axis it divides is the usual recipe.
  • A vertical separator has no height in a flex row until it gets one, either from align-self: stretch or from an explicit size.
  • Use it where the division carries meaning. A line that is only decoration is better off as a border on the element next to it, since that keeps it out of the accessibility tree.

Anatomy

Render it on its own.

NameRequiredDescription
Separator true Renders a <div role="separator">.
<script setup lang="ts">
import { Separator } from '@maas/mirror/vue'
</script>

<template>
  <Separator />
</template>

Examples

Horizontal and vertical

orientation decides what the separator divides, and is written to the element as data-orientation, which is what you size it from.

<template>
  <Separator class="separator" />

  <Separator orientation="vertical" class="separator" />
</template>

<style>
.separator {
  background: var(--app-color-surface-bg-higher);
}

.separator[data-orientation='horizontal'] {
  block-size: 1px;
  inline-size: 100%;
}

.separator[data-orientation='vertical'] {
  align-self: stretch;
  inline-size: 1px;
}
</style>

In a toolbar

Grouped actions read as groups once a separator sits between them, both on screen and out loud.

<template>
  <div role="group" aria-label="Document">
    <Button>Edit</Button>
    <Button>Duplicate</Button>

    <Separator orientation="vertical" class="separator" />

    <Button>Delete</Button>
  </div>
</template>

As another element

asChild hands the role and the data attribute to the element you render, which is how a separator becomes an <hr> or a list item.

<template>
  <Separator as-child>
    <hr class="separator" />
  </Separator>

  <ul>
    <li>Duplicate</li>

    <Separator as-child>
      <li role="separator" class="separator" />
    </Separator>

    <li>Delete</li>
  </ul>
</template>

API reference

Standalone. Ordinary props, no store, no context. Separator takes no part in a Field.

Separator

Renders a <div role="separator">.

Props

PropTypeDefault
orientation
'horizontal' | 'vertical''horizontal'

Emits

None. Separator has no state to report.

Slot props

PropType
orientation
'horizontal' | 'vertical'

Data attributes

AttributeValue
data-orientation
horizontal | vertical

CSS variables

None. A separator has no functional CSS, so its whole appearance is yours.

Errors

None. Separator has no context and no required prop.

Accessibility

The rendered element is a role="separator" that never takes focus, so it carries no keyboard interaction.

A horizontal separator is the default in ARIA, so aria-orientation is only written when the separator is vertical. Screen readers announce the division either way.

A role="separator" that takes focus is a splitter. Separator never takes focus, so build a splitter yourself where you need one.