# Visually hidden

Words for screen readers only: the name of a button drawn as an icon, or the rest of a sentence the page says by layout. They stay in the page and are read in place; nothing is drawn. With `focusable`, the content shows while it or something inside it has keyboard focus, which is how a skip link works.

- Registry name: `visually-hidden` (`@candor/visually-hidden`)
- Tier: Pro. Installing it needs a Pro, Premium or Team licence key: the person runs `npx candor-ui key <key>` themselves; never ask for the key in chat or write it to a file.
- Docs: https://candor.themethodic.com/docs/visually-hidden

## Install

```bash
npx candor-ui add visually-hidden
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/visually-hidden`.
It brings in: tokens, utils.
npm packages: @base-ui/react@^1.9.0.

## Example

```tsx
"use client"

import { X } from "lucide-react"
import { VisuallyHidden } from "@/components/candor/visually-hidden"
import { Button } from "@/components/candor/ui/button"

// An icon button named for screen readers, and a skip link that shows when it takes focus (press Tab).
export default function Example() {
  return (
    <div className="flex items-center gap-4">
      {/* oxlint-disable-next-line jsx-a11y/control-has-associated-label -- the words are the children */}
      <VisuallyHidden focusable render={<a href="#example-main" className="rounded-md bg-card px-3 py-2 text-sm shadow-raised" />}>
        Skip to content
      </VisuallyHidden>
      <Button variant="outline" size="icon">
        <X aria-hidden />
        <VisuallyHidden>Close the panel</VisuallyHidden>
      </Button>
      <p id="example-main" className="text-sm text-muted-foreground">
        Content
      </p>
    </div>
  )
}
```

## <VisuallyHidden>

Props:

- `focusable?: boolean | undefined` (default `false`): Shows the content while it, or a link or button inside it, has focus, so a keyboard user sees where they are: a "Skip to content" link. Without it, focusable content inside would be focused while unseen.
- `render?: useRender.RenderProp | undefined`: The element to draw instead of a `<span>`: `render={<a href="#main" />}` for a skip link.
- `className?: string | undefined`: Classes for the element, applied last; with `focusable`, style how it looks while shown.
- `children?: React.ReactNode | undefined`: The words to read out.

Also takes the props of `React.ComponentProps<"span">`.

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider`: its fixed strings in `strings`, its nouns in `nouns`; entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
