Skip to content

React

npm install @aejkatappaja/phantom-ui

Run npx @aejkatappaja/phantom-ui init once to generate a phantom-ui.d.ts file for JSX types (or create it manually, see TypeScript below).

import { useState, useEffect } from "react";
import "@aejkatappaja/phantom-ui";
function UserCard() {
const [user, setUser] = useState(null);
useEffect(() => {
fetchUser().then(setUser);
}, []);
return (
<phantom-ui loading={!user}>
<div className="card">
<img src={user?.avatar ?? "/placeholder.png"} className="avatar" />
<h3>{user?.name ?? "Placeholder Name"}</h3>
<p>{user?.bio ?? "A short bio goes here for measurement."}</p>
</div>
</phantom-ui>
);
}

phantom-ui treats loading="false" as falsy, so you can pass booleans directly:

<phantom-ui loading={isLoading}>

This works the same in React 18 and React 19. React 18 sets loading as a string attribute ("true" / "false"); the component resolves it to a boolean and clears the stale attribute when it becomes falsy, so content is revealed correctly when loading ends.

If you prefer not to run init, create src/phantom-ui.d.ts manually:

import type { PhantomUiAttributes } from "@aejkatappaja/phantom-ui";
declare module "react/jsx-runtime" {
export namespace JSX {
interface IntrinsicElements {
"phantom-ui": PhantomUiAttributes;
}
}
}

Or run:

npx @aejkatappaja/phantom-ui init