@mistri/ui on its own
Draw a page of your own with the buttons, fields, dialogs and menus an App is drawn with, without a server behind it.
npm install @mistri/ui react react-dom @base-ui/reactimport '@mistri/ui/style.css';import { useState } from 'react';import { Button, Field, Modal } from '@mistri/ui';
export function Invite() { const [open, setOpen] = useState(false); const [email, setEmail] = useState(''); return ( <> <Button intent="primary" onClick={() => setOpen(true)}>Invite</Button> {open && ( <Modal className="invite" aria-label="Invite a teammate" onClose={() => setOpen(false)}> <Field label="Email" hint="They get a link to sign in."> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} /> </Field> <Button intent="primary" onClick={() => setOpen(false)}>Send</Button> </Modal> )} </> );}A primitive reads no data, no address and no message catalog: its words, its icons and its answers are props. React, React DOM and Base UI are peers, so your project installs them. An App does not need this package: mistri brings it.
What you’ll see
Section titled “What you’ll see”- The App’s own button, field and dialog, in the platform’s tokens, light or dark by the reader’s setting.
- A field that wires its label, hint and problem into the control (
id,aria-describedby,aria-invalid), so no form joins them by hand. - A dialog that holds focus, closes on Escape and a click on its scrim, and draws a menu or a listbox opened inside it within itself.
What it holds
Section titled “What it holds”| Export | What it is |
|---|---|
Button |
intent (primary, secondary, quiet, danger), size (compact, default, large), busy |
Field |
A label over one control, a hint under it, then a problem; children is the control, or a function of its wiring for a control of several parts |
Modal |
Open while mounted; onClose is told once, however it closed |
DropMenu, DropItem, DropGroup, DropSeparator |
A menu on a button |
Dropdown |
A listbox: one choice from a list |
Typeahead |
A box with a list that narrows as you type |
DateField |
A date and its calendar, in the words it is given |
Icon, registerIcons |
Draws the glyphs you register, by name |
style.css is the tokens and the primitives’ rules in a mistri-ui cascade
layer, so any rule of your page’s own wins. To place them in a layer of your
own, import the two files it joins: @import '@mistri/ui/tokens.css' layer(base); and @mistri/ui/primitives.css the same way.
Common mistakes
Section titled “Common mistakes”- An icon draws nothing → register its glyph first with
registerIcons; the package ships none. - A dialog will not close from its own button → unmount it: a
Modalis open for as long as it is rendered. - A rule of your own loses to a primitive’s → your stylesheet is in a cascade
layer declared before
mistri-ui; import the two files into your layer instead ofstyle.css.
Related
Section titled “Related”- Component library: every primitive and room, in each look, light and dark.
- Custom components: the same primitives inside an App.
- Themes: the tokens a look sets, and how to set your own.