# Name the thing focus lands on

A code block that scrolls sideways needs a tab stop, or a keyboard user cannot
reach the rest of the line. Both of ours had one. Neither said what it was.

## Finding it by class, not by instance

The interesting move was not fixing the code block. It was asking what *else*
had the same shape. Every element in the package that renders `tabindex="0"`:

| Component | Role | Named |
| --- | --- | --- |
| `scroll-area/root` | `region` | yes, required |
| `table/container` | `region` | yes, required |
| `tabs/content` | `tabpanel` | yes |
| `context-menu/trigger` | `group` | yes |
| `code-block/body` | none | **no** |
| `carousel/content` | `group` | **no** |

Two gaps, not one. The carousel was the better find: its root names itself and
carries `aria-roledescription="carousel"`, each slide names itself and carries
`slide`, and the focusable scroll viewport between them announced a group and
nothing else.

## The worst case is the empty one

For the code block, the case that turns this from polish into a real gap is the
one with no title, no language, and copying switched off. The header is omitted
entirely, so the `figure` has no `figcaption` and therefore no name either. The
name on the body is then the only name anywhere in the subtree.

## The rule that came out of it

**The outer element carries the consumer's name; the inner scroll container
says what is inside it.** A code block's figure is named by its title, and the
body is named "Code" or "bash code". A carousel is named "Featured products" by
whoever placed it, and the viewport is named "Slides".

That is why the inner name is derived rather than required. Ask the consumer
for a second name and there are only two things they can write: the outer name
again, which is a duplicate announcement, or the default spelled out by hand.
Requiring it buys redundancy or boilerplate, never information.