# Midnight → Unity component map

Exhaustive map of every public `@payfit/midnight` export to its
`@payfit/unity-components`, `@payfit/unity-icons`, `@payfit/unity-themes`
or `@payfit/unity-illustrations` counterpart.

**How to use this map**

- Find the Midnight component you're porting in the left column.
- The middle column is the Unity replacement (or `—` if none exists).
- The right column is a one-line note: composition pattern, behavior
  delta, or "no equivalent" reason. Prop renames, the disabled-tooltip
  rule, and full a11y deltas live in `../SKILL.md` — don't repeat them
  per row.

If a row says **no equivalent**, accept the gap. Do not invent a Unity
component, do not reach for an external library unless explicitly
allowed (see `VirtualizedList`), and do not style a non-link element to
look like a link.

> Cross-package targets: `Icon` lives in `@payfit/unity-icons`;
> `Illustration` and `LazyIllustration` live in
> `@payfit/unity-illustrations`; `UnityThemeProvider` lives in
> `@payfit/unity-themes`. Everything else is `@payfit/unity-components`.

## Layout & containers

| Midnight        | Unity                      | Note                                                                  |
| --------------- | -------------------------- | --------------------------------------------------------------------- |
| `Box`           | `Flex` (1D) / `Grid` (2D)  | No 1:1; pick `Flex` with `direction`/`gap`/`align`, `Grid` for 2D     |
| `CalloutCard`   | `Card`                     | Deprecated in Midnight; compose with `Card` + `Text` + icon/action    |
| `Card`          | `Card`                     | Use `shadow` and `bgColor` props for the visual variants              |
| `CardContainer` | `Card`                     | Card with `asChild` + `RawLink` (or `Link`) for interactive cards     |
| `Column`        | `Flex direction="column"`  | —                                                                     |
| `DataCard`      | `Card` + `Text` (composed) | No direct equivalent; compose label/value/action from primitives      |
| `Grid`          | `Grid`                     | —                                                                     |
| `Layout`        | `Flex`                     | Internal Midnight primitive; pick `Flex` (or `Grid`) at the call site |
| `Row`           | `Flex direction="row"`     | —                                                                     |
| `Scrollable`    | `Flex` + overflow utility  | Compose with `uy:overflow-auto`/`uy:overflow-y-auto` classes          |
| `Section`       | `Flex asElement="section"` | Add `Text variant="h*"` for the heading                               |

## Typography

| Midnight   | Unity                     | Note                                                                      |
| ---------- | ------------------------- | ------------------------------------------------------------------------- |
| `Code`     | native `<code>`           | No Unity equivalent; use the native element                               |
| `Heading`  | `Text variant="heading*"` | No dedicated `Heading`; typography is a `Text` variant                    |
| `LinkText` | `Link`                    | Use `Link` directly — links must look like links                          |
| `Markdown` | —                         | No equivalent; do not pull in an external library unless explicitly asked |
| `Text`     | `Text`                    | Prop shape differs (`size`/`variation` → `variant`); see Unity docs       |

## Buttons & actions

| Midnight        | Unity                    | Note                                                            |
| --------------- | ------------------------ | --------------------------------------------------------------- |
| `Actionable`    | `Actionable`             | `onAction` → `onPress`                                          |
| `Button`        | `Button`                 |                                                                 |
| `IconButton`    | `IconButton`             | `CircularIconButton` for the round variant                      |
| `Link`          | `RawLink` / `Link`       | Router-agnostic `RawLink`; router-aware `Link` from integration |
| `Linkable`      | `RawLink`                | Internal Midnight; use `RawLink` directly                       |
| `MinimalButton` | `Button variant="ghost"` | —                                                               |
| `Navigable`     | `RawLink`                | Internal Midnight; use `RawLink` (or router-aware `Link`)       |
| `SubmitButton`  | `Button type="submit"`   | No dedicated submit button                                      |

## Form structure

| Midnight   | Unity       | Note                                                             |
| ---------- | ----------- | ---------------------------------------------------------------- |
| `Field`    | `FormField` | Wrapper with `FormLabel` / `FormHelperText` / `FormFeedbackText` |
| `FieldSet` | `Fieldset`  | Casing change (`FieldSet` → `Fieldset`)                          |
| `Form`     | `Form`      | Pair with `useTanstackUnityForm` — see `unity-tanstack-form`     |

