npm
Foundations

Skins & motion

One grammar, two renderings, and choreography that plays everywhere.

Chapter complete
2,450
import "@objectifthunes/royal-games-ui/tokens.css";
import { SkinProvider, useSkin } from "@objectifthunes/royal-games-ui";

<SkinProvider defaultSkin="enamel">
  <App />
</SkinProvider>

// anywhere below:
const { skin, setSkin } = useSkin();
setSkin(skin === "enamel" ? "gloss" : "enamel");

Enamel draws every component with a dark contour, a gold bevel frame and a matte material face. Gloss renders the same grammar borderless, gradients, extrusion shadows and a glossy cap. The stylesheet keys everything on data-rg-skin, so switching skins is one attribute, no re-render of your tree.

Both skins, side by side

2,450
2,450

Motion is everywhere

import { useEntranceMotion } from "@objectifthunes/royal-games-ui";

const { ref, playing, replay } = useEntranceMotion<HTMLDivElement>();

<div
  ref={ref}
  className={playing ? "rg-entering rg-play" : undefined}
>
  <Coin decorative={false} title="Coin" size="large" />
  <Gem decorative={false} title="Gem" size="large" />
</div>
<Button width="wide" onClick={replay}>Replay entrance</Button>

There is no motion module to opt into, every preview on this site is a live motion scope, and so is every package Screen. useEntranceMotion owns a local choreography scope and exposes its active state; replay() restarts that scope. The ▶ MOTION control in the header replays the whole page. Reduced motion is respected by the package.