# mwui Full Context > MediaWeb's installable UI component library. This file expands the Markdown pages listed in https://mwui.vercel.app/llms.txt. Use https://mwui.vercel.app/registry.json for the machine-readable shadcn registry index. --- URL: https://mwui.vercel.app/docs.md Publish installable registry items with public docs from the same workspace. # Introduction Publish installable registry items with public docs from the same workspace. This registry publishes copy-and-paste components, blocks, hooks, files, themes, styles, fonts, bases, and universal items that can be installed with the shadcn CLI. Use the docs in this section to set up the registry, customize the site, and publish your own items. Registry docs live in `registry/docs`. Installable source lives in `registry/items`. You can update any of these files freely (or completely delete them!) --- URL: https://mwui.vercel.app/docs/installation.md Install and run the registry template locally. # Installation Install and run the registry template locally. After forking the template, install dependencies with [Vite+](https://viteplus.dev/guide/) and start the local docs app. ```sh vp install vp dev ``` Open the local URL from Vite+ to preview your docs, registry catalog, and install pages. ## Customize the Registry Update `registry/config.ts` before publishing your fork. This file controls the public registry identity, namespace, description, homepage, repository URL, and generated install URLs. ## Add Registry Items Scaffold new installable items under `registry/items/**` with the starter script. ```sh bun --bun ./scripts/new.ts --type registry:ui --name example-card --description "A compact card component." ``` You can also run `bun --bun ./scripts/new.ts` for an interactive prompt. Use `--target` for `registry:page`, `registry:file`, custom alias installs such as `@ui/ai/prompt-input.tsx`, or targeted `registry:item` files. The scaffold creates the item source, `_registry.mdx` metadata and usage docs, and an optional `_preview.tsx` preview. Public documentation pages live directly in `registry/docs/`. ## Verify Changes Run the registry doctor after item changes, check the files you touched, and build before publishing. ```sh bun --bun ./scripts/doctor.ts vp check --fix vp build ``` --- URL: https://mwui.vercel.app/docs/registry.md Scaffold and author installable registry items under registry/items. # Registry Scaffold and author installable registry items under registry/items. Registry items live under `registry/items/**` and can be installed by shadcn-compatible CLIs. Start new items with the scaffold command so the folder, `_registry.mdx`, source file, metadata, and generated registry JSON paths follow the template conventions. ```sh bun --bun ./scripts/new.ts --type registry:ui --name example-card --description "A compact card component." ``` Or, run the command without flags if you want an interactive prompt (recommended). ```sh bun --bun ./scripts/new.ts ``` [Make sure Bun is installed before running these scripts.](https://bun.com/) ## Item Types Choose the registry type from what the item installs: | Type | Use For | Folder | | -------------------- | ----------------------------------------- | ------------------------------ | | `registry:ui` | Shadcn-style UI components | `registry/items/components/**` | | `registry:component` | Components outside `components/ui` | `registry/items/components/**` | | `registry:block` | Larger composed UI patterns | `registry/items/blocks/**` | | `registry:hook` | React hooks | `registry/items/hooks/**` | | `registry:lib` | Utility or helper modules | `registry/items/lib/**` | | `registry:page` | App page files with explicit targets | `registry/items/pages/**` | | `registry:file` | Other files with explicit install targets | `registry/items/files/**` | | `registry:style` | Style-level CSS and dependency metadata | `registry/items/styles/**` | | `registry:theme` | Theme CSS variables | `registry/items/themes/**` | | `registry:font` | Font metadata | `registry/items/fonts/**` | | `registry:base` | Design system base configuration | `registry/items/bases/**` | | `registry:item` | Universal or metadata-only items | `registry/items/items/**` | The scaffold creates each item in its own folder: ```text registry/items/components/example-card/ _registry.mdx _preview.tsx example-card.tsx ``` ## CLI Flags Use flags for agent-friendly and CI-friendly scaffolding: ```sh bun --bun ./scripts/new.ts --type registry:block --name team-access-panel --description "A team member access panel." bun --bun ./scripts/new.ts --type registry:ui --name prompt-input --description "An AI prompt input." --target @ui/ai/prompt-input.tsx bun --bun ./scripts/new.ts --type registry:page --name dashboard-page --description "A starter dashboard page." --target app/dashboard/page.tsx bun --bun ./scripts/new.ts --type registry:file --name chart-theme --description "Shared chart theme tokens." --target styles/chart-theme.css --file-extension css bun --bun ./scripts/new.ts --type registry:font --name font-inter --description "Inter font metadata." --font-family "'Inter Variable', sans-serif" --font-import Inter --font-variable=--font-sans ``` Supported flags: - `--type`: registry item type. Defaults to `registry:ui`. - `--name`: required kebab-case item name. - `--title`: optional public title. Defaults from the name. - `--description`: required public description. - `--target`: required for `registry:page` and `registry:file`; optional for source-backed items that need a custom install path, including shadcn target placeholders like `@ui/ai/prompt-input.tsx`. - `--file-extension`: for `registry:file` and targeted `registry:item`; defaults to `ts`. - `--font-family`, `--font-import`, `--font-variable`: required for noninteractive `registry:font` scaffolds. Use `bun --bun ./scripts/new.ts --help` to print the full usage. ## Authoring Use `_registry.mdx` for public metadata and usage docs. Put the optional named `Preview` export in `_preview.tsx`. Keep both files private to authoring; never list them in `files`. For one-file `registry:ui` items, the catalog infers `.tsx`. Hooks, libs, blocks, pages, target paths, and multi-file items should list `files` explicitly. Metadata-only styles, themes, fonts, bases, and universal items can omit `files`. List authored source files with paths relative to the item `_registry.mdx` file. The catalog automatically emits `files[].target` placeholders such as `@ui/.tsx`, `@components/.tsx`, `@hooks/.ts`, and `@lib/.ts` for file types that should install through the user's `components.json` aliases. Use explicit `target` values for `registry:page`, `registry:file`, and nested alias installs like `@ui/ai/prompt-input.tsx`; do not add `registry/items/**` prefixes or a separate `sourcePath` field. Use `localRegistryDependencies` for dependencies on other local registry items. After editing an item, run `vp check --fix` on touched files and `bun --bun ./scripts/doctor.ts`. Run `vp build` when registry docs, routes, JSON output, catalog loading, or source loading changed. --- URL: https://mwui.vercel.app/docs/agents.md Give AI coding tools the right context for using and authoring this registry. # Agents Give AI coding tools the right context for using and authoring this registry. This template is designed to work well with coding agents and LLM-powered tools. It exposes Markdown-first routes for reading context, and it ships an installable Agent Skill for authoring registry items correctly. ## Install the Registry Skill Install the `mwui` registry authoring skill: ```sh npx skills add mgalexandre/mwui --skill shadcn-registry ``` Forks can install the same skill from their own repository: ```sh npx skills add / --skill shadcn-registry ``` After installing the skill, ask for registry work directly: - "add a button component to the registry" - "adapt this modal from my app into a reusable registry component" - "add a reusable hook to the registry" - "turn this dashboard section into a registry block" The skill covers all public registry item types, previews, usage docs, dependency metadata, and the scaffold command for creating new items non-interactively. ## Point Agents At Markdown The generated [`/llms.txt`](/llms.txt) route gives AI tools a compact map of the docs, registry catalog, and item pages. Use [`/llms-full.txt`](/llms-full.txt) when a tool needs expanded context with generated Markdown content inlined. Every docs page, the registry catalog, and each registry item also has a Markdown route: - [`/docs.md`](/docs.md) - [`/docs/agents.md`](/docs/agents.md) - [`/registry.md`](/registry.md) - [`/components/autosize-textarea.md`](/components/autosize-textarea.md) Inspired by [Fumadocs](https://www.fumadocs.dev/docs/headless/utils/negotiation), "human" permalinks support Markdown content negotiation too. AI clients can request `text/markdown`, `text/x-markdown`, or `text/plain` in the `Accept` header on pages like [`/docs`](/docs) or [`/components/autosize-textarea`](/components/autosize-textarea) and receive Markdown without changing URLs. ## Recommended Agent Workflow For registry authoring tasks, agents should: 1. Read `AGENTS.md`, this docs section, and `/llms.txt` or `/llms-full.txt` for project context. 2. Use the `shadcn-registry` skill when available. 3. Scaffold new items with `bun --bun ./scripts/new.ts --type --name --description ""`. 4. Add `--target` for `registry:page`, `registry:file`, custom alias installs like `@ui/ai/.tsx`, and targeted `registry:item` files; use `--file-extension` for `registry:file` and targeted `registry:item` files. 5. Edit the generated source, `_registry.mdx`, and `_preview.tsx` with usage docs, previews, and dependency metadata. 6. Run `vp check --fix` on touched files, `bun --bun ./scripts/doctor.ts`, and `vp build` before handoff when docs, routes, registry JSON, catalog loading, or source loading changed. --- URL: https://mwui.vercel.app/docs/cli.md Install items from this registry with the shadcn CLI. # CLI Install items from this registry with the shadcn CLI. Install a registry item with the command shown on its docs page. ```sh npx shadcn@latest add https://mwui.vercel.app/r/autosize-textarea.json ``` The command that's displayed uses the `homepage` value from `registry/config.ts` for the base URL. Human-facing item pages also work with the shadcn CLI through content negotiation. For example, a browser can view [`/components/autosize-textarea`](/components/autosize-textarea), while the CLI receives the installable item JSON from the same URL: ```sh npx shadcn@latest add https://mwui.vercel.app/components/autosize-textarea ``` Use the package manager selector on item pages to switch between npm, pnpm, yarn, bun, vite+, and deno commands. ## Endpoints The registry index is served from both the root and the `/r` path, while installable item JSON lives under `/r`: | Route | Serves | | ------------------ | ------------------------ | | `/registry.json` | The registry index. | | `/r/registry.json` | The same registry index. | | `/r/.json` | One installable item. | Authored metadata is validated against the schemas from [`shadcn/schema`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/registry/schema.ts), so anything these routes serve is CLI-compatible. --- URL: https://mwui.vercel.app/docs/theming.md Customize the docs shell and published components with your own design tokens. # Theming Customize the docs shell and published components with your own design tokens. The docs app uses the local shadcn configuration in `components.json` and the global theme in `src/styles.css`. Published registry items are independent from the docs shell. Put installable component source in `registry/items/**`, and include any required CSS, dependencies, or registry dependencies in the item frontmatter. Use semantic tokens such as `background`, `foreground`, `primary`, `muted`, and `border` so installed components remain easy to customize. --- URL: https://mwui.vercel.app/components.md Installable UI primitives and components. # Components Installable UI primitives and components. - [Autosize Textarea](https://mwui.vercel.app/components/autosize-textarea): A textarea that grows with its content between row bounds. - [Avatar Group](https://mwui.vercel.app/components/avatar-group): A stacked avatar row with overflow counting and tooltips. - [Color Picker](https://mwui.vercel.app/components/color-picker): An accessible, composable color picker with a saturation area, hue and alpha sliders, eyedropper, swatches, and hex/rgb/hsl/oklch output. - [Command Palette](https://mwui.vercel.app/components/command-palette): A searchable command palette with groups, nested pages, and recent actions. - [Confirm Dialog](https://mwui.vercel.app/components/confirm-dialog): A promise-based confirmation dialog driven by an imperative confirm() call. - [Copy Button](https://mwui.vercel.app/components/copy-button): A copy-to-clipboard button with success feedback. - [Date Range Picker](https://mwui.vercel.app/components/date-range-picker): A date range picker with a self-contained calendar, quick presets, and keyboard-first navigation. - [File Dropzone](https://mwui.vercel.app/components/file-dropzone): A drag-and-drop file input with previews, validation, and per-file progress. - [Multi Select](https://mwui.vercel.app/components/multi-select): A multi-select combobox with chips, async search, and grouped options. - [OTP Input](https://mwui.vercel.app/components/otp-input): A one-time-code input with per-character slots and paste support. - [Phone Input](https://mwui.vercel.app/components/phone-input): An international phone input with country select and formatting. - [Tags Input](https://mwui.vercel.app/components/tags-input): A free-form chip input with paste splitting, validation, and duplicate handling. - [Time Picker](https://mwui.vercel.app/components/time-picker): A keyboard-first time input with 12/24-hour formats and step granularity. - [Timeline](https://mwui.vercel.app/components/timeline): A vertical timeline for activity feeds and status history. --- URL: https://mwui.vercel.app/components/autosize-textarea.md A textarea that grows with its content between row bounds. # Autosize Textarea A textarea that grows with its content between row bounds. ## Installation ```bash npx shadcn@latest add https://mwui.vercel.app/r/autosize-textarea.json ``` [Registry JSON](https://mwui.vercel.app/r/autosize-textarea.json) ## Preview ```tsx import * as React from "react"; import { AutosizeTextarea } from "@/components/ui/autosize-textarea"; export function Preview() { const [message, setMessage] = React.useState( "Type a few lines here and watch the field grow.\nIt stops after six rows and scrolls instead.", ); return (
setMessage(event.target.value)} minRows={2} maxRows={6} placeholder="Write a message…" />

