v0.3.0
Components
@monowind/ui. A menu (with submenus), a dialog, a popover, and a tooltip, each a Zag.js state machine wired to the engine. Zag runs the roles and states, the keyboard, typeahead, focus trapping and restore, and dismissal; the engine places each floating part against its trigger in cells, in the top layer, above everything and outside any scroller it opened from. Headless: mark the parts withdata-partand mount on their root (menu(root, { id })), then style the parts with Tailwind and monowind classes.positioning.placementtakes Zag's placements (bottom-start,top,right-end, …) and flips when the part would overflow the host;positioning.gutterandpositioning.offsetcount cells, and a margin utility on the positioner does the same (mt-1under a trigger is a gap,-mt-1on a submenu levels its first item with the item that opened it).- React, Vue, and Svelte.
@monowind/ui-react(useMenu,useDialog,usePopover,useTooltip),@monowind/ui-vue(composables), and@monowind/ui-svelte(runes) fold Zag's adapter in, one function per component with the same props everywhere. They need React 18, Vue 3.5, or Svelte 5.20 and up. Examples for all three, plus a Vue example app, and the playground sample now opens a menu and a dialog. - Surfaces. A popover or dialog takes the theme's text and background colors, as the browser gives it the canvas's.
bg-clearon a menu's or popover's content sees through to whatever sits behind the host.
Top layer
- Popovers and modal dialogs paint last. An open
[popover]or modal<dialog>is laid out as a fixed box of the host and painted above everything, outside its ancestors' clips, scrolling, and transforms, in the order they opened.::backdropis drawn beneath it:backdrop:bg-black/50dims the page,backdrop:backdrop-blur-smblurs it. Afixedbox paints and hit-tests from the host's origin too, where it used to vanish inside a scroller. - Under a modal dialog the page is blocked, grid included, so grid mode falls back to the dialog's own pointer and selection.
- Exits. A popover's exit through
transition-discreteplays to the end before it leaves the top layer.
Anchor positioning
position-area. An out-of-flow box with aposition-areais placed in a cell of its anchor's 3×3 grid and aligned toward it; anchors are named byanchor-name, or implied by a popover's invoker (popovertarget,commandfor).position-try-fallbacksflips the box where it would overflow, and its margins flip with it as in CSS;anchor-centercenters on the anchor;position-anchorreadsnormal,auto,none, andmatch-parent. The area taken is written asdata-mw-area, and a box follows its anchor through scrolling.
Theming
- Derived tokens.
--mw-fgand--mw-bgnow derive from the host's owncolorandbackground-color(a transparent host reads the background behind it, the canvas past the page), sotext-*andbg-*on<mono-wind>drive the focus invert and everything that reads the tokens. A change to an ancestor's class or style, or to the color scheme, applies at once. Migration: the built-in themes setcolorandbackground-colorinstead of the two tokens; a stylesheet still declaring--mw-fg/--mw-bgkeeps its values.
Engine
align-middleon inline boxes lands the line's text on the box's middle row, where it used to behave as top.- Painting over glyphs. A glyph painted over another keeps only the fill beneath it: a heading stuck over an italic run no longer turns italic, and a plain run over colored or underlined text stays plain.
- Box model. A box sized below its borders and padding (Tailwind's
<hr>:height: 0plus a border) keeps its border row, in block and flex layout alike. - Aligned lines. A button or other inline box on a centered or right-aligned line sits where the line's text is.
- Focus and pointer. A menu, listbox, tree, or grid container leaves the focus invert to its items; a press over a focusable target focuses it; a grid drag can start from a menu's border cell;
summaryand[contenteditable]count as interactive. - Locks in a cascade layer. The companion's engine rules moved into
@layer theme, so a!utility (bg-red-500!,w-40!,text-2xl!) or an unlayered!importantrule no longer paints the element's own box over the grid or pushes it off its cells; the value still reaches the grid's paint.pointer-events-auto!keeps working as the hit-target escape hatch. - Attributes. The host follows the attributes that render (class, style, HTML rendering attributes, ARIA states,
data-*) instead of every attribute. Migration:observedAttributesis gone fromregisterLeafRenderer; the host follows every attribute of a leaf, so drop the field.
Full changelog: v0.2.14...v0.3.0