Keep Oat’s semantic HTML, tiny footprint, and token system. Add Oatbase when a product needs richer selection, navigation, content, or application patterns. The complete Oat-inclusive CSS and JavaScript is about 30.0 kB gzipped; the extension-only layer stays under 20 kB. Individual entries let applications pay only for the pieces they use.
Browse Oatbase additions and the Oat core patterns available through the complete bundle. The source filter makes the ownership boundary explicit.
Browse by source
⌕
No components found
Try another term or broaden the source filter.
Coverage map
shadcn component equivalents
Mappings for the 66 components in the shadcn catalog checked on 20 October 2026. Equivalent product needs do not imply identical React APIs or every advanced variant.
Loading optional patterns
The default Oatbase bundle includes the established components and AI primitives. Load patterns.css and patterns alongside it for the additional controls, or use their focused imports. Date Picker, Direction, Navigation Menu, and Separator are native recipes. Calendar is a single-date Gregorian view; Date Picker uses the browser UI.
The package includes a machine-readable shadcn-coverage.json with all mappings and material limitations.
Native compositions
AI Elements
21 agent-interface recipes inspired by shadcn AI Elements, composed from semantic HTML, Oat, and Oatbase.
Small primitives, application-owned execution
Message, Message Scroller, Trace, Code Block, and Attachment are focused Oatbase additions. File Tree reuses Tree; Terminal reuses Log Viewer. Approval, prompts, model choices, and context meters compose native controls. Model calls, SDK adapters, uploads, persistence, permissions, and tool execution stay in application code.
Every recipe has a live preview and copyable source. Native controls and disclosures remain usable without JavaScript; the scroller progressively adds following behavior.
Patterns
Compositions
Recipes
Application patterns composed from Oat and Oatbase components. Recipes show ownership boundaries without growing the component bundle.
Complete pages assembled from shipped Oat and Oatbase primitives. Each preview runs in an opaque-origin sandbox with no access to the documentation page; switch to Code for the full document.
Getting started
Installation
Oatbase has not been published to a package registry or CDN yet. Use the current source checkout locally while the first release is prepared.
Local package
Enter nix develop to use the checked-in development shell, or install Bun, Node.js/npm, and GNU Make. Then install dependencies and build the distribution from the Oatbase directory:
npm ci
make dist
Then install that directory from your application. Adjust the relative path to match your checkout:
Projects that already load Oat can add only the extensions they use. The extension-only aggregate is also available as @oddship/oatbase/extensions.css and @oddship/oatbase/extensions.
import '@knadh/oat/oat.min.css';
import '@knadh/oat/oat.min.js';
import '@oddship/oatbase/combobox.css';
import '@oddship/oatbase/combobox';
// CSS-only additions need no JavaScript import.
import '@oddship/oatbase/drawer.css';
import '@oddship/oatbase/item.css';
Getting started
Principles
Oatbase extends Oat without creating a second component system on top of it.
Native first
If an Oat or native HTML element solves the problem, use it. The drawer is CSS around <dialog>; the combobox keeps a real <select> as its form control and fallback.
Progressive enhancement
Forms still submit and essential controls remain usable before JavaScript loads. JavaScript adds search, keyboard movement, and richer interaction rather than basic access.
Small pieces
Every component is independently loadable. The aggregate bundle is a convenience, not a requirement.
Oat tokens
Oatbase introduces no parallel theme. It consumes variables such as --card, --border, --accent, Oat’s spacing scale, and its --radius-* scale. The documentation intentionally preserves those radius defaults.
Getting started
Customizing
Oat owns the visual language. Oatbase inherits it and exposes only the component geometry that Oat cannot describe.
Theme contract
Override Oat’s semantic variables after the default Oatbase stylesheet. With extension-only imports, place the overrides after Oat and before or after the extensions. The same palette, type, spacing, radius, shadow, and motion values flow through both layers.
Oatbase ships four alternative token maps plus an explicit Oat reset for nested scopes. The top-bar theme picker provides five choices. Presets contain no component selectors or JavaScript.
Theme
Character
Oat
The unchanged Oat foundation.
Doordarshan
Monospace, terracotta, saffron, peacock, and warm terminal surfaces.
Forest
Quiet greens and natural neutral surfaces.
Ocean
Cool blue surfaces with cyan accents.
Paper
Warm editorial surfaces with a serif stack and restrained corners.
/* All presets, including the scoped Oat reset */
import '@oddship/oatbase/themes';
/* Or one independently */
import '@oddship/oatbase/themes/doordarshan.css';
document.documentElement.dataset.oatTheme = 'doordarshan';
Scoped theme lab
The preset select and native radio controls apply the shipped variables only to the preview. The rest of the documentation keeps its top-bar selection.
Component geometry hooks
Oatbase variables are prefixed and have local fallbacks. Override them globally, within a subtree, or on one component.
<ot-theme-switcher> selects system, light, or dark appearance by setting color-scheme. Explicit light and dark choices also set data-theme on the document root so scoped Oat overrides work as documented.
Component · JavaScript
Command
A command palette with local or application-supplied results, keyboard navigation, and an optional global shortcut.
Call event.preventDefault() to keep the palette open after selection.
Application-supplied results
Set data-filter="manual" when results come from an API or application index. Oatbase emits each query without hiding existing rows. Replace or update the semantic list, then call refresh() so keyboard focus, aria-activedescendant, groups, and the empty state reflect the new DOM.
The application owns fetching, cancellation, caching, and result markup. Each selectable result still uses data-command-item. A listener may also cancel oatbase:query to suppress local filtering for one query.
Global shortcut
Add data-shortcut="mod+k" to open with Command-K on macOS or Control-K elsewhere.
API
Surface
Purpose
data-shortcut="mod+k"
Registers the optional global Command-K or Control-K shortcut.
data-command-open / data-command-close
Opt existing buttons into opening or closing the palette.
data-command-search / data-command-list
Identify the search input and semantic result list.
data-command-item
Marks a selectable result. Use aria-disabled="true" for an unavailable result.
data-value / data-keywords
Provide the emitted value and additional searchable text.
data-filter="manual"
Leaves filtering and result insertion to the application; Oatbase continues to own listbox navigation and selection.
data-keep-open
Keeps the dialog open after that item is accepted.
query
Returns the current trimmed query string.
items / visibleItems
Expose all result elements or the currently available filtered results.
open() / close()
Control the native dialog programmatically.
refresh()
Reindexes inserted results and synchronizes roles, active item, groups, empty state, and aria-activedescendant.
oatbase:query
Cancelable event with { query }. Canceling it skips local filtering for that input.
oatbase:select
Cancelable event with { value, item }; preventing default keeps the palette open.
oatbase:open / oatbase:close
Report palette lifecycle changes.
Component · CSS only
Drawer
A native dialog styled as a sheet from the top, right, bottom, or left edge.
Use <kbd> for each physical key and wrap combinations in .kbd-group. Set data-variant="inline" when a shortcut is embedded inside another compact control and should not create a nested keycap surface. Keyboard hints are documentation; wire the actual shortcut separately.