@payfit/unity-components
Version:
181 lines (149 loc) • 17.1 kB
Markdown
# Midnight → Unity component map
Exhaustive map of every public `/midnight` export to its
`/unity-components`, `@payfit/unity-icons`, `/unity-themes`
or `/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 `/unity-icons`;
> `Illustration` and `LazyIllustration` live in
> `/unity-illustrations`; `UnityThemeProvider` lives in
> `/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 `/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` (`/unity-icons`) | Pass typed `src: UnityIcon` string literal — do not cast `as UnityIcon` |
| `Illustration` | `Illustration` / `LazyIllustration` (`/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` (`/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` (`/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`) | — |