From 9e0146f083b3e5d063aed30aa3b239aa4607bb7c Mon Sep 17 00:00:00 2001 From: Minsu Lee Date: Fri, 13 Nov 2026 12:32:30 +0900 Subject: [PATCH 1/2] feat(ui-sdk): add ui-sdk plugin Adds the ui-sdk skill from vercel-labs/ui (installed via skills.sh) as a built-in plugin, with marketplace entry and relevance signal for @ui-sdk/* deps, generated Codex/Antigravity/Cursor manifests, release-please config, and README entry. --- .agents/plugins/marketplace.json | 12 + .claude-plugin/marketplace.json | 19 ++ .cursor-plugin/marketplace.json | 5 + .release-please-manifest.json | 3 +- README.md | 6 + plugins/ui-sdk/.agents/skills/ui-sdk/SKILL.md | 56 ++++ .../skills/ui-sdk/references/agent-ready.md | 136 ++++++++++ .../ui-sdk/references/build-interface.md | 187 +++++++++++++ .../ui-sdk/references/create-component.md | 88 +++++++ .../skills/ui-sdk/references/patterns.md | 246 ++++++++++++++++++ .../skills/ui-sdk/references/styles.md | 66 +++++ .../skills/ui-sdk/references/testing.md | 172 ++++++++++++ .../ui-sdk/references/web-components.md | 78 ++++++ plugins/ui-sdk/.claude-plugin/plugin.json | 26 ++ plugins/ui-sdk/.codex-plugin/plugin.json | 40 +++ plugins/ui-sdk/.cursor-plugin/plugin.json | 31 +++ plugins/ui-sdk/plugin.json | 26 ++ plugins/ui-sdk/skills-lock.json | 11 + release-please-config.json | 26 ++ 19 files changed, 1233 insertions(+), 1 deletion(-) create mode 100644 plugins/ui-sdk/.agents/skills/ui-sdk/SKILL.md create mode 100644 plugins/ui-sdk/.agents/skills/ui-sdk/references/agent-ready.md create mode 100644 plugins/ui-sdk/.agents/skills/ui-sdk/references/build-interface.md create mode 100644 plugins/ui-sdk/.agents/skills/ui-sdk/references/create-component.md create mode 100644 plugins/ui-sdk/.agents/skills/ui-sdk/references/patterns.md create mode 100644 plugins/ui-sdk/.agents/skills/ui-sdk/references/styles.md create mode 100644 plugins/ui-sdk/.agents/skills/ui-sdk/references/testing.md create mode 100644 plugins/ui-sdk/.agents/skills/ui-sdk/references/web-components.md create mode 100644 plugins/ui-sdk/.claude-plugin/plugin.json create mode 100644 plugins/ui-sdk/.codex-plugin/plugin.json create mode 100644 plugins/ui-sdk/.cursor-plugin/plugin.json create mode 100644 plugins/ui-sdk/plugin.json create mode 100644 plugins/ui-sdk/skills-lock.json diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index ccec2508..c9647365 100644 --- a/.agents/plugins/marketplace.json +++ b/.agents/plugins/marketplace.json @@ -1052,6 +1052,18 @@ }, "category": "Tooling" }, + { + "name": "ui-sdk", + "source": { + "source": "local", + "path": "./plugins/ui-sdk" + }, + "policy": { + "installation": "AVAILABLE", + "authentication": "ON_INSTALL" + }, + "category": "UI" + }, { "name": "skill-optimizer", "source": { diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 31dc5d47..c06b0613 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -1427,6 +1427,25 @@ "tags": ["skills", "vercel"], "source": "./plugins/eve" }, + { + "name": "ui-sdk", + "description": "Build interfaces with ui-sdk in React, Vue, Svelte, Solid or web components — compose its unstyled, accessible components, build missing ones from @ui-sdk/core behaviors, make interfaces agent-ready with createAgent and WebMCP, and test keyboard, focus, ARIA, SSR and RTL.", + "category": "ui", + "keywords": ["ui-sdk", "ui", "components", "accessibility", "react", "vue", "svelte", "solid", "web-components", "webmcp"], + "tags": ["skills", "vercel", "frontend"], + "source": "./plugins/ui-sdk", + "relevance": { + "topic": "ui-sdk", + "signals": { + "manifestDeps": [ + { + "file": "[/\\\\]package\\.json$", + "pattern": "\"@ui-sdk/[a-z-]+\"\\s*:" + } + ] + } + } + }, { "name": "skill-optimizer", "description": "Measure and improve how well a plugin's skills help agents solve real tasks. Runs activation and content evals, diagnoses gaps, fixes instructions, and re-runs until scores improve.", diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index 1662329f..0478e2c6 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -359,6 +359,11 @@ "source": "./plugins/eve", "description": "Build durable backend AI agents with the eve framework. Use when creating, editing, or debugging an eve project — agent instructions, skills, tools, connections, channels, sandboxes, subagents, schedules, or evals." }, + { + "name": "ui-sdk", + "source": "./plugins/ui-sdk", + "description": "Build interfaces with ui-sdk in React, Vue, Svelte, Solid or web components — compose its unstyled, accessible components, build missing ones from @ui-sdk/core behaviors, make interfaces agent-ready with createAgent and WebMCP, and test keyboard, focus, ARIA, SSR and RTL." + }, { "name": "skill-optimizer", "source": "./plugins/skill-optimizer", diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 85502e82..85533c4a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -75,5 +75,6 @@ "plugins/orpc": "1.1.3", "plugins/deno": "1.1.2", "plugins/genkit": "1.1.3", - "plugins/evlog": "1.1.0" + "plugins/evlog": "1.1.0", + "plugins/ui-sdk": "1.0.0" } diff --git a/README.md b/README.md index 2aa5b156..1d2a74bc 100644 --- a/README.md +++ b/README.md @@ -439,6 +439,12 @@ Build durable backend AI agents with the eve framework. Use when creating, editi **Install:** `/plugin install eve@pleaseai` | **Source:** [plugins/eve](https://github.com/pleaseai/claude-code-plugins/tree/main/plugins/eve) +#### ui-sdk + +Build interfaces with [ui-sdk](https://github.com/vercel-labs/ui) in React, Vue, Svelte, Solid or web components — compose its unstyled, accessible components, build missing ones from `@ui-sdk/core` behaviors, make interfaces agent-ready with `createAgent` and WebMCP, and test keyboard, focus, ARIA, server rendering and right-to-left layout. + +**Install:** `/plugin install ui-sdk@pleaseai` | **Source:** [plugins/ui-sdk](https://github.com/pleaseai/claude-code-plugins/tree/main/plugins/ui-sdk) + #### Skill Optimizer Measure and improve how well a plugin's skills help agents solve real tasks. Runs activation and content evals, diagnoses gaps, fixes instructions, and re-runs until scores improve. diff --git a/plugins/ui-sdk/.agents/skills/ui-sdk/SKILL.md b/plugins/ui-sdk/.agents/skills/ui-sdk/SKILL.md new file mode 100644 index 00000000..35009a16 --- /dev/null +++ b/plugins/ui-sdk/.agents/skills/ui-sdk/SKILL.md @@ -0,0 +1,56 @@ +--- +name: ui-sdk +description: Builds interfaces with ui-sdk in React, Vue, Svelte, Solid or web components. Covers choosing and composing its components, building a component or behavior it doesn't ship from @ui-sdk/core (like a stepper, splitter, transfer list or emoji picker), making the interface usable by agents through createAgent, agent tools and WebMCP, and testing keyboard, focus, ARIA, server rendering and right to left, including writing tests for an existing component. Use whenever a project has @ui-sdk/* installed or the user mentions ui-sdk. +--- + +# Build with ui-sdk + +ui-sdk is a library of UI behaviors: keyboard navigation, focus, selection, dismissal, popups, drag and drop and the ARIA they need. Its components are built from those behaviors and render no styles of their own, in React, Vue, Svelte, Solid and web components. `@ui-sdk/core/web.css` gives them an optional default look. When a component is missing, you build it from the same behaviors in `@ui-sdk/core`, and it gets the same keyboard, focus, server rendering and right to left support. + +## Read first + +The docs for the installed version ship in each package, as Markdown: + +- `node_modules/@ui-sdk//docs/llms.txt` is the index. Read it first. `` is `react`, `vue`, `svelte`, `solid` or `web`. +- Then read only the pages your task needs, like `docs/components/select.md`. Don't read the whole `docs/` folder; it's large. +- An interface built from our components doesn't need `docs/core.md`. Only path 2 below does, and even then you search it by heading: it's over 300 KB. `docs/rendering.md` sits next to it in the same `docs/` folder. +- Don't read compiled JavaScript in `dist/*.js`, even to debug. The docs and the `.d.ts` types are the API; when they don't answer, write a small test that tries it. + +The same docs are online at https://ui-sdk.dev/docs. Prefer the installed copy: it matches the version in the project. + +A page with no build step, like an Artifact, installs nothing: it loads `https://ui-sdk.dev/web.js` and `web.css` with two tags. Read https://ui-sdk.dev/web.md instead of `llms.txt`. It's the web components docs in one file, for that page, and [references/web-components.md](references/web-components.md#without-a-bundler) has the rest. + +Otherwise, if no `@ui-sdk` package is installed yet, install `@ui-sdk/core` and the framework's package with the project's package manager. + +## Pick your path + +1. **Build an interface from our components**, like a settings page, a form or a command palette: read [references/build-interface.md](references/build-interface.md). +2. **Build a component or behavior ui-sdk doesn't ship**, or extend one of ours: read [references/create-component.md](references/create-component.md). + +Most interfaces only need path 1. When one part of it needs a component we don't have, follow path 2 for that part. + +Every path ends the same way: + +3. **Make it agent-ready**: [references/agent-ready.md](references/agent-ready.md). +4. **Test it**: [references/testing.md](references/testing.md). + +## Rules for every path + +- **Import from entries.** Each component has its own entry, like `@ui-sdk/react/select`. There's no root import from a framework package. Never import `@ui-sdk/core/internal/*`. +- **One shape everywhere.** A root and its parts, nested as the component page's Composition shows. Change a part's element with `render`, never an `as` prop. +- **Default or controlled.** `defaultValue` to start, or `value` with `onValueChange(value, details)` to control it (each framework's idiom: `v-model` in Vue, `bind:value` in Svelte, properties and events in web components). `details` has `reason`, `source` and `cancel()`. +- **Name every control.** Use the component's label part (`FieldLabel`, `SelectLabel`, `DialogTitle`), or `aria-label` when there's no visible text. People using screen readers and agents both find controls by name. +- **Style from state.** Target `data-slot` and state attributes like `data-open` or `data-pressed`, and the CSS variables each component lists. Never inline styles for state, and never generated ids. When the app uses `web.css`, read [references/styles.md](references/styles.md) first: it draws icons and sets sizes you can't see in the markup. +- **Declare the ui-sdk layer.** Put `@layer ui-sdk;` at the top of the global stylesheet, above `@import "tailwindcss"` if there is one. +- **Check color.** Text needs 4.5:1 against what's behind it, and control edges, focus rings and state fills 3:1. jsdom can't see color, so check it in a real browser. +- **Key lists by value or id**, never by index. +- **Right to left needs no provider.** Components read the direction from the page. +- **Comments are rare.** Write one only when a reader would get the code wrong without it, like a browser quirk or a trade-off, in one or two lines. Never comment what the code does, what a value is, or which section starts here, and no JSDoc blocks on app code. +- **Don't hand-roll what we ship.** Before you write any `role=` attribute, look for the component in the table in [references/build-interface.md](references/build-interface.md). A `div` with `role="listbox"`, `"menu"`, `"dialog"`, `"tablist"`, `"separator"`, `"switch"`, `"slider"`, `"radiogroup"`, `"toolbar"` or `"tree"` next to an installed ui-sdk package is almost always a bug. + +## When you're done + +1. **Typecheck.** If the root `tsconfig.json` has `"files": []` and `references`, `npx tsc --noEmit` checks nothing: run `npx tsc -b` or `npx tsc --noEmit -p `. For Svelte, run `svelte-check`; for Vue, `vue-tsc`. +2. **Write and run tests** (see testing.md). Every task gets tests, and every interface gets at least the agent test from agent-ready.md. If a test finds a bug in code you were asked only to test, mark it `test.fails` (or `it.fails`) with a one-line reason, report the bug, and leave the suite green. +3. **Read every comment in your diff.** Delete it unless it names a browser quirk, an APG rule or a trade-off, and cut what's left to two lines. Turn JSDoc on app code into a plain comment or delete it. Never tell the reader to replace something. +4. **Report** each command you ran with its exit code, anything you couldn't check, and anything the docs or types got wrong or left out. diff --git a/plugins/ui-sdk/.agents/skills/ui-sdk/references/agent-ready.md b/plugins/ui-sdk/.agents/skills/ui-sdk/references/agent-ready.md new file mode 100644 index 00000000..2ab89c09 --- /dev/null +++ b/plugins/ui-sdk/.agents/skills/ui-sdk/references/agent-ready.md @@ -0,0 +1,136 @@ +# Make it agent-ready + +An app built with ui-sdk can let an agent read its components and call their actions directly, through `createAgent`, instead of clicking through the page. An interface is agent-ready when an agent can find every control by name, call what it needs, and the app sees each change as the agent's and can refuse it. + +The full docs are the Agents pages: `docs/agents.md` in each package, or https://ui-sdk.dev/docs/agents. + +## The checklist + +1. **Every control has a name.** The bridge's `label` is the accessible name: `FieldLabel`, the component's label part, or `aria-label`. Labels should be unique where they sit, because a step finds its component by label (`{ ref: "Project name", … }`). Two "Name" fields in two sections are fine only if a step can still tell them apart by ref or row text. + - A label matches every label that holds its words, and an exact match doesn't win, since labels are page text other people can write. "Tip" and "Custom tip" collide, and so do a "Water the plants" button and a "Done today: Water the plants" checkbox. Give each control in a row a verb of its own ("Open Water the plants"), so none is the bare title. + - Items and tabs are named by their visible text. `aria-label` on an item is ignored. + - A part like a password's Show toggle or a number input's step buttons belongs to its component's entry, and doesn't need a name unique on the page. + - Components that only support another still show up. Give a shared Tooltip its own `aria-label`, an Avatar `role="img"` with `aria-label`, and an Accordion with more than one section `aria-label` on its root. Put `aria-hidden="true"` on a decorative one, which hides it from agents too, and `data-agent-hidden` on a toast region (it drops its label while it's empty). + - A Dialog with several triggers has no name while it's closed: put `keepMounted` on its content, so its title names it. A Menu can't take a name of its own, so don't share one Menu between rows: give each row its own Menu, with a trigger named for its row, like `aria-label="Actions for Jane Doe"`. Labels inside a dialog should differ from the page's too: the bridge still sees the page behind an open modal. +2. **Every control an agent should use is one of our parts.** `snapshot()` lists only ui-sdk components. These are invisible, so an agent can't fill or press them: + - a plain `` in web components), including submit buttons and a wizard's Back and Continue; + - a bare ``, `