## Form inputs

> Form-bound usage is via Tanstack form (`useTanstackUnityForm`), where
> Unity components are exposed as `<field.*>` after wiring the form
> hook. Top-level `*Field` exports use the deprecated RHF binding and
> will be removed — see `unity-tanstack-form` for the supported path.
> The "Unity" column below names the component; how to bind it lives in
> that skill.

| Midnight           | Unity                                                        | Note                                                                                   |
| ------------------ | ------------------------------------------------------------ | -------------------------------------------------------------------------------------- |
| `Checkbox`         | `Checkbox` / `CheckboxField`                                 | `CheckboxField` is the form organism                                                   |
| `CheckboxGroup`    | `CheckboxGroup` / `CheckboxGroupField`                       | —                                                                                      |
| `DatePickerField`  | `DatePicker` / `DatePickerField`                             | Range: `DateRangePicker` standalone or `<field.DateRangePickerField>` in Tanstack form |
| `Dropzone`         | —                                                            | No equivalent                                                                          |
| `MultiSelectField` | `MultiSelect` / `MultiSelectField`                           | —                                                                                      |
| `MultiUploadField` | —                                                            | No equivalent                                                                          |
| `PasswordField`    | `PasswordField`                                              | Tanstack-form-bound only — accessed via `<field.PasswordField>`                        |
| `RadioGroup`       | `RadioButtonGroup` + `RadioButton` / `RadioButtonGroupField` | Multi-card layout: `SelectableCardRadioGroupField`                                     |
| `SearchField`      | `Search`                                                     | `Input type="search"` as a non-styled fallback                                         |
| `SelectField`      | `Select` / `SelectField`                                     | —                                                                                      |
| `Slider`           | —                                                            | No equivalent                                                                          |
| `Switch`           | `ToggleSwitch` / `ToggleSwitchField`                         | —                                                                                      |
| `TextAreaField`    | `TextArea`                                                   | No dedicated `TextAreaField` organism; compose with `FormField`                        |
| `TextField`        | `Input` / `TextField`                                        | `Input` standalone; `TextField` is the form organism                                   |
| `UploadField`      | —                                                            | No equivalent                                                                          |

## Overlays & dialogs

| Midnight       | Unity                                        | Note                                                                           |
| -------------- | -------------------------------------------- | ------------------------------------------------------------------------------ |
| `Banner`       | `Alert`                                      | `variation` → `variant` (info/warning/success/danger/insight)                  |
| `ConfirmModal` | `Dialog` + `DialogContent` + `DialogActions` | Deprecated in Midnight; compose explicitly                                     |
| `ContentModal` | `Dialog`                                     | Deprecated in Midnight                                                         |
| `DropdownMenu` | `Menu`                                       | Trigger + content composition                                                  |
| `FormModal`    | `Dialog`                                     | Deprecated in Midnight; submit via the inner `Form`                            |
| `Modal`        | `Dialog`                                     | Use `PromoDialog` for marketing dialogs                                        |
| `Popover`      | `Popover`                                    | Unity exposes `title` / `displayCloseButton`                                   |
| `Toast`        | `ToastManager` + `toast()`                   | Mount `ToastManager` at root; call `toast(...)` from anywhere                  |
| `Tooltip`      | `Tooltip`                                    | Unity refuses to render on a disabled control — see SKILL.md "Common Mistakes" |

## Navigation

| Midnight            | Unity                   | Note                                               |
| ------------------- | ----------------------- | -------------------------------------------------- |
| `Pagination`        | `Pagination`            | Pair with `DataTable` for table-bound paging       |
| `PrimaryNavigation` | `AppMenu` + `AppLayout` | Compose `AppMenu` inside `AppLayout`'s `menu` slot |
| `Tabs`              | `Tabs`                  | —                                                  |

## Data display

