---
name: upgrade-vui-v4-to-v5
description: >
  Upgrade a React application from @veracity/vui v4 to v5. Use when migrating
  Notification, Button, IconButton, Tag, Badge, CloseButton/DismissButton,
  Dialog close controls, iconLeft/iconRight aliases, CSS variables, or visual
  regressions caused by VUI 5 spacing and token changes.
sources:
  - 'WEB-VUI:apps/docs/stories/guides/overview/ReleaseNotes.mdx'
  - 'WEB-VUI:apps/docs/stories/guides/overview/MigrationGuide.mdx'
  - 'WEB-VUI:apps/docs/static/llms/components/button.md'
  - 'WEB-VUI:apps/docs/static/llms/components/notification.md'
  - 'WEB-VUI:apps/docs/static/llms/components/iconButton.md'
  - 'WEB-VUI:apps/docs/static/llms/components/tag.md'
  - 'WEB-VUI:apps/docs/static/llms/components/badge.md'
  - 'WEB-VUI:packages/vui/src/notification/notification.tsx'
  - 'WEB-VUI:packages/vui/src/button/buttons.tsx'
  - 'WEB-VUI:packages/vui/src/tag/tag.tsx'
  - 'WEB-VUI:packages/vui/src/badge/badge.tsx'
  - 'WEB-VUI:packages/vui/src/dialog/dialog.tsx'
metadata:
  type: lifecycle
  library: '@veracity/vui'
  library_version: '5.2.3'
---

# Upgrade VUI 4 to VUI 5

Treat this as a migration checklist. Make safe mechanical edits, leave explicit TODOs for visual choices, and run project validation after editing.

## Migration Workflow

1. Inspect the app's package manager and installed `@veracity/vui` version.
2. Upgrade `@veracity/vui` to `^5.0.0` or the repo's approved v5 range.
3. Search for VUI 4 patterns listed below.
4. Apply exact API migrations where behavior is clear.
5. Preserve visual behavior when the old default changed.
6. Run typecheck, lint, and relevant UI tests.
7. Visually verify Button and Notification layouts because VUI 5 changed spacing.

Useful searches:

```bash
rg -n "Notification\\.Button|NotificationButton|showDismissButton|onClose=|status=|verticalAlign=|variant=\"(subtle|banner|solid|minimal|blue|menu|primaryDark|secondaryDark|tertiaryDark|primaryLight|secondaryLight|tertiaryLight)|CloseButton|Dialog\\.CloseButton|IconButton|iconLeft=|iconRight=" src
```

Adjust the search root for the host repository.

## Notification

### Dismiss Button

VUI 5 does not show a dismiss button just because `onClose` exists. Add `showDismissButton` when the user still needs a visible dismiss control:

```tsx
// VUI 4
<Notification onClose={() => setVisible(false)} />

// VUI 5
<Notification showDismissButton onClose={() => setVisible(false)} />
```

If `onClose` was passed for a side effect but no dismiss control should appear, leave it only after verifying that the prop is still needed.

### Removed Notification.Button

Replace `Notification.Button` or `NotificationButton` with `action` or custom children:

```tsx
// VUI 4
<Notification title="Update available">
  <Notification.Button onClick={update}>Update</Notification.Button>
</Notification>

// VUI 5
<Notification title="Update available" action={<Button variant="primary" text="Update" onClick={update} />} />
```

### Variant And Intent

Migrate legacy combined variants to `variant` + `intent`:

```tsx
<Notification variant="subtleBlue" />
<Notification variant="inline" intent="info" />

<Notification variant="subtleRed" />
<Notification variant="inline" intent="danger" />

<Notification variant="subtleGreen" />
<Notification variant="inline" intent="success" />

<Notification variant="subtleYellow" />
<Notification variant="inline" intent="warning" />

<Notification variant="bannerBlue" />
<Notification variant="banner" intent="info" />
```

`status` still works as a deprecated shorthand, but new and touched code should use `variant`, `intent`, `isLoading`, and explicit icons as needed.

### Status Mapping

Use these replacements for common `status` values:

```tsx
<Notification status="error" />
<Notification variant="inline" intent="danger" />

<Notification status="loading" />
<Notification variant="inline" intent="info" isLoading />

<Notification status="bannerSuccess" />
<Notification variant="banner" intent="success" />
```

Current VUI 5 source auto-injects an icon for `intent` in the default render path. Keep explicit `icon=""` only when suppressing the icon intentionally.

### Align Prop

Rename `verticalAlign` to `align`. Replace `flex-start` with `top`:

```tsx
<Notification verticalAlign="flex-start" />
<Notification align="top" />

<Notification verticalAlign="center" />
<Notification align="center" />
```

## Button

Migrate legacy button variants to the two-prop API:

```tsx
<Button variant="primaryDark" />
<Button variant="primary" intent="brand" />

<Button variant="secondaryDark" />
<Button variant="secondary" intent="brand" />

<Button variant="tertiaryDark" />
<Button variant="tertiary" intent="brand" />

<Button variant="primaryLight" />
<Button variant="primary" intent="contrast" />

<Button variant="secondaryLight" />
<Button variant="secondary" intent="contrast" />

<Button variant="tertiaryLight" />
<Button variant="tertiary" intent="contrast" />

<Button variant="solidGreen" />
<Button variant="primary" intent="success" />

<Button variant="solidRed" />
<Button variant="primary" intent="danger" />
```

