Skip to main content
Mantı UI logoMantı UIv0.13.0
Studio

v0.13.0

Released 2026-09-14.

Oklava: the Theme Studio, in your app

The Theme Studio lets you tune a theme against its own preview. @manti-ui/oklava is the same control rail as a devtool you drop into your own project, so the screens you are tuning are yours.

pnpm add -D @manti-ui/oklava
import { Oklava } from '@manti-ui/oklava';

{
  import.meta.env.DEV && <Oklava />;
}

That is the whole setup. There is no stylesheet to import: the panel writes its own chrome into the document on mount. The package is side-effect free and single-entry, so that DEV branch tree-shakes all of it, font catalogue included, out of a production build.

Every knob writes a token override, injected as one unlayered <style> in <head>. Manti's defaults ship inside @layer manti.tokens, so an unlayered declaration wins without !important — the same escape hatch you would reach for by hand. What the app looks like with the panel open is what it looks like once the CSS is pasted in, because one builder feeds both.

The panel hands the theme back three ways: the :root CSS block, a brief a coding agent can act on in your repo, or JSON that can be pasted back in. Full detail in the Oklava guide.

The docs site runs it too, so any page here can be rethemed from the launcher in the corner.

Combobox holds a long list

A Combobox rendered every match. Handing it a catalogue of a few thousand options — fonts, countries, icons — put thousands of list items into the DOM on open, each with a set of machine props, and blocked the main thread for as long as that took.

maxVisibleItems now caps what reaches the DOM at 200 by default. Filtering still runs over the whole list, and a line under the rows says how many matches are still hidden:

<Combobox items={twoThousandFonts} maxVisibleItems={50} />

The collection is built from the same slice, so keyboard navigation never walks onto a row that is not there.

Combobox stops fighting a controlled value

The effect that keeps the check indicator in step with the typed text cleared the selection whenever the text stopped matching it. Against a controlled value that could never settle: setValue([]) was undone by the prop, setInputValue re-fired the query, the effect saw a selection again, and the render loop spun until the tab was wedged. Typing a single character into a controlled Combobox froze the page.

A controlled owner decides what is selected, so the effect now stands down there, the same way it already did for multi-select.

Floating Panel can be sized and placed

The machine accepts a starting size and position, but the adapter dropped them, and the panel writes its own width and height as inline styles — so a stylesheet rule could not size it either. defaultSize, minSize, maxSize and defaultPosition are now props:

<FloatingPanel
  defaultSize={{ width: 352, height: 560 }}
  defaultPosition={{ x: 24, y: 24 }}
  minSize={{ width: 288, height: 240 }}
  trigger={<Button>Open</Button>}
>

</FloatingPanel>

Last updated

Built end-to-end with Manti UI components and design tokens. Manti UI is a framework-agnostic design system on Zag.js.

GitHub