Migrating to v4
Apps using a framework integration can upgrade without changing their CSS Hooks
code, but @css-hooks/core has an updated setup API and some framework
integrations have updated compatibility requirements.
Core setup
buildHooksSystem has been renamed to createHooksSystem. It now returns an
object containing createHooks and mergeStyles, rather than returning
createHooks directly. Destructure the functions your integration needs from
the result:
// v3 import { buildHooksSystem } from "@css-hooks/core"; const createHooks = buildHooksSystem<CSSProperties>(stringify); // v4 import { createHooksSystem } from "@css-hooks/core"; const { createHooks, mergeStyles } = createHooksSystem<CSSProperties>(stringify);
The new mergeStyles function is bound to the same CSS properties type as
createHooks and preserves contextual style inference when it is used in a
pipeline.
Framework compatibility
Preact
@css-hooks/preact now supports Preact v11 and requires Preact v10.27.2 or
later. Upgrade Preact before upgrading CSS Hooks if your app uses an earlier
Preact v10 release.
Solid
@css-hooks/solid now targets Solid v2 through @solidjs/web instead of Solid
v1 through solid-js. Migrate your app to Solid v2 before upgrading CSS Hooks.
See the Solid quickstart for the package,
Vite plugin, and TypeScript configuration changes.
Qwik
@css-hooks/qwik now targets Qwik v2 through @qwik.dev/core instead of Qwik
v1 through @builder.io/qwik. Migrate your app to Qwik v2 before upgrading CSS
Hooks. See the Qwik quickstart for the
package, optimizer import, and TypeScript configuration changes.
Property conflict protection
The React, Preact, Qwik, and Solid integrations now use TypeScript to prevent conflicting CSS declarations across base and override styles. For example, v3 allowed a shorthand and one of its longhands to be mixed:
pipe({ margin: 0 }, on("&:hover", { marginTop: 8 }));
This can produce unexpected results because the declarations can overwrite one another. In v4, it is a type error. Use the same property for the base and override values instead:
pipe({ marginTop: 0 }, on("&:hover", { marginTop: 8 }));
Protection includes shorthand and longhand properties, physical and logical
equivalents, aliases, and conflicts across multiple on calls. Because some of
these declarations only overlap in certain writing modes, the check is
intentionally conservative; prefer using a consistent property throughout a
pipeline.
TypeScript must retain the specific keys in each style object for accurate
checking. If you explicitly annotate a reusable style with a broad framework
type such as CSSProperties, use satisfies instead:
const baseStyle = { color: "black", } satisfies CSSProperties;
This protection is compile-time only. JavaScript users and custom integrations
built directly with @css-hooks/core do not receive it automatically.