Translate familiar interface concepts into React composition, explicit state, and supported Liquidify components.
Liquidify uses concepts that may be familiar to SwiftUI developers: composable controls, semantic roles, visual variants, and interfaces driven by state. Those similarities can help you understand the library. React remains the programming model, and SwiftUI code and modifiers cannot be used directly.
| SwiftUI concept | React and Liquidify approach |
|---|---|
| A hierarchy of views | React elements composed through JSX and children |
| Local state | React state owned by a component |
| A binding to a value | A controlled prop and change callback, such as Toggle's checked and onChange |
| A button action | Button's onPress callback |
| A button style | A supported Button variant |
| Shared environment configuration | A documented provider, where Liquidify supplies one |
These relationships describe a way of thinking. A controlled prop and callback are separate inputs to a React component, not a SwiftUI binding object. The mappings do not imply equivalent lifecycle behavior, inherited styling, or platform services.
Import named components from the public package entry points. Pass content through children and configure supported behavior through props. Use React composition to combine controls with the rest of the application.
For example, Button's onPress identifies the action callback and variant chooses a visual treatment. The Migration guide shows a complete Button example with the aggregate stylesheet.
The application supplies the operation. Applying a prop to an arbitrary parent does not automatically apply it to every child. In a framework with React Server Components, place interactive examples behind a client boundary; functions passed as event handlers must be available on the client.
For a controlled value, pass the current state and update it when the component requests a change. Toggle's onChange receives the next Boolean value, not a DOM change event. Passing setEnabled commits that requested value to React state; leaving the controlled value unchanged leaves the setting unchanged. Liquidify's default switch has no visible label of its own; provide visible context as well as an accessible name.
import { useId, useState } from "react"
import { Toggle } from "@liquidify/react"
import "@liquidify/react/styles.css"
export function NotificationPreference() {
const labelId = useId()
const [enabled, setEnabled] = useState(false)
return (
<div>
<span id={labelId}>Email notifications</span>
<Toggle
aria-labelledby={labelId}
checked={enabled}
onChange={setEnabled}
/>
</div>
)
}This example changes React state in the current view. It does not persist a notification preference or subscribe anyone to messages. Connect it to application storage only when that behavior is required and implemented.
For an uncontrolled Toggle, use defaultChecked to seed its initial value instead of passing checked. Keep that ownership consistent while the component is mounted. Remounting a component can reset its local state; keep a draft in an appropriate parent when it must survive changing views. See Controlled state for details and callback differences.
Use variants, sizes, roles, and tint where the component exposes them. Use public tokens and scoped CSS classes for supported customization. Do not translate a SwiftUI modifier into an assumed React prop.
Some concepts deliberately differ. Button's translucent variant and Liquidify's material grades have their own implementations. An omitted Button variant becomes plain inside ControlGroup, but this specific context is not general inheritance of a SwiftUI buttonStyle modifier. Read Button guidance for supported treatments and roles.
The web interface must work with its rendered HTML semantics, focus order, keyboard input, and application routes. A visual resemblance to an Apple control does not provide native platform services.
Use appropriate links for navigation and action controls for application operations. Give controls accessible names. Review layout and focus behavior at the viewport sizes and input methods your application supports.
A similar name can hide an important semantic difference: Liquidify Form is a layout group, and TextEditor is a native textarea. Neither supplies a submission service or rich-text editing model. See Forms and Text toolbar for composition boundaries.
A Button role does not attach an operation or make Return activate it from anywhere in a view. Likewise, passing a callback does not make the component own asynchronous work. Keep pending state, errors, routing, and completion feedback in the application.