# Heading scope

Says the content inside sits under a heading of `level`, so each Candor item in it draws its heading one level below (`level + 1`) unless it is given `headingLevel`. Put it round a section the app titles itself:

```tsx
<section aria-labelledby="usage">
  <h2 id="usage">Usage</h2>
  <HeadingScope level={2}>
    <DetailsList … />   // draws its title as <h3>
  </HeadingScope>
</section>
```

Candor's dialogs, sheets, drawers, settings sections and dashboard tiles set one round their content themselves. A scope inside another replaces it; it doesn't add to it.

- Registry name: `heading-scope` (`@candor/heading-scope`)
- 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/heading-scope

## Install

```bash
npx candor-ui add heading-scope
```

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

## Example

```tsx
"use client"

import type { HeadingLevel } from "@/lib/candor/heading-level"
import { HeadingScope, belowLevel, useHeadingLevel } from "@/lib/candor/heading-scope"
import { Heading } from "@/components/candor/heading"

/** A card as Candor's items draw one: its title at the level the scope gives, its sections one below. */
function UsageCard({ title, sections, headingLevel }: { title: string; sections: string[]; headingLevel?: HeadingLevel | undefined }) {
  const level = useHeadingLevel(headingLevel)
  return (
    <div className="flex flex-col gap-2 rounded-lg border p-4">
      <Heading level={level} size="base">
        {title} <span className="font-normal text-muted-foreground">(h{level})</span>
      </Heading>
      {sections.map((s) => (
        <Heading key={s} level={belowLevel(level)} size="sm">
          {s} <span className="font-normal text-muted-foreground">(h{belowLevel(level)})</span>
        </Heading>
      ))}
    </div>
  )
}

export default function Example() {
  return (
    <section aria-labelledby="usage-heading" className="flex flex-col gap-3">
      <Heading id="usage-heading" level={2} size="lg">
        Usage <span className="font-normal text-muted-foreground">(h2)</span>
      </Heading>
      <HeadingScope level={2}>
        <div className="grid gap-3 sm:grid-cols-2">
          <UsageCard title="This month" sections={["Runs", "Spend"]} />
          <UsageCard title="Last month" sections={["Runs", "Spend"]} />
        </div>
      </HeadingScope>
    </section>
  )
}
```

## <HeadingScope>

Props:

- `level: HeadingLevel`: The level of the heading the content sits under: `2` when the section's own heading is an `<h2>`.
- `children?: React.ReactNode | undefined`: The content under that heading.

## Functions

### useHeadingLevel

```ts
useHeadingLevel(headingLevel?: HeadingLevel | undefined)
```

The level an item draws its top heading at: `headingLevel` when given; else one below the nearest `HeadingScope`; else 2. Never deeper than 6.

```tsx
function Summary({ title, headingLevel }: { title: string; headingLevel?: HeadingLevel | undefined }) {
  const level = useHeadingLevel(headingLevel)
  const Tag = `h${level}` as const
  return <Tag className="text-base font-semibold">{title}</Tag>
}
```

### belowLevel

```ts
belowLevel(level: HeadingLevel, n: number = 1)
```

The level `n` steps below `level` (one by default), for the headings an item draws under its own top heading. Never deeper than 6. `belowLevel(useHeadingLevel(headingLevel))` is the level of a card's title inside a list.

## Types from other items

The props above take these. Each is defined by another item; import it from the path shown.

### HeadingLevel

Import: `import type { HeadingLevel } from "@/lib/candor/heading-level"` (item `heading-level`, https://candor.themethodic.com/docs/heading-level.md)

A heading's level in the page's outline: `1` is `<h1>`, `6` is `<h6>`. Every Candor item that draws a heading takes its `headingLevel` as this type; the level is where the heading sits in the outline, never how large it looks.

```ts
1 | 2 | 3 | 4 | 5 | 6
```

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