Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/ui/content/docs/(root)/get-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,6 @@ For developers migrating from **Radix UI**, many of our **UI primitives** includ

We structure the documentation to make the components **AI-friendly**, so language models can understand, reason about, and modify them. To support this, we include:

- **[Agent Skills](/ui/docs/skills)** — Install coss knowledge directly into your AI assistant with `npx skills add cosscom/coss`. Covers all 53 primitives, styling conventions, migration patterns, and particle examples.
- A [llms.txt](/ui/llms.txt) file that provides a map of the documentation and component structure for your AI agent.
- A **Copy Markdown** button on every page, so you can easily share content or feed it to your AI workflows.
9 changes: 8 additions & 1 deletion apps/ui/content/docs/(root)/meta.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
{
"pages": ["index", "get-started", "styling", "radix-migration", "roadmap"],
"pages": [
"index",
"get-started",
"styling",
"radix-migration",
"skills",
"roadmap"
],
"title": "Overview"
}
2 changes: 1 addition & 1 deletion apps/ui/content/docs/(root)/roadmap.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Origin UI offered a large collection of 600+ ready-to-use UI components. With th

## Current Status

- **40+ UI primitives** already available, with more on the way.
- **50+ UI primitives** already available, with more on the way.
- A **growing set of particles**, progressively expanding to match and surpass the current Origin UI collection.

## What’s Next
Expand Down
58 changes: 58 additions & 0 deletions apps/ui/content/docs/(root)/skills.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
title: Skills
description: Give your AI assistant deep knowledge of coss ui components, patterns, and best practices.
---

Skills provide AI coding assistants with structured knowledge about **coss ui** — component APIs, composition patterns, styling conventions, migration rules, and common pitfalls. When installed, your assistant knows how to use coss primitives correctly without guessing.

For example, you can ask your assistant to:

- _"Add a settings dialog with a form and save/cancel buttons."_
- _"Add a select with grouped options and a search filter."_
- _"Migrate this shadcn dropdown menu to coss."_
- _"Build a toast notification for form submission errors."_

## Install

```bash
npx skills add cosscom/coss
```

This installs the coss skill into your project. Once installed, your AI assistant automatically loads it when working with coss ui components.

