Integrations
React
Use the React components in Next.js, Astro and a WordPress plugin, styled by the same stylesheets as the HTML.
@pelatform/react holds React components with the markup, classes and ARIA of the HTML components: Button, with buttonClass() for a link, and Modal with its parts. Their pages show each example’s React code and the props. React keeps their state, focus and keyboard behavior, so a page needs only the stylesheet.
Install
Install @pelatform/react with its peers: react and react-dom 18.3 or 19, and @pelatform/ui of the same version for the stylesheets (Get the files). Leave @pelatform/ui out where the page loads the stylesheets another way, as a WordPress plugin does.
Clean or Prefixed
The import path sets the classes’ mode, as with the stylesheets; one document uses one mode. Import the matching stylesheet once and put the components inside an element with data-plf-root:
| Components | Stylesheet | Classes |
|---|---|---|
@pelatform/react |
@pelatform/ui/css |
Clean: btn |
@pelatform/react/prefixed |
@pelatform/ui/css/prefixed |
Prefixed: plf: |
import '@pelatform/ui/css';
import { Button } from '@pelatform/react';
export function App() {
return (
<div data-plf-root>
<Button color="primary">Save</Button>
</div>
);
}Classes you add in className follow the mode too, such as plf:mt-4 with Prefixed.
Next.js
Button and Modal are client components, so a Server Component renders them; your component that holds a Modal’s open starts with 'use client'. Import the stylesheet in the root layout and put data-plf-root on its <body>. buttonClass() needs no client code, so a Server Component gives a Link a button’s look:
import Link from 'next/link';
import { buttonClass } from '@pelatform/react';
export default function Page() {
return <Link href="/projects" className={buttonClass({ color: 'primary' })}>Projects</Link>;
}Astro
With @astrojs/react, a React component is an island: Astro renders it on the server, and a client:* directive hydrates it in the browser, such as client:visible once it scrolls into view; without one it stays static HTML. An island needs no provider:
---
import '@pelatform/ui/css';
import Invite from '../components/Invite.tsx';
---
<div data-plf-root>
<Invite client:visible />
</div>Invite stands for your own component, such as one that opens a Modal. The init() and observe(document) of the Astro setup leave islands to React, as their markup carries no data-plf-* hooks.
WordPress
- Build the plugin with
@wordpress/scripts. It runs on WordPress’s own React, 18.3.1 in WordPress 7.1: the build mapsreact,react-domandreact/jsx-runtimeto WordPress’s scripts, so the plugin bundles@pelatform/reactand no React. - Import
@pelatform/react/prefixed, as WordPress pages share their CSS. - Load the Prefixed stylesheet with
plf_ui_enqueue()fromwordpress.php, here on an admin page that prints<div id="my-app" data-plf-root></div>:
add_action('admin_enqueue_scripts', function ($hook) {
if ($hook !== 'toplevel_page_my-app') {
return;
}
plf_ui_enqueue();
$asset = require __DIR__ . '/build/index.asset.php';
wp_enqueue_script('my-app', plugins_url('build/index.js', __FILE__), $asset['dependencies'], $asset['version'], array('in_footer' => true));
});import { createRoot } from '@wordpress/element';
import { Button } from '@pelatform/react/prefixed';
createRoot(document.getElementById('my-app')).render(<Button color="primary">Save</Button>);plf_ui_enqueue() also loads the Full script for the HTML components, which leaves React’s markup alone.
A page that holds only React, such as a signed-in app on the front end, needs only the stylesheets. One page can serve the whole app: a rewrite rule sends /app/ and every path below it to the page, here through the query variable my_app, a router switches its pages without a reload, and @wordpress/api-fetch sends the signed-in user’s nonce to the REST API:
add_action('wp_enqueue_scripts', function () {
if (!get_query_var('my_app')) {
return;
}
wp_enqueue_style('plf-ui-preflight');
wp_enqueue_style('plf-ui');
$asset = require __DIR__ . '/build/app.asset.php';
wp_enqueue_script('my-app', plugins_url('build/app.js', __FILE__), $asset['dependencies'], $asset['version'], array('in_footer' => true));
});The libraries the plugin bundles run on WordPress’s React too, so each needs React 18.3: React Router 7 does, while React Router 8 needs React 19.2.7 or later. Both setups were checked in WordPress 7.1 in Chromium, with WordPress’s production and development builds of React.
Live example
The buttons and Modal below are an island on this page: Astro renders them on the server, and client:visible hydrates them once they scroll into view.