# Introducing UI SDK

A library of behaviors to build your components. Made for agents.

[Watch the launch video](https://5i7hyknqgxeqd9wd.public.blob.vercel-storage.com/ui-sdk-launch-v91.mp4)

Today we're releasing UI SDK.

UI SDK is a TypeScript library of UI behaviors, the layers that make up a component library. It provides building blocks for keyboard navigation, focus, selection, popups, drag and drop, and the ARIA attributes those interactions need.

For example, `createRovingFocus` moves focus with the arrow keys, `createTypeahead` finds an option as you type, and `createPopup` opens a popup next to its button.

We built more than 50 of them. You, or your agent, combine them to build your own components.

## Build a component

Here's a small popover. You define it once with `@ui-sdk/core`, and `createPopup` does the hard part: it opens next to its button, closes on Escape or a click outside, and puts focus back where it was.

```ts title="lib/share.ts"
import {
  createPopup,
  definePrimitive,
  popupContent,
  popupState,
  popupTrigger,
} from "@ui-sdk/core"
import { popoverPreset } from "@ui-sdk/core/popover"

const share = definePrimitive({
  name: "share",
  options: { defaultOpen: "boolean" },
  state: (options: { defaultOpen?: boolean }) => popupState(options),
  api: (context) => createPopup(context, { preset: popoverPreset }),
  slots: (slot) => ({
    trigger: popupTrigger(slot),
    content: popupContent(slot),
  }),
})

export { share }
```

Don't worry, you don't have to learn to write this. We taught agents how to do it, and they're really good at it. Ask yours for the component you need.

Then make it a component in your framework:

**React**

```ts title="components/ui/share.ts"
"use client"

import { createParts } from "@ui-sdk/react/primitive"
import { share } from "@/lib/share"

const parts = createParts(share, { trigger: "button", content: "div" })

const Share = parts.Root
const ShareTrigger = parts.Trigger
const ShareContent = parts.Content

export { Share, ShareContent, ShareTrigger }
```

**Vue**

```ts title="components/ui/share.ts"
import { createParts } from "@ui-sdk/vue/primitive"
import { share } from "@/lib/share"

const parts = createParts(share, { trigger: "button", content: "div" })

const Share = parts.Root
const ShareTrigger = parts.Trigger
const ShareContent = parts.Content

export { Share, ShareContent, ShareTrigger }
```

**Svelte**

```ts title="components/ui/share.ts"
import { createParts } from "@ui-sdk/svelte/primitive"
import { share } from "@/lib/share"

const parts = createParts(share, { trigger: "button", content: "div" })

const Share = parts.Root
const ShareTrigger = parts.Trigger
const ShareContent = parts.Content

export { Share, ShareContent, ShareTrigger }
```

**Solid**

```ts title="components/ui/share.ts"
import { createParts } from "@ui-sdk/solid/primitive"
import { share } from "@/lib/share"

const parts = createParts(share, { trigger: "button", content: "div" })

const Share = parts.Root
const ShareTrigger = parts.Trigger
const ShareContent = parts.Content

export { Share, ShareContent, ShareTrigger }
```

**Web Components**

```ts title="components/ui/share.ts"
import { createParts, wrappedButton } from "@ui-sdk/web"
import { share } from "@/lib/share"

createParts(share, {
  root: "share-popover",
  trigger: { tag: "share-trigger", target: wrappedButton },
  content: "share-content",
})
```

Then use it like any other component:

**React**

```tsx title="pages/index.tsx"
import { Share, ShareContent, ShareTrigger } from "@/components/ui/share"

function Example() {
  return (
    <Share>
      <ShareTrigger>Share</ShareTrigger>
      <ShareContent>Anyone with the link can view.</ShareContent>
    </Share>
  )
}
```

**Vue**

```vue title="pages/index.vue"
<script setup lang="ts">
import { Share, ShareContent, ShareTrigger } from "@/components/ui/share"
</script>

<template>
  <Share>
    <ShareTrigger>Share</ShareTrigger>
    <ShareContent>Anyone with the link can view.</ShareContent>
  </Share>
</template>
```

**Svelte**

```svelte title="pages/index.svelte"
<script lang="ts">
  import { Share, ShareContent, ShareTrigger } from "@/components/ui/share"
</script>

<Share>
  <ShareTrigger>Share</ShareTrigger>
  <ShareContent>Anyone with the link can view.</ShareContent>
</Share>
```

**Solid**

```tsx title="pages/index.tsx"
import { Share, ShareContent, ShareTrigger } from "@/components/ui/share"

function Example() {
  return (
    <Share>
      <ShareTrigger>Share</ShareTrigger>
      <ShareContent>Anyone with the link can view.</ShareContent>
    </Share>
  )
}
```

**Web Components**

```html title="pages/index.html"
<script type="module">
  import "@/components/ui/share"
</script>

<share-popover>
  <share-trigger><button>Share</button></share-trigger>
  <share-content>Anyone with the link can view.</share-content>
</share-popover>
```

To build one step by step, read [Build a Component](/docs/core/build-a-component). To combine several behaviors, read [Compose Behaviors](/docs/core/compose-behaviors).

## Component libraries

We used the same behaviors to build a component library for every framework: more than 50 ready-made components, from a Select to a Date Picker, with the same parts in React, Vue, Svelte, Solid and Web Components. You bring the styles.

**React**

```tsx
import {
  Select,
  SelectContent,
  SelectItem,
  SelectLabel,
  SelectTrigger,
  SelectValue,
} from "@ui-sdk/react/select"

function Example() {
  return (
    <Select placeholder="Select a role">
      <SelectLabel>Role</SelectLabel>
      <SelectTrigger>
        <SelectValue />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value="viewer">Viewer</SelectItem>
        <SelectItem value="editor">Editor</SelectItem>
      </SelectContent>
    </Select>
  )
}
```

**Vue**

```vue
<script setup lang="ts">
import {
  Select,
  SelectContent,
  SelectItem,
  SelectLabel,
  SelectTrigger,
  SelectValue,
} from "@ui-sdk/vue/select"
</script>

<template>
  <Select placeholder="Select a role">
    <SelectLabel>Role</SelectLabel>
    <SelectTrigger>
      <SelectValue />
    </SelectTrigger>
    <SelectContent>
      <SelectItem value="viewer">Viewer</SelectItem>
      <SelectItem value="editor">Editor</SelectItem>
    </SelectContent>
  </Select>
</template>
```

**Svelte**

```svelte
<script lang="ts">
  import {
    Select,
    SelectContent,
    SelectItem,
    SelectLabel,
    SelectTrigger,
    SelectValue,
  } from "@ui-sdk/svelte/select"
</script>

<Select placeholder="Select a role">
  <SelectLabel>Role</SelectLabel>
  <SelectTrigger>
    <SelectValue />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="viewer">Viewer</SelectItem>
    <SelectItem value="editor">Editor</SelectItem>
  </SelectContent>
</Select>
```

**Solid**

```tsx
import {
  Select,
  SelectContent,
  SelectItem,
  SelectLabel,
  SelectTrigger,
  SelectValue,
} from "@ui-sdk/solid/select"

function Example() {
  return (
    <Select placeholder="Select a role">
      <SelectLabel>Role</SelectLabel>
      <SelectTrigger>
        <SelectValue />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value="viewer">Viewer</SelectItem>
        <SelectItem value="editor">Editor</SelectItem>
      </SelectContent>
    </Select>
  )
}
```

**Web Components**

```html
<script type="module">
  import "@ui-sdk/web/select"
</script>

<ui-select placeholder="Select a role">
  <ui-select-label>Role</ui-select-label>
  <ui-select-trigger>
    <button>
      <ui-select-value></ui-select-value>
    </button>
  </ui-select-trigger>
  <ui-select-content>
    <ui-select-item value="viewer">Viewer</ui-select-item>
    <ui-select-item value="editor">Editor</ui-select-item>
  </ui-select-content>
</ui-select>
```

## Agents

These days, agents build our interfaces. And more and more, agents use them too. So we built UI SDK for both.

Everything you build with UI SDK is easy for an agent to use. An agent can read what's on the page and press, type and pick, just like a person would, within the permissions you set.

Give an agent your page with `createAgent`:

```ts
import { createAgent } from "@ui-sdk/react/agent"

const agent = createAgent({
  allow: ({ component, label, action }) =>
    component === "select" && label === "Region" && action === "setValue",
})

agent.snapshot()

await agent.act({
  steps: [{ ref: "Region", action: "setValue", args: ["north-america"] }],
})
```

WebMCP lets a page give tools to the agent built into a browser. Call `registerTools` and the browser's agent can read your components and call their actions too. To set it up, read [WebMCP](/docs/agents/connect-an-agent/webmcp).

## Get started

Copy the setup prompt into your agent, and it sets up UI SDK for you.

**React**

```text prompt
Set up ui-sdk in this React project. It needs React 19 or newer.

1. Install @ui-sdk/react and @ui-sdk/core with the project's package manager.
2. Add a note to AGENTS.md, creating it if needed: before using ui-sdk, follow the ui-sdk skill if it's installed, and read node_modules/@ui-sdk/react/docs/llms.txt. To build a new component, also search node_modules/@ui-sdk/react/docs/core.md by heading, and read rendering.md next to it.
3. If you support skills, run: npx skills add vercel-labs/ui --skill ui-sdk
```

**Vue**

```text prompt
Set up ui-sdk in this Vue project. It needs Vue 3.5 or newer.

1. Install @ui-sdk/vue and @ui-sdk/core with the project's package manager.
2. Add a note to AGENTS.md, creating it if needed: before using ui-sdk, follow the ui-sdk skill if it's installed, and read node_modules/@ui-sdk/vue/docs/llms.txt. To build a new component, also search node_modules/@ui-sdk/vue/docs/core.md by heading, and read rendering.md next to it.
3. If you support skills, run: npx skills add vercel-labs/ui --skill ui-sdk
```

**Svelte**

```text prompt
Set up ui-sdk in this Svelte project. It needs Svelte 5.33 or newer.

1. Install @ui-sdk/svelte and @ui-sdk/core with the project's package manager.
2. Add a note to AGENTS.md, creating it if needed: before using ui-sdk, follow the ui-sdk skill if it's installed, and read node_modules/@ui-sdk/svelte/docs/llms.txt. To build a new component, also search node_modules/@ui-sdk/svelte/docs/core.md by heading, and read rendering.md next to it.
3. If you support skills, run: npx skills add vercel-labs/ui --skill ui-sdk
```

**Solid**

```text prompt
Set up ui-sdk in this Solid project. It needs Solid 2: solid-js and @solidjs/web 2.0.0-rc.14 or newer.

1. Install @ui-sdk/solid and @ui-sdk/core with the project's package manager.
2. Add a note to AGENTS.md, creating it if needed: before using ui-sdk, follow the ui-sdk skill if it's installed, and read node_modules/@ui-sdk/solid/docs/llms.txt. To build a new component, also search node_modules/@ui-sdk/solid/docs/core.md by heading, and read rendering.md next to it.
3. If you support skills, run: npx skills add vercel-labs/ui --skill ui-sdk
```

**Web Components**

```text prompt
Set up ui-sdk in this Web Components project. Each component registers its tags when you import its entry, like @ui-sdk/web/dialog.

1. Install @ui-sdk/web and @ui-sdk/core with the project's package manager.
2. Add a note to AGENTS.md, creating it if needed: before using ui-sdk, follow the ui-sdk skill if it's installed, and read node_modules/@ui-sdk/web/docs/llms.txt. To build a new component, also search node_modules/@ui-sdk/web/docs/core.md by heading, and read rendering.md next to it.
3. If you support skills, run: npx skills add vercel-labs/ui --skill ui-sdk
```

Want to learn more? Read the [introduction](/docs/core).

UI SDK is currently in beta. Try it, and tell us what you think on [GitHub](https://github.com/vercel-labs/ui).

## Thank you

UI SDK is everything we learned from years of using and building component libraries. Thank you to the teams behind [Radix](https://www.radix-ui.com), [Base UI](https://base-ui.com), [React Aria](https://react-spectrum.adobe.com/react-aria/), [shadcn/ui](https://ui.shadcn.com), [Nuxt UI](https://ui.nuxt.com) and [Geist](https://vercel.com/geist), and to the [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/).
