# Separator: Руководства

## Паттерны

### Разделитель на панели инструментов

Когда использовать:

- соседним действиям нужна ненавязчивая визуальная граница

Заметки по композиции:

- используйте `orientation='vertical'`
- задайте родителю реальную высоту

Компромиссы:

- малый визуальный вес
- зависит от размеров родителя

```tsx
import { Icon, IconButton, Separator } from '@vega-ui/react';
import { AlignCenter, AlignLeft, Bold, Italic, Link, List, ListOrdered } from '@vega-ui/icons';

export default function VerticalDividerInToolbar() {
  return (
    <div
      role='toolbar'
      aria-label='Text formatting'
      style={{
        display: 'flex',
        alignItems: 'center',
        gap: 'var(--spacing-2)',
        padding: 'var(--spacing-2)',
        border: '1px solid var(--separator-opaque)',
        borderRadius: 'var(--radius-3)',
        background: 'var(--surface-primary)',
      }}
    >
      <IconButton aria-label='Bold' variant='secondary' appearance='transparent'>
        <Icon><Bold /></Icon>
      </IconButton>
      <IconButton aria-label='Italic' variant='secondary' appearance='transparent'>
        <Icon><Italic /></Icon>
      </IconButton>
      <IconButton aria-label='Insert link' variant='secondary' appearance='transparent'>
        <Icon><Link /></Icon>
      </IconButton>
      <Separator orientation='vertical' style={{ height: 'var(--spacing-10)', marginInline: 'var(--spacing-2)' }} />
      <IconButton aria-label='Bulleted list' variant='secondary' appearance='transparent'>
        <Icon><List /></Icon>
      </IconButton>
      <IconButton aria-label='Numbered list' variant='secondary' appearance='transparent'>
        <Icon><ListOrdered /></Icon>
      </IconButton>
      <Separator orientation='vertical' style={{ height: 'var(--spacing-10)', marginInline: 'var(--spacing-2)' }} />
      <IconButton aria-label='Align left' variant='secondary' appearance='transparent'>
        <Icon><AlignLeft /></Icon>
      </IconButton>
      <IconButton aria-label='Align center' variant='secondary' appearance='transparent'>
        <Icon><AlignCenter /></Icon>
      </IconButton>
    </div>
  );
}
```

### Разрыв раздела внутри панели

Когда использовать:

- в панели есть две связанные, но разные области

Заметки по композиции:

- ставьте разделитель между областями, у которых уже есть подписи
- добавляйте отступы раскладкой, а не самим разделителем

Компромиссы:

- поверхность остаётся чистой
- не объясняет причину разделения

```tsx
import { Card, Heading, Separator, Text } from '@vega-ui/react';

export default function SectionBreakInsideAPanel() {
  return (
    <Card style={{ display: 'grid', gap: 'var(--spacing-8)', width: '100%' }}>
      <section aria-labelledby='plan-usage-title' style={{ display: 'grid', gap: 'var(--spacing-2)' }}>
        <Heading as='h3' size={4} id='plan-usage-title'>Usage this month</Heading>
        <Text size={2} style={{ color: 'var(--label-secondary)', fontVariantNumeric: 'tabular-nums' }}>7,420 of 10,000 API requests used.</Text>
      </section>
      <Separator />
      <section aria-labelledby='plan-billing-title' style={{ display: 'grid', gap: 'var(--spacing-2)' }}>
        <Heading as='h3' size={4} id='plan-billing-title'>Next invoice</Heading>
        <Text size={2} style={{ color: 'var(--label-secondary)', fontVariantNumeric: 'tabular-nums' }}>$49.00 on April 1, charged to Visa ending in 4242.</Text>
      </section>
    </Card>
  );
}
```

### Разрыв в плотной форме

Когда использовать:

- одна поверхность формы содержит несколько коротких групп

Заметки по композиции:

- используйте `Separator` вместе с явными подписями или legend
- не полагайтесь только на линию

Компромиссы:

- большие формы остаются читаемыми
- рядом всё равно нужны семантические подписи разделов