| Midnight          | Unity                       | Note                                                                                           |
| ----------------- | --------------------------- | ---------------------------------------------------------------------------------------------- |
| `Badge`           | `Badge`                     | `color` → `variant` (success/warning/danger/neutral/promo/attention/contextual/numeric)        |
| `ExpandableTable` | `DataTable` (row-expansion) | Add an expansion column via TanStack Table's row-expansion API                                 |
| `Pill`            | `Pill`                      | Unity `Pill` is numeric-only and has fewer colors; intent is the same (small inline indicator) |
| `SelectableTable` | `DataTable` (row-selection) | Add a selection column via TanStack Table's row-selection API                                  |
| `Table`           | `Table` / `DataTable`       | `Table` for layout-only; `DataTable` for sorting/filter/pagination via TanStack Table          |
| `Tag`             | —                           | No equivalent (dismissible chip; Unity `Badge` is non-dismissible)                             |
| `VirtualizedList` | `ListView`                  | Fallback to `@tanstack/virtual` directly only if the design genuinely cannot fit `ListView`    |

## Feedback & status

| Midnight             | Unity                        | Note                                                      |
| -------------------- | ---------------------------- | --------------------------------------------------------- |
| `EmptyState`         | `EmptyState`                 | Unity ships `EmptyState*` presets (NoSearchResults, etc.) |
| `Loader`             | `Spinner` / `FullPageLoader` | `Spinner` for inline; `FullPageLoader` for full-screen    |
| `ObfuscatedContent`  | —                            | No equivalent                                             |
| `ObfuscatedDataCard` | —                            | No equivalent                                             |
| `ObfuscatedText`     | —                            | No equivalent                                             |

## Media

| Midnight       | Unity                                                               | Note                                                                    |
| -------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| `Avatar`       | `Avatar`                                                            | `type` → `variant` (circle/square)                                      |
| `AvatarGroup`  | —                                                                   | No equivalent (planned)                                                 |
| `Icon`         | `Icon` (`@payfit/unity-icons`)                                      | Pass typed `src: UnityIcon` string literal — do not cast `as UnityIcon` |
| `Illustration` | `Illustration` / `LazyIllustration` (`@payfit/unity-illustrations`) | `LazyIllustration` for animated assets                                  |
| `Image`        | native `<img>`                                                      | No Unity equivalent                                                     |
| `Svg`          | native `<svg>` (or `Icon` if it's an icon)                          | No Unity equivalent for arbitrary SVGs                                  |

## Misc

| Midnight           | Unity                                         | Note                                                                |
| ------------------ | --------------------------------------------- | ------------------------------------------------------------------- |
| `Accordion`        | `Collapsible`                                 | Unity `Collapsible` is single-item; no multi-item accordion         |
| `MidnightProvider` | `UnityThemeProvider` (`@payfit/unity-themes`) | Mount once at app root                                              |
| `Overlay`          | —                                             | Internal Midnight primitive; use `Dialog`/`Popover`/`Menu` directly |
| `Transition`       | `uy:transition-*` / `uy:duration-*` classes   | No JS helper; use TailwindCSS utilities                             |

## v2 components

Midnight v2 was a transitional API. Most v2 components map 1:1 to a
Unity primitive.

| Midnight v2       | Unity                                                               | Note                                                          |
| ----------------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
| `v2/AsyncImage`   | native `<img>`                                                      | No Unity equivalent                                           |
| `v2/Avatar`       | `Avatar`                                                            | —                                                             |
| `v2/Box`          | `Flex` / `Grid`                                                     | Same guidance as v1 `Box`                                     |
| `v2/Flex`         | `Flex`                                                              | Drop the `v2/` namespace; same props                          |
| `v2/Grid`         | `Grid`                                                              | Drop the `v2/` namespace                                      |
| `v2/Icon`         | `Icon` (`@payfit/unity-icons`)                                      | Same target as v1 `Icon`                                      |
| `v2/Illustration` | `Illustration` / `LazyIllustration` (`@payfit/unity-illustrations`) | Same target as v1 `Illustration`                              |
| `v2/Image`        | native `<img>`                                                      | —                                                             |
| `v2/PageLayout`   | `AppLayout` / `Page`                                                | `AppLayout` for the app shell; `Page` for the content surface |
| `v2/Stack`        | `Flex` (with `direction` + `gap`)                                   | —                                                             |
