ElectroGridy
Linux와 Windows에서 무료
AI 코딩 에이전트를 위한 디자인 시스템, Proper UI 레지스트리에서 실제 React 컴포넌트 설치
The design system for AI coding agents. Claude Code, Codex, Cursor, Lovable and any MCP client search Proper UI's registry and install real, axe-tested React components, with tokens, HTML components a
디자인TypeScript · MDXGitHub @properui온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
The open-source React 19 component library built for AI-generated code. Machine-readable registry, /llms.txt docs mirror, copy-in CLI. React Aria + Tailwind v4. MIT.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
The open-source React 19 component library built for AI-generated code.
Proper UI is a component library, a documentation site and a copy-in CLI in one repository, designed for the way UI
code gets written now: by a coding agent, at speed. A model writing UI from memory invents class names, props and markup
that look plausible and do not compile. This library is readable by machines on purpose: a public JSON registry your
assistant fetches real source from, a plain-markdown mirror of every documentation page indexed at
/llms.txt, and a CLI that writes the files into your project.README 전문 보기 ↗The open-source React 19 component library built for AI-generated code.
properui.dev · Documentation · Components · llms.txt
Proper UI is a component library, a documentation site and a copy-in CLI in one repository, designed for the way UI
code gets written now: by a coding agent, at speed. A model writing UI from memory invents class names, props and markup
that look plausible and do not compile. This library is readable by machines on purpose: a public JSON registry your
assistant fetches real source from, a plain-markdown mirror of every documentation page indexed at
/llms.txt, and a CLI that writes the files into your project.
Components ship as readable TypeScript source rather than a compiled bundle, so you can install @properui/ui as a
normal dependency or copy the files in with npx @properui/cli@latest add and own them outright. Behaviour, keyboard
handling and ARIA come from React Aria Components; styling is Tailwind
CSS v4 utilities resolved through a semantic token layer, so re-branding the whole system means editing one file, and a
generated screen lands on the system rather than near it. Vue, Angular, Svelte, Astro and plain-HTML projects get the
same tokens plus a smaller, curated set of HTML components and custom elements: see Beyond React.
The registry currently holds 818 entries: 89 published component groups (125 counting foundations, shared assets and example-page groups) across seven layers (26 base, 45 application, 18 marketing sections, 12 application page examples, 10 marketing page examples, 8 foundations, 6 shared assets), 446 section variants and 233 full-page examples (679 composable variants total), and the shared hooks, utils and styles they depend on.
Nothing here is specific to one assistant. The surfaces below are plain HTTP, a shell command and a standard MCP server, so Claude Code, Codex, Cursor, v0, Bolt and Lovable can all drive them.
| Surface | URL | What an assistant does with it |
|---|---|---|
| Markdown docs index | /llms.txt | Finds the plain-markdown twin of every page, so it reads the same reference you do without parsing rendered HTML. |
| Component registry | /r/index.json, /r/<name>.json | Fetches a component's real source, props, npm dependencies and registry dependencies: 818 entries. |
| shadcn-compatible registry | /r/shadcn/registry.json, /r/shadcn/<name>.json | The same registry in shadcn's own format under the @properui namespace, so npx shadcn@latest add @properui/<component> and shadcn's MCP server work against it too (see docs/ecosystem.md). |
| Config schema | /schema.json | Validates and autocompletes the components.json that init writes. |
CLI: add | npx @properui/cli@latest add <component> | Writes the .tsx into the project, resolves the dependency chain, rewrites @/ imports to the configured alias, and reports (or, with --install, runs) the install. |
CLI: remove | npx @properui/cli@latest remove <component> | Deletes an installed entry from the project and warns if something else installed still depends on it. |
CLI: why | npx @properui/cli@latest why <component> | Prints what pulled a given entry in, for auditing an install you didn't expect. |
CLI: check | npx @properui/cli@latest check | The token guard: flags raw palette classes and arbitrary values in place of semantic tokens. |
Why generated code comes out better against this library specifically:
bg-primary, text-tertiary, bg-brand-solid),
so a model has a small named set to choose from instead of the open set of arbitrary Tailwind values.strict and noUncheckedIndexedAccess across the monorepo mean
a DOM prop where an Aria prop belongs (disabled instead of isDisabled, a name that doesn't exist on the type) is
a compile error the agent can read and fix. That covers names, not behaviour: a prop that exists on both DOM and
Aria vocabularies but means something subtly different will typecheck and still be wrong, which is why dev-mode
warnings cover the common aliases (readOnly/isReadOnly, required/isRequired, checked/isSelected) instead
of relying on the type system alone..dark-mode class repoints every token and spacing uses logical properties,
so there are no dark: utilities to forget on half the elements and no second stylesheet to hand-write..tsx you own. There is no opaque wrapper between the generated code and
what renders.AGENTS.md holds the conventions an assistant working in this repository should follow. The MCP server
(packages/mcp) registers with claude mcp add properui -- npx -y @properui/mcp, or without installing
anything through the remote endpoint with claude mcp add --transport http properui https://properui.dev/api/mcp; see
properui.dev/mcp for every client and docs/mcp.md for Cursor, Codex, Windsurf
and VS Code.
Install the Proper UI Skill, which tells an assistant when and how to use all of the above, with
npx @properui/cli@latest agent init, or with npx skills add properui/properui (skills.sh, 75+ agents).
axe smoke test that runs in CI: zero detected violations across 150 automated suites; see
the accessibility page for what that does and does not cover.@theme blocks in
packages/ui/src/styles/theme.css. There is no tailwind.config.js.dark: utilities. A .dark-mode class anywhere in the ancestor chain re-maps every semantic
token. Components written against bg-primary / text-secondary are correct in both themes automatically.ms-*,
ps-*, start-*, text-start) so dir="rtl" flips the layout without a fork. The migration away from physical
utilities is still in progress in parts of the marketing layer. See docs/rtl.md.strict and noUncheckedIndexedAccess across the monorepo; every prop is typed and
JSDoc-documented, and tsc --noEmit runs in CI..tsx with per-component subpath exports, so a bundler only ever
sees the components you import.@properui/ui as a normal dependency and importing it in a Vite (or other bundler) project needs no @/ path alias
or tsconfig change on your end. Next.js still needs transpilePackages (see below) because it does not compile
TSX from node_modules by default, not because of any alias.1. Install
pnpm add @properui/ui
# npm install @properui/ui · yarn add @properui/ui
2. Import the stylesheet and let Tailwind scan the package
@properui/ui/styles/globals.css already contains the Tailwind import, the token layer, typography and every plugin
the components need. Tailwind v4 does not scan node_modules by default, so add one @source line:
/* app/globals.css */
@import "@properui/ui/styles/globals.css";
@source "../node_modules/@properui/ui/src/**/*.{ts,tsx}";
3. Transpile the package
Next.js compiles only your own source by default, and this package ships TSX. withProperUI is the one-liner —
it appends @properui/ui to transpilePackages, deduplicated, and leaves the rest of your config alone:
// next.config.ts
import type { NextConfig } from "next";
import { withProperUI } from "@properui/ui/next";
const nextConfig: NextConfig = {};
export default withProperUI(nextConfig);
Equivalent by hand:
// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
transpilePackages: ["@properui/ui"],
};
export default nextConfig;
4. Wrap the app in the providers
ThemeProvider maps next-themes onto the .light-mode / .dark-mode classes the tokens key off. RouterProvider
hands React Aria the Next router so every component that accepts href performs a client-side transition. Both carry
their own "use client" directive, so they can be rendered straight from a server layout:
// app/layout.tsx
import { ThemeProvider } from "@properui/ui/providers";
import { RouterProvider } from "@properui/ui/providers/router-provider";
import "./globals.css";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body className="bg-primary text-primary antialiased">
<ThemeProvider>
<RouterProvider>{children}</RouterProvider>
</ThemeProvider>
</body>
</html>
);
}
suppressHydrationWarning is required: next-themes writes the theme class onto <html> before React hydrates.
1. Install
pnpm add @properui/ui
pnpm add -D @tailwindcss/vite
2. Register the Tailwind plugin
// vite.config.ts
import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [react(), tailwindcss()],
});
3. Import the stylesheet and let Tailwind scan the package
/* src/index.css */
@import "@properui/ui/styles/globals.css";
@source "../node_modules/@properui/ui/src/**/*.{ts,tsx}";
4. Wrap the app in the providers
ThemeProvider is framework-agnostic and works as-is. RouterProvider from @properui/ui/providers/router-provider is Next-only.
In Vite, use React Aria's own RouterProvider and hand it your router's navigate function:
// src/main.tsx
import { StrictMode } from "react";
import { RouterProvider } from "react-aria-components";
import { createRoot } from "react-dom/client";
import { BrowserRouter, useNavigate } from "react-router-dom";
import { ThemeProvider } from "@properui/ui/providers";
import { App } from "./app";
import "./index.css";
const Providers = ({ children }: { children: React.ReactNode }) => {
const navigate = useNavigate();
return (
<ThemeProvider>
<RouterProvider navigate={navigate}>{children}</RouterProvider>
</ThemeProvider>
);
};
createRoot(document.getElementById("root")!).render(
<StrictMode>
<BrowserRouter>
<Providers>
<App />
</Providers>
</BrowserRouter>
</StrictMode>,
);
With no router at all, drop RouterProvider entirely: every component still renders and works; href links just do a
full page load.
import { Button } from "@properui/ui/components/base/buttons/button";
export const Example = () => (
<Button size="md" color="primary" onPress={() => console.log("pressed")}>
Get started
</Button>
);
Import from the subpath (@properui/ui/components/<layer>/<group>/<file>) so bundlers pull in only that component.
The root barrel (import { Button } from "@properui/ui") re-exports everything and is handy while prototyping.
Interactive components are React Aria based: use onPress rather than onClick, and isDisabled rather than
disabled.
Prefer to own the source? Skip the dependency and use the CLI:
npx @properui/cli@latest init
npx @properui/cli@latest add button
init writes components.json, your theme file, the cx utility and the Tailwind @source line, and wires up
ThemeProvider. add copies a component's files (plus everything it depends on) into your project. See
docs/cli.md.
The React layer above is the full library. For projects that are not React there are three smaller packages on the same tokens, so a Vue or plain-HTML page looks the same as a React one:
@properui/tokens: the token layer as plain CSS (theme.css for Tailwind v4 in any framework, tokens.css as
bare CSS variables, the theme presets, and a prebuilt properui.min.css).@properui/html: pui- component classes, small dependency-free behaviours (dropdowns, tabs, modals, tooltips,
toasts) and copy-paste .html snippets.@properui/elements: light-DOM custom elements (<pui-button>, <pui-modal>, ...) for Vue, Angular, Svelte and
Astro templates.They cover a curated set of about twenty components (buttons, form fields, badges, alerts, tabs, dropdowns, modals,
tables, pagination and similar), with accessibility from native HTML (<dialog>, <details>, real form controls) plus
ARIA set by the scripts, not React Aria. Data tables, date pickers, charts, the marketing sections and the page examples
are React-only. docs/frameworks.md has the component-by-component matrix.
No build step:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@properui/tokens/dist/properui.min.css" />
<script src="https://cdn.jsdelivr.net/npm/@properui/html/dist/properui-html.iife.js" data-auto-init defer></script>
<button type="button" class="pui-btn pui-btn--primary pui-btn--md">Save</button>
With a bundler (Vue shown; Angular needs CUSTOM_ELEMENTS_SCHEMA):
npm i @properui/tokens @properui/html @properui/elements
// main.ts
import "@properui/elements/register";
<pui-button color="primary">Save</pui-button>
The CLI detects the framework: npx @properui/cli@latest init on a Vue, Angular, Svelte, Astro or plain-HTML project
writes "platform": "html" to components.json, and add buttons then installs the HTML snippets instead of TSX.
Every colour, radius, shadow and type step is a CSS variable in
packages/ui/src/styles/theme.css. The tokens are layered: a raw palette, a
wider --color-utility-* set for charts and badges, and semantic tokens (--color-bg-primary, --color-text-secondary,
--color-border-tertiary) that components consume as bg-primary, text-secondary, border-tertiary.
A re-brand starts with one edit: replace the eleven --color-brand-* values. If your neutrals or status colours
(success, warning, and so on) are not Tailwind's stock ramps either, shadow those in the same theme.css file,
which now declares the neutral and status ramps, and their ring/border families, that the semantic layer consumes,
so there is one file to grep for every colour a re-brand depends on, not a ramp that is used but never declared.
@theme {
--color-brand-50: rgb(249 245 255);
--color-brand-100: rgb(244 235 255);
--color-brand-200: rgb(233 215 254);
--color-brand-300: rgb(214 187 251);
--color-brand-400: rgb(182 146 246);
--color-brand-500: rgb(158 119 237);
--color-brand-600: rgb(127 86 217);
--color-brand-700: rgb(105 65 198);
--color-brand-800: rgb(83 56 158);
--color-brand-900: rgb(66 48 125);
--color-brand-950: rgb(44 28 95);
}
Every semantic token references those through var(), so buttons, focus rings, links, selected states and charts follow
in both light and dark mode. Full detail in docs/theming.md.
apps/docs documentation site: Next.js 15 App Router + MDX
packages/ui @properui/ui: the component library
src/components base/ application/ marketing/ app-examples/
marketing-examples/ foundations/ shared-assets/
src/styles globals.css · theme.css · typography.css
src/{hooks,utils,providers}
packages/cli properui: the init/add CLI
packages/registry generated registry JSON consumed by the CLI and the docs site
scripts generators, screenshot and visual-diff tooling
docs these guides
Requires Node 20+ and pnpm 9.
pnpm install
pnpm dev # docs site → http://localhost:3000
pnpm storybook # Storybook → http://localhost:6006
pnpm test # type-check + lint + prettier + vitest/axe across the workspace
pnpm gen:all # regenerate barrels, demos, variants, nav and the registry
The documentation site is hosted at properui.dev. pnpm dev serves the same site locally
at http://localhost:3000.
Other useful commands:
pnpm type-check # tsc --noEmit everywhere
pnpm lint # eslint
pnpm prettier # format the repo
pnpm build # build every package and the docs site
pnpm docs:shot <slug> # screenshot a docs page with Playwright
pnpm docs:diff <slug> # pixel-diff it against the stored reference
Contributions are welcome. CONTRIBUTING.md covers the setup, the component conventions that matter
(kebab-case files, Aria* import aliases, semantic tokens only, the styles = sortCx({}) pattern, and the demo, story,
test and docs page every component ships with), how to run the checks, and the changeset-based release flow.
docs/contributing-components.md walks through adding a component end to end.
ROADMAP.md lists what is not built yet (full RTL coverage, visual regression baselines and a few others) so you can see where help is most useful.
By participating you agree to abide by the Code of Conduct. Security issues should be reported privately. See SECURITY.md.
Released under the MIT License. Use it in personal and commercial projects, without attribution.
Every component, example, icon and page in this repository is included. There is no paid tier, no private registry and nothing held back behind an account.
Some components are derived from Untitled UI React, which is released
under the MIT License. Its licence text is kept at
LICENSES/untitledui-react-MIT.txt. Thanks to that project for the token system
and the base component APIs this library builds on.
Built on React Aria Components and Tailwind CSS.
CLI: icons | npx @properui/cli@latest icons | Lists and installs icon components the same way add handles the rest of the registry. |
| HTML registry entries | /r/<component>-html.json | Fetches @properui/html snippets (type: "html") for Vue, Angular, Svelte, Astro and plain HTML; add picks them on an html-platform project. |
| Prebuilt stylesheet | /css/properui.min.css | Tokens plus the html component classes in one file, for a <link> on a page with no build step (also @properui/tokens/dist/properui.min.css on jsDelivr). |
| MCP server | npx -y @properui/mcp | The same registry and add as MCP tools (search_components, get_component, add_component, ...), for assistants that speak MCP. |
| Remote MCP endpoint | /api/mcp (https://properui.dev/api/mcp) | Streamable HTTP, no account. Searches screens, flows, sections and components and returns an install plan; the agent then runs the CLI. Setup per client on /mcp. |
npx @properui/cli@latest add button@/