Change8

component@0.6.0

Breaking Changes
📦 remixView on GitHub →
6 breaking9 features🐛 1 fixes🔧 10 symbols

Summary

This release introduces a major shift towards a mixin composition model in @remix-run/component, removing several legacy host element props (`on`, `css`, `animate`, `connect`) and deprecating the entire @remix-run/interaction package. It also updates server rendering to require explicit head element rendering.

⚠️ Breaking Changes

  • Removed legacy host-element `on` prop support in `@remix-run/component`. Fix: Use the `on()` mixin instead: `<button mix={[on('click', () => {})]} />` instead of `<button on={{ click() {} }} />`. Component-level `handle.on(...)` remains supported.
  • Removed legacy host-element `css` prop runtime support in `@remix-run/component`. Fix: Use the `css(...)` mixin instead: `<div mix={[css({ color: 'red' })]} />` instead of `<div css={{ color: 'red' }} />`.
  • Removed legacy host-element `animate` prop runtime support in `@remix-run/component`. Fix: Use animation mixins instead: `<div mix={[animateEntrance(), animateExit(), animateLayout()]} />` instead of `<div animate={{ enter: true, exit: true, layout: true }} />`.
  • Removed legacy host-element `connect` prop support in `@remix-run/component`. Fix: Use the `ref(...)` mixin instead: `<div mix={[ref((node, signal) => {})]} />` instead of `<div connect={(node, signal) => {}} />`.
  • The `@remix-run/interaction` package has been removed. `handle.on(...)` APIs were also removed from component and mixin handles. Migration requires replacing `@remix-run/interaction` APIs with equivalent APIs from `@remix-run/component`. Specifically, replace `on(target, listeners)` with `addEventListeners(target, handle.signal, listeners)` and replace `defineInteraction` patterns with `createMixin` and `on` mixins.
  • Render head content manipulation: `renderToStream()`, hydration, client updates, and frame reloads no longer hoist bare `title`, `meta`, `link`, `style`, or `script[type="application/ld+json"]` elements into `document.head`. Fix: Render head content inside an explicit `<head>` or pass values like `title` to a layout component that renders the head.

Migration Steps

  1. Replace usage of the host `on` prop with the `on()` mixin: `<button mix={[on('click', () => {})]} />`.
  2. Replace usage of the host `css` prop with the `css(...)` mixin: `<div mix={[css({ color: 'red' })]} />`.
  3. Replace usage of the host `animate` prop with animation mixins: `<div mix={[animateEntrance(), animateExit(), animateLayout()]} />`.
  4. Replace usage of the host `connect` prop with the `ref(...)` mixin: `<div mix={[ref((node, signal) => {})]} />`.
  5. Remove dependency on `@remix-run/interaction`. Replace APIs like `defineInteraction` and `createContainer` with `createMixin` and other APIs from `@remix-run/component`.
  6. Replace `handle.on(target, listeners)` with `addEventListeners(target, handle.signal, listeners)` within component handles.
  7. Ensure all head content (`title`, `meta`, `link`, etc.) is rendered inside an explicit `<head>` element in server-rendered components or passed explicitly to layout components.
  8. Update `run()` initialization to `run({ loadModule, resolveFrame })` if using custom frame resolution logic.

✨ New Features

  • Added the new host `mix` prop and mixin authoring APIs in `@remix-run/component`, including exports: `createMixin`, `MixinDescriptor`, `MixinHandle`, `MixinType`, `MixValue`, `on(...)`, `ref(...)`, and `css(...)`.
  • Added new interaction mixins for normalized user input events: `pressEvents(...)` for pointer/keyboard "press" interactions and `keysEvents(...)` for keyboard key state events.
  • Added mixin-first animation APIs for host elements: `animateEntrance()`,`animateExit()`,`animateLayout()`.
  • The `mix` prop now accepts either a single mixin descriptor or an array of mixin descriptors.
  • Allow client `resolveFrame(...)` callbacks to return `RemixNode` content in addition to HTML strings and streams.
  • Automatically intercept anchor and area navigations through the Navigation API, supporting `rmx-target`, `rmx-src`, and `rmx-document` attributes.
  • Added imperative frame-navigation runtime APIs and a `link(href, { src, target, history })` mixin for declarative client navigations. `run()` initialization signature changed, and new exports include `navigate(href, { src, target, history })`.
  • Allow `resolveFrame(src, signal, target)` to receive the named frame target for targeted reloads.
  • Added SSR frame source context for nested frame rendering via `frameSrc` and `topFrameSrc` arguments to `renderToStream()`.

🐛 Bug Fixes

  • Frame updates now clear previously rendered HTML before mounting new node-based content when `resolveFrame` returns `RemixNode` content.

Affected Symbols