Learn more about the skills ecosystem at [skills.sh](https://skills.sh).

## What's Included

The skill covers the full coss ui surface:

### Component Knowledge

Reference guides for all primitives — imports, minimal patterns, inline code examples, composition rules, and common pitfalls. The assistant knows when to use Dialog vs Sheet vs Drawer, how to compose trigger-based overlays, and how to structure forms with Field.

### Styling Conventions

Tailwind v4 token usage, semantic color system, icon sizing rules, `data-slot` selectors, `--alpha()` syntax, and the font variable contract (`--font-sans`, `--font-mono`, `--font-heading`).

### Migration Patterns

Rules for migrating from shadcn/Radix to coss/Base UI — `asChild` to `render`, `onSelect` to `onClick`, Select items-first pattern, ToggleGroup `type` to `multiple`, and Slider scalar values.

### CLI and Registry

Full reference for installing components via the shadcn CLI, discovery fallbacks, and manual install paths.

### Particle Examples

The skill references the particle catalog — real-world composition examples for every primitive — so the assistant can produce production-realistic code, not just minimal stubs.

## How It Works

1. **Skill activation** — Your AI agent detects the installed skill files in your project.
2. **Progressive loading** — The root `SKILL.md` provides core rules and a component registry index. Detailed per-component guides and rule references are loaded on demand when the task requires them.
3. **Pattern enforcement** — The assistant follows coss composition rules: `render` prop for trigger composition, `DialogHeader`/`DialogPanel`/`DialogFooter` section structure, `variant="ghost"` for cancel buttons, and correct Base UI APIs.
4. **Example-driven output** — Before generating code, the assistant consults particle examples to match real coss patterns.

## Supported Agents

Skills work with any agent that supports the Agent Skills specification, including Claude Code, Cursor, Codex, Cline, Windsurf, GitHub Copilot, and many more.
1 change: 1 addition & 0 deletions apps/ui/lib/docs.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const PAGES_NEW = [
// "/docs/components/{component-name}",
"/docs/skills",
"/docs/components/drawer",
"/docs/components/input-otp",
];
2 changes: 1 addition & 1 deletion apps/ui/public/r/textarea.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"files": [
{
"path": "registry/default/ui/textarea.tsx",
"content": "\"use client\";\n\nimport { Field as FieldPrimitive } from \"@base-ui/react/field\";\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport type * as React from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\n\nexport type TextareaProps = React.ComponentPropsWithoutRef<\"textarea\"> &\n React.RefAttributes<HTMLElement> & {\n size?: \"sm\" | \"default\" | \"lg\" | number;\n unstyled?: boolean;\n };\n\nexport function Textarea({\n className,\n size = \"default\",\n unstyled = false,\n ref,\n ...props\n}: TextareaProps): React.ReactElement {\n return (\n <span\n className={\n cn(\n !unstyled &&\n \"relative inline-flex w-full rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base text-foreground shadow-xs/5 ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] has-focus-visible:has-aria-invalid:border-destructive/64 has-focus-visible:has-aria-invalid:ring-destructive/16 has-aria-invalid:border-destructive/36 has-focus-visible:border-ring has-disabled:opacity-64 has-[:disabled,:focus-visible,[aria-invalid]]:shadow-none has-focus-visible:ring-[3px] not-has-disabled:has-not-focus-visible:not-has-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] sm:text-sm dark:bg-input/32 dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:has-not-focus-visible:not-has-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)]\",\n className,\n ) || undefined\n }\n data-size={size}\n data-slot=\"textarea-control\"\n >\n <FieldPrimitive.Control\n ref={ref}\n value={props.value}\n defaultValue={props.defaultValue}\n disabled={props.disabled}\n id={props.id}\n name={props.name}\n render={(defaultProps: React.ComponentProps<\"textarea\">) => (\n <textarea\n className={cn(\n \"field-sizing-content min-h-17.5 w-full rounded-[inherit] px-[calc(--spacing(3)-1px)] py-[calc(--spacing(1.5)-1px)] outline-none max-sm:min-h-20.5\",\n size === \"sm\" &&\n \"min-h-16.5 px-[calc(--spacing(2.5)-1px)] py-[calc(--spacing(1)-1px)] max-sm:min-h-19.5\",\n size === \"lg\" &&\n \"min-h-18.5 py-[calc(--spacing(2)-1px)] max-sm:min-h-21.5\",\n )}\n data-slot=\"textarea\"\n {...mergeProps(defaultProps, props)}\n />\n )}\n />\n </span>\n );\n}\n\nexport { FieldPrimitive };\n",
"content": "\"use client\";\n\nimport { Field as FieldPrimitive } from \"@base-ui/react/field\";\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport type * as React from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\n\nexport type TextareaProps = React.ComponentPropsWithoutRef<\"textarea\"> &\n React.RefAttributes<HTMLTextAreaElement> & {\n size?: \"sm\" | \"default\" | \"lg\" | number;\n unstyled?: boolean;\n };\n\nexport function Textarea({\n className,\n size = \"default\",\n unstyled = false,\n ref,\n ...props\n}: TextareaProps): React.ReactElement {\n return (\n <span\n className={\n cn(\n !unstyled &&\n \"relative inline-flex w-full rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base text-foreground shadow-xs/5 ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] has-focus-visible:has-aria-invalid:border-destructive/64 has-focus-visible:has-aria-invalid:ring-destructive/16 has-aria-invalid:border-destructive/36 has-focus-visible:border-ring has-disabled:opacity-64 has-[:disabled,:focus-visible,[aria-invalid]]:shadow-none has-focus-visible:ring-[3px] not-has-disabled:has-not-focus-visible:not-has-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] sm:text-sm dark:bg-input/32 dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:has-not-focus-visible:not-has-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)]\",\n className,\n ) || undefined\n }\n data-size={size}\n data-slot=\"textarea-control\"\n >\n <FieldPrimitive.Control\n ref={ref}\n value={props.value}\n defaultValue={props.defaultValue}\n disabled={props.disabled}\n id={props.id}\n name={props.name}\n render={(defaultProps: React.ComponentProps<\"textarea\">) => (\n <textarea\n className={cn(\n \"field-sizing-content min-h-17.5 w-full rounded-[inherit] px-[calc(--spacing(3)-1px)] py-[calc(--spacing(1.5)-1px)] outline-none max-sm:min-h-20.5\",\n size === \"sm\" &&\n \"min-h-16.5 px-[calc(--spacing(2.5)-1px)] py-[calc(--spacing(1)-1px)] max-sm:min-h-19.5\",\n size === \"lg\" &&\n \"min-h-18.5 py-[calc(--spacing(2)-1px)] max-sm:min-h-21.5\",\n )}\n data-slot=\"textarea\"\n {...mergeProps(defaultProps, props)}\n />\n )}\n />\n </span>\n );\n}\n\nexport { FieldPrimitive };\n",
"type": "registry:ui"
}
],
Expand Down
2 changes: 1 addition & 1 deletion apps/ui/registry/default/ui/textarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type * as React from "react";
import { cn } from "@/registry/default/lib/utils";

export type TextareaProps = React.ComponentPropsWithoutRef<"textarea"> &
React.RefAttributes<HTMLElement> & {
React.RefAttributes<HTMLTextAreaElement> & {
size?: "sm" | "default" | "lg" | number;
unstyled?: boolean;
};
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/textarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { cn } from "@coss/ui/lib/utils";
import type * as React from "react";

export type TextareaProps = React.ComponentPropsWithoutRef<"textarea"> &
React.RefAttributes<HTMLElement> & {
React.RefAttributes<HTMLTextAreaElement> & {
size?: "sm" | "default" | "lg" | number;
unstyled?: boolean;
};
Expand Down
Loading