# Migration to v6

> Track and review changes to the CoreUI for Vue.js components to help you migrate from v5 to v6.

CoreUI for Vue is the Vue.js version of the CoreUI components library, so before reading this
migration guide, please also check the
[CoreUI 5 to 6 migration guide](https://coreui.io/bootstrap/docs/migration/v6/) — it covers the
markup, class names, Sass architecture and design tokens this release is built on. This page covers
what changes in the Vue API.

## Dependencies

- <span className="badge bg-danger">Breaking</span> **Popper is gone; positioning runs on
  [Floating UI](https://floating-ui.com/).** `@popperjs/core` is replaced by `@floating-ui/dom`.
  Update your lockfile — nothing else is required for the default configuration.
- <span className="badge bg-danger">Breaking</span> **`popperConfig` is now `floatingConfig`** on
  `CDropdown`, `CPopover` and `CTooltip`, and it takes a Floating UI
  [`ComputePositionConfig`](https://floating-ui.com/docs/computePosition#options) instead of a
  Popper one. The `popper` boolean prop stays and still switches static positioning.
- <span className="badge bg-danger">Breaking</span> **Positioned elements are stamped with
  `data-coreui-placement`**, not `data-popper-placement`. Custom CSS, tests or scripts keyed on the
  old attribute must be updated. The v6 stylesheet draws tooltip, popover and menu arrows from this
  attribute, so it is not optional.
- <span className="badge bg-danger">Breaking</span> **The exported composables are renamed**:
  `usePopper` → `useFloating`, `useDropdownWithPopper` → `useDropdownWithFloating`.

## New components

- **`CCombobox`** — a `.form-control` toggle over a popup list box: the options are
  `CListBoxOption` children or an `items` array, the selection is single or multiple, the panel
  takes an optional search field with `searchNormalize`, and `name` submits the value through a
  hidden select that takes part in form validation. Ships with the `useCombobox()` composable.
- **`CDateInput`, `CTimeInput`** — section fields: a masked, keyboard-first
  input where every part of the value (day, month, year, hour…) is its own editable section.
  `<CDateInput type="datetime">` carries the time too. The pickers are built on them, and they
  work standalone.
- **`CDialog`** and **`CDrawer`** — the native-`<dialog>` popup and side panel with the Bootstrap 6
  look and the `dialog-*` / `drawer-*` classes. `CDialog` is a centered floating panel over a
  blurred backdrop with optional slide-in variants; `CDrawer` is a floating, inset, rounded panel
  with sheet, translucent, fit-content and fullscreen variants plus responsive breakpoints.
  `CDialog`'s `fullscreen` takes a breakpoint as well as `true`, like `CModal`'s.

  They share their behavior with `CModal` and `COffcanvas`, which keep the classic look and the v5
  vocabulary — and one event vocabulary of their own: `show`, `close` and `close-prevented` on
  both, where the legacy pair says `hide`. **`CModal` and `COffcanvas` are deprecated and may be
  removed in v7** — prefer `CDialog` and `CDrawer` for new work. Pick one per surface; they are
  independent components.
- **`CListBox`** — the ARIA listbox pattern as a component: single, multiple or no selection,
  sections, descriptions, link options, an empty state, typeahead and an `activeDescendant` mode
  that keeps the focus in your own input. Ships with `CListBoxOption`, `CListBoxSection`,
  `CListBoxEmpty`, the header parts (`CListBoxHeader`, `CListBoxSelectAll`, `CListBoxTitle`,
  `CListBoxSubtitle`) and the `useListBox()` composable.
- **`CMenu`** — contextual overlays with submenus, container teleport, responsive placement and
  logical (`start`/`end`) placements. Ships with `CMenuToggle`, `CMenuContent`, `CMenuItem`,
  `CMenuHeader`, `CMenuDivider`, `CMenuText`, `CSubmenu` and the `useMenu()` composable. See the
  [Menu docs](https://coreui.io/vue/docs/components/menu/).
- **`CNumberInput`** — a number field with a stepper you can hit, in place of the browser's own
  spinner (tiny in some engines, absent on iOS). `min`, `max` and `step` stay native.
- **`CTransfer`** — two list boxes and four buttons that move values between them, with a
  select-all header and counter per list, an optional search, a one-way mode and an announcement
  of every move through `announce()`. Ships with the `useTransfer()` composable.

## Field components

`CAutocomplete`, `CMultiSelect`, `CDatePicker`, `CDateRangePicker` and `CTimePicker` are built on
one frame and one panel. These two changes apply to all five; the per-component sections below
cover what is specific to each.

- <span className="badge bg-danger">Breaking</span> **A field component *is* the frame.** It carries
  `.form-control-group` on its own root instead of nesting one, so a field is a direct child of an
  `.input-group` like any other control and there is no wrapper level to reach through. Custom CSS
  written as `.date-picker .form-control-group` no longer matches anything. On the pickers, the
  label and the validation feedback also move out of the frame.

  The frame replaces the per-component shells: `.autocomplete-input-group`,
  `.form-multi-select-input-group` and their `-sm`/`-lg` variants are gone, the adornments are
  `.form-control-cleaner` / `.form-control-action` (replacing `.autocomplete-cleaner`,
  `.form-multi-select-cleaner`, `.autocomplete-indicator`, `.form-multi-select-indicator`), and the
  `size` prop puts `.form-control-sm` / `.form-control-lg` on the frame itself.

- <span className="badge bg-danger">Breaking</span> **The options/picker panel exists only while it
  is open.** It is built when the field opens and removed once the exit transition has played, so a
  closed field carries no panel markup at all — code that queried `.combobox-popup` or
  `.date-picker-popup` up front, or held a ref to it across a close, needs to look it up per open.

## Theme colors

<span className="badge bg-danger">Breaking</span> **`light` and `dark` are replaced by `inverse`.**
They were theme colors named after a color scheme and neither followed one: `<CButton color="dark">`
stayed near-black on a near-black page. There are seven colors now — `primary`, `secondary`,
`success`, `info`, `warning`, `danger`, `inverse` — and the runtime validator lists them, so
`color="dark"` and `color="light"` warn in the console instead of passing silently.

- **`color="dark"` becomes `theme="inverse"`.** `inverse` resolves to gray-900 in light mode and
  gray-100 in dark, so it stands against the page in both.
- **`color="light"` becomes `theme="secondary"`.** `secondary` is the light neutral now (gray-100 /
  gray-600) rather than the mid gray-blue `#6b7785`, so components already using it change
  appearance.
- **Where the class was painting a plain panel** rather than naming a color, reach for
  `bg-4` or `bg-3`; where it was a fixed dark backdrop, set
  `data-coreui-theme="dark"` on the container.

- <span class="badge bg-danger">Breaking</span> **`color` on buttons is deprecated in favour of
  `theme`.** A v6 button is a shape plus a colour: `variant` picks the shape (`solid`, `outline`,
  `subtle`, `ghost`) and `theme` picks the colour. `color` renders the v5 spelling `btn-{color}`,
  which fuses the two and cannot inherit a colour from an ancestor; it still works and is removed in
  v7. `` becomes ``, and
  `` becomes
  ``. `color="link"` becomes the
  `link` property — a link button is a shape, not a colour, and it takes its colour from the link
  colour rather than from a theme. `color="transparent"` is gone with the
  `.btn-transparent` class it rendered — use `variant="ghost"`, which shows nothing but the
  button's content until hover and carries the base styling on its own.

- <span class="badge bg-danger">Breaking</span> **The theme colour tokens finish their rename.**
  `--cui-{color}-text-emphasis` is `--cui-{color}-fg-emphasis` and
  `--cui-{color}-border-subtle` is `--cui-{color}-border`, matching the slot names the
  components already read. Custom CSS naming the old tokens has to follow; the class names
  (`.text-primary-emphasis`, `.border-primary-subtle`) are unchanged.

- <span class="badge bg-danger">Breaking</span> **The bare theme colour tokens are gone.**
  `--cui-primary`, `--cui-secondary`, `--cui-success`, `--cui-info`, `--cui-warning`,
  `--cui-danger` and `--cui-inverse` no longer exist. A theme colour is its set of slots —
  `-base`, `-bg`, `-fg`, `-fg-emphasis`, `-bg-subtle`, `-bg-muted`, `-border`, `-focus-ring`,
  `-contrast` — and the colour itself is the `-base` slot: `--cui-primary-base` is what
  `--cui-primary` was, the 100–900 scale is mixed from it, and `-bg` (the action background)
  points at it. Rename reads one to one, in custom CSS and in the inline styles the
  examples use to retint a component:

  ```diff
  - 
  + 

  - :root { --cui-primary: #6f42c1; }
  + :root { --cui-primary-500: #6f42c1; }
  ```

  No component prop is affected — `theme="primary"` is unchanged.

- <span class="badge bg-danger">Breaking</span> **The palette is the theme colours.**
  `$colors` holds `primary`, `success`, `info`, `warning`, `danger` and `gray`; the ten
  hues (`$blue` … `$cyan`) and every `--cui-{hue}` and `--cui-{hue}-{stop}` token are
  gone, as are `$secondary` and `$inverse`. Each `$theme-colors` entry points `base` and
  `bg` at its palette's `500` stop and the other slots at that scale; `secondary` reads
  `--cui-gray-200` and `inverse` `--cui-gray-900`. No palette token is bare: the literal
  sits in `-500`, so `--cui-gray-500` is what `--cui-gray` was, and `--cui-primary-500` is
  the runtime knob for the whole family:

  ```diff
  - :root { --cui-primary-base: #6f42c1; }
  + :root { --cui-primary-500: #6f42c1; }

  - 
  + 
  ```

- <span className="badge bg-danger">Breaking</span> **Under a theme the theme wins over a component color token.** A component
  reads the `--cui-theme-*` slot on the property and its own token only as the fallback. In v5 the
  color came from the component's tokens, so a token you set on a colored alert applied; in v6 a
  token set on a themed component, or for the whole page in your CSS or a `$…-tokens` map, changes
  only the components without a theme. To recolor one themed component, set the slot instead:
  `<CAlert theme="danger" :style="{ '--cui-theme-bg-subtle': '#fde2e4' }">`.
- **Variants keep the component token as the override point.** Button variants, `variant="solid"`
  on an alert, `subtle` and `outline` on a badge, `subtle` on an avatar and `outline` on a chip map
  the component tokens to their own slots and paint from the tokens, so there a component token you
  set wins over the theme. Validation states win over a theme too.

## Surface ladder

<span className="badge bg-danger">Breaking</span> **The neutral surfaces are a numbered ladder.**
`.bg-body-secondary`, `.bg-body-tertiary`, `.text-body-secondary` and `.text-body-tertiary` are
deprecated in favor of ordinal names: `.bg-1` … `.bg-4` for surfaces and `.fg-body`, `.fg-1` …
`.fg-4` for the text hierarchy, with two new rungs (`.bg-1`, `.bg-2`) between the body and the old
surfaces. The deprecated names render identically and are removed in v7. The tokens moved with
them — `--cui-bg-body`, `--cui-bg-1` … and `--cui-fg-body`, `--cui-fg-1` … are canonical, and
`--cui-secondary-bg`, `--cui-tertiary-bg`, `--cui-secondary-color`, `--cui-tertiary-color`,
`--cui-body-bg` and `--cui-body-color` remain as aliases until v7. No component prop is affected.

The deprecated surface names sit two rungs lower than they first did: `.bg-body-secondary`
renders `--cui-bg-3` and `.bg-body-tertiary` `--cui-bg-2`, the v5 stops one rung apart, while
`.text-body-secondary` stays `--cui-fg-2` and `.text-body-tertiary` `--cui-fg-3` — tertiary text
was the lighter of the two in v5 and still is.

- <span class="badge bg-danger">Breaking</span> **The ladder is three Sass maps, not a row of
  scalars.** `$theme-bgs`, `$theme-fgs` and `$theme-borders` replace `$bg-body`, `$bg-1` …
  `$bg-4`, `$fg-body`, `$fg-1` … `$fg-4`, `$border-subtle`, `$border-muted` and
  `$border-emphasized`. Each map lives in `scss/_theme.scss` in the `defaults()` shape, `:root`
  emits every entry as `--cui-bg-{key}`, `--cui-fg-{key}` or `--cui-border-{key}`, and the
  `.bg-*`, `.fg-*` and `.border-*` utilities are generated from the same maps. `$border-color`
  stays a scalar — it is the default every component reads, not a rung. Override an entry
  instead of a variable:

  ```diff
  - $bg-body: #000;
  - $fg-body: #111;
  + $theme-bgs: ("body": #000);
  + $theme-fgs: ("body": #111);
  ```

## Sass options

- <span class="badge bg-danger">Breaking</span> **`$enable-important-utilities` is gone with the
  `!important` suffix.** Utilities are emitted in the last cascade layer, so they already beat
  every component and modifier without it, and no switch brings the suffix back. The one case
  it covered is your own **unlayered** CSS, which beats every layer: move that CSS into
  `@layer custom` and utilities win again.
- <span class="badge bg-danger">Breaking</span> **`$enable-negative-margins` is gone with the
  `.m*-n*` utilities.** Two negative inline steps ship unconditionally — `.me--1`, `.me--2`,
  `.ms--1` and `.ms--2` — from the `$negative-spacers` map; add a key there to extend the set.
  The block margins have no negative form.

## Breakpoints

- <span className="badge bg-danger">Breaking</span> **The `xxl` breakpoint prop is `2xl`, and the
  three largest breakpoints move.** `lg` is `1024px` (was 992), `xl` `1280px` (was 1200) and the
  top tier is `2xl` at `1536px` (was `xxl` at 1400); `sm` and `md` are unchanged. A prop whose name
  starts with a digit needs the shorthand or the colon form in a template — `<CCol :2xl="6">`,
  `<CContainer 2xl>` — and a quoted key in an options object.

  | v5 | v6 |
  | --- | --- |
  | `<CCol xxl="6">` | `<CCol :2xl="6">` |
  | `<CRow :xxl="{ cols: 3 }">` | `<CRow :2xl="{ cols: 3 }">` |
  | `<CContainer xxl>` | `<CContainer 2xl>` |
  | `<CPlaceholder :xxl="4">` | `<CPlaceholder :2xl="4">` |
  | `v-c-placeholder="{ xxl: 4 }"` | `v-c-placeholder="{ '2xl': 4 }"` |
  | `<CDropdown :alignment="{ xxl: 'end' }">` | `<CDropdown :alignment="{ '2xl': 'end' }">` |
  | `<CDialog fullscreen="xxl">`, `<CModal fullscreen="xxl">` | `fullscreen="2xl"` |
  | `<CDrawer responsive="xxl">`, `<COffcanvas responsive="xxl">` | `responsive="2xl"` |
  | `<CHeader container="xxl">`, `<CNavbar container="xxl">` | `container="2xl"` |
  | `<CNavbar expand="xxl">` | `expand="2xl"` |
  | `<CListGroup layout="horizontal-xxl">` | `layout="horizontal-2xl"` |
  | `<CTable responsive="xxl">` | `responsive="2xl"` |

- **Responsive placement reads the new scale.** `placement="top 2xl:bottom"` on `CMenu`,
  `CPopover` and `CTooltip` replaces the `xxl:` prefix, and `lg:`/`xl:` switch at 1024px and
  1280px.
- **The exported `Breakpoints` type ends in `'2xl'`** instead of `'xxl'`.
- **Size variants that spell `xxl` are not breakpoints and keep their name** — `CIcon`'s
  `size="xxl"` among them.

## Grid and sizing

- <span class="badge bg-danger">Breaking</span> **A denser spacing scale.** `$spacers` has thirteen steps, `0`–`12`: `.25 / .375 / .5 / .75 / 1 / 1.25 / 1.5 / 1.75 / 2 / 2.25 / 2.5 / 3 rem` from `1` (v5: `.25 / .5 / 1 / 1.5 / 3`). Every spacing, gap, space and gutter utility changes value under the same number, and so do the numeric `gutter`, `gutterX` and `gutterY` values of `CRow`; the v5 steps map to v6 as `1`→`1`, `2`→`3`, `3`→`5`, `4`→`7`, `5`→`12`. `p-3` becomes `p-5`, `mb-4` becomes `mb-7`, `<CRow :xs="{ gutter: 3 }">` becomes a gutter of `5`. Components keep their size, cards aside (see `CCard`): their tokens read the stops that carry the v5 values.

- **New: `.w-1` … `.w-12`**, one `$spacer` per step from the `$sizes` map, alongside the
  percentage widths — see the [width utilities](https://coreui.io/vue/docs/utilities/width/).
- <span class="badge bg-danger">Breaking</span> **`$grid-gutter-width` is `$grid-gutter-x`, and
  `$grid-gutter-y` joins it.** `make-row()` takes both (`make-row($gutter-x, $gutter-y)`) and
  writes them to `--cui-gutter-x` / `--cui-gutter-y`; the row gutter defaults to `0` as before,
  so nothing moves unless you set it. `$grid-gutter-width` stays as a deprecated alias of
  `$grid-gutter-x` until v7 — set the new name, the alias only reads. `CRow`'s `xs`/`sm`… gutter
  values follow the new spacing scale (see A denser spacing scale).

## Z-index

- **New keys in `$zindex-levels`: `menu`, `drawer`, `dialog`**, on the same values as `dropdown`,
  `offcanvas` and `modal` (1000, 1045, 1055). Each emits a `--cui-z-*` token and a `.z-*` utility,
  and `CMenu`, `CDrawer` and `CDialog` read their own key instead of the legacy component's. The
  legacy keys stay; both spellings of a pair always resolve to one number.

## Typography

- <span class="badge bg-danger">Breaking</span> **`$font-sizes` sets a line height per stop
  instead of one value for all headings.** `xs` is 1.25, `sm` … `lg` the body leading
  (`--cui-body-line-height`, 1.5), `xl` 2.5⁄1.75, `2xl` 3⁄2.25, `3xl` 1.2, `4xl` and `5xl` 1.1,
  `6xl` 1 — the larger the type, the tighter the leading, and the small stops read at body
  leading instead of 1.2. The sizes are unchanged. Headings follow their stop through
  `--cui-line-height-*`: `h5` (`lg`) and `h4` (`xl`) get taller lines, `h1` (`4xl`) a tighter
  one. `$headings-line-height` still feeds `--cui-heading-line-height` for anything that reads
  it directly.

## Shadows

- <span class="badge bg-danger">Breaking</span> **Every shadow is a stack of two to four layers
  with a negative spread** instead of one wide blur: a tight layer for contact, wider ones for
  ambient light, each at 4–9 % alpha, so a card reads as lifted rather than smeared.
  `.shadow-xs` and `--cui-box-shadow-xs` are new (one thin layer). The inset shadow reads 8 % in
  the light scheme and 26 % in the dark one, and `--cui-shadow-strength` in the dark scheme is
  `2.4` (was 2.5). The knobs are unchanged: `--cui-shadow-color` and `--cui-shadow-strength` on
  `:root`, `.shadow-{color}` and `.shadow-opacity-*` on the element, `$shadows` in Sass — a
  custom entry is now a comma-separated list of layers.

## Components

### The `visible` family

- **`visible` is deprecated in favour of `show` / `v-model:show`** on `CAlert`, `CDialog`,
  `CDrawer`, `CDropdown`, `CMenu`, `CModal`, `COffcanvas`, `CPopover`, `CSidebar`, `CToast` and
  `CTooltip`. The old prop was semi-controlled: it fed the internal state, but the component still
  closed itself, so the prop and reality desynchronized on the first Escape or backdrop click — a
  confirm-before-close dialog or a pinned tooltip could not be built on it. One prop now covers
  both needs:
  - `show` passed one-way seeds the starting state, and the component keeps managing itself from
    there.
  - `v-model:show` hands the state to your component. Close and trigger gestures (Escape, a
    backdrop or outside click, the dismiss button, hover, the autohide timer) then only emit
    `update:show`, and nothing moves until you flip the value.
  - `update:show` — emitted with the requested state either way.

  `visible` keeps its old behaviour unchanged, is ignored when `show` is set, and is removed in v7.
- **`show` replaces `visible` on the purely controlled components too** — `CCollapse`, `CTabPane`,
  `CTabPanel` and `CBackdrop` take `show`, and `visible` stays as a deprecated alias that loses to
  it. These never owned their state, so nothing changes in behaviour; the library speaks one word
  for the same thing.
- **`CSubmenu` takes `show` / `v-model:show`** in place of its `visible`, which was a seed the
  submenu silently overwrote on hover; a submenu can be controlled now.
- **`CNavGroup` moves to `show` / `v-model:show`.** With a `v-model:show` (or a bare
  `@update:show` listener) the group renders what the prop says and the toggler only emits the
  request; without a listener a bare `show` is the default-open seed and nothing freezes.
  `visible`, `v-model:visible` and `update:visible` stay as deprecated aliases — `update:visible`
  keeps firing alongside `update:show` — and the `togglerContent` slot receives `{ show }` (with
  `visible` still present).

### Controlled value props

<span className="badge bg-danger">Breaking</span> **The value and state props are fully controlled
when set** — the same contract the `visible` family moved to, applied to the props that hold a
component's value. They used to be semi-controlled: the prop fed the internal state, but the
component still wrote to it, so the prop and reality desynchronized on the first user interaction.
Now the component renders exactly what you pass, an interaction only emits, and nothing moves until
you feed the change back — a bare value prop without its listener freezes the control. Code that
passed one as an initial value migrates to the new `default*` twin, which seeds the state once, on
mount:

| component | controlled prop | initial-value twin |
| --- | --- | --- |
| `CAutocomplete`, `CMultiSelect` | `value` | `defaultValue` |
| `CButton` (toggle mode) | `active` | `defaultActive` |
| `CChip` | `selected` | `defaultSelected` |

Props that carry a real `v-model` binding need no twin, and none was added: `modelValue` on
`CRangeSlider`, `CRating`, `CStepper` and `COneTimePassword`, `showPassword` on `CPasswordInput`,
`openItemKeys` on `CAccordion`, `show` on the `visible` family, and `date` / `time` /
`startDate` / `endDate` on the pickers and the date-time inputs all seed the starting state when
passed one-way, and hand the state over only once you bind them with `v-model`.

- **A bare `YYYY-MM-DD` string is read in the local timezone.** `Date.parse` treats it as UTC
  midnight, so `` landed on the 13th west of Greenwich and at
  the local offset east of it. Every Vue component that takes a date string is affected —
  `CCalendar`, `CDatePicker`, `CDateRangePicker`, `CDateInput`. The vanilla and React editions
  already read it this way, so this closes a divergence rather than opening one.

- <span className="badge bg-danger">Breaking</span> **The pickers and the date-time inputs drop
  their `default*` twins** — `defaultDate` on `CDatePicker` and `CDateInput`,
  `defaultTime` on `CTimePicker` and `CTimeInput`, `defaultStartDate` /
  `defaultEndDate` on `CDateRangePicker`, and `defaultValue` on `COneTimePassword`. Pass the value
  prop one-way instead: `` seeds the picker, which keeps managing
  itself. `CDateInput` and `CTimeInput` follow the same rule now — a one-way
  `date` / `time` no longer freezes the field; only a `v-model` binding hands the state over.

- **`CAutocomplete`, `CMultiSelect`: the per-option `selected` flags are a seed**, ignored entirely
  when `value` or `defaultValue` is set, and they no longer re-apply on later renders of the same
  option. In `CAutocomplete` a flag applies once, when its option first appears. In `CMultiSelect`
  it applies only to the options the component starts with: options that arrive later never change
  the selection, and `resetSelectionOnOptionsChange` empties it and takes the marked options when
  the values change. With `value` set the reset only requests the empty selection through
  the `change` event.
- **Form controls answer a native form reset the same way, bound ones included.**
  `CAutocomplete`, `CChipInput`, `CCombobox`, `CDateInput`, `CDatePicker`, `CDateRangeInput`,
  `CDateRangePicker`, `CFormRange`, `CMultiSelect`, `COneTimePassword`, `CRangeSlider`,
  `CRating`, `CTimeInput` and `CTimePicker` with a bound value used to keep it on a reset; they
  now ask for the value they started with through the events that report their value (`change`
  for `CAutocomplete` and `CMultiSelect`, `update:modelValue` for `CFormRange`, the update and
  change events for the rest) and show your
  value until you take it, so a page that resets its own state from the form's `reset` gets that
  request after its handler. A reset brings `CRating`, `CRangeSlider` and `CFormRange` back to the
  value they started with rather than the current prop, `COneTimePassword` emits `change` only
  when the reset changes the code, and `CStepper` keeps the validation marks of a form reset a
  listener cancels.
- **`CButton`: a toggle button's `active` is controlled when set** — a click only emits `click`
  and the pressed state follows your prop; seed an uncontrolled toggle with `defaultActive`.
  Without either prop nothing changes.
- **`CCalendar`: equal re-renders no longer reset the view.** A parent re-rendering with an equal
  `calendarDate`, `startDate` or `endDate` (a fresh `Date` object holding the same value) used to
  yank back the navigated month and cancel an in-progress range selection; only a real value
  change syncs now. Month names also follow `locale` and `monthFormat` changes at runtime.

### Validation state

<span className="badge bg-warning">Deprecated</span> **One `validation-state` prop replaces the
`valid` and `invalid` booleans** on every form control, field and picker, and on `CFormFeedback`.
`validation-state="invalid"` renders `is-invalid` and sets `aria-invalid` on the control,
`"valid"` renders `is-valid`, and any custom state from the `$form-validation-states` Sass map
renders `is-{state}` — two independent flags could neither express a third state nor refuse
`valid` and `invalid` at once. On the components that had them in v5 the booleans keep working as
deprecated aliases (with both set, `invalid` wins, where they used to stack), and are ignored
whenever `validation-state` is set; `CCheckbox`, `CChipInput`, `CCombobox`, `CDateInput`,
`CDateRangeInput`, `CNumberInput`, `CRadio`, `CSwitch` and `CTimeInput` take `validation-state`
only. Four side effects worth knowing:

- `feedback` follows the state: it renders only while `validation-state` is set, styled after it,
  and describes the control in every state, not only the invalid one.
- Every control that reads `validation-state="invalid"` now sets `aria-invalid="true"`, except
  `CCombobox`, whose toggle is a button and takes only the message in `aria-describedby`; a control
  without a validation state still sets none.
- <span className="badge bg-danger">Breaking</span> `validation-state="invalid"` (or the deprecated
  `invalid`) blocks the submit on `CFormInput`, `CFormSelect`, `CFormTextarea`, `CNumberInput`,
  `CPasswordInput`, `CCheckbox`, `CRadio`, `CSwitch`, `CFormCheck` and `CFormSwitch`, with the text
  of the invalid feedback as the browser's message, the way it already did on the fields that
  build their own markup. Each control emits `update:validationState` with `undefined` when the
  user changes its value or the form is reset; bind it with `v-model:validation-state` (with the
  deprecated `invalid`, set it to `false` on that event instead), or a form you gave an invalid
  state stays blocked until you clear it yourself. See
  [Validation](https://coreui.io/vue/docs/forms/validation/#custom-validation).
- <span className="badge bg-danger">Breaking</span> `CMultiSelect`, `CChipInput`, `CCombobox`,
  `COneTimePassword`, the date and time fields, the pickers and `CAutocomplete` take and show their
  validation state the same way, described under
  [Form components](https://coreui.io/vue/docs/forms/validation/#form-components). A field a validation reports shows the
  state on the component's frame, and `<CForm>` and `CStepper` leave the field that carries the
  value to the component. After taking the result over with `preventDefault()` in a `validate`
  listener, keep `event.isValid` rather than calling `checkValidity()`: the call reports every
  invalid field again, and the components then show their error.

### Help text and feedback ids

**`text` and the feedback get ids of their own.** A form control used to hand its
`aria-describedby` to the `text` and to the feedback as their id, so the help text and the error
shared one id: the control read the help text and never the error, a valid control with
`feedback-invalid` was described by the hidden error, and an `aria-describedby` that pointed at an
element of the page gave that id to a second element. Now `text`, `feedback`, `feedback-invalid` and
`feedback-valid` get generated ids, and the control lists them in its own `aria-describedby` after
the one you pass: the text always, `feedback` while `validation-state` is set, `feedback-invalid`
only while the control is invalid and `feedback-valid` only while it is valid, whether that state
comes from `validation-state` or, in a `data-coreui-validate` form, from the browser's `:user-invalid`
and `:user-valid` (the date and time fields and the pickers use the field's own verdict instead). A
`validation-state` you set takes precedence. Pass
`aria-describedby` only to point at elements of your own; a value you passed so that the `text`
would carry it is no longer needed, and CSS or scripts that found the text by that id need another
hook. `CFormControlWrapper` and `CFormControlValidation` replace their undocumented `describedby`
prop with `description-id`, the prefix the ids are built from (`<description-id>-label`, `-text`,
`-feedback`, `-feedback-invalid` and `-feedback-valid`).

### CAccordion

- <span className="badge bg-danger">Breaking</span> **The accordion is built on the native
  `<details>` and `<summary>` elements.** `CAccordionItem` renders a `<details class="accordion-item">`
  and `CAccordionHeader` its `<summary>`, so the browser owns opening, closing, keyboard
  interaction and the disclosure semantics — none of it depends on the component being mounted.
- <span className="badge bg-danger">Breaking</span> **`CAccordionButton` is removed**, together
  with `.accordion-button`, `.accordion-collapse` and `.collapsed`. The trigger is the `<summary>`
  itself and the panel is the element's own content, revealed through `::details-content`.
  `CAccordionHeader` already rendered the button for you, so markup written against the components
  needs no change; custom CSS keyed on those classes does. Style the open state with
  `.accordion-item[open] > .accordion-header`.
- <span className="badge bg-danger">Breaking</span> **`CAccordionHeader` renders a `<summary>`,
  not an `<h2>`.** A `<summary>` is not a heading — where the accordion divides a page into
  sections, wrap the label in an `<h2>`–`<h6>` inside the header. The heading inherits the
  summary's typography, so nothing looks different.
- **Grouping is the `name` attribute.** Without `alwaysOpen` the items of one accordion share a
  generated `name`, and the browser keeps a single one open.
- <span className="badge bg-danger">Breaking</span> **The open items follow the controlled /
  uncontrolled split the rest of the library uses.** `activeItemKey` fed the initial state, so it
  read like a controlled prop and behaved like a default: changing it after mount did nothing, and
  nothing reported back when the user opened an item. It is deprecated in favour of three props
  that say which is which:
  - `openItemKeys` passed one-way is the initial value, where `activeItemKey` maps — the accordion
    manages the open items from there.
  - `v-model:open-item-keys` hands them to your component, which then has to feed each `change`
    back.
  - `change` — emitted with the new list either way.

  They are named for what an accordion holds. `active` is the vocabulary of a selection — one
  item out of a set, which is what tabs have — while a `<details>` element is open or closed,
  and that is what `CAccordionItem` calls its own prop.

  All three take a single key as well as an array; an array only opens more than one item under
  `alwaysOpen`, since the HTML Standard forbids leaving more than one open item in a `name` group.
- **New: `shown` / `hidden` events on `CAccordionItem`**, fired from the element's own `toggle`
  event — so they report the state whichever path opened the item, including the browser closing a
  sibling of the same `name`.
- **The panel animation is CSS-driven** through `interpolate-size: allow-keywords`, which only
  Chromium implements today. Elsewhere the component measures the two sizes and the stylesheet
  times the move, exactly as `CCollapse` does; that part goes away, without a breaking change, once
  Firefox and Safari ship `calc-size()`.
- **The indicator can be an element.** Put a node carrying `accordion-icon` in the header and it
  replaces the chevron the header draws for itself; a second one marked `accordion-icon-active` is
  swapped in while the item is open.
- **New: `theme` on `CAccordion`** tints the open item. Closed items are untouched, so it marks
  what is expanded rather than recoloring the control.
- <span className="badge bg-danger">Breaking</span> **`CAccordionItem` takes `open`, and `visible`
  is deprecated.** The item renders a `<details>` element and that is what the attribute is called
  there, so the prop no longer carries a second word for the same state. It is also the controlled
  form for a single item, for the cases `openItemKeys` does not cover; `visible` keeps working.
- **A collapsed item stays findable.** `<details>` keeps its content searchable and the browser
  expands the item on a find-in-page match, so the accordion needs no counterpart to `CCollapse`'s
  `hiddenUntilFound`.

### CAlert

- **`dismissible` is no longer required to position a close button.** An alert makes room for a
  `` rendered as its direct child and positions it on its own. The prop keeps
  working and stays the way to get the built-in button. The button has to be a *direct* child to be
  pushed to the trailing edge — one nested in a wrapper is laid out by that wrapper.
- <span className="badge bg-danger">Breaking</span> **`color` applies `.theme-{color}`, not
  `.alert-{color}`.** The two emit a byte-identical block of `--cui-theme-*` declarations — the
  `.alert-*` names survive in v6 only as back-compat aliases, and every other themeable component
  reads the same class. Markup that still carries `.alert-success` renders exactly as it did; the
  component just stops generating the older spelling.
- <span className="badge bg-danger">Breaking</span> **`variant="solid"` renders `.alert-solid`
  alongside the theme class, not `bg-{color} text-white`.** The old pair hard-coded white text,
  which fails WCAG AA on five of the eight theme colors — 1.10 on `light`, where white on
  near-white is invisible. `.alert-solid` reads the theme's own contrast token, so every color
  lands above the threshold, including one you define yourself. The value also narrows to
  `'solid'`; v6 has no other alert variant.
- <span className="badge bg-danger">Breaking</span> **The alert lays its children out in a row.**
  It is `display: flex` with `--cui-alert-gap` between children, so an icon beside a label needs no
  `d-flex` and no spacing utility. Text mixed with inline elements is unaffected, but an alert
  built from **several block elements** — a heading, paragraphs, an `<hr>` — now sits side by side.
  Wrap that content in a `.vstack`.
- **An alert rendered with `transition` fades in when it is added to the page**, not only out when
  it is dismissed. Nothing to change; `@starting-style` supplies the state the animation was
  missing in that direction.
- **An `<hr>` inside an alert takes the alert's border color** rather than the page's neutral
  grey: the theme's border color, or `--cui-alert-border-color` without a theme, so a separator
  follows a border you recolored. With `variant="solid"` the border has the surface color, so the
  separator takes the theme's border color instead.
- <span className="badge bg-danger">Breaking</span> **The alert is rounded with `--cui-radius-7` (`.75rem`)**, like the dropdown,
  popover, toast, dialog, drawer and accordion; v5 used `.375rem`. Set
  `--cui-alert-border-radius: .375rem` to keep the v5 corners.
- <span className="badge bg-danger">Breaking</span> **`--cui-alert-border` is gone.** The border is written in the rule from
  `--cui-alert-border-width` and the border color, so that a theme can color it. Set those two
  instead, and `border-style` on the alert for a dashed or dotted line.
- <span className="badge bg-danger">Breaking</span> **`.alert-dismissible` is no longer rendered.**
  The class carries no styling in v6 — the close button is a flex item pushed to the end with
  `margin-inline-start: auto`, so the alert reserves no extra padding and needs no marker. The
  `dismissible` prop is unchanged and still renders the button and the self-dismiss behaviour;
  only the dead class is gone. CSS of your own that targeted it should target `.alert` or the
  button instead.

### CAutocomplete, CMultiSelect

- **`loading` shows a row below the options instead of covering them.** The white cover with a
  spinner that sat over the options while `loading` was set is gone: the list is marked
  `aria-busy="true"`, a row with a spinner and the new `loadingLabel` text (`'Loading…'`) shows
  below the options and is announced to screen readers when the shown list starts loading or the list shows up loading, and the options it
  shows can still be picked with the pointer and the keyboard.
- <span className="badge bg-danger">Breaking</span> **The options list of both is a
  [`<CListBox>`](https://coreui.io/vue/docs/components/list-box/)**, so the panel is built from `list-box-*` classes:
  `list-box`, `list-box-header`, `list-box-options`, `list-box-option` (+ `-indicator`,
  `-label`, `-description`), `list-box-section` (+ `-label`), `list-box-empty` and
  `list-box-select-all`, with the `selected`, `active` and `indeterminate` state classes. The
  `combobox-*` option classes and the former `autocomplete-dropdown` / `autocomplete-option(s)`
  and `form-multi-select-dropdown*` / `-options*` / `-option*` / `-all*` / `form-multi-selected`
  classes are gone, along with their Sass variables and CSS custom properties — theme the list
  through `--cui-list-box-*` and the panel around it through `--cui-combobox-*`. This markup is
  generated by the components, so only custom CSS targeting the menu internals needs updating.
- <span className="badge bg-danger">Breaking</span> **`role="listbox"` is on `.list-box-options`,
  not on the panel**, and a group is a `.list-box-section` rather than a label followed by loose
  siblings. In `CMultiSelect` the panel also holds the search field and the select-all button,
  which the old placement claimed as options.
- <span className="badge bg-danger">Breaking</span> **`selectAllStyle` and `optionsGroupsStyle`
  are removed** from `CMultiSelect`. One marker answers for the whole list: `indicator`
  reaches the options, the group labels and the select-all button alike.
- **The `show` and `hide` events fire once per transition**, and neither fires on mount.
  `CMultiSelect` used to fire `hide` every time the menu opened.
- <span className="badge bg-danger">Breaking</span> **`CAutocomplete` keeps the selection and the
  typed text apart.** `value` and `defaultValue` take an option value, compared as text, so `1` and
  `'1'` select the same option; a string used to be matched against the labels. `:value="null"`
  selects nothing. `@change` reports an option or `null`, never typed text: text the user types
  without picking an option stays in the field and is posted under `name`. The text is a state of
  its own: `defaultInputValue` starts it, `v-model:input-value` controls it, and the new
  `update:inputValue` event reports every change, picks included, while `@input` reports the search
  the options are filtered by. <kbd>Enter</kbd> on text that names no option no longer reports it
  through `@change`. From `@change` store `option.value`, `option.label` for an option without a
  value, or the string of a plain string option.
- **`CAutocomplete` shows the cleaner for typed text** when `allow-only-defined-options` is off,
  keeps it out of the Tab order, and leaves the focus in the field after a click.
- <span className="badge bg-danger">Breaking</span> **`CAutocomplete` keeps the focus in its
  input.** The arrows move a highlight the input reports through `aria-activedescendant` instead
  of moving the focus into the options, so the field keeps every keystroke — including
  <kbd>Space</kbd>, <kbd>Home</kbd> and <kbd>End</kbd>, which now belong to the caret. Options gain
  the `active` class while highlighted.
- <span className="badge bg-danger">Breaking</span> **`CMultiSelect` opens a dialog instead.** The
  panel is `role="dialog"` named by the control, and the focus moves into it: onto the search box
  when `search` is on, otherwise onto the option the list points at. Options take a roving
  `tabindex` and the arrows move the focus itself, so there is no `aria-activedescendant` to read
  any more. <kbd>Tab</kbd> cycles through the panel and the search box without leaving them, and
  <kbd>Escape</kbd> closes the panel and hands the focus back to the control. <kbd>Shift</kbd> +
  arrows, <kbd>Shift</kbd> + <kbd>Home</kbd>/<kbd>End</kbd> and <kbd>Ctrl</kbd>/<kbd>Cmd</kbd> +
  <kbd>A</kbd> extend or fill the selection, and the select-all button left the arrow order for the
  header, where <kbd>Tab</kbd> reaches it.
- <span className="badge bg-danger">Breaking</span> **`CMultiSelect`'s `search` no longer takes
  `'global'`.** Typing reaches the search box from anywhere in the component by default, which is
  what that value used to turn on, so `search="global"` becomes `search` and
  `:search="{ external: true, global: true }"` becomes `search="external"`. Set
  `:global-search="false"` to keep typing local: the search box then filters only while it has the
  focus, and a keystroke over the options list jumps to the first option starting with it (with
  `search="external"` it does nothing, since the list holds only the last results).
- <span className="badge bg-danger">Breaking</span> **`CMultiSelect`'s `search` no longer takes an
  object.** It takes `true`, `false` or `'external'`, so `:search="{ external: true }"` becomes
  `search="external"`.
- <span className="badge bg-danger">Breaking</span> **`CAutocomplete`'s `search` takes only
  `'external'`, and global typing is `globalSearch`, on by default.** `search="global"` goes away:
  typing on the picker button or in the options panel reaches the field without it. The object form
  goes too, so `:search="{ external: true, global: true }"` becomes `search="external"`. Set
  `:global-search="false"` to keep a keystroke where the focus is. The space bar and shortcuts with
  Ctrl or Cmd stay with the button that has the focus, a character typed with AltGr or Option
  reaches the field like any other, in `CMultiSelect` too, and typing in the field no longer moves
  the highlight to the first option that starts with the typed text.
- **`CCombobox` and a `CListBox` given a text field as `activeDescendant` leave typing in the field
  to the field.** The list ran its typeahead on the same keys, so a letter typed in the search field
  also moved the highlight to the first option starting with it, and <kbd>Enter</kbd> picked that
  option. The highlight now moves only with the arrows and the filter.
- **`CAutocomplete` and `CMultiSelect` read the typed text without the spaces around it**, in the
  filter, the highlight, the hint, <kbd>Enter</kbd> and leaving the field, and `CMultiSelect` creates
  an option from the trimmed text. A query of spaces lists every option. In `CMultiSelect` the search
  matches option labels only: a group whose own label matches no longer keeps all of its options,
  and a group without options is not listed.
- **`CMultiSelect` blocks the submit while `validationState` is `'invalid'`**, and emits
  `update:validationState` with `undefined` when the user changes the selection or the form is
  reset, so `v-model:validation-state` drops the state. A native form reset now restores the
  selection given by `defaultValue` or the options' `selected`. See
  [Validation](https://coreui.io/vue/docs/forms/multi-select/#validation).
- **`CAutocomplete` blocks the submit while `validationState` (or the deprecated `invalid`) is
  `'invalid'`**, and emits `update:validationState` with `undefined` when the user changes the text
  or the form is reset, so `v-model:validation-state` drops the state. The frame also shows the
  state a validation reports for the input, where it used to show only the state you gave. An
  `aria-invalid` attribute on the component is ignored; set `validation-state` instead. See
  [Validation](https://coreui.io/vue/docs/forms/autocomplete/#validation).
- **Keyboard, `CAutocomplete`:** `ArrowDown` out of the input highlights the first *enabled*
  option, and `Escape` hands the focus back to the input. A closed field renders
  `aria-expanded="false"` instead of omitting the attribute.
- <span className="badge bg-danger">Breaking</span> **`CMultiSelect`'s search field no longer reaches
  the server.** The input that filters the options carried a `name` built from the field's own, and
  a plain text input is serialized, so every form holding a `CMultiSelect` submitted whatever the
  user had typed to narrow the list. It carries no `name` now and the `search…` key is gone from
  the payload.
- <span className="badge bg-danger">Breaking</span> **An unnamed `CMultiSelect` stays out of the
  form.** The native select took `name: props.name ?? uniqueId`, so a component the page had not
  named still submitted its value under a key nobody chose. The attribute is written only when
  `name` is given.
- <span className="badge bg-danger">Breaking</span> **An unnamed `CAutocomplete` stays out of the
  form too.** Its input took a generated `name` when the prop was not set, so a form carried a key
  nobody chose. It does not now. The generated `id` is unaffected.
- <span className="badge bg-danger">Breaking</span> **`CAutocomplete`'s typeahead hint no longer takes
  the field's `id`.** With `showHints`, the decorative hint input rendered the same `id` as the real
  one, so `document.getElementById`, a `label[for]` and the floating label association all resolved
  to the hint. It carries no `id` now.

- <span className="badge bg-warning">Deprecated</span> **CMultiSelect: `selection-type="tags"` is
  `"chips"`, and `aria-tag-delete-label` is `aria-chip-remove-label`.** The selection renders
  [chips](https://coreui.io/vue/docs/components/chip/), so the mode carries their name and `"chips"` is the default. `"tags"`
  renders the same until v7. The old label prop still names the remove button and takes precedence
  while it is set.
- <span className="badge bg-danger">Breaking</span> **CMultiSelect's classes drop the `form-`
  prefix**, so they carry the component's name like `.autocomplete`, `.chip-input` and
  `.date-picker`. There is no alias; update CSS that targets them.

  | v5 | v6 |
  | --- | --- |
  | `.form-multi-select` | `.multi-select` |
  | `.form-multi-select-selection`, `.form-multi-select-selection-tags` | `.multi-select-selection`, `.multi-select-selection-chips` |
  | `.form-multi-select-search`, `.form-multi-select-placeholder` | `.multi-select-search`, `.multi-select-placeholder` |
  | `--cui-form-multi-select-selection-tags-gap`, `-padding-y` | `--cui-multi-select-selection-chips-gap`, `-padding-y` |

  The filled state is `.multi-select-filled`, and the component stylesheet is
  `@coreui/coreui-pro/css/components/forms/multi-select.css`.
- **CMultiSelect: <kbd>Backspace</kbd> in the empty search box focuses the last chip.** It removed
  the last value at once; the first press now moves the focus to the last chip and the second removes
  it, as in `CChipInput`. The arrow keys move between the search box and the chips, the selection is
  one tab stop, removing a focused chip moves the focus to its neighbour, and a value removed through
  a chip, <kbd>Backspace</kbd> or the cleaner is announced (`aria-removed-announcement`). A single
  select and the `counter` and `text` selections still remove the last value at once.

### CAvatar

- <span className="badge bg-danger">Breaking</span> **`text-color` is removed.** It wrote a single
  `fg-{value}` class, and the values it listed from v5 (`body-secondary`, `body-tertiary`,
  `*-emphasis`, `black-50`, `white-50`) had no rule in v6, so the text kept its inherited color. Put
  the color utility on the component instead: `class="fg-2"` for `body-secondary`, `fg-3` for
  `body-tertiary`, `fg-emphasis-primary` for `primary-emphasis`, `text-body-emphasis` for
  `body-emphasis`, `fg-white fg-50` and `fg-black fg-50` for `white-50` and `black-50`, and
  `fg-{color}` for a theme color.
- <span className="badge bg-danger">Breaking</span> **`color` applies a theme class, not a
  background utility.** It rendered `bg-{color}`, which left the letters on the inherited color and
  is why the docs paired it with a hand-picked `textColor` — a recipe that failed WCAG AA on five
  of the six examples they shipped. `.theme-*` supplies the background *and* the color that reads
  on it, so drop the `textColor` that went with it. A bare `<CAvatar>` is a neutral circle instead
  of a transparent one.
- **New: `variant="subtle"`** — a tinted avatar that keeps the theme color in the letters rather
  than behind them.
- **New: `ariaStatusLabel`** names the status indicator, rendering `role="img"` with the label. The
  indicator is color and nothing else, so a state that carries meaning needs a name; `aria-label`
  on a bare `<span>` has no role to attach to and may be ignored. Without the property the
  indicator stays decorative, as before.
- **`size` takes `xs`** on `CAvatar` and `CAvatarStack`, alongside `sm`, `md`, `lg`, `xl` — the
  five sizes the stylesheet ships.
- The custom properties behind the size moved: `--cui-avatar-width` / `-height` become
  `--cui-avatar-size`, and `--cui-avatar-status-width` / `-height` become
  `--cui-avatar-status-size`. Only inline overrides of those names need updating.

### CBadge

- <span className="badge bg-danger">Breaking</span> **`text-color` is removed.** It wrote a single
  `fg-{value}` class, and the values it listed from v5 (`body-secondary`, `body-tertiary`,
  `*-emphasis`, `black-50`, `white-50`) had no rule in v6, so the text kept its inherited color. Put
  the color utility on the component instead: `class="fg-2"` for `body-secondary`, `fg-3` for
  `body-tertiary`, `fg-emphasis-primary` for `primary-emphasis`, `text-body-emphasis` for
  `body-emphasis`, `fg-white fg-50` and `fg-black fg-50` for `white-50` and `black-50`, and
  `fg-{color}` for a theme color.
- <span className="badge bg-danger">Breaking</span> **`color` applies a theme class, not a
  background utility.** It rendered `bg-{color}`, which in v6 leaves the badge on the inherited
  text color instead of white — the `.badge-*` namespace carries the variants now, and the color
  comes from `.theme-*`. The prop is unchanged at the call site; only the class it emits moved.
  A bare `<CBadge>` is neutral rather than invisible, so a badge that relied on a utility for its
  background can drop it.
- <span className="badge bg-danger">Breaking</span> **`color` no longer takes a gradient.** v6
  removes the `bg-*-gradient` utilities the value mapped to.
- <span className="badge bg-danger">Breaking</span> **`textBgColor` is gone.** It emitted
  `.text-bg-{color}`, which resolves to the same two values `color` now supplies through the theme
  class — `--cui-{color}-contrast` on the text and the colour itself behind it — so the two props
  had become one. Keeping it was also destructive: `.text-bg-*` ships in the `helpers` layer and
  writes `color` and `background-color` directly, over the tokens `.badge` reads, so pairing it
  with `variant="outline"` filled in the background the variant had cleared. Use `color`.
- **New: `variant`** — `"subtle"` or `"outline"`, alongside the default solid.
- **`size` also takes `"lg"`.**

### CBreadcrumb

- <span className="badge bg-danger">Breaking</span> **A step is a padded, hoverable target.**
  `CBreadcrumbItem` renders `.breadcrumb-link` on the link its `href` produces, and wraps an active
  step in a `<span class="breadcrumb-link">` so every step keeps the same height. To keep the
  plain text link of v5, render your own link as a child instead of passing `href`.
- **New: `CBreadcrumbDivider`** — a separator you put in the markup, carrying whatever you give it:
  an inline SVG, an icon, a character. An empty one renders the default divider. The automatic
  `::before` divider steps aside wherever an element is placed, so the two never double up, and the
  component marks itself `aria-hidden`.
- **A step can open a menu.** Wrap the step's content in a `CMenu` whose `CMenuToggle` takes the
  new `custom` prop, and the toggle behaviour is wired onto your own `.breadcrumb-link` button
  instead of a `CButton`.

### CCalendar

- **Changed.** **The range band sits under the day cells and follows the theme.**
  `--cui-calendar-cell-range-bg` is `--cui-primary-bg-subtle` (the theme's `bg-subtle` under a
  `.theme-*` class) instead of a 12.5% tint laid over the cells, so the selected start and end keep
  their solid fill and the day numbers are no longer tinted. A hovered day in the range takes
  `--cui-primary-bg-muted` (the theme's `bg-muted`), one step stronger than the band.
- **Changed.** **`min-date` and `max-date` are compared by the day.** v5 compared a day cell at
  midnight with the instant, so a limit that carried a time of day, such as `:min-date="new Date()"`,
  disabled its own day. Now that day can be picked; the date picker's time selects and the field
  bound the time on it.
- **Changed.** **A week row stands for the ISO week that holds most of its days.** With
  `first-day-of-week` other than `1` a row spans two ISO weeks, and v5 numbered it by its last day but
  picked the week of its first day: a Sunday-first row from August 30 to September 5, 2026 showed
  36 and picked `2026W35`, and that value given back as `start-date` did not select the same row.
  The number, the picked value, the weeks of `start-date`, `end-date`, `min-date` and `max-date`, and
  the range and its preview now all follow the row's majority week, so that row is `2026W36` and
  the picked date is its Monday, August 31, the date `2026W36` stands for. With Tuesday to
  Thursday first, the numbers move instead, so the row from September 1 to 7 shows 36 where it
  showed 37.
- **Changed.** **In week selection `disabled-dates` disables a week only when it disables every day of
  it**, as it does for a month, quarter or year. Before, a week was disabled when its row's first
  day was: with Monday first a single disabled Monday disabled its week, and with Sunday first a
  function that disables weekends disabled every row. A range of weeks across a week that holds a
  disabled day is kept, as a range of months is.
- **Changed.** **In week selection `min-date` and `max-date` count as whole weeks**, so their weeks can
  be picked on any first day of the week, as the month, quarter or year of a limit can in those
  selections, and the months view opens a month only when its page holds a week inside them.
  Before, a `min-date` later than the first day of its row disabled that row, and with Tuesday to
  Thursday first a `max-date` of `2026W36` disabled the row of week 36.
- <span className="badge bg-danger">Breaking</span> **`start-date-change` and `end-date-change`
  receive the `Date` first**, the same shape the pickers use, and the value formatted per
  `selectionType` second — a `Date` for day selection but a string for week (`'2026W27'`), month
  (`'2026-01'`), quarter (`'2026Q1'`) and year (`'2026'`). v5 passed them the other way round.
- <span className="badge bg-danger">Breaking</span> **`selectAdjacementDays` and
  `showAdjacementDays` are spelled `selectAdjacentDays` and `showAdjacentDays`** on `CCalendar`
  and every picker built on it. The typo is fixed in the vanilla and React libraries in the same
  release.
- <span className="badge bg-danger">Breaking</span> **`date-hover` is gone** from `CCalendar`,
  `CDatePicker` and `CDateRangePicker`, as `cellHover` is from the vanilla calendar. It served the
  hover preview in the field, which went with `previewDateOnHover`. To follow the pointer or the
  focus over a `CCalendar`, listen for `mouseover` or `focusin` on an element that wraps it: each
  day, month, quarter and year cell the calendar shows carries its date in `data-coreui-date`, in
  the `toDateString()` form, and a week row carries it on the day cells it shows. Unlike the event,
  the listeners also see cells that cannot be picked, and only `mouseout` or `focusout` tells that
  the pointer or the focus left. The pickers have no replacement for it.
- <span className="badge bg-danger">Breaking</span> **Each grid is one tab stop, and `tabindex` no
  longer marks a selectable cell.** The arrows, `Home`, `End` and the page keys move within a
  calendar and Tab leaves it, which is what `role="grid"` promises. Every cell inside `minDate` /
  `maxDate` can take the focus, also one that cannot be picked: the keys stop on a date in
  `disabledDates` instead of skipping it, a screen reader announces it as unavailable, and Enter
  and Space do nothing there, so a month where nothing can be picked is explored like any other.
  A selectable day, month, quarter, year or week row carries `data-coreui-selectable`, and
  `tabindex="0"` sits on one cell per grid, so a two-month range picker keeps a stop in each
  month that reaches into the limits. Custom CSS or scripts that reached for `.calendar-cell[tabindex="0"]` need
  `.calendar-cell[data-coreui-selectable]`.
- <span className="badge bg-danger">Breaking</span> **`navigation` and `nav-year-first` are gone**
  from `CCalendar`, `CDatePicker` and `CDateRangePicker`. With `:navigation="false"` the
  month and year buttons stayed on screen but did nothing; the arrows are always there now.
  To hide them, hide `.calendar-nav-prev` and `.calendar-nav-next` in your CSS. The month and
  year buttons still open the months and years views; to keep the calendar on the month you set,
  hide `.calendar-nav` and give the month a heading of your own.
  The order of the year and the month follows the locale instead of `nav-year-first`: the year
  comes first in locales that write it first (for example Japanese, Chinese, Korean, Hungarian
  or Lithuanian).
- <span className="badge bg-danger">Breaking</span> **The navigation icon slots trade places in a
  right-to-left layout and render inside `.calendar-nav-icon`**, like the built-in chevrons. In
  right-to-left `#navPrevIcon` shows on the next button and `#navNextIcon` on the previous one, and
  the double slots likewise, so give the icons for a left-to-right page and drop any mirroring you
  did for right-to-left. `.calendar-nav-icon` is a 1rem box in the icon colour; a slot that renders
  text or a larger icon needs its own size on that class.
- <span className="badge bg-danger">Breaking</span> **The calendar's classes and data attributes are the
  vanilla calendar's.** A panel is `.calendar` without the view class (`days`, `months`, `quarters`,
  `years`) and carries its position in `data-coreui-calendar-index`; the view is named on the cell
  content instead (`.calendar-cell-inner.day`, `.month`, `.quarter`, `.year`), and quarter and year
  cells no longer carry `quarters` / `year`. The navigation buttons carry `btn-double-prev`,
  `btn-prev`, `btn-month`, `btn-year`, `btn-next` and `btn-double-next`, and
  `data-coreui-selectable` is empty instead of `"true"`, and a week row no longer carries `data-coreui-date`, which stays on its day cells. A rule that styled a
  panel by its view needs `.calendar:has(.calendar-cell-inner.month)` instead of
  `.calendar.months`, and one that styled `.calendar-cell.quarters` or `.calendar-cell.year`
  needs `.calendar-cell:has(> .calendar-cell-inner.quarter)` or `.year`, since the cell states
  (`selected`, `range`, `disabled`) stay on the cell.
- <span className="badge bg-danger">Breaking</span> **Setting `calendarDate` to `null` keeps the
  month on screen.** v5 moved the calendar back to today; to show today, pass today's date.
- **New: `view-change`** fires when the calendar switches between the days, months, quarters and
  years views, and with the starting view each time the calendar mounts.
- **The grid answers the full APG keyboard model.** On top of the arrows: `Home` / `End` move
  within the focused week, `Page Down` / `Page Up` move a month at a time (a year in the months and
  quarters views, the twelve years of a page in years), and `Shift` with either moves a year in the
  days view. A jump never lands outside `minDate` / `maxDate`: focus stops on the limit, also when
  that date cannot be picked. Every cell carries its own `data-coreui-date`.
- **`selectionType="week"` is reachable from the keyboard.** The day cells take no focus in that
  mode because the row is what gets picked, and the row itself was not a tab stop — so the grid had
  none at all and week selection was mouse-only. The rows are tab stops now, and `Home` / `End`
  move to the first and last week of the month.
- **Picking a date keeps the months on screen.** A picked day of an adjacent month
  (`selectAdjacentDays`) used to turn the calendar to that month; it now shows as selected with an
  outline on a subtle background instead of the solid fill. Without `calendarDate` the view follows
  a start date the parent changes to a new instant, the day already selected included (a Today
  button after browsing); it stays for the calendar's own picks passed back before the view moves
  and for the same instant passed again.
- A selected day or week keeps its colour under the pointer, a shade darker
  (`--cui-calendar-cell-selected-hover-bg`, `--cui-calendar-cell-selected-hover-color`); it used to
  take the hover colour until the pointer left.
- The range preview no longer stays on the date just picked, and in week selection it no longer
  drops while the pointer crosses a day of the adjacent month inside the row it previews.
- In the years view the navigation names the page it shows, `2020 – 2031`, instead of the one year the
  page is built around, so turning a page is announced as the new range. The grid label and the
  navigation write the range in the locale's own digits.
- In the years view the double arrows and `Page Down` / `Page Up` turn the calendar by the twelve
  years a page shows instead of ten, so a turn no longer repeats two years of the previous page.
- In the years view the year button goes back to the view that picks the date instead of doing
  nothing, and it is disabled in year selection, where the years view is the one that picks.
- Without `weekNumbersLabel` the week-number column is named for screen readers with the locale's
  word for week, in a visually hidden span; before, its header was empty. Each week number is named
  the same way with its number (`Week 36`), and the new `ariaWeekNumberLabel` prop takes a function
  of the week number to name it yourself.
- <span className="badge bg-danger">Breaking</span> **The years view names its double arrows with new
  `ariaNavNextYearsLabel` / `ariaNavPrevYearsLabel` props** (`'Next 12 years'` / `'Previous 12 years'`)
  instead of the year labels, which stay on the days, months and quarters views. A page that
  translates `ariaNavNextYearLabel` / `ariaNavPrevYearLabel` needs to translate these two as well.
- **A grid in which nothing can be picked is described by the new `ariaNothingToPickLabel` prop**
  (`'Nothing on this page can be picked'`), also announced when the calendar turns to such a page,
  so a page that translates the other calendar labels translates this one too.
- **A pick is announced through the new `ariaSelectedDateAnnouncement` and
  `ariaSelectedRangeAnnouncement` props** (`'Selected date: {date}'`, `'Selected range: {start} to
  {end}'`); before, picking a date with <kbd>Enter</kbd> left a screen reader silent. A page that
  translates the other calendar labels translates these two as well.
- The toggle of `CDatePicker` and of `CDateRangePicker` is named with the value the picker holds
  (`Toggle calendar, Friday, August 14, 2026`), so a screen reader reads the picked date when the
  popup closes and focus goes back to it.
- The month and year between the navigation arrows are no longer a live region. A page turn is
  announced through `announce()`, inside the panel of a date picker when the calendar sits in one,
  and a key that leaves a day or a week row names no page, since the date that takes focus names
  it: a key that moved from August 31 to September 1 used to be read twice, as the date and then
  as `September 2026`.
- A locale whose own calendar has different months (Persian by default in `fa-IR`, or an Islamic,
  Hebrew or Chinese calendar asked for with `-u-ca-`) now shows the calendar in the Gregorian
  calendar, in its own language and digits. The grid was always Gregorian, so `fa-IR` used to show
  September 1, 2026 as the 10th of Shahrivar 1405 and name the January cell Dey. Calendars that
  share the Gregorian months, such as Thai Buddhist or Japanese, keep their year numbering in the
  calendar. The date field lays out and reads Gregorian numbers for every locale, without the
  locale's era.
- The navigation writes the full year whatever `yearFormat` is, and `yearFormat` sets only the year
  cells of the years view. With `'2-digit'` the year button above September 2026 now reads `2026`
  instead of `26`.
- <span className="badge bg-danger">Breaking</span> **A cell drawn by the `dayCell` slot no longer
  gets an `aria-label`**, so its content is what a screen reader reads. Every cell slot receives the
  cell's full name as `label` (`Wednesday, August 12, 2026`, `August 2026`, `Q3 2026`, `2026`); put it
  in the cell, for example in a `visually-hidden` span next to a short visible label marked
  `aria-hidden="true"`. Day cells the calendar draws itself announce the full date with the weekday
  instead of the short numeric date (`8/12/2026`), which also leaves their `title` tooltip, and in
  week selection the row that takes focus is named by the days it spans (`August 10 – 16, 2026`),
  after its week number when week numbers are shown (`Week 33, August 10 – 16, 2026`), instead of
  reading out all seven.
- In day selection the `dayCell` slot receives `isInRange: false` for a day among an adjacent
  month's days that only fills the grid, which the range is not drawn on, as it already did for
  `isToday`. With `selectAdjacentDays` the range and its hover preview are now drawn on the adjacent
  month's days as well, and `isInRange` stays `true` for them.
- A cell that cannot be picked carries `aria-disabled="true"`: a day outside `minDate` / `maxDate`
  or in `disabledDates`, a week row, month, quarter or year outside the range, and in day selection a
  day among an adjacent month's days unless `selectAdjacentDays` is on. Such an adjacent day is no
  longer `aria-selected` either, and the `dayCell` slot gets `isDisabled: true` and `isSelected: false`
  for it, so the copy of a picked date that fills the next panel reads as unavailable filler.
- With `range`, the grid of the view that picks the range is `aria-multiselectable`, and every day,
  week row, month, quarter or year of the selected range that can be picked carries
  `aria-selected="true"`, not only its two ends, so a screen reader announces the ones in between as
  selected. The months and years views of a day range only navigate and keep it on the ends, and
  `isSelected` still marks only the ends.
- In week selection, the `#dayCell` slot gets the `isDisabled`, `isInRange` and `isSelected` of the
  day's week row, the way the calendar draws it: every day of a selected week is `isSelected`, every
  day of a week in the range is `isInRange`, and a day is `isDisabled` only when its row cannot be
  picked. Before, each field described the day alone, so a selected week reported only the day
  holding its start or end date as selected.
- A year below 100 stays as written: a calendar on December of year 99 draws the days of year 99,
  where it drew 1999, and its next panel shows January of year 100, where it showed January 2000.
  The month, quarter and year views, the arrow keys and paging keep the year the same way. Years
  before 1 cannot be picked, as dates before `minDate` cannot: their cells are disabled, and the
  arrow keys and paging stop at 1 January of year 1.
- A year string written in four digits keeps its year: `0026-05`, `0026W05`, `0026Q2`, `0026` and
  `12/31/0099` given to the calendar or a picker stand for the years 26 and 99, where they became
  2026 and 1999. Two digits still expand to the century within 50 years of today. The value reported
  for week, month, quarter and year selection writes the year in at least four digits (`0026-05`,
  where it was `26-05`), so it reads back as the same year.

### CCallout

- **New: `theme`.** It sets the color context and renders a `.theme-*` class, so the callout also
  picks up a theme class placed on any element above it. The class colors the leading edge and tints
  the border.
- <span className="badge bg-danger">Deprecated</span> **`color` still works and is removed in v7.**
  It renders the same `.theme-{color}` class as `theme` and loses to `theme` when both are set, so
  the modifier classes the component used to emit (`.callout-{color}`) are gone from its output.
- **A callout without a color no longer draws its leading edge in `currentColor`.** The class read a
  custom property that only the color modifiers declared, so on a bare `<CCallout>` the declaration
  was invalid and the property fell back to its initial value. It now defaults to the callout's own
  border color.
- **The 1px border of a colored callout is tinted** instead of staying neutral. The leading edge is
  unchanged.

### Deprecated color classes

- **`$enable-deprecated-classes` drops the v5 color modifiers from the CSS build.** It defaults to
  `true`, so nothing changes unless you set it. Set it to `false` once your markup uses the theme
  classes and `.alert-{color}`, `.btn-{color}`, `.btn-outline-{color}`, `.btn-ghost-{color}`,
  `.callout-{color}`, `.chip-{color}` and `.list-group-item-{color}` leave the stylesheet. The
  components render theme classes now, so none of them emit those spellings — the flag only affects
  markup you wrote by hand. They are removed outright in v7.

### CCard

- <span className="badge bg-danger">Breaking</span> **`text-color` is removed.** It wrote a single
  `fg-{value}` class, and the values it listed from v5 (`body-secondary`, `body-tertiary`,
  `*-emphasis`, `black-50`, `white-50`) had no rule in v6, so the text kept its inherited color. Put
  the color utility on the component instead: `class="fg-2"` for `body-secondary`, `fg-3` for
  `body-tertiary`, `fg-emphasis-primary` for `primary-emphasis`, `text-body-emphasis` for
  `body-emphasis`, `fg-white fg-50` and `fg-black fg-50` for `white-50` and `black-50`, and
  `fg-{color}` for a theme color.
- <span className="badge bg-danger">Breaking</span> **A card is roomier, rounder and framed in the solid
  border colour.** `--cui-card-spacer-y` / `-x` go from `1rem` to `--cui-spacer-6` (`1.25rem`) and the
  image-overlay padding follows them. `CCardHeader`, `CCardFooter` and a `CListGroup` placed directly in
  the card take `--cui-card-spacer-x` as their inline padding, so their text lines up with the body; the
  header and footer keep `.5rem` of block padding. The border reads `--cui-border-color` instead of
  `--cui-border-color-translucent`, except on a `translucent` card, and the radius is `--cui-radius-7`
  (`.75rem`; v5 used `.375rem`). A card filled with `textBgColor` or `color` keeps that neutral frame;
  add the matching `border-<color>` class to frame it in the fill colour. To keep the v5 look, set
  `--cui-card-spacer-y` and `-x` to `var(--cui-spacer-5)` and `--cui-card-border-radius` to `.375rem`
  on the card.
- <span className="badge bg-danger">Breaking</span> **`CCardLink` is removed.** `.card-link` is
  gone from v6 — it existed to space sibling links with an inline margin, which only worked while
  they were inline, and `.card-body` is a flex column with `--cui-card-body-gap` now. Wrap the
  links yourself: `<div class="hstack gap-4"></div>`.
- <span className="badge bg-danger">Breaking</span> **`.card-body` is a flex column.** It spaces
  its children with `--cui-card-body-gap` and zeroes their block margins, so nothing in a card
  needs `.mb-*` any more. Two consequences for existing markup: a direct child takes its natural
  width rather than filling the card — add `.w-100` where a block child has to stretch — and
  `text-align` no longer moves a button or a link, because they are flex items. Use `.mx-auto` or
  `.ms-auto` instead.
- **Stacked sections are divided by a single rule.** A `<CCardBody>`, a list group or a bottom image
  that follows a top image, a body or a list group draws a divider above itself in the card's own
  border, so two bodies in a row, or an image above a body, no longer sit with nothing between
  them, and a border utility or a theme on the card carries over to every divider. A section
  hidden with `hidden` or `.d-none` does not count. `<CCardHeader>` and `<CCardFooter>` draw their
  own divider, as before.
- **`<CCardGroup>` squares the corners at each seam along the writing direction.** The rules named
  the physical corners, so a right-to-left group squared its outer corners and rounded the ones
  that meet. A list group at the edge of a grouped card is squared like the other sections.
- <span className="badge bg-danger">Breaking</span> **`color` no longer takes a gradient.** v6
  removes the `bg-*-gradient` utilities the value mapped to. Reach for `.bg-gradient` alongside
  the color if you want the sheen.
- **Gradient bars.** `--cui-progress-bar-bg-image` paints the bar with an image over its colour, so
  a gradient is one variable in `style`; stripes layer over it and have their own
  `--cui-progress-bar-stripes` and `--cui-progress-bar-stripe-color`.
- **`segmented` and `segments` on `CProgress`.** The track becomes a row of rounded segments —
  `--cui-progress-segment-min-width` wide and `--cui-progress-segment-gap` apart, or at most
  `segments` of them — and the bar fills whole segments only, recounted as the track resizes.
  Corners come from `--cui-progress-segment-border-radius`.
- <span className="badge bg-danger">Breaking</span> **`.card-header-pills` is gone.** It pulled
  the pill row out to the header's padding edge, which is wrong for pills — they carry their own
  background, so flush against the inner edge they touch the border. Drop the class from
  `<CNav variant="pills">`.
- <span className="badge bg-danger">Breaking</span> **`<CCardGroup>` attaches from a container
  query, not a media query.** The `sm` breakpoint is the width of the nearest query container, not
  the viewport. Mark an ancestor with `.contains-inline`; without a container the query has nothing
  to read and the cards stay stacked at every width. The same applies to `<CListGroup>` with
  `layout="horizontal-*"`.
- **New: `theme`** paints the card's frame and caps with a theme color, with contrast text in the
  header and footer; the body keeps the card background. It is a different axis from `color`, which
  still applies the `bg-{color}` utility across the whole surface, and from `textBgColor`. Put the
  class on a single section — `<CCardFooter class="theme-danger">` — and only that section
  follows it.
- **New: `variant="subtle"`** swaps the solid fill for the theme's subtle background and border,
  and **new: `translucent`** blurs whatever is behind the card and thins the caps to match. They
  are independent — `.card-subtle` and `.card-translucent` combine — which is why `translucent` is
  a boolean of its own and not a second `variant` value.
- **New: `layout="row"`** lays a card out along the inline axis, with
  `<CCardImage orientation="start" | "end">` for an image cap on either side. It replaces the
  `<CRow class="g-0">` + `<CCol md="4">` recipe, which needed a wrapper per section and drew no
  divider between them.

### CCarousel

- <span className="badge bg-danger">Breaking</span> **The carousel runs on native CSS scroll
  snapping.** The track is a scroll container, so dragging, swiping, momentum and trackpad
  scrolling come from the browser; the component layers on the controls, indicators, autoplay and
  active-slide tracking. There is no `.slide` class any more, and programmatic navigation animates
  the scroll position instead of translating slides.
- <span className="badge bg-danger">Breaking</span> **`index` is renamed to `activeIndex`**, and
  the carousel now follows post-mount changes — updating the prop slides to the new index.
- <span className="badge bg-danger">Breaking</span> **`touch` and `wrap` are gone.** Touch
  gestures are the scroll container's own, and `ends` supersedes `wrap`: `'loop'` (default)
  continues seamlessly where the layout allows, `'wrap'` jumps to the other end, `'stop'` disables
  the matching control at each end.
- <span className="badge bg-danger">Breaking</span> **`CCarouselItem` drops `direction`** — the
  scroll position, not a per-slide class, decides how a slide enters.
- **New**: `autoplay` (turns off for good once the user interacts), `playPause` with
  `pauseLabel` / `playLabel` (WCAG 2.2.2), `keyboard`, `center`, `variableWidth`, and the
  `--cui-carousel-items` / `-gap` / `-peek` custom properties for multi-item layouts.

### CChip, CChipSet, CChipInput

- <span className="badge bg-danger">Breaking</span> **`CChipInput` carries its chips in a hidden
  `<textarea>`, submitted only once you name it.** It took a generated `name` when the prop was not
  set, so a form carried a key nobody chose; the field is now named only by the prop. It is a
  `<textarea>` instead of an `<input type="hidden">`, because the browser leaves a hidden input out
  of validation, and the submitted value is the same, the chips separated by commas. With it
  `CChipInput` takes `required`, `validation-state`, `update:validationState` and the feedback
  props, blocks the submit while it is empty and required, and a native form reset puts back the
  chips it started with. A disabled `CChipInput` is no longer submitted, like any disabled field.
  It renders its messages after the frame, so the component has two root nodes; reach the frame
  through the exposed `rootRef`. See [Validation](https://coreui.io/vue/docs/forms/chip-input/#validation).

- <span className="badge bg-danger">Breaking</span> **`CChip` loses the `active` prop.** `selected`
  is the single prop that renders the `.active` class on any chip; the toggle behaviour, ARIA state
  and the filter check icon apply only with `selectable` or `filter`. Replace `active` with
  `selected` on a static chip.
- <span className="badge bg-danger">Breaking</span> **The chips expose real roles.** A selectable
  `CChipSet` is a horizontal `role="listbox"` (with `aria-multiselectable` outside single mode)
  whose chips are `role="option"` carrying `aria-selected`; a non-selectable set is a
  `role="group"`. A **standalone** selectable `CChip` is a toggle button (`role="button"`) and
  reflects its state through **`aria-pressed` instead of `aria-selected`**.
- <span className="badge bg-danger">Breaking</span> **`aria-disabled` is stamped only on a chip
  that carries a role.** On a role-less chip the attribute was invalid; the `disabled` class and
  the removed interactivity carry the state.
- <span className="badge bg-danger">Breaking</span> **`CChipInput` no longer stamps
  `aria-disabled`/`aria-readonly` on its container.** The container is a generic element, so those
  attributes were invalid on it; the native `disabled`/`readonly` states of the inner input carry
  the semantics.
- **Adding and removing chips is announced.** `CChipSet` and `CChipInput` announce each change
  through `announce()`; the wording is configurable through `ariaAddedAnnouncement` and
  `ariaRemovedAnnouncement`.
- **Every remove button names its chip.** `CChip` and `CChipSet` named each remove button
  `Remove`, so a set read the same name for every chip; the button is `Remove <text>` now, as
  `CChipInput` and `CMultiSelect` already did. `aria-remove-label` (and `aria-chip-remove-label` on
  `CMultiSelect`) takes a string, where `{label}` stands for the chip's text and is appended when
  missing, or a function of the text for a different word order. A label that already spelled the
  text out now repeats it; drop it or use `{label}`.
- **A selectable chip hides its remove affordance.** A chip with a role — a selectable chip, which
  is a toggle button, or an option in a selectable set — gets a `<span aria-hidden="true">` instead
  of a `<button>` inside it, so its name is its text and a control is no longer nested in a button.
  Backspace and Delete remove it from the keyboard, the affordance from the pointer.
- **A chip set is one tab stop.** `CChipSet` and `CChipInput` gave every chip `tabindex="0"`, so
  Tab walked through each chip. The chip that last had focus is the tab stop now, the first chip
  until then, and the arrow keys move between the rest, chips without a `value` included. `CChip`
  computes its `tabindex` from `selectable`, `removable` and `disabled`; a `tabindex` passed to it is
  ignored.
- **`CChipInput` keeps focus among the chips after a removal.** Removing the focused chip sent
  focus to the text input; it now moves to the next chip, else the previous one, and reaches the
  text input once no chip is left, the rule `CChipSet` follows.

### CCloseButton

- <span className="badge bg-danger">Breaking</span> **The `white` and `dark` props are gone.** The
  glyph is drawn with a CSS mask and takes the button's inherited `color`, so on any surface that
  paints its own text — a `.text-bg-inverse` toast, a dark navbar's offcanvas — it is already the
  right color, and neither prop has anything left to do.

  `white` rendered `.btn-close-white`, which v6 removed. `dark` stamped
  `data-coreui-theme="dark"` on the button, which used to match a rule that inverted the glyph
  through a `filter`; that rule went with the mask, and what the attribute still sets — the shadow
  strength and `color-scheme` — reaches nothing the close button draws. To flip a region, put the
  attribute on the section and give it a surface (`.bg-body.text-body`); the button follows the
  text it inherits.

### CCollapse

- **The stylesheet owns the animation where the browser can interpolate a size to `auto`.**
  `CCollapse` no longer writes an inline `height`/`width` there — driving the size from the
  component as well would run the same expansion from both ends. Browsers without
  `interpolate-size` keep the measured path, and both read the duration and easing from
  `--cui-transition-collapse-duration` / `-timing` instead of a hardcoded 350 ms.
- <span className="badge bg-danger">Breaking</span> **`.collapse` stays on the element for the
  whole run.** It used to be dropped while `.collapsing` was on, which in v6 means the element
  misses `interpolate-size` and the transition the stylesheet puts on `.collapse` — so the CSS
  path would not animate at all. `.show` also lands at the *start* of the opening run rather than
  at its end, because the stylesheet reads it as the open state and animates towards it. Custom
  CSS that keyed off the old combinations needs updating.
- **New: `hiddenUntilFound`** hides the collapsed area with `hidden="until-found"` rather than
  taking it out of the layout, so find-in-page searches it and the browser expands it on a match.
  The `show` event fires when that happens — set `show` from it, or the stylesheet hides the
  content the reader was just sent to. Off by default; the attribute is left off entirely below
  Chrome 102 / Firefox 148 / Safari 26.2.

### CContextMenu

- **New component.** `<CContextMenu>` is the trigger area: a right-click, or <kbd>Shift</kbd>+<kbd>F10</kbd> /
  the <kbd>Menu</kbd> key while it has focus, opens the `<CMenuContent>` inside it at the pointer
  and suppresses the browser's own menu. It is a `CMenu` positioned against the pointer with
  `position: fixed`, so items, submenus, keyboard navigation and `autoClose` are the Menu's. Focus
  moves into the menu on open and returns to the area on close; the page does not scroll while
  the menu is open. A row's own `@contextmenu` handler runs first — prevent the event there to
  keep both menus closed.

### CDateInput, CDateRangeInput, CTimeInput

- <span className="badge bg-danger">Breaking</span> **A required field blocks the form.** The value
  moved from an `<input type="hidden">`, which the browser leaves out of validation, to a `<textarea>`
  laid invisibly over the field, with `tabindex="-1"` and `aria-hidden="true"`; a textarea, unlike a
  text input, leaves Enter submitting a form that has no submit button. A `required` field that is
  empty, incomplete or holds a rejected date now stops the submit, and the browser puts focus on its
  first empty section with its own message over the field. The field marks itself invalid whenever a
  validation reports it, also outside a submit, and its value field fires native `input` and
  `change` events when the date changes. This applies to the pickers and to both ends of a date range as well. Code that
  selects `input[type="hidden"]` inside the field needs `.form-date-time > textarea`.
- <span className="badge bg-danger">Breaking</span> **A given state is a verdict on one value.**
  `validation-state="invalid"` now blocks the submit, with the text of the message after the field,
  until it is cleared. The user's next change of the value and a native form reset emit
  `update:validationState` with `undefined` before the change is reported, so bind the state with
  `v-model:validation-state`; a value your code sets keeps the state. Without a given state the field
  shows what a validation reports and, in a form with `validate`, the `:user-invalid` and
  `:user-valid` states of its value field, as a native field does. `aria-invalid` sits on the
  sections, not on the group, and an `aria-invalid` you pass is not read as a state. This applies to
  the pickers and to both ends of a date range as well.

### CDatePicker, CDateRangePicker, CTimePicker

The pickers are no longer monoliths. Each is a composition of a **section field**, a **calendar or
time selection**, and an **anchored panel** — which is what removes most of the props below: the
field and the panel are now the same primitives you can use directly.

- <span className="badge bg-danger">Breaking</span> **`CDatePicker` is its own component.** In v5
  it was a thin wrapper over `CDateRangePicker` and inherited its props; it now has its own,
  single-date API (`date`, `v-model:date`).
- <span className="badge bg-danger">Breaking</span> **The button-configuration props are gone** —
  `todayButton`, `todayButtonColor`, `todayButtonSize`, `todayButtonVariant`, `cancelButton*`,
  `confirmButton*` and `rangesButtons*`. Project the content instead: the `footer` scoped slot
  receives the picker's context, so a button you render yourself can act on the picker and read
  its state. The same context is available to any descendant through `useDatePicker()`,
  `useDateRangePicker()` and `useTimePicker()`.

  ```vue
  <CDatePicker>
    <template #footer="{ today, clear, close, isDateSelectable }">
      <CButton :disabled="!isDateSelectable(new Date())" size="sm" @click="isDateSelectable(new Date()) && today()">Today</CButton>
      <CButton size="sm" @click="clear">Clear</CButton>
      <CButton size="sm" @click="close">OK</CButton>
    </template>
  </CDatePicker>
  ```

- <span className="badge bg-danger">Breaking</span> **`CDateRangePicker`: `ranges` is a projected
  region too.** It is a scoped slot receiving the context, so a preset button calls `setRange`
  with its own dates; `rangesButtonsColor`/`-Size`/`-Variant` are gone with it. The range is
  `startDate`/`endDate` (one-way to seed, `v-model` to bind), and the two fields take
  `startName`/`endName`.
- **A picker action shows its date in the calendar.** `setRange`, `reset`, `setDate` and `today`
  from the picker's context turn the calendar to the date they set (a range's start, else its end)
  in the view it is in, also when the value does not change and over a `calendarDate` you pass, so a
  preset clicked again after browsing brings its range back. `clear` and an invalid date leave the
  calendar where it is; a typed date, a picked time and the dates you pass move it as before.
- <span className="badge bg-danger">Breaking</span> **A date field is submitted only once you name
  it.** `CDatePicker` and `CDateRangePicker` built the name of their inputs from `id` when `name`
  was absent, so `` posted `delivery-date` and the range posted
  `delivery-start-date` / `delivery-end-date`. That fallback was deprecated in 5.3.0 and is gone:
  an `id` names the element for a label, it does not put the value in the payload. Pass `name`, or
  `startName`/`endName`, for the field to reach the server.
- <span className="badge bg-danger">Breaking</span> **The field props are gone**:
  `inputDateFormat`, `inputOnChangeDelay`, `inputReadOnly`, `placeholder`, `separator`. The value
  is a mask now — pass `format` (or a section layout) and, for the placeholder text, one prop
  per section — `dayPlaceholder`, `monthPlaceholder`, `yearPlaceholder` and the rest. The
  range placeholder also named the two fields; `CDateRangePicker` names them with
  `ariaStartLabel` and `ariaEndLabel` now ("Start date" and "End date" by default), or with
  `floatingLabels` when set. Use `readOnly` for a read-only control and `separatorIcon` for the
  artwork between the two range fields.
- **Kept.** `timepicker` still adds the time half to `CDatePicker`, now as a row of time selects
  under the calendar rather than a second panel beside it. Because the two halves own different
  parts of one value, a picker with time does not auto-close: picking a day keeps the time and
  picking a time keeps the day. `hours`, `minutes` and `seconds` narrow what the time half offers.
- **Changed.** With `timepicker`, a `min-date` or `max-date` that carries a time of day bounds the
  time on its day: the time selects disable the hours, minutes and seconds before `min-date` or
  after `max-date` there, a time the panel sets beyond the limit (the current time when that day is
  picked) moves to the limit, and a typed time beyond it marks the field invalid. A limit without a
  time of day covers its whole day.
- <span className="badge bg-danger">Breaking</span> **`hours` is 0 to 23 in every locale.** v5 read
  the list and the filter in the column's cycle, so on a locale whose v5 columns were 12-hour (the
  ones that write AM and PM in Latin letters, such as `en-US`) `:hours="[1, 3, 5, 7]"` meant 1, 3, 5
  and 7 in the morning and in the afternoon, `12` meant noon and midnight, and a filter received 1
  to 12. The 12-hour column still lists 1 to 12 next to AM/PM, but each entry now stands for the
  24-hour hours the list allows: picking an hour that only one period allows sets that period, and
  the period the picked hour does not allow is disabled. To keep such a list, name both halves:
  `:hours="[1, 3, 5, 7, 13, 15, 17, 19]"`, with `0` and `12` for `12`. More locales get 12-hour
  columns than in v5, because the columns follow the field's clock, Korean, Traditional Chinese,
  Arabic and Mexican Spanish among them; their v5 columns were 24-hour, so a list written for them
  keeps its meaning. The day period column also speaks the locale, 오전 and 오후 in Korean, where it
  read "AM" and "PM". A longer name widens its column, so `--cui-time-picker-cell-width` is now the
  narrowest a cell gets, and `--cui-time-picker-cell-padding-x` keeps the name off the cell's edges.
- <span className="badge bg-danger">Breaking</span> **The time picker's roll classes lose the `roll`
  infix, and the date picker's time controls carry its own name.** `.time-picker-roll-col` and
  `.time-picker-roll-cell` are `.time-picker-col` and `.time-picker-cell`, with
  `--cui-time-picker-col-*` and `--cui-time-picker-cell-*` in place of their `-roll-` spellings;
  `.time-picker-roll` was always present on `.time-picker-body`, so it is gone rather than renamed,
  and `--cui-time-picker-body-padding` went with it. `.time-picker-inline-icon` and
  `.time-picker-inline-select` are `.date-picker-time-icon` and `.date-picker-time-select`, with
  `--cui-date-picker-time-*` tokens, because they belong to the date picker's panel. Custom CSS
  written against any of these names needs the new one.
- <span className="badge bg-danger">Breaking</span> **`CTimePicker`: `variant` is gone.** Each
  picker has one time rendering — the time picker shows the roll, and the date picker's time half
  shows the selects, which is what v5 rendered inside a date picker with time. The selects ship in
  the date picker stylesheet, so a page that only uses the time picker no longer downloads them.
- <span className="badge bg-danger">Breaking</span> **The time selection is one tab stop.**
  <kbd>Tab</kbd> reaches the body once, <kbd>Arrow Left</kbd> and <kbd>Arrow Right</kbd> move
  between the hour, minute, second and AM/PM parts and stop at the ends, and <kbd>Arrow Up</kbd> /
  <kbd>Arrow Down</kbd> change the focused value. Both renderings answer the same keys.
- <span className="badge bg-danger">Breaking</span> **`CTimePicker`: `ampm` is gone.** The hour
  cycle follows the field's mask when it names one (`HH` vs `hh a`) and the locale otherwise.
- <span className="badge bg-danger">Breaking</span> **`closeOnSelect` and `previewDateOnHover` are
  gone.** A complete selection closes the panel unless a `footer` projects actions the user still
  needs.
- <span className="badge bg-danger">Breaking</span> **`indicator` is gone.** The button that opens
  the panel is always rendered; the `pickerIcon` slot replaces its artwork. The button that
  clears the value is the one you can switch off, with `cleaner`.
- <span className="badge bg-danger">Breaking</span> **The v1 shell class names are gone**:
  `date-picker-input`, `date-picker-input-wrapper`, `date-picker-input-preview`,
  `date-picker-cleaner`, `time-picker-input`, `time-picker-cleaner`, and the `-dropdown` panels are
  now `.date-picker-popup` / `.time-picker-popup`.
- **The panel is rendered through a portal by default** (`portal`), into `container` when given.
  It is built on the first open, not on mount.
- **New props across the family**: `cleaner` and the `cleanerIcon` slot, the `pickerIcon` slot,
  `disabled`, `show` / `v-model:show` with the `show`/`hide` events,
  `size`, and the accessible labels `ariaCleanerLabel` / `ariaPickerLabel`.
- **`CDatePicker` and `CDateRangePicker` emit `view-change`** from their calendar, with the starting
  view each time the panel opens.
- **Pickers open on the platform's dropdown keys.** `Alt`+`ArrowDown` and `F4` open the panel and
  move focus into it — onto the selected date, else today or the `minDate` / `maxDate` today falls
  outside of, also when that date cannot be picked. The
  field's own arrows keep editing the value, as `<input type="date">` does. Opening with the mouse
  moves focus in too.

### CDropdown

- **Placements are mirrored once now, by Floating UI.** The `-start`/`-end` half of a placement is
  logical — Floating UI resolves it from the writing direction of the floating element — and the
  library was mirroring it a second time, which cancelled it. In a right-to-left context that moves
  every placement whose suffix you set: `alignment="end"` now hangs from the inline end, and an
  explicit `placement="bottom-start"` opens from the right edge instead of the left. The sides are
  the other way round: Floating UI never mirrors `left`/`right`, so a logical `start`/`end` side
  still maps to the physical one the direction asks for and `dropend`/`dropstart` still swap. Also
  in this change: a `dropup` aligned to the end keeps its side (it resolved to `bottom-end`
  before), `direction="center"` resolves to `bottom` rather than `bottom-start`, a submenu in a
  right-to-left context anchors to the top of its trigger rather than the bottom, and
  `useDropdownWithFloating` asks Floating UI for a plain `bottom-start`. `CMenu`, `CSubmenu`,
  `CContextMenu` and the picker panels all resolve a placement the same way. `CTooltip` and
  `CPopover` keep mirroring a physical `left`/`right` as a v5 compatibility fallback, which is
  removed in v7.
- **A panel sent through a portal carries the direction of its trigger.** Out in `document.body` it
  no longer inherits the direction that resolves the suffix, so it would have been laid out as
  left-to-right while its trigger sat in a `dir="rtl"` subtree. A `dir` you set yourself on the
  panel is left alone.
- **`CDropdown` is now a compatibility layer over `CMenu`.** The v5 markup, class names, props and
  events keep working — the two share one engine underneath, so the dropdown also gained
  `Escape` closing regardless of `autoClose`. **Deprecation notice: `CDropdown` may be removed in
  v7** — prefer `CMenu` for new work.
- <span className="badge bg-danger">Breaking</span> `popperConfig` → `floatingConfig`, see
  [Dependencies](#dependencies).
- **`placement` takes what `CMenu` takes and wins over `direction` and `alignment`** — logical
  placements (`start`, `end`), physical ones, and breakpoint prefixes such as
  `bottom-start md:top-end`. Its default is now unset, which keeps deriving the placement from
  `direction` and `alignment` as in v5.
- <span className="badge bg-danger">Breaking</span> **A responsive `alignment` object no longer
  renders `.dropdown-menu-{sm|md|lg|xl|2xl}-{start|end}`** — those classes ship only in the opt-in
  `coreui-legacy.css`. The object becomes a responsive placement instead, so the menu keeps dynamic
  positioning at every breakpoint; a statically positioned menu (`:popper="false"`, or a navbar)
  carries the resolved placement in `data-coreui-placement`, which the stylesheet positions from.
  Custom CSS keyed on the responsive alignment classes must move to that attribute.

### CFocusTrap

- **`additionalContainer` accepts an element**, not only a ref. A ref is read when the trap
  activates, which is too early for a panel that is built on open.

### CFooter

- <span className="badge bg-danger">Breaking</span> **`CFooter` is removed.** It rendered a `.footer`
  class whose nine declarations utilities already cover, so a footer is plain markup now:
  `<footer class="d-flex flex-wrap align-items-center justify-content-between bg-3 border-top px-5 py-3">`.
  The `min-height: 3rem` floor has no utility — set it yourself where it matters, or pad with `py-4`.
- <span className="badge bg-danger">Breaking</span> **The `position` prop goes with it.** Use
  `.sticky-bottom` in place of `position="sticky"` (it pins the same way, on `--cui-z-sticky` rather
  than `--cui-z-fixed`) and `.fixed-bottom` in place of `position="fixed"`, which emitted a
  `.footer-fixed` class the PRO stylesheet has never defined.

### CForm

- **`validate` with `novalidate` validates the form on submit.** `<CForm>` stops an invalid submit
  (`submit` is emitted only for a submit that goes through), marks the invalid controls
  with `.is-invalid` and `aria-invalid`, links the message of each to it with `aria-describedby`
  while it stays invalid, and moves focus to the first. A hand-written `@submit` that only called
  `checkValidity()` and `preventDefault()` can go. The new `validate` event is emitted first; call
  `preventDefault()` on its argument to handle the result yourself.

### CFormCheck

- <span className="badge bg-danger">Breaking</span> **`hit-area` is removed.** It rendered the label
  as a `stretched-link` so a whole list group item would toggle the box; the list group item can
  be the label itself now — `<CListGroupItem as="label"> Text
  </CListGroupItem>` — which is what the stylesheet is written for.

### CFormFloating

- <span className="badge bg-danger">Breaking</span> **The placeholder shows once the field has
  focus.** It used to stay transparent in every state; it now appears under the floated label while
  the field, or the control inside a field component, has focus, and stays hidden while the label
  rests in the field. A `plainText` control keeps it hidden.
- **New: `always`** on `<CFormFloating>` and **`floatingLabelAlways`** on every form control that
  renders a floating label keep the label floated and the placeholder showing while the field is
  empty. See [Always floating](https://coreui.io/vue/docs/forms/floating-labels/#always-floating).

### CFormLabel

- <span className="badge bg-danger">Breaking</span> **`customClassName` is removed.** It was the one
  prop in the library that *replaced* the class list instead of adding to it, and only `CFormCheck`
  and `CFormSwitch` used it internally to render a label without `.form-label`; they render a plain
  `<label>` now. Pass `class` for extra classes; a label without the base class is a plain
  `<label>` element.

### CFormRange

- **Changed.** **A pressed thumb takes `--cui-primary-bg-muted`**, the theme's `bg-muted` under a
  `.theme-*` class, instead of a 30% tint of the primary color.
- <span className="badge bg-danger">Breaking</span> **`<CFormRange>` renders a wrapper.** The input
  sits inside `<div class="form-range">` as `.form-range-input`; `class`, `style`, `theme`, `dir`
  and `hidden` land on the wrapper, which carries the tokens, while every other attribute still
  reaches the input. A `label` without an `id` gets a generated one, so the label names the input.
  The component writes `--cui-range-fill` (0–1) from the value, so the track fills up to the thumb,
  a shade lighter than it, in every browser; `:track="false"` leaves it unfilled.
  `update:modelValue` fires on `input` (it fired on `change`), so a bound value follows the thumb
  while it moves; `change` still fires on release. Without `v-model` the range seeds from `value`
  (the native midpoint without it), and a form reset brings it back there.
- **`tooltips`, `tooltips-format` and `tooltip-class-name`** show the value above the thumb, on
  hover, drag and focus or `"always"`; **`ticks`** renders tick marks from an array of values,
  labels or `{ value, label, className, style }` objects, labels beneath. Both follow the vanilla
  `Range` plugin, which also reads a `<datalist>`, and share names with `<CRangeSlider>`. Several
  handles, `distance`, clickable ticks and a vertical orientation are what `<CRangeSlider>` adds.

### CHeader

- <span className="badge bg-danger">Breaking</span> **`position` renders position utilities.**
  `position="sticky"` emits `.sticky-top` in place of `.header-sticky`, which the stylesheet no
  longer defines — the two rules were identical, so the header pins exactly as before.
  `position="fixed"` emits `.fixed-top`; the `.header-fixed` class it used to render was never
  defined anywhere, so that value had no effect at all. For the bottom variants, or a responsive
  one like `.sticky-md-top`, pass the utility through `class` instead.

### CInputGroup

- <span className="badge bg-danger">Breaking</span> **Validation feedback moves out of the group.**
  The `.has-validation` class is gone, and a group keeps its corner logic by having the control as
  its last child — a `CFormFeedback` left inside squares off the end of the control it belongs to.
  Wrap the group in a `CFormField` and put the feedback after it, so the message renders under the
  whole frame. Inside a group that means a standalone `CFormFeedback` rather than the `feedback`,
  `feedback-valid` or `feedback-invalid` props, which render it next to the control.

  ```vue
  <CFormField>
    <CInputGroup>
      <CInputGroupText>@</CInputGroupText>
      
    </CInputGroup>
    <CFormFeedback validation-state="invalid">Please choose a username.</CFormFeedback>
  </CFormField>
  ```

### CLoadingButton

- **`spinnerType` is deprecated in favour of `spinnerVariant`** — the same word `CSpinner` uses for
  `border` / `grow`; the old name loses to the new one. The `click` event receives the click event,
  as on `CButton`, instead of nothing.
- **The spinner takes the button's font size.** It no longer asks `CSpinner` for `size="sm"` — a
  spinner is `1em` square in v6, so inside a button it already lands where the small size used to
  put it. Custom CSS targeting `.btn-loading-spinner.spinner-border-sm` or `.spinner-grow-sm` has
  nothing to match; the sizing classes are gone from that element.
- <span className="badge bg-danger">Breaking</span> **`disabledOnLoading` no longer renders the
  `disabled` attribute.** A disabled button drops focus, so a keyboard or screen
  reader user who pressed it landed on the page body. While loading, the button now gets
  `aria-disabled="true"` and `.disabled`, keeps focus, and ignores clicks and form submission until
  it stops. CSS or tests that read `:disabled` on a loading button should read
  `[aria-disabled="true"]` instead.
- **The start and the end of loading are announced** when the button has focus: its name followed
  by the new `ariaLoadingLabel` prop, then its name again. The spinner no longer renders
  `role="status"` or the "Loading..." text that Safari read on an idle button (while loading it is a
  `role="img"` named by `ariaLoadingLabel`), and the component's own props (`loading`,
  `disabledOnLoading`, `timeout`) no longer reach the button as attributes.

### CMenu

- **New: `custom` on `CMenuToggle`.** With it the single child element receives the toggle
  behaviour — `aria-expanded`, `aria-haspopup`, the click handler and the ref — and keeps its own
  markup and classes, instead of the toggle rendering a `CButton`. `CDropdownToggle` has carried
  the same prop since v4; this closes the gap in the component that replaces it.

### CModal, COffcanvas

- <span className="badge bg-danger">Breaking</span> **Both render a native `<dialog>`.** The
  browser provides the top layer, the `::backdrop`, focus trapping, background inertness and the
  dialog ARIA semantics, so the markup drops `role`, `aria-modal`, `aria-hidden` and
  `tabindex="-1"`, and the component no longer renders a backdrop, a focus trap or a teleport of
  its own.
- <span className="badge bg-danger">Breaking</span> **The wrapper layers are gone.**
  `.modal > .modal-dialog > .modal-content` flattens to a single `<dialog class="modal">` holding
  the header, body and footer directly. `CModal` rendered the wrappers for you, so markup written
  against the components is unchanged; custom CSS targeting those two classes is not, and the
  `contentClassName` prop goes with them.
- <span className="badge bg-danger">Breaking</span> **`teleport` and `container` are gone.** They
  existed to lift the modal out of a stacking context. A dialog opened with `showModal()` renders
  in the top layer, above every stacking context on the page, so there is nothing left to escape.
- <span className="badge bg-danger">Breaking</span> **`focus` is gone** — a modal dialog always
  traps focus, and the option could only have turned off something the browser does.
- <span className="badge bg-danger">Breaking</span> **`alignment` is gone** — the browser centers
  a modal dialog. `alignment="top"` has no replacement; a dialog that must sit at the top is a
  positioning override in your own CSS.
- <span className="badge bg-danger">Breaking</span> **`.modal-dialog-scrollable` is
  `.modal-scrollable`**, and `.modal-backdrop` / `.offcanvas-backdrop` are gone with the elements
  they styled — the backdrop is the `::backdrop` pseudo-element, themed through
  `--cui-modal-backdrop-*` and `--cui-offcanvas-backdrop-*`.
- <span className="badge bg-danger">Breaking</span> **Animation opt-out is a class now.**
  `:transition="false"` on `CModal` and `:animation="false"` on `COffcanvas` render
  `.modal-instant` / `.offcanvas-instant` instead of dropping `.fade`; the offcanvas `.showing` state class is replaced by the native `open` attribute, and
  `.hiding` carries the exit.
- **New: `:modal="false"` on `CModal`** opens the dialog non-modally, leaving the rest of the page
  interactive. **New: `animation` on `COffcanvas`.**
- **Scroll locking moved to the root element** — `dialog-open` with `scrollbar-gutter: stable`,
  instead of inline `overflow` and `padding-right` on the body.

### CNavGroup

- <span className="badge bg-danger">Breaking</span> **The group animation no longer writes `display`
  and `height` inline.** The items get `.collapsing` for the length of the run and the stylesheet
  times it; where the browser supports `interpolate-size`, nothing is written to the element at all.
  Custom CSS or tests keyed on the inline `style` the group used to carry need updating.

### COneTimePassword

- <span className="badge bg-danger">Breaking</span> **Only `COneTimePassword`'s hidden input
  carries the field's `name`.** Each `COneTimePasswordInput` was given `<name>-<index>` on top of
  it, so a six-slot field submitted seven keys where the prop is documented as the name of the
  hidden input. The slots are unnamed now, and a `name` you pass to a slot is left alone instead of
  being overwritten.
- <span className="badge bg-danger">Breaking</span> **The code is validated as one value.** It
  moved from an `<input type="hidden">`, which the browser leaves out of validation, to a text
  input laid invisibly over the group, with `tabindex="-1"`, `aria-hidden="true"`, a `pattern` for
  the full length of the code and the `required` that the slots used to carry. A `required` code
  that is empty or incomplete stops the submit, so does an incomplete code that is not required,
  and the browser puts focus on the first empty slot. Once the browser reports the code, every slot
  carries `aria-invalid="true"` and the error message while the code stays invalid, as it already
  did for `validation-state="invalid"`, and the stylesheet shows the message after the group, which
  it never did for a slot marked invalid. A native form reset returns a code without `v-model` to
  the value it was created with. Code that selects `input[type="hidden"]` inside the field needs
  `.form-otp > input:not(.form-otp-control)`, and a `data-coreui-invalid-feedback` written on the
  slots goes on `COneTimePassword`.
- <span className="badge bg-danger">Breaking</span> **`COneTimePassword` blocks the submit while
  `validation-state` (or the deprecated `invalid`) is `'invalid'`**, and emits
  `update:validationState` with `undefined` when the user changes the code or the form is reset,
  so `v-model:validation-state` drops the state. The state class moved from each
  `COneTimePasswordInput` to the `.form-otp` group, which the stylesheet colours as a whole, so CSS
  or tests keyed on `.form-otp-control.is-invalid` need `.form-otp.is-invalid`. An `aria-invalid`
  on the component or on a slot is no longer passed on, the hidden input sends `input` and `change`
  whenever the code changes, also through `v-model`, and a `class` on `COneTimePassword` joins the
  classes of the group instead of replacing them. See
  [Validation](https://coreui.io/vue/docs/forms/one-time-password-input/#validation).
- <span className="badge bg-danger">Breaking</span> **The `readonly` prop is removed, and every slot is
  editable.** A code the user cannot type has no use in a form, so a `readonly` on
  `COneTimePassword` or on a `COneTimePasswordInput` no longer makes a slot read-only; use
  `disabled` to show a code the user cannot change.

### CPasswordInput

- <span className="badge bg-danger">Breaking</span> **Renamed `ariaLabelToggler` to
  `ariaToggleLabel`.**
- <span className="badge bg-danger">Breaking</span> **The toggle icon is rendered by the component
  instead of being drawn by CSS**, and is replaceable through the new `showIcon` / `hideIcon`
  slots. `.form-password-action-icon` is gone, the frame is `.form-control-group` and the button is
  `.form-control-action`.

### CPlaceholder

- **`animation="wave"` is a sweeping highlight and the recommended loading animation.** A narrow
  bright band crosses the placeholders every 1.6s instead of a wide gradient every 2s, and it also
  works on text. The opacity pulse is `animation="pulse"` now; `animation="glow"` stays as its alias.
  The prop still has no default. The keyframes are renamed to `placeholder-pulse` with it.
  With reduced motion the wave stops and drops its mask.
- **Placeholders are paler, taller and rounded.** The resting opacity is `.18` (was `.5`) and the
  pulse dips to `.1` (was `.2`); the default height is `1.25em` (was `1em`), capped a quarter em
  below the line height so a placeholder never makes a heading taller, and `.75em`, `1em` and
  `1.75em` for the `xs`, `sm` and `lg` sizes (were `.6em`, `.8em`, `1.2em`). Each placeholder has a
  `--cui-radius-3` corner; a `CButton`, `CAvatar`, `CBadge` or `CChip` with the `placeholder` class
  keeps its own height and corners. The wave reads its own `--cui-placeholder-wave-opacity-max` and
  `-min`.

### CPopover, CTooltip

- **New: `shown` / `hidden` events**, emitted once the entry or exit transition has finished. `show`
  and `hide` keep firing when the tip starts showing or hiding, after `delay`.

### CProgress, CProgressBar

- <span className="badge bg-danger">Breaking</span> **`thin` is removed from `CProgress`.** It
  rendered `.progress-thin`, which v6 does not ship; set `height` for a slimmer bar.
- <span className="badge bg-danger">Breaking</span> **`color` no longer takes a gradient.** v6
  removes the `bg-*-gradient` utilities the value mapped to. Reach for `.bg-gradient` alongside
  the color if you want the sheen.

### CRangeSlider

- <span className="badge bg-danger">Breaking</span> **The slider renders the markup of the
  range.** It is a `<div class="form-range">` with one native `.form-range-input` per handle;
  `class`, `style`, `theme`, `dir`, `hidden`, `role`, a string `aria-label` and `aria-labelledby` land on that `div`, and other input attributes,
  such as `id` (on the first handle) and `aria-describedby`, reach the handles. The classes follow:
  `.range-slider` → `.form-range`, `.range-slider-input` → `.form-range-input`,
  `.range-slider-vertical` → `.form-range-vertical`, `.range-slider-tooltip` →
  `.form-range-tooltip` (now a `<div>`), `.range-slider-ticks`/`.range-slider-tick` →
  `.form-range-ticks`/`.form-range-tick` with the text in `.form-range-tick-label`, and the
  per-tick `.clickable` → `.form-range-ticks-clickable` on the container;
  `.range-slider-inputs-container`, `.range-slider-track` and the `.disabled` class are gone. The
  handles no longer carry `role="slider"`, `aria-valuemin`, `aria-valuemax` or `aria-valuenow`: the
  native inputs expose them.
- <span className="badge bg-danger">Breaking</span> **The handles and the track read the range's
  tokens.** `--cui-range-slider-*` is gone: set `--cui-range-thumb-*`, `--cui-range-track-*`,
  `--cui-range-track-fill-bg` (was `-track-in-range-bg`), `--cui-range-track-disabled-bg` (was
  `-disabled-track-in-range-bg`) and `--cui-range-tick-label-color` and `-font-size` (were
  `--cui-range-slider-label-*`) on the slider. The label padding has no counterpart, the tooltips
  sit like the range's without `--cui-range-slider-tooltip-margin-*`, and a vertical slider's
  height is `--cui-range-vertical-height` and its track width `--cui-range-track-height`.
- <span className="badge bg-danger">Breaking</span> **`aria-labels` is `aria-label`**, an array
  with one name per handle or a function `(index, total) => string`; a string is the attribute.
- **The slider is a group named after the field.** The `.form-range` gets `role="group"` with the
  `aria-label` string or `aria-labelledby` you pass, so a screen reader announces the field when the
  focus enters it. With several handles, each handle carries only its own name ("Minimum value");
  a single handle takes the name of the group. `aria-describedby` describes every handle, and a
  `role` you pass replaces `group` on the slider.
- **The slider takes a validation state.**
  `validation-state` shows on the slider and on the handles, and `'invalid'` blocks the submit
  through the first handle until the user moves a handle or the form is reset; the slider emits
  `update:validationState` with `undefined` then. See
  [Validation](https://coreui.io/vue/docs/forms/range-slider/#validation).
- <span className="badge bg-danger">Breaking</span> **`labels` is `ticks`, `clickableLabels` is
  `clickableTicks`.** An entry is a number (a tick without text), a string (a label placed by its
  position), or `{ value, label, className, style }`; a bare VNode is no longer an entry, pass it
  as `{ label: h('strong', 'High') }`.
- **Interaction follows the native control.** Pressing a handle no longer moves it; a press on the
  track or a clickable tick moves the nearest handle and it follows the pointer (mouse, touch or
  pen); a form reset restores `value`. A slider bound with `v-model` whose parent ignores the
  update keeps the handle on its value instead of letting it follow the pointer until the drag
  ends.
- **`tooltips` takes `"always"`.** `true` shows a handle's tooltip on hover, drag and focus;
  `"always"` keeps them on.

### CRating

- **A read-only rating submits its value under the `name` you give it.** `readOnly` used to
  disable the radios, so the form left the value out; now they stay enabled, the mouse and the
  keyboard cannot change them, only the checked star takes focus (the first star while no star is checked), and the group carries
  `aria-readonly="true"`. A read-only rating without `name` still submits nothing.
- **A star with keyboard focus shows the focus ring.**
- **A read-only rating shows no tooltips.**
- **The rating takes a validation state and can be required.** `validation-state` colours the
  focus ring, and `'invalid'` sets `aria-invalid` and blocks the submit until
  you drop the state; the rating asks for that with `update:validationState` and `undefined` when
  the user picks or clears a star or the form is reset. `required` makes every radio required. See
  [Validation](https://coreui.io/vue/docs/forms/rating/#validation).
- **Empty stars are `--cui-fg-4`**: gray-500 in the light scheme and gray-600 in the dark one, the
  lightest grays that keep 3:1 against the page background. The empty stars of v5 were 38% of the
  text colour, below 3:1 against the page in the light scheme.

### CSidebar

- **`visible-change` is deprecated in favour of `in-viewport-change`.** The event reports whether
  the sidebar is on screen — it is off-canvas on narrow viewports — not the `show` state, and the
  old name read like the latter's twin. Both fire while listened to.
- **Theme variants.** A `.theme-{color}` class on the sidebar paints the surface, text, icons and
  the hover and active links from that colour's slots.
- **`color-scheme="light"` joins `color-scheme="dark"` as the scheme switch**, so a light
  navigation column can sit on a dark page.
- **Hover and active links read the foreground ladder** instead of the pure black/white emphasis
  color and a Sass-computed translucent background — slightly stronger on a light sidebar,
  slightly weaker on a dark one. Set `--cui-sidebar-nav-link-hover-bg` / `-active-bg` on the nav
  for a different tint.

### CSmartTable

- <span className="badge bg-danger">Breaking</span> **The props are renamed.** Every filter prop
  says which filter it means, the column configuration drops the v3 underscores and the sorter
  icons take the names the other data components use:

  | v5 | v6 |
  | --- | --- |
  | `itemsNumber` | `totalItems` |
  | `tableFilter`, `tableFilterValue` | `globalFilter`, `globalFilterValue` |
  | `tableFilterLabel`, `tableFilterPlaceholder` | `globalFilterLabel`, `globalFilterPlaceholder` |
  | `:columnSorter="{ resetable: true }"` | `:columnSorter="{ resettable: true }"` |
  | `Column._style`, `Column._props` | `Column.headerStyle`, `Column.headerProps` |
  | `Column._colStyle`, `Column._colProps` | `Column.cellStyle`, `Column.cellProps` |
  | `Column.sorter: false` | `Column.sortable: false` (`sorter` is the comparator only) |
  | `Column.filter: false` | `Column.filterable: false` (`filter` is the custom filter only) |
  | `FooterItem._props` | `FooterItem.props` |
  | `elementCover` slot | `loadingContent` prop and slot |
  | `sortingIcon`, `sortingIconAscending`, `sortingIconDescending` slots | `sortNeutralIcon`, `sortAscendingIcon`, `sortDescendingIcon` props and slots |
  | `@table-filter-change` | `@global-filter-change` |
  | `@selected-items-change` | `@selected-change` |
  | `@select-all` | — (`@selected-change` carries the same information) |

- <span className="badge bg-danger">Breaking</span> **A column group is `{ label, children }`.**
  The group label moves from `group` to `label` and a group no longer needs a `key`:
  `{ group: 'Address', key: 'address', children: [...] }` becomes
  `{ label: 'Address', children: [...] }`.

- <span className="badge bg-danger">Breaking</span> **One `external` prop replaces the six
  `external` options.** `columnFilter`, `tableFilter`, `columnSorter`, `pagination`,
  `itemsPerPageSelect` and `selectAll` each carried an `external` flag; `external` on the table
  says the same thing once — the items arrive already filtered, sorted and sliced, so the table
  renders them as they are and only reports the requested state. Pair it with `totalItems` so it
  can compute the number of pages. Where the option only meant "let the parent own this piece of
  state", pass the controlled prop instead.

- <span className="badge bg-danger">Breaking</span> **`SorterValue` is `{ column, direction }` and
  the sorter value is always an array.** `state: 'asc' | 'desc' | 0` becomes
  `direction: 'asc' | 'desc'`, with an absent entry standing for "not sorted", and
  `sorterValue`, `defaultSorterValue` and the `sorter-change` payload are `SorterValue[]` whether
  or not `:columnSorter="{ multiple: true }"` is set — no more `Array.isArray` at the call site.

- <span className="badge bg-danger">Breaking</span> **`Item._selected` is removed.** Seed the
  selection with `defaultSelected`, or own it with `selected` — the flag in the data was a second
  source of truth and the two drifted apart.

- <span className="badge bg-danger">Breaking</span> **`activePage`, `itemsPerPage`, `selected`,
  `sorterValue`, `columnFilterValue` and `globalFilterValue` are controlled props.** They no longer
  seed the state and then let the table take over: what you pass is what renders, and an
  interaction only emits the matching event. Use `defaultActivePage`, `defaultItemsPerPage`,
  `defaultSelected`, `defaultSorterValue`, `defaultColumnFilterValue` and
  `defaultGlobalFilterValue` to seed a table that manages itself.

- **The selection checkboxes and the cleaner have accessible names.** `ariaSelectAllLabel`
  (`'Select all rows'`), `ariaSelectRowLabel` (`'Select row'`) and `ariaCleanerLabel`
  (`'Clear filters and sorting'`) name controls that a screen reader announced as unlabelled
  before.

- **`itemKey` identifies a row.** With it set, the selection and the row keys compare
  `item[itemKey]` instead of the whole object, so a selected row survives a re-fetch of the data.
  The internal `_id` the component used to inject into every item — and leak back through
  `row-checked` and the selection payload — is gone.

- **The layout is composable.** `<CSmartTable>` provides its state to
  `<CSmartTableFilter>`, `<CSmartTableCleaner>`, `<CSmartTableContent>`,
  `<CSmartTablePagination>` and `<CSmartTableItemsPerPage>`, and renders the familiar toolbar,
  table and pagination row only while its default slot is empty. Fill the slot and you place those
  parts yourself; `useSmartTableContext()` reads and writes the same state from a component of your
  own. See the [smart table](https://coreui.io/vue/docs/components/smart-table/#custom-layout).

- **The state runs in a composable of its own.** `useSmartTable(options)` takes the state props of
  the table — refs, getters or plain values — and returns the filtered, sorted and paginated items
  together with the selection and the writers, without rendering anything. Use it when the data
  needs a layout a table cannot give it, a list of cards or a chart.
  See [headless](https://coreui.io/vue/docs/components/smart-table/#headless).

- **The selection checkboxes render `.check` instead of `.form-check-input`.** The row cells render
  `<CCheckbox>`, the select-all header cell the same bare `<input class="check">` — custom CSS keyed
  on `.form-check-input` inside the table needs updating.

### CSpinner

- **`visuallyHiddenLabel` is deprecated in favour of `ariaLoadingLabel`**, which works as
  `ariaLoadingLabel` does on `CLoadingButton`: the text defaults to `'Loading'` instead of
  `'Loading...'`, and an empty string hides the spinner from screen readers. `visuallyHiddenLabel`
  still sets the text while `ariaLoadingLabel` is unset.

- **Spinners are sized in `em`, not `rem`.** A spinner is `1em` square now, so it takes the font
  size of whatever it sits in instead of being a fixed 32 px block. Inside a button or a heading it
  lands at the size you previously had to ask for with `size="sm"`; standalone it is half of what it
  was. Set `--cui-spinner-width` / `--cui-spinner-height` to go back to a fixed size.

- **`size="sm"` renders `.spinner-sm`, not `.spinner-border-sm` / `.spinner-grow-sm`.** The prop is
  unchanged; only custom CSS targeting the old per-type classes needs updating.

- **`.spinner-grow` eases with `ease-in-out`** instead of pulsing linearly. Override
  `--cui-spinner-animation-timing-function` to change either spinner's easing.

- **`.spinner-rotate` is new.** Pass it through `class` on any element to spin your own artwork
  without inheriting the bordered circle.

### CStepper

- <span className="badge bg-danger">Breaking</span> **`--cui-stepper-step-indicator-active-bg` is removed.** The active step's
  indicator background is a 5% tint of the stepper's theme color, or of
  `--cui-stepper-step-indicator-active-color` without one. To give it another background, set
  `--cui-stepper-step-indicator-bg` on `.stepper-step-button.active` in your stylesheet.

- **A failed step moves focus to the first invalid control, and the panes are no longer live
  regions.** With a `novalidate` form the invalid controls also get `aria-invalid`, and the message
  is read with the field: the stepper adds the `.invalid-feedback` that follows the control, which
  covers `feedback-invalid`, or the elements named in `data-coreui-invalid-feedback`, to its
  `aria-describedby`. The panes used to read out every message that appeared in them; a message that
  changes while the user types is now silent, so pass the ones that have to be heard to
  [`announce()`](https://coreui.io/vue/docs/accessibility/screen-readers/#announcing-messages).
- **`stepValidationComplete` is emitted before the stepper decides.** A validity its handler sets
  with `setCustomValidity()` blocks the step, and `isValid` tells whether every control passed
  before the handler ran. A `novalidate` step form is marked each time the step is validated, also
  when it passes, so `data-coreui-validate="valid"` now marks the valid controls of a passing step
  with `.is-valid`.
- **`next()` on the last step finishes the stepper**, as `finish()` does: it validates the step and
  emits `finish` when it passes. It used to do nothing there.
- **A non-linear stepper validates the step being left.** With `:linear="false"`, clicking a later
  step used to skip validation; it now runs it like `next()` does and stays put while the step is
  invalid. Going back is never blocked. Add `:validation="false"` for the old behaviour.

### CTable

- <span className="badge bg-danger">Breaking</span> **`caption` is the caption and `captionTop` is
  a boolean.** `caption="top"` no longer carries a magic value and `captionTop` no longer carries
  text: `<CTable caption="top"><CTableCaption>…</CTableCaption></CTable>` becomes
  `<CTable caption-top>…</CTable>`, and `` becomes
  ``.
- **New: `card`** wraps the table in a card's border and corner radius, clips its cells and drops
  its bottom margin and the borders that would stack on the frame. With `responsive` the class lands on the same
  wrapper. See [Card-like tables](https://coreui.io/vue/docs/components/table/#card-like-tables).

### CToast and CToaster

- <span className="badge bg-danger">Breaking</span> **`CToaster` renders a store.** `createToaster()` creates a store of toasts outside the component tree, and `` renders a `<CToast>` per entry: `add()` returns the id and upserts when the id exists (a closing toast is replaced), `update()` rewrites in place, `close()` hides one or all, `promise()` follows an operation through loading, success and error; `limit` keeps the newest toasts visible and parks the rest with `inert`, `priority: 'high'` picks the assertive live region. `useToaster()` returns the store inside a `<CToaster>`. Without the `toaster` property the component stays the slot container it was.
- <span className="badge bg-danger">Breaking</span> **`CToast.index` is removed** and the `close` and `show` events no longer carry the index argument. Key your toasts by id and read it from your own state; the toaster does that for you.
- <span className="badge bg-danger">Breaking</span> **A toast rendered by a store carries no `role` or `aria-live`.** Every added or updated toast passes its `title` and `description` to `announce()`, which reads them as a message at the priority `priority` selects, so an update announces without the toast element changing role. A standalone `<CToast>` keeps its `role="alert"` and `aria-live="assertive"` defaults.
- **New toaster options.** `ariaLabel` names the `region` landmark, `enter` and `leave` pick the edges a toast slides in from and out to, `pauseOnHover` stops every timer while the pointer or focus is inside the container, and `stack` lays the toasts out as a deck that spreads on hover. See the [toaster](https://coreui.io/vue/docs/components/toaster/).
- <span className="badge bg-danger">Breaking</span> **`CToaster` places itself with the `toast-container-{placement}` classes** (nine values, `top|middle|bottom` × `start|center|end`) instead of the `position-fixed top-0 end-0` utility stack. Custom CSS targeting those utilities on the container needs updating.
- **New: `translucent`** renders `.toast-translucent` — the background shows through the toast,
  blurred, and the header thins out with it.
- **The fade moved to CSS.** The toast no longer renders the `fade` and `showing` helper classes
  and no longer drives its own opacity — `show` alone drives the transition, with
  `@starting-style` supplying the state to animate from and a discrete `display` transition
  keeping the toast laid out until the fade-out finishes. `:animation="false"` now renders
  `.toast-instant` instead of dropping `fade`, and finishes both directions immediately.
  The prop itself is unchanged; only custom CSS targeting `.toast.fade` or `.toast.showing`
  needs updating. Tune the motion with `--cui-toast-transition-duration` and
  `--cui-toast-transition-timing`.

### CWidgetStatsA – CWidgetStatsF

- <span className="badge bg-danger">Breaking</span> **The six widget components are removed.** They
  were the one family in the library with no stylesheet of their own: each rendered a `CCard` and a
  fixed stack of utility classes, so they carried a layout decision rather than styling you cannot
  write in place. Compose the same markup directly, which also lets a widget diverge from the six
  shapes we happened to ship:

```vue
<!-- Before -->
<CWidgetStatsF color="primary" title="Users" value="87.500">
  <template #icon>
    <CIcon :icon="cilSettings" size="xl" />
  </template>
</CWidgetStatsF>

<!-- After -->
<CCard>
  <CCardBody class="d-flex flex-row align-items-center">
    <div class="me-4 fg-white bg-primary p-4">
      <CIcon :icon="cilSettings" size="xl" />
    </div>
    <div>
      <div class="fs-6 fw-semibold fg-primary">87.500</div>
      <div class="fg-2 text-uppercase fw-semibold small">Users</div>
    </div>
  </CCardBody>
</CCard>
```

- **The six shapes live on as [blocks](https://coreui.io/vue/docs/blocks/widgets/).** Every one of them is on that page as
  markup to copy, with the names they go by now: `CWidgetStatsA` is the stat with a chart,
  `CWidgetStatsB` the stat with a progress bar, `CWidgetStatsC` the one with an icon and a progress
  bar, `CWidgetStatsD` the stat group, `CWidgetStatsE` the compact stat and `CWidgetStatsF` the stat
  with an icon.
- **Three of them did not survive the v6 stylesheet unchanged, which is the other half of the
  reason they are going.** `CCardBody` became a flex column in v6, so `CWidgetStatsA` stacked its
  menu under the figure instead of putting it in the corner, `CWidgetStatsF` stacked its icon above
  the text, and `CWidgetStatsD` stacked its values instead of laying them in a row. The blocks carry
  the `flex-row` and `w-100` those layouts now need.
