# useDocyrusAdaptiveCardItemDetail URL: /docs/web/hooks/use-docyrus-adaptive-card-item-detail Generate an Adaptive Card JSON payload from a Docyrus field list + a single record — mapping Docyrus field types onto the Adaptive Cards element vocabulary — and render it with the shared AdaptiveCard renderer. ## Installation ```bash pnpm dlx @docyrus/cli add @docyrus/hooks-use-docyrus-adaptive-card-item-detail ``` **Dependencies:** - [react](https://react.dev) ## Overview `useDocyrusAdaptiveCardItemDetail` is the bridge between **Docyrus field types** (`field-select`, `field-money`, `field-image`, …) and the **Adaptive Cards** element vocabulary (`TextBlock`, `FactSet`, `Image`, `Badge`, `CodeBlock`, …). You hand it a field list + one record and it **generates an Adaptive Card JSON payload** (`card`) — the primary output. The card is then drawn by the shared [`AdaptiveCard`](/docs/web/components/adaptive-card) renderer; the hook also returns a ready-to-render `view` and the full [`useAdaptiveCard`](/docs/web/hooks/use-adaptive-card) runtime (state / controls / `cardProps`) so you can wire actions. It is **backend-agnostic** — no network I/O. Pass any Docyrus-shaped field list (`IField[]`, `DataSourceField[]`, or the loose `DocyrusAdaptiveCardField[]`) and a plain record object. When a [`DocyrusTenantProvider`](/docs/web/hooks/use-docyrus-tenant) is mounted, date / number / currency values are formatted with the tenant's preferences automatically. ## Usage ### Generate + render a detail card ```tsx 'use client'; import { useDocyrusAdaptiveCardItemDetail } from '@docyrus/ui/hooks/use-docyrus-adaptive-card-item-detail'; export function DealDetail({ fields, record }) { const { view } = useDocyrusAdaptiveCardItemDetail({ fields, record }); return view; } ``` ### Use the generated JSON directly The `card` field is a plain Adaptive Card payload — persist it, post it to Teams, or render it yourself with ``. ```tsx import { AdaptiveCard } from '@docyrus/ui/components/adaptive-card'; import { useDocyrusAdaptiveCardItemDetail } from '@docyrus/ui/hooks/use-docyrus-adaptive-card-item-detail'; const { card } = useDocyrusAdaptiveCardItemDetail({ fields, record }); // `card` === { type: 'AdaptiveCard', version: '1.5', body: [...] } await fetch('/api/teams/notify', { method: 'POST', body: JSON.stringify(card) }); return ; ``` ### Pin slots, add actions, react to clicks ```tsx const { view } = useDocyrusAdaptiveCardItemDetail({ fields, record, slots: { titleField: 'name', badgeField: 'status', coverImageField: 'cover', subtitleField: 'description' }, actions: [ { type: 'Action.OpenUrl', title: 'Open record', url: `/records/${record.id}` } ], onAction: (event) => { if (event.type === 'openUrl') router.push(event.url); } }); ``` ## Field-type → Adaptive Card element mapping The card body is assembled from three regions: a header (cover / avatar / title / subtitle / status badge), a `FactSet` of scalar fields, and standalone blocks for rich fields. Slots are auto-detected from field type + slug (see [Slot detection](#slot-detection)); everything else lands in the body. | Docyrus field type | Adaptive Card representation | |--------------------|------------------------------| | `field-text`, `field-email`, `field-url`, `field-phone`, `field-currency`, `field-color`, `field-icon`, `field-formula`, `field-identity` | Header title **or** `FactSet` value (`TextBlock`) | | `field-number`, `field-autonumber`, `field-money`, `field-percent`, `field-duration`, `field-rating` | `FactSet` value — formatted (currency, `%`, `★`, `hh:mm:ss`) | | `field-checkbox`, `field-switch` | `FactSet` value — `Yes`/`No`, `On`/`Off` | | `field-date`, `field-dateTime`, `field-time`, `field-dateRange` | `FactSet` value — tenant-formatted date/time | | `field-select`, `field-radioGroup`, `field-enum`, `field-systemEnum`, `field-status`, `field-approvalStatus` | Header status `Badge` (semantic color) **or** `FactSet` value (option name) | | `field-multiSelect`, `field-tagSelect` | `FactSet` value — comma-joined option names | | `field-userSelect` | `FactSet` value — user display name | | `field-userMultiSelect` | `FactSet` value — joined user names | | `field-relation`, `field-relatedField` | `FactSet` value — related record label | | `field-image`, `field-avatar` | Cover / avatar `Image`, or an `Image` / `ImageSet` body block | | `field-textarea`, `field-markdown`, `field-htmlEditor`, `field-emailEditor`, `field-docEditor` | Wrapped `TextBlock` block (HTML stripped) | | `field-json`, `field-jsonSchema`, `field-jsonata`, `field-handlebars`, `field-code`, `field-codeEditor`, `field-queryBuilder`, `field-dsql` | `CodeBlock` block (language-tagged) | | `field-file` | `FactSet` value — file name | | `field-locationSelect` | `FactSet` value — address label | | `field-taskList`, `field-todo` | `FactSet` value — `done / total` summary | | `field-adaptiveCard`, `field-button`, `field-password`, `field-inlineForm`, `field-schema*`, `field-inlineData`, `field-dynamic`, `field-conversationChannel`, `field-fileStorageFolder`, `field-system*` | Skipped (no meaningful card representation) | Enum / status colors (Tailwind families or hex) are classified to the nearest Adaptive Card badge style: green → `good`, red → `attention`, amber → `warning`, blue/purple → `accent`, otherwise `informative`. ## Slot detection When you don't pin slots, bindings are auto-detected from the field list using the same heuristics as the [data gallery](/docs/web/hooks/use-docyrus-data-gallery) (slug hints first, then type). Override any slot with a slug, or `null` to disable a detected binding: | Slot | Auto-detected from | |------|--------------------| | `titleField` | slug `name` / `title` / `subject` / `label`, then a text/identity field | | `subtitleField` | slug `description` / `summary` / `subtitle`, then a textarea field | | `coverImageField` | slug `cover` / `image` / `thumbnail` / `banner`, then a `field-image` | | `avatarField` | slug `avatar` / `profile_photo`, then a `field-avatar` | | `badgeField` | slug `status` / `priority` / `stage`, then a status/select field | | `timelineField` | slug `due` / `deadline` / `start`, then a `field-date` (leads the facts) | | `bodyFields` | every remaining non-system field | ## API Reference ### `UseDocyrusAdaptiveCardItemDetailOptions` | Option | Type | Default | Description | |--------|------|---------|-------------| | `fields` | `DocyrusAdaptiveCardField[]` | — | Field metadata (accepts `IField` / `DataSourceField` / `DocyrusFieldLike`). | | `record` | `Record \| null` | — | The record to render. | | `enumOptions` | `Record` | — | Per-field-slug enum options. Falls back to each field's inline `enums`. | | `slots` | `DocyrusAdaptiveCardSlotOverrides` | — | Pin (`string`) or disable (`null`) individual slot bindings. | | `includeFields` | `string[]` | — | Explicit, ordered body field list (replaces auto-detected body). | | `excludeFields` | `string[]` | — | Field slugs to drop from the body. | | `title` | `string` | — | Force the header title text. | | `actions` | `AdaptiveCardAction[]` | — | Card-level actions appended to `payload.actions`. | | `hideEmpty` | `boolean` | `true` | Drop empty fields instead of rendering an em-dash. | | `factLayout` | `'facts' \| 'stacked'` | `'facts'` | Scalar layout — a `FactSet` or stacked label/value blocks. | | `version` | `string` | `'1.5'` | Adaptive Card schema version. | | `formatDate` | `(value) => string` | tenant context | Override the date formatter. | | `formatDateTime` | `(value) => string` | tenant context | Override the datetime formatter. | | `formatNumber` | `(value, opts?) => string` | tenant context | Override the number/currency/percent formatter. | | `className` | `string` | — | Class forwarded to the rendered `view`. | | `onAction` | `(event: AdaptiveCardActionEvent) => void` | — | Forwarded to `useAdaptiveCard`. | | `hostConfig` | `AdaptiveCardHostConfigOverride` | — | Forwarded to `useAdaptiveCard`. | | `customElements` | `Record` | — | Forwarded to `useAdaptiveCard`. | | `onChoiceQuery` | `(request) => Promise` | — | Forwarded to `useAdaptiveCard`. | ### `UseDocyrusAdaptiveCardItemDetailReturn` Extends [`UseAdaptiveCardReturn`](/docs/web/hooks/use-adaptive-card) (`state`, `controls`, `cardProps`, `hostConfig`) with: | Field | Type | Description | |-------|------|-------------| | `card` | `AdaptiveCardPayload` | The generated Adaptive Card JSON — the primary output. | | `slots` | `DocyrusAdaptiveCardSlots` | The resolved slot bindings. | | `view` | `ReactNode` | Ready-to-render `` for the generated card. | ## Type Exports | Type | Description | |------|-------------| | `UseDocyrusAdaptiveCardItemDetailOptions` | Hook options. | | `UseDocyrusAdaptiveCardItemDetailReturn` | Hook return. | | `DocyrusAdaptiveCardField` | Minimal field shape (`slug` + `name` + `type`, optional `enums`). | | `DocyrusAdaptiveCardSlots` | Resolved slot bindings. | | `DocyrusAdaptiveCardSlotOverrides` | Slot override map (`string` to pin, `null` to disable). | | `DocyrusAdaptiveCardFactLayout` | `'facts' \| 'stacked'`. | ## See also - [`useDocyrusAdaptiveCardItemList`](/docs/web/hooks/use-docyrus-adaptive-card-item-list) — the same mapping, for a list of records. - [`AdaptiveCard`](/docs/web/components/adaptive-card) — the renderer. - [`useAdaptiveCard`](/docs/web/hooks/use-adaptive-card) — the underlying runtime.