Operant has two consumption paths. Pick the plain HTML/CSS path unless you're specifically building a React app that wants typed components — it's the primary path, has zero dependencies, and is what the design system actually is under the hood.
Path A — Plain HTML / CSS (primary, zero-dependency)
Copy css/tokens.css, css/base.css, and css/components.css from the repo into your project (or
reference them directly if you're working inside this monorepo), and load them in this order:
<!doctype html>
<html lang="en" data-theme="dark" data-density="comfortable">
<head>
<link rel="stylesheet" href="css/tokens.css">
<link rel="stylesheet" href="css/base.css">
<link rel="stylesheet" href="css/components.css">
</head>
<body>
<!-- compose with .ods-* classes -->
</body>
</html>
The order matters: tokens.css defines every CSS custom property, base.css resets defaults and
sets up typography roles, and components.css styles .ods-* components against those tokens.
Two attributes on <html> (or on any subtree, e.g. a single panel) control appearance:
data-theme—"light"or"dark".data-density—"comfortable"(default) or"compact".
See Theming for how these cascade through the token layers.
No build step, no bundler, no framework required. This is the path most existing apps and static pages should use.
Path B — React, via @operant/ui
@operant/ui is a set of React components (Button, Card, Badge, Composer, Modal, and
more) that render the exact same .ods-* classes from components.css, using
Radix UI underneath purely for keyboard/focus/ARIA behavior — never a
second class system or a different visual language. @operant/styles re-exports the three
stylesheets above as an importable package so a React app doesn't need to vendor the CSS files
directly.
npm install @operant/ui @operant/styles
// once, at your app root
import "@operant/styles/styles.css";
import { Button, Card, CardBody, Badge } from "@operant/ui";
export default function Example() {
return (
<Card>
<CardBody>
<Badge variant="success">Live</Badge>
<Button variant="primary">Run workflow</Button>
</CardBody>
</Card>
);
}
Theme and density still work exactly as in Path A — set data-theme / data-density on <html>
(or a Provider-less wrapper element); @operant/ui has no theme context of its own to configure.
A note on package availability
@operant/ui and @operant/styles are npm workspace packages inside this monorepo
(packages/ui, packages/styles) — they are not yet published to the public npm registry.
npm install @operant/ui @operant/styles works today if you're inside this repo (npm workspaces
resolve them locally); it will not resolve from a project outside the repo until they're
published. If you need them today from an external project, consume the repo as a git dependency,
or npm run build inside packages/ui/packages/styles and vendor the output. Publishing to the
public npm registry is on the roadmap — see Architecture for the
monorepo layout and rationale.