Migration
Migrating from 0.5 to the 1.0 line
Every verified packaging, behavior and peer-range change between the 0.5 baseline and the current 0.x line that leads to 1.0, with before/after examples.
Quartz has not released 1.0. This page covers the development path from the 0.5 baseline to the current 0.x line and lists only changes that are
recorded in CHANGELOG.md, the per-release acceptance records under docs/releases/ and the code. Releases not listed here changed nothing you
need to act on. Public signatures are guarded by docs/api/snapshots/; the current list of exports is in docs/api/API_INVENTORY.md.
Do these first
- Install both scoped packages at the same version; Primitives declares
@quartz-headless/coreat that version as a peer (^X.Y.Zfor stable releases, the exact version for-beta.N/-rc.N):npm install @quartz-headless/core@X @quartz-headless/primitives@X. - Use Angular
^21.2.0 || ^22.0.0(see Peer ranges). - Rebuild with
strictTemplatesand fix compile errors, then re-run your keyboard and focus tests against the behavior changes below.
Packaging (0.2.0)
| Before | After | |
|---|---|---|
| npm package | one unscoped package, quartz-headless |
@quartz-headless/core and @quartz-headless/primitives |
| Status of the old | — | frozen at 0.2.1; no further releases |
quartz add <ui> |
copied Core source next to a Primitive | prints npm install @quartz-headless/core; Core pieces still copy |
| Forms (0.9) | not available | optional entry @quartz-headless/primitives/forms; @angular/forms is an optional peer |
// before
import { OverlayTriggerDirective } from 'quartz-headless';
// after (OverlayTriggerDirective is a Core export; accessible patterns such as DialogService are in Primitives)
import { OverlayTriggerDirective } from '@quartz-headless/core';
import { DialogService } from '@quartz-headless/primitives';
0.5 baseline
Button-first Checkbox/Switch/Toggle hosts, the committed Switch output, non-interactive Tooltip and the TreeNodeContext shape — see
Migrating to the 0.5 baseline.
<!-- before -->
<div qzSwitch (toggled)="save($event)">Notifications</div>
<!-- after -->
<button qzSwitch [(checked)]="enabled" (checkedChangeCommitted)="save($event)">
Notifications
</button>
0.7 — Core behavior fixes (no export, signature or selector change)
isFocusable(plainDiv)is nowfalse; give the element atabindex(usually-1) beforefocusSafely(div).closeOnScroll: falsenow follows scrolling instead of staying put; an anchor removed from the document closes the overlay.flipAxis: 'cross' | 'both'flip as documented (previously equal to'main').ViewportService.height()follows height-only resizes;CollectionStore.typeahead()with no match keeps the active item.
0.8 — modal isolation
Rendering a Dialog now makes the rest of the page inert (or aria-hidden as fallback). Content you render into <body> while a modal is open is
treated as background. A Dialog needs an accessible name: bind a title to ariaLabelledBy, use a valid configured id, or set ariaLabel.
TooltipDirective now appends/removes its own id in aria-describedby instead of overwriting it.
0.9 — Forms and selection
- Angular Forms adapters moved to the secondary entry (
QUARTZ_FORMS):import { QUARTZ_FORMS } from '@quartz-headless/primitives/forms'. SelectOptionDirective.labelis now() => string(default: the option text). The template syntax[qzSelectOptionLabel]is unchanged.- Tabs and Accordion no longer rewrite a bound value during teardown; Select typeahead no longer throws for options without a label.
0.10 – 0.16 — additive
Existing exports and selectors are unchanged (see 0.9 → 0.10 and 0.10 → 0.11). Behavior to check:
- Combobox ignores input during IME composition, reports
valueChangeCommitted(null)when a selected value is edited, andcloseOnSelectdefaults per mode. ToggleGroupno longer rendersaria-orientationon itsrole="group"host; usedata-qz-orientation.SplitterHandleDirectivereportsaria-orientationas the separator's own axis (a horizontal container's handle isvertical); the secondary panel usesflex: 1 1 0%instead of a computed percentage.- Documentation URLs moved to
/docs/core/*and/docs/primitives/*; old root URLs redirect.
0.17 — consumers, SSR and hydration
- IDs: generated ids come from the application-scoped
QzIdGenerator(@quartz-headless/core). Server renders are identical across requests and ids survive hydration. If you relied on module-global counters or a specificqz-*-Nvalue, stop: bind your ownidwhere you need a stable one. - NavigationMenu no longer puts
aria-orientationon its plain<ul>; Sidebar starts closed on a first render at a mobile width. - CLI:
quartz addplans first, refuses to overwrite modified files without--force, is repeatable, rolls back on failure and supports--dry-run/--output. - Angular peers are
^21.2.0 || ^22.0.0(were^21.0.0): Angular 21.0 fails to build because the Toast template uses an arrow function that needs 21.2.
Peer ranges
| Package | Peer | Range |
|---|---|---|
| both | @angular/core, @angular/common |
^21.2.0 || ^22.0.0 |
| both | rxjs |
^7.8.0 |
| Primitives | @quartz-headless/core |
same version as Primitives (^X.Y.Z; exact for pre-releases) |
| Primitives | @angular/forms |
^21.2.0 || ^22.0.0, optional |
What is not promised
Unsupported Angular or Node versions, deep imports into dist/, ɵ-prefixed or non-public members, and any export not in docs/api/API_INVENTORY.md. 1.0 is not
declared; the freeze rules are in docs/api/FREEZE_POLICY.md.