# Separator

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

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.

::component-preview{name="SeparatorPreview"}
```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.

::component-anatomy
---
parts:
  - name: Separator
    required: true
    description: 'Renders a <div role="separator">.'
---
::

```vue
<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.

```vue
<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.

```vue
<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.

```vue
<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

::docs-table
---
columns:
  - label: Prop
  - label: Type
  - label: Default
rows:
  - items:
      - label: orientation
        description: 'What the separator [divides](#horizontal-and-vertical).'
      - label: '''horizontal'' | ''vertical'''
      - label: '''horizontal'''
---
::

#### Emits

None. `Separator` has no state to report.

#### Slot props

::docs-table
---
columns:
  - label: Prop
  - label: Type
rows:
  - items:
      - label: orientation
        description: Mirrors `data-orientation`.
      - label: '''horizontal'' | ''vertical'''
---
::

#### Data attributes

::data-attributes
::

#### 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.