{message.length} characters · {message.split("\n").length} lines

); } ``` ## Source ### ui/autosize-textarea.tsx ```tsx "use client"; import * as React from "react"; import { ScrollArea } from "@/components/ui/scroll-area"; import { useResizeObserver } from "@/hooks/use-resize-observer"; import { cn } from "@/lib/utils"; type AutosizeTextareaProps = Omit, "rows"> & { minRows?: number; maxRows?: number; scrollArea?: boolean; onHeightChange?: (height: number) => void; }; function AutosizeTextarea({ minRows = 2, maxRows, scrollArea = true, onHeightChange, className, ref, value, defaultValue, onChange, ...props }: AutosizeTextareaProps) { const textareaRef = React.useRef(null); const containerRef = React.useRef(null); const { ref: observerRef, width } = useResizeObserver(); const [internalValue, setInternalValue] = React.useState(defaultValue ?? ""); const resolvedValue = value ?? internalValue; const scrolled = scrollArea && maxRows !== undefined; const onHeightChangeRef = React.useRef(onHeightChange); React.useEffect(() => { onHeightChangeRef.current = onHeightChange; }); const setRefs = React.useCallback( (node: HTMLTextAreaElement | null) => { textareaRef.current = node; observerRef(node); if (typeof ref === "function") { ref(node); } else if (ref) { ref.current = node; } }, [observerRef, ref], ); React.useLayoutEffect(() => { const textarea = textareaRef.current; if (!textarea) return; const styles = getComputedStyle(textarea); const lineHeight = Number.parseFloat(styles.lineHeight) || 20; const padding = Number.parseFloat(styles.paddingTop) + Number.parseFloat(styles.paddingBottom); const border = Number.parseFloat(styles.borderTopWidth) + Number.parseFloat(styles.borderBottomWidth); textarea.style.height = "auto"; const contentHeight = textarea.scrollHeight + border; const minHeight = minRows * lineHeight + padding + border; const maxHeight = maxRows === undefined ? Infinity : maxRows * lineHeight + padding + border; const height = scrolled ? Math.max(contentHeight, minHeight) : Math.min(Math.max(contentHeight, minHeight), maxHeight); textarea.style.height = `${height}px`; textarea.style.overflowY = !scrolled && contentHeight > maxHeight ? "auto" : "hidden"; const container = containerRef.current; if (container) { // The viewport is the element that actually scrolls, so the row cap belongs on it. const viewport = container.querySelector("[data-slot=scroll-area-viewport]") ?? container; viewport.style.maxHeight = `${maxHeight}px`; container.style.maxHeight = `${maxHeight}px`; } onHeightChangeRef.current?.(Math.min(height, maxHeight)); }, [resolvedValue, width, minRows, maxRows, scrolled]); const field = (