Replace old blue variants:

```tsx
<Button variant="solidBlue" />
<Button variant="primary" intent="brand" />

<Button variant="blueOutlined" />
<Button variant="secondary" intent="brand" />

<Button variant="blueText" />
<Button variant="tertiary" intent="brand" />
```

For `subtleBlue`, `subtleRed`, `subtleGreen`, `subtleYellow`, `menuLight`, and `menuDark`, migrate to the closest `secondary` or `tertiary` hierarchy and verify visually. Use CSS variable overrides only when the old component-specific look is required.

## Tag And Badge (5.2.0)

`Tag` and `Badge` adopt the two-prop `variant` + `intent` API. Legacy combined-string variants and `iconLeft` / `iconRight` still work but emit dev-mode warnings and will be removed in VUI 6.0.

Split combined variant keys into `variant` + `color`:

```tsx
<Tag variant="subtleBrand" iconLeft="uiCheck">Done</Tag>
<Tag variant="subtle" color="blue" startIcon="uiCheck">Done</Tag>

<Tag variant="solidDanger" iconRight="uiXmark">Error</Tag>
<Tag variant="solid" color="red" endIcon="uiXmark">Error</Tag>

<Badge variant="subtleSuccess">New</Badge>
<Badge variant="subtle" color="green">New</Badge>

<Badge variant="solidBlue">Beta</Badge>
<Badge variant="solid" color="blue">Beta</Badge>
```

**Tag** icon props: `startIcon` (before text), `endIcon` (after text), `icon` (icon-only — replaces all content). `iconLeft`/`iconRight` are deprecated aliases for `startIcon`/`endIcon`.
**Badge** icon prop: `icon` renders a leading icon alongside the label (`iconLeft` is a deprecated alias).

Tag supports `variant`: `subtle | solid` and `color`: `blue | green | red | yellow | lavender | eucalyptus | terracotta | grey`. Badge supports 5 colors: `blue | green | red | yellow | grey`.

For interactive filter chips or pressed-state pills, use `Tag` with `isInteractive`:

```tsx
<Tag isInteractive aria-pressed={isSelected} onClick={toggle}>Filter</Tag>
```

## Icon Props

Rename deprecated icon aliases in touched code:

```tsx
<Button iconLeft="uiPlus" iconRight="uiArrowRight" />
<Button startIcon="uiPlus" endIcon="uiArrowRight" />
```

Apply the same rename for `Tag`, `Badge`, `Link`, `ListItem`, `Input`, and `Definition`.

## Close And Dismiss Buttons

Rename standalone `CloseButton` imports to `DismissButton`:

```tsx
import { CloseButton } from '@veracity/vui'
<CloseButton onClick={onClose} />

import { DismissButton } from '@veracity/vui'
<DismissButton onClick={onClose} />
```

Use a specific `aria-label` when "Dismiss" is not the right accessible name:

```tsx
<DismissButton onClick={onClose} aria-label="Close dialog" />
```

Rename `Dialog.CloseButton` to `Dialog.DismissButton`:

```tsx
<Dialog.CloseButton />
<Dialog.DismissButton />
```

Some VUI 5 builds keep deprecated aliases with warnings. Migrate anyway; aliases are not the stable API.

## IconButton Default

`IconButton` now defaults to `variant="secondary"`. If the old tertiary visual style must be preserved, add `variant="tertiary"`:

```tsx
<IconButton icon="uiPen" title="Edit" />
<IconButton icon="uiPen" title="Edit" variant="tertiary" />
```

Do not change `BackButton`; it retains its tertiary preset.

## CSS Variables

For new or touched CSS, prefer VUI 5 `--vui-*` variables:

```css
.alert {
  background: var(--vui-feedback-info-subtle);
  border-color: var(--vui-feedback-info-solid);
  color: var(--vui-foreground-default);
}
```

Prefer semantic tokens over primitive color tokens.

## Common Mistakes

### HIGH Keeping onClose Without showDismissButton

Wrong:

```tsx
<Notification onClose={handleClose} title="Session expired" />
```

Correct:

```tsx
<Notification showDismissButton onClose={handleClose} title="Session expired" />
```

Without `showDismissButton`, users do not get a visible dismiss control.

### HIGH Preserving IconButton Appearance Implicitly

Wrong:

```tsx
<IconButton icon="uiTrashAlt" title="Delete" />
```

Correct when preserving VUI 4 appearance:

```tsx
<IconButton icon="uiTrashAlt" title="Delete" variant="tertiary" />
```

VUI 5 changed the implicit `IconButton` variant from tertiary to secondary.

### MEDIUM Replacing Status Without Loading State

Wrong:

```tsx
<Notification variant="inline" intent="info" title="Uploading" />
```

Correct replacement for `status="loading"`:

```tsx
<Notification variant="inline" intent="info" isLoading title="Uploading" />
```

The old loading status encoded both info intent and spinner state.
