React DOM Component Kit
Build performant, accessible web applications with @boodoo/react
(boodoo/react). Pure React components designed specifically for web and Next.js, featuring zero
DOM-hijacking scripts, native semantic HTML elements, accessible form fields, expandable tables, and scoped CSS
layer integration.
Pure DOM Components
Zero React Native primitives on web. Direct semantic rendering
into <button>, <dialog>, <table>, and
<input>.
Scoped CSS & Host Theming
Ships under @layer boodoo and .boodoo
namespace without reboot resets, avoiding style leaks into host apps.
Multi-Platform Parity
Shares identical component names and prop mental models with
boodoo/react-native for seamless cross-platform teams.
1. Installation & Setup
Install Boodoo and peer dependencies into your React 18+ or Next.js 14+ project:
npm install boodoo react react-dom
Import the scoped React stylesheet in your application root (e.g. app/layout.tsx,
src/main.jsx, or _app.tsx):
import 'boodoo/css/react';
// Or if you want the full global utility classes:
// import 'boodoo/css';
2. BoodooProvider & Density
Wrap your application root with BoodooProvider to control themes and UI density:
import { BoodooProvider, Button } from 'boodoo/react';
export default function App() {
return (
<BoodooProvider theme="auto" density="compact">
<div className="p-4">
<Button variant="primary">Compact Theme Button</Button>
</div>
</BoodooProvider>
);
}
3. Accessible Form Controls (`Field`)
The Field wrapper automatically wires id, htmlFor,
aria-describedby, and aria-invalid down to form inputs:
import { Field, Input, Select } from 'boodoo/react';
export function UserForm() {
return (
<form className="d-flex flex-column gap-3 max-w-md">
<Field
label="Work Email"
required
description="We will send your verification token here."
learnMore="We respect your privacy. No marketing emails without consent."
>
<Input type="email" placeholder="alex@company.com" />
</Field>
<Field label="Account Role">
<Select
options={[
{ label: 'Administrator', value: 'admin' },
{ label: 'Editor', value: 'editor' },
{ label: 'Viewer', value: 'viewer' },
]}
/>
</Field>
</form>
);
}
4. Combobox with Accent-Folding
Keyboard-accessible autocomplete with fuzzy search and subtitle metadata:
import { Combobox } from 'boodoo/react';
const users = [
{ label: 'René Descartes', value: 'rene', meta: 'Philosophy / Paris' },
{ label: 'Søren Kierkegaard', value: 'soren', meta: 'Theology / Copenhagen' },
{ label: 'Ada Lovelace', value: 'ada', meta: 'Computing / London' },
];
export function UserSearch() {
return (
<Combobox
items={users}
placeholder="Search philosopher (try 'Rene' or 'Soren')..."
onChange={(val) => console.log('Selected:', val)}
/>
);
}
5. Controlled Data Table
Sort columns and expand rows declaratively without DOM manipulation:
import { useState } from 'react';
import { Table, Badge } from 'boodoo/react';
const columns = [
{ key: 'name', title: 'Service Name', sortable: true },
{
key: 'status',
title: 'Health',
render: (val) => (
<Badge variant={val === 'active' ? 'success' : 'warning'}>
{val}
</Badge>
),
},
{ key: 'latency', title: 'Latency (ms)', sortable: true },
];
const data = [
{ id: '1', name: 'API Gateway', status: 'active', latency: 42, details: 'v2.4.1 deployed in us-east-1' },
{ id: '2', name: 'Auth Service', status: 'active', latency: 19, details: 'Session cache warm, 0 failures' },
];
export function MetricsTable() {
const [sortCol, setSortCol] = useState('name');
const [sortDir, setSortDir] = useState('asc');
const [expanded, setExpanded] = useState(['1']);
return (
<Table
columns={columns}
data={data}
keyField="id"
sortColumn={sortCol}
sortDirection={sortDir}
onSort={(key, dir) => {
setSortCol(key);
setSortDir(dir);
}}
expandedKeys={expanded}
expandedRowRender={(row) => (
<div className="p-3 bg-light rounded text-muted fs-7">
<strong>Telemetry Details:</strong> {row.details}
</div>
)}
/>
);
}
6. Action Barrier ConfirmDialog
Prevent destructive accidents by requiring matching confirmation strings:
import { useState } from 'react';
import { ConfirmDialog, Button } from 'boodoo/react';
export function ProjectSettings() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<Button variant="danger" onClick={() => setIsOpen(true)}>
Delete Workspace
</Button>
<ConfirmDialog
isOpen={isOpen}
onClose={() => setIsOpen(false)}
onConfirm={() => {
console.log('Deleted workspace');
setIsOpen(false);
}}
title="Delete Workspace"
message="This action is irreversible. All associated metrics, API keys, and databases will be purged."
mustMatch="DELETE WORKSPACE"
confirmLabel="Permanently Delete"
/>
</>
);
}