# VisuallyHidden

> Package `@umriss-ui/core`, version 0.40.0. Demo page: <https://romanhaendler.github.io/umriss-ui/core/visuallyhidden/>. Every page in one line: [llms.txt](https://romanhaendler.github.io/umriss-ui/core/llms.txt); every page in full: [llms-full.txt](https://romanhaendler.github.io/umriss-ui/core/llms-full.txt).

Text a screen reader announces but the eye does not see (also called screen-reader-only or sr-only). Reach for it when a visible label is clear from its surroundings but not on its own, and for a skip link.

```ts
import { VisuallyHidden, announce } from "@umriss-ui/core";
```

Demo page: https://romanhaendler.github.io/umriss-ui/core/visuallyhidden/

## Examples

### Complete a label

The eye reads "Acknowledge" beside the incident; a screen reader hears which one.

```tsx
import { Button, VisuallyHidden } from "@umriss-ui/core";

export default function CompleteALabel() {
  return (
    <Button size="sm">
      Acknowledge
      <VisuallyHidden> incident INC-1048</VisuallyHidden>
    </Button>
  );
}
```

### Add a skip link

Render it as a link with `focusable`: it is the first Tab stop on the page and shows itself only while it has focus.

```tsx
import { Stack, Text, VisuallyHidden } from "@umriss-ui/core";

export default function SkipLink() {
  return (
    <Stack gap={2} align="flex-start">
      <VisuallyHidden as="a" href="#shipments" focusable>
        Skip to the shipment list
      </VisuallyHidden>
      <Text size="sm" tone="secondary">
        Tab into this example: the link appears above this line.
      </Text>
    </Stack>
  );
}
```

### Name the same action in every row

Twenty "Edit budget" buttons sound alike to a screen reader; append each row's name hidden and each says what it edits.

```tsx
import { Button, Stack, Text, VisuallyHidden } from "@umriss-ui/core";

/* Data from the controlling world, written out here so the example runs on its own. */
interface CostCentre {
  id: string;
  name: string;
  owner: string;
  /** The budget of one month. */
  monthlyBudget: number;
}

const COST_CENTRES: readonly CostCentre[] = [
  { id: "CC-1100", name: "Sales", owner: "Helen Marsh", monthlyBudget: 142_000 },
  { id: "CC-1200", name: "Marketing", owner: "Rafael Ortiz", monthlyBudget: 68_000 },
  { id: "CC-2100", name: "Engineering", owner: "Anika Sørensen", monthlyBudget: 188_000 },
  { id: "CC-2200", name: "Design", owner: "Paul Whitaker", monthlyBudget: 54_000 },
  { id: "CC-3100", name: "Customer service", owner: "Grace Obi", monthlyBudget: 61_000 },
  { id: "CC-4100", name: "Finance", owner: "Martina Vogel", monthlyBudget: 47_000 },
  { id: "CC-4200", name: "People", owner: "Daniel Frost", monthlyBudget: 39_000 },
  { id: "CC-4300", name: "IT", owner: "Kenji Arai", monthlyBudget: 83_000 },
  { id: "CC-4400", name: "Facilities", owner: "Olga Ivanova", monthlyBudget: 72_000 },
];

export default function ActionsInRows() {
  return (
    <Stack gap={2} style={{ maxWidth: 420 }}>
      {COST_CENTRES.slice(0, 4).map((centre) => (
        <Stack key={centre.id} direction="row" gap={3} align="center" justify="space-between">
          <Text size="sm">
            {centre.name} <Text as="span" size="xs" tone="muted">{centre.owner}</Text>
          </Text>
          <Button size="sm" variant="ghost">
            Edit budget
            <VisuallyHidden> of {centre.name}</VisuallyHidden>
          </Button>
        </Stack>
      ))}
    </Stack>
  );
}
```

## When to use something else

- A hint every user should be able to see → Tooltip
- A button that shows only an icon → IconButton

## Keyboard

| Key | Action |
|---|---|
| `Tab` | Reaches a `focusable` one and shows it while it has focus. |

## API

### `VisuallyHiddenProps<E extends ElementType = "span">`

| Prop | Type | Default | Description |
|---|---|---|---|
| `as` | `E` | `"span"` | Element to render as.<br>Shown in: [Add a skip link](https://romanhaendler.github.io/umriss-ui/core/visuallyhidden/#skip-link) |
| `focusable` | `boolean` | `false` | Becomes visible as soon as the content receives the focus (skip link).<br>Shown in: [Add a skip link](https://romanhaendler.github.io/umriss-ui/core/visuallyhidden/#skip-link) |
| `ref` | `Ref<HTMLElement>` | — | Receives the component's root element. From `RefProp`.<br>Shown in: [A row that holds still (Sizes)](https://romanhaendler.github.io/umriss-ui/core/sizes/#a-row-that-holds-still), [An anchored surface (Popover)](https://romanhaendler.github.io/umriss-ui/core/popover/#anchored-surface), [Take the width of the trigger (Popover)](https://romanhaendler.github.io/umriss-ui/core/popover/#width-from-anchor) and 2 more |

Also takes every attribute of the chosen element – without `as`, `ref`.

## Known limits

- It hides from the eye only; to hide something from everyone, do not render it.

What umriss deliberately does not build, and why: [ADR-0032](https://romanhaendler.github.io/umriss-ui/what-umriss-ui-is-not/).
