# Separator

> Small layout primitives.

Component · Foundations · Halo kit · [Live page](https://ui.twentyfirst.media/halo/components/Separator/)

Small layout primitives.

- **Separator**: a hairline between groups, horizontal or vertical, optionally with a label in the middle ("or").
- **Label**: the field label on its own, with a required mark or a muted hint ("optional").
- **AspectRatio**: a box that keeps its ratio (16 : 9 by default) for images, video and placeholders.

## Example

```tsx
import * as React from "react";
import { AspectRatio, Button, Input, Label, Separator } from "@twentyfirstmedia/halo";

export default function Preview() {
  return (
    <div
      className="tf-grid"
      style={{ "--cols": "1fr 1fr", gap: 24, alignItems: "start" } as React.CSSProperties}
    >
      <div className="tf-panel" style={{ gap: 16 }}>
        <div className="tf-col" style={{ gap: 8 }}>
          <Label htmlFor="sep-mail" required>
            Work email
          </Label>
          <Input id="sep-mail" placeholder="you@company.com" />
        </div>
        <div className="tf-col" style={{ gap: 8 }}>
          <Label htmlFor="sep-team" hint="optional">
            Team name
          </Label>
          <Input id="sep-team" placeholder="Design" />
        </div>
        <Separator label="or" />
        <Button variant="secondary" icon="globe">
          Continue with Google
        </Button>
        <div className="tf-row" style={{ gap: 12, alignItems: "center", flexWrap: "nowrap" }}>
          <span className="tf-card-desc">Docs</span>
          <Separator orientation="vertical" />
          <span className="tf-card-desc">Status</span>
          <Separator orientation="vertical" />
          <span className="tf-card-desc">Changelog</span>
        </div>
      </div>
      <div className="tf-panel" style={{ gap: 12 }}>
        <AspectRatio ratio={16 / 9}>
          <div
            className="tf-gallery-ph tf-t-sky"
            style={{ height: "100%", display: "grid", placeItems: "center" }}
          >
            16 : 9
          </div>
        </AspectRatio>
        <div
          className="tf-grid"
          style={{ "--cols": "1fr 1fr", "--cols-sm": "1fr 1fr", gap: 12 } as React.CSSProperties}
        >
          <AspectRatio ratio={1}>
            <div
              className="tf-gallery-ph tf-t-mint"
              style={{ height: "100%", display: "grid", placeItems: "center" }}
            >
              1 : 1
            </div>
          </AspectRatio>
          <AspectRatio ratio={4 / 5}>
            <div
              className="tf-gallery-ph tf-t-butter"
              style={{ height: "100%", display: "grid", placeItems: "center" }}
            >
              4 : 5
            </div>
          </AspectRatio>
        </div>
      </div>
    </div>
  );
}
```

## Props

### Separator

| Prop | Type | Notes |
| --- | --- | --- |
| `orientation?` | `"horizontal" \| "vertical"` |  |
| `label?` | `string` | Text in the middle of the line ("or"). |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### Label

| Prop | Type | Notes |
| --- | --- | --- |
| `htmlFor?` | `string` |  |
| `required?` | `boolean` |  |
| `hint?` | `ReactNode` | Muted text after the label ("optional"). |
| `children?` | `ReactNode` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### AspectRatio

| Prop | Type | Notes |
| --- | --- | --- |
| `ratio?` | `number` | Width divided by height (default 16 / 9). |
| `children?` | `ReactNode` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### Input

| Prop | Type | Notes |
| --- | --- | --- |
| `type?` | `string` |  |
| `placeholder?` | `string` |  |
| `value?` | `string` |  |
| `defaultValue?` | `string` |  |
| `disabled?` | `boolean` |  |
| `onChange?` | `(e: ChangeEvent<HTMLInputElement>) => void` |  |
| `label?` | `string` |  |
| `hint?` | `string` |  |
| `error?` | `string` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### Button

| Prop | Type | Notes |
| --- | --- | --- |
| `variant?` | `"primary" \| "secondary" \| "soft" \| "ghost" \| "danger" \| "danger-solid"` |  |
| `size?` | `"md" \| "sm"` |  |
| `icon?` | `IconName` |  |
| `iconRight?` | `IconName` |  |
| `disabled?` | `boolean` |  |
| `type?` | `"button" \| "submit" \| "reset"` |  |
| `onClick?` | `(e: MouseEvent<HTMLButtonElement>) => void` |  |
| `children?` | `ReactNode` |  |
| `asChild?` | `boolean` | Render the single child element (a link, a router Link) with the button's look instead of a <button>. |
| `id?` | `string` |  |
| `name?` | `string` | Form field name and value, sent with the form when this button submits it. |
| `value?` | `string` |  |
| `form?` | `string` | The id of the form this button belongs to, when it sits outside it. |
| `title?` | `string` |  |
| `tabIndex?` | `number` |  |
| `autoFocus?` | `boolean` |  |
| `aria-label?` | `string` |  |
| `aria-labelledby?` | `string` |  |
| `aria-describedby?` | `string` |  |
| `aria-expanded?` | `boolean \| "true" \| "false"` | For disclosure and menu triggers: whether what the button controls is open. |
| `aria-controls?` | `string` |  |
| `aria-haspopup?` | `boolean \| "true" \| "false" \| "menu" \| "listbox" \| "tree" \| "grid" \| "dialog"` |  |
| `aria-pressed?` | `boolean \| "true" \| "false" \| "mixed"` | For toggle buttons. |
| `aria-current?` | `boolean \| "true" \| "false" \| "page" \| "step" \| "location" \| "date" \| "time"` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |
