# Needs you line

One line at the top of a home page that says what waits on this person in this scope: "3 things need you" with a Review link, "Nothing needs you right now" only when the count is known and zero, and "Couldn't check what needs you" with the reason and Retry when it couldn't be read. Each state has its icon and tone beside its words.

Pass the same count you give the navigation's urgent badge (a `NavItem`'s `count` with `urgent`, in `AppSidebar` or the rail), read from the same source and scoped the same way, so the line and the badge never disagree. Put the app's own words after it with `after` ("Here's what happened since yesterday").

When Retry is pressed and the count arrives, Retry leaves the page; if Retry still had focus, focus moves to the line, never to the page's body. If the person had moved on (to another control, or by clicking elsewhere), focus stays where they put it and the new sentence is announced instead.

- Registry name: `needs-you-line` (`@candor/needs-you-line`)
- 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/needs-you-line

## Install

```bash
npx candor-ui add needs-you-line
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/needs-you-line`.
It brings in: link, locale, motion, tokens, use-announcer, utils.
npm packages: lucide-react@^1.67.0.

## Example

```tsx
"use client"

import * as React from "react"
import { Badge } from "@/components/candor/ui/badge"
import { NeedsYouLine } from "@/components/candor/needs-you-line"

export default function Example() {
  // One count, read once, scoped to the workspace on screen: the line says it and the navigation's urgent badge shows
  // it (here a badge; in the app, the `count` of the Approvals place, with `urgent`).
  const [waiting, setWaiting] = React.useState<number | null>(null)
  return (
    <div className="flex flex-col gap-4">
      <div className="flex items-center gap-2 text-sm">
        <span>Approvals</span>
        {waiting !== null && waiting > 0 && <Badge>{waiting}</Badge>}
      </div>
      <NeedsYouLine
        count={waiting}
        href="#approvals"
        reason="The approvals service didn’t answer."
        onRetry={() => setWaiting(3)}
        after="Here’s what happened since yesterday."
      />
      <NeedsYouLine count={0} after="Here’s what happened since yesterday." />
    </div>
  )
}
```

## <NeedsYouLine>

Props:

- `count: number | null`: How many things wait on this person in this scope: the number the navigation's urgent badge shows. `null` when it couldn't be checked.
- `href?: string | undefined`: Where those things are: "Review" is a link there.
- `onOpen?: (() => void) | undefined`: Opens those things, when they aren't at an address: "Review" is a button. `href` wins when both are given.
- `reason?: string | undefined`: Why the count couldn't be checked, shown after the sentence when `count` is null.
- `onRetry?: (() => void) | undefined`: Tries the check again; shown as Retry when `count` is null.
- `after?: string | undefined`: The app's words after the sentence: "Here's what happened since yesterday".
- `className?: string | undefined`

## Strings (`needsYouLine`)

The fixed words, English by default. Override any of them under `needsYouLine` in `<LocaleProvider strings={{ needsYouLine: { … } }}>`; the table is exported as `needsYouLineStrings`.

- `nothing`: Nothing needs you right now
- `some`: { one: "{count} thing needs you", other: "{count} things need you" }
- `unknown`: Couldn’t check what needs you
- `review`: Review
- `retry`: Retry

## Motion

- **count** (value, fade): When the count changes while the line is on screen (a new count arrives, or a check that failed succeeds), the sentence crossfades to the new one. A line that mounts with its count draws it still, and the change isn't announced: the navigation's badge and the notifications carry news.

Set with `--cd-motion-needs-you-line-<moment>-*` in your brand file; the families are in the design reference.

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