---
title: Behavior without the look
description: "@markless/ui gives you menus, dialogs and pickers that already handle keyboard, focus and screen readers, and leaves the look to you."
sidebar: { label: Overview }
---

Your configuration already lists `ui()`. So what does `@markless/ui` put in your app?

A dialog takes ten minutes to draw. Then Escape does nothing, focus slips behind it, and a screen reader never hears it open.

`@markless/ui` handles that hard part. It ships 46 component **families**. Each one owns state, keyboard, focus and screen reader labels. It owns no colors, fonts or spacing. You bring those with your own CSS.

A family is a set of parts. The `root` part holds the state. The other parts read it, and most of them show it on their own element as a `ui-*` attribute.

Click **Edit address**. Then press Escape.

<UiPartsFigure />

Notice that one change of `open` marked four parts at once. Escape also put focus back on **Edit address**.

```tsrx edit-address.tsrx
import { modal } from '@markless/ui';

export default function EditAddress() @{
	<modal.root>
		<modal.trigger>Edit address</modal.trigger>
		<modal.backdrop>
			<modal.content>
				<modal.title>Edit delivery address</modal.title>
				<modal.close>Cancel</modal.close>
			</modal.content>
		</modal.backdrop>
	</modal.root>
}
```

You wrote no handlers. The modal's own tests check that:

- **Escape** closes it and puts focus back on the trigger.
- While it is open, the page behind it is out of reach for the mouse, keyboard and screen readers.
- **Tab** never moves focus to the page behind it.
- `modal.title` becomes the name a screen reader announces.

Each part name is one lowercase word. `select.itemtrigger` is the trigger of one item. `slider.valuelabel` is a label that shows the value.

:::info[Why "toggle" and not "switch"?]
`switch` is a reserved word in JavaScript, so no export can use that name. The on/off switch family is `toggle`.
:::

:::warning[Which version do I have?]
These docs follow version 0.5.0 in the Markless repository. The latest `@markless/ui` on npm is 0.4.0, and it has fewer families. If a family is missing from your install, check your version.
:::

**Next:** How do these parts get into your app? [Using components →](/ui/using-components)
