# useAutoDensity

The value for `data-density` on the app's root (or any container): `"spacious"` or `"compact"`, or `undefined` for the default density. With `"auto"` (the default), a coarse primary pointer (a finger on a phone or tablet) gives `"spacious"`, so controls are big enough to touch, and a fine one gives the default; it follows the pointer when it changes, as when a tablet's keyboard and trackpad are attached. Any other choice is the person's and wins over the pointer, so offer the choice in your settings with "Automatic" first.

On the server and while the page hydrates it returns `undefined` (the default density), so the server's markup and the first render agree; the pointer is read just after. `window` isn't touched when the module is imported.

```tsx
const density = useAutoDensity(settings.density)
return <div data-density={density}>…</div>
```

- Registry name: `use-auto-density` (`@candor/use-auto-density`)
- 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/use-auto-density

## Install

```bash
npx candor-ui add use-auto-density
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/use-auto-density`.
It brings in: tokens.

## Example

```tsx
"use client"

import * as React from "react"
import { useAutoDensity } from "@/lib/candor/use-auto-density"
import { ToggleGroup, ToggleGroupItem } from "@/components/candor/ui/toggle-group"
import { TooltipProvider } from "@/components/candor/ui/tooltip"
import { Button } from "@/components/candor/ui/button"

type Choice = "auto" | "compact" | "default" | "spacious"
const choices: readonly Choice[] = ["auto", "compact", "default", "spacious"]
const isChoice = (value: string): value is Choice => (choices as readonly string[]).includes(value)

export default function Example() {
  // The person's setting, kept with their other preferences. "Automatic" follows the pointer: spacious for a finger.
  const [choice, setChoice] = React.useState<Choice>("auto")
  const density = useAutoDensity(choice)
  return (
    <TooltipProvider>
      {/* In an app, data-density goes on the root (<html> or the layout's outer element). */}
      <div data-density={density} className="flex flex-col items-start gap-4">
        <ToggleGroup type="single" variant="outline" value={choice} onValueChange={(value) => isChoice(value) && setChoice(value)} aria-label="Density">
          <ToggleGroupItem value="auto">Automatic</ToggleGroupItem>
          <ToggleGroupItem value="compact">Compact</ToggleGroupItem>
          <ToggleGroupItem value="default">Default</ToggleGroupItem>
          <ToggleGroupItem value="spacious">Spacious</ToggleGroupItem>
        </ToggleGroup>
        <div className="flex gap-2">
          <Button size="sm">Approve</Button>
          <Button size="sm" variant="outline">
            Ask for changes
          </Button>
        </div>
        <p className="text-xs text-muted-foreground">Density now: {density ?? "default"}</p>
      </div>
    </TooltipProvider>
  )
}
```

## Functions

### useAutoDensity

```ts
useAutoDensity(choice: "auto" | "compact" | "default" | "spacious" | undefined = "auto")
```

## 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`.
