@johncomposed/rcup
v0.1.0-alpha.0
Published
A collection of UI plugins for React Cosmos
Downloads
29
Readme
@johncomposed/rcup
A collection of UI plugins for React Cosmos.
Plugins
| Plugin | Description |
| ---------------- | --------------------------------------------------------------------------------------------------- |
| slider-input | Range sliders in the control panel's Inputs section, created from fixtures with useFixtureSlider. |
| theme-controls | A sun/moon dark mode toggle in the renderer toolbar, persisted across reloads. |
| hello-world | Demo plugin and template: a renderer toolbar button that logs a configurable greeting. |
Installation
npm install -D @johncomposed/rcupEnable all plugins at once in cosmos.config.json:
{
"plugins": ["@johncomposed/rcup"]
}Or enable individual plugins:
{
"plugins": [
"@johncomposed/rcup/plugins/slider-input",
"@johncomposed/rcup/plugins/theme-controls",
"@johncomposed/rcup/plugins/hello-world"
]
}Don't mix the two forms — the package root already includes every plugin.
slider-input
Like useFixtureInput, but the value renders as a range slider in the
playground's Inputs panel instead of a number field:
import { useFixtureSlider } from '@johncomposed/rcup/useFixtureSlider';
export default function MyFixture() {
const [size, setSize] = useFixtureSlider('size', {
defaultValue: 120,
min: 40,
max: 280,
step: 1,
});
return <Box size={size} />;
}min, max, and step are optional (defaults: 0, 100, 1). The hook
returns [value, setValue] like useFixtureInput.
theme-controls
Adds a sun/moon toggle to the renderer toolbar. The chosen theme is written
to Cosmos fixture state (and persisted by the playground's storage plugin);
your fixtures decide how to apply it via a global decorator using the
useThemeControls hook.
Add a cosmos.decorator.tsx to your root fixture folder:
import React from 'react';
import { useThemeControls } from '@johncomposed/rcup/useThemeControls';
export default function GlobalDecorator({ children }: { children: React.ReactNode }) {
const { dark } = useThemeControls();
React.useLayoutEffect(() => {
// Or a data attribute, a context provider, a CSS variable...
document.documentElement.classList.toggle('dark', dark);
return () => document.documentElement.classList.remove('dark');
}, [dark]);
return children;
}hello-world
A demo plugin kept as a template for new plugins: a toolbar button that logs
a greeting configured via the ui.helloWorld section of cosmos.config.json:
| Key | Type | Default | Description |
| ---------- | -------- | ---------------------------------- | -------------------------------------------------- |
| greeting | string | "Hello from @johncomposed/rcup!" | Message logged when the toolbar button is clicked. |
Development
This repo includes a local Cosmos playground (vite-based, dev-only — none of it is published):
pnpm install
pnpm build # or `pnpm dev` for watch mode
pnpm cosmosCosmos loads the built bundles from dist/, so rebuild (or keep pnpm dev
running) and reload the browser to see plugin changes. Playground fixtures
live in playground/.
How UI plugins work
UI plugin bundles are injected at run-time into the pre-bundled Cosmos UI,
which exposes shared libraries as globals: react, react-dom,
react-plugin, and styled-components must not be bundled — tsdown maps
them onto those globals (see tsdown.config.ts). Renderer-side hooks
(useFixtureSlider, useThemeControls) are ordinary library builds imported
by fixtures through package subpaths.
Adding a plugin
- Create
src/<camelName>/with anindex.tsxthat callscreatePlugin()+register(), and aspec.tsdefining its name/config types. - Import it from
src/index.ts(the aggregate bundle). - Add a
uiPlugin({ <camelName>: 'src/<camelName>/index.tsx' })entry intsdown.config.ts. For renderer-side exports add afixtureSide()entry plus a root subpath dir with a nestedpackage.json(seeuseFixtureSlider/), and list it in package.jsonfiles. - Add
plugins/<kebab-name>/cosmos.plugin.json(+ a one-linepackage.jsonwith"main": "./cosmos.plugin.json") so it can be enabled individually. - Document it in this README.
