What changed
useMachine signature
useMachine now returns a service object instead of a [state, send] tuple. The machine definition is passed directly as an object — no longer as a function call.
TypeScript caveat for generic components
Becausemachine is now an object rather than a function, TypeScript inference is limited for generic components such as combobox and select. Use the exported Machine type to cast:
Controlled vs uncontrolled value
Previously, you passed the initial value to the machine constructor and a controlled value inside a separatecontext option — a pattern that was error-prone and confusing.
Now both options live at the same level with explicit names:
value prop.
Controlled vs uncontrolled open state
The same pattern applies to disclosure components (Dialog, Popover, Tooltip, etc.). Theopen.controlled workaround is removed:
Type renames
TheContext type exported by each component package is renamed to Props:
Toast
The toast component now requires you to create an explicit store (manager) and pass it to the machine. This removes the need to propagate thetoaster through React context.
For Solid.js users: use the
<Key> component exported from @zag-js/solid when mapping over toast items instead of <For>.Removed
useActor hook
useActor hook
useActor is removed. Use useMachine everywhere instead.open.controlled context property
open.controlled context property
Replaced by the explicit
defaultOpen and open props described above.Pagination: api.setCount
Pagination: api.setCount
Removed. Pass
count as a prop directly to the machine instead:Select and Combobox: api.setCollection
Select and Combobox: api.setCollection
Removed. Pass
collection as a prop directly:Bug fixes
- Menu: Fixed context menu not updating positioning on subsequent right-clicks.
- Avatar: Fixed
api.setSrcnot working. - File Upload: Fixed drag-and-drop failing when
directoryistrue. - Carousel: Fixed initial page not being applied correctly. Fixed pagination sync breaking after interacting with dot indicators.
Performance
Zag v1 eliminates the external store in favor of each framework’s native reactive primitives. The following benchmarks measure mount time for 10,000 instances of each component.Avatar — ~27% faster mount, ~99% faster update
Avatar — ~27% faster mount, ~99% faster update
Accordion — ~61% faster mount
Accordion — ~61% faster mount
Collapsible — ~65% faster mount
Collapsible — ~65% faster mount
Dialog — ~80% faster mount
Dialog — ~80% faster mount
Editable — ~56% faster mount
Editable — ~56% faster mount
Tooltip — ~82% faster mount
Tooltip — ~82% faster mount
Presence — ~64% faster mount
Presence — ~64% faster mount
Tabs — ~6% faster mount
Tabs — ~6% faster mount
Bundle size
The@zag-js/core package powers every component. In v1 it is under 2 KB minified — a 98% reduction.
| Size | |
|---|---|
| Before | 13.78 KB |
| After | 1.52 KB |
Notes for contributors
activitiesis renamed toeffects.prop,context, andrefsare now passed explicitly to the machine. Previously everything was folded intocontext, which had a measurable performance cost.- The
watchsyntax has changed significantly. Refer to any built-in machine for the current pattern — it works similarly touseEffectin React, with an explicit dependency-tracking step. createMachineis now an identity function. The machine’s reactive work is performed inside the framework’suseMachinehook rather than at construction time.