```tsx
import {
  Button,
  Fieldset,
  FieldsetLegend,
  Label,
  Separator,
  Text,
  TextField,
  TextFieldInput,
} from '@vega-ui/react';
import { useState, type FormEvent } from 'react';

export default function DividerBetweenFieldGroups() {
  const [saved, setSaved] = useState('');

  const onSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    const data = new FormData(event.currentTarget);
    setSaved(`Saved ${data.get('fullName')} <${data.get('email')}>, ${data.get('company')}`);
  };

  return (
    <form
      onSubmit={onSubmit}
      onReset={() => setSaved('')}
      style={{ display: 'grid', gap: 'var(--spacing-12)', width: '100%' }}
    >
      <Fieldset style={{ display: 'grid', gap: 'var(--spacing-8)' }}>
        <FieldsetLegend style={{ marginBlockEnd: 'var(--spacing-8)' }}>Personal details</FieldsetLegend>
        <div style={{ display: 'grid', gap: 'var(--spacing-3)' }}>
          <Label htmlFor='billing-name'>Full name</Label>
          <TextField>
            <TextFieldInput id='billing-name' name='fullName' autoComplete='name' required />
          </TextField>
        </div>
        <div style={{ display: 'grid', gap: 'var(--spacing-3)' }}>
          <Label htmlFor='billing-email'>Email</Label>
          <TextField>
            <TextFieldInput id='billing-email' name='email' type='email' autoComplete='email' required />
          </TextField>
        </div>
      </Fieldset>
      <Separator />
      <Fieldset style={{ display: 'grid', gap: 'var(--spacing-8)' }}>
        <FieldsetLegend style={{ marginBlockEnd: 'var(--spacing-8)' }}>Company</FieldsetLegend>
        <div style={{ display: 'grid', gap: 'var(--spacing-3)' }}>
          <Label htmlFor='billing-company'>Company name</Label>
          <TextField>
            <TextFieldInput id='billing-company' name='company' autoComplete='organization' />
          </TextField>
        </div>
      </Fieldset>
      <div style={{ display: 'grid', gap: 'var(--spacing-6)' }}>
        <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 'var(--spacing-4)' }}>
          <Button type='reset' variant='secondary' appearance='ghost'>Reset</Button>
          <Button type='submit'>Save</Button>
        </div>
        {saved && <Text size={2} role='status' style={{ color: 'var(--label-secondary)', overflowWrap: 'anywhere' }}>{saved}</Text>}
      </div>
    </form>
  );
}
```

## Сравнение

### Быстрое правило выбора

Используйте `Separator` для лёгкого визуального разделения. Используйте `Heading` или `Fieldset`, когда интерфейсу нужна именованная структура, а не просто линия.

### `Separator` или `Fieldset`

- Используйте `Separator` для визуального разделения.
- Используйте `Fieldset` для семантики группы полей формы.

### `Separator` или `Heading`

- Используйте `Separator`, когда видимый заголовок не нужен.
- Используйте `Heading`, когда разделу нужна семантическая подпись.

### `Separator` или `Card`

- Используйте `Separator` внутри существующей раскладки.
- Используйте `Card`, когда всему разделу нужна собственная поверхность.

### Выбирайте этот компонент, когда

- двум соседним областям нужен ненавязчивый разделитель
- семантическая группировка уже решена в другом месте

### Не выбирайте этот компонент, когда

- разделу нужна подпись
- набору контролов нужна нативная семантика группы

## Решение проблем

### Вертикальный разделитель не виден

#### Симптом

Задано `orientation='vertical'`, но разделителя не видно.

#### Вероятная причина

Родительская раскладка не задаёт высоту, которую разделитель мог бы заполнить.

#### Как проверить

- изучите высоту родительского контейнера
- временно задайте явную высоту и проверьте, появится ли разделитель

#### Решение

Задайте родителю определённую высоту или контекст растяжения, когда используете вертикальный разделитель.

### Разделитель не создаёт достаточно места

#### Симптом

Содержимое по-прежнему выглядит тесным, хотя разделитель есть.

#### Вероятная причина

`Separator` только рисует линию и не управляет отступами раскладки.

#### Как проверить

- изучите значения gap, margin или padding вокруг

#### Решение

Добавьте отступы в родительской раскладке, а за разделителем оставьте только визуальное разделение.

### Разделители есть, но структуры всё равно не хватает

#### Симптом

Разделы визуально разделены, но пользователи не понимают, что означает каждый из них.

#### Вероятная причина

Разделители используются там, где структуру должны задавать заголовки или legend формы.

#### Как проверить

- мысленно уберите линии и проверьте, остаётся ли смысл разделов понятным

#### Решение

Добавьте `Heading`, `Label` или `FieldsetLegend` там, где нужна семантическая подпись.
