home / skills / thunderboltdev / shadcn-baseui / shadcn-baseui

shadcn-baseui skill

/SKILL.md

This skill enforces Base UI patterns in shadcn/ui projects, preventing incorrect Radix UI guidance and ensuring render prop usage.

npx playbooks add skill thunderboltdev/shadcn-baseui --skill shadcn-baseui

Review the files below or copy the command above to add this skill to your agents.

Files (3)
SKILL.md
3.3 KB
---
name: shadcn-baseui
description: Enforces Base UI patterns in shadcn/ui projects. Prevents LLMs from incorrectly suggesting Radix UI patterns (asChild, etc.) when working with Base UI.
metadata:
  author: thunderbolt
  version: "1.0.0"
---

# shadcn/ui + Base UI Guidelines

A guide for using shadcn/ui components when working with Base UI. Prevents LLMs from incorrectly suggesting Radix UI patterns (asChild, etc.).

⚠️ **CRITICAL:** Before suggesting any code, verify this is a Base UI project by checking `components.json`. The `style` field should start with `"base-"` (e.g., `"base-vega"`, `"base-nova"`, `"base-maia"`, `"base-lyra"`, `"base-mira"`). If it starts with something else, this skill does not apply.

Ensure the `@base-ui/react` package is installed. If not, install it using the appropriate package manager.

## Slot Pattern

The major difference between Radix UI and Base UI is the slot pattern. Radix UI uses `asChild`, while Base UI uses the `render` prop. Always use `render` prop over `asChild`.

**Rule:** Always use `render` prop instead of `asChild` for ALL trigger/wrapper components.

Applies to: `DialogTrigger`, `AlertDialogTrigger`, `PopoverTrigger`, `DropdownMenuTrigger`, `TooltipTrigger`, `SelectTrigger`, `TabsTrigger`, `AccordionTrigger`, `Button` (when wrapping links), etc.

```tsx
// ❌ INCORRECT
<DialogTrigger asChild>
  <Button variant="outline">Click me</Button>
</DialogTrigger>

// ✅ CORRECT
<DialogTrigger render={<Button variant="outline" />}>
  Click me
</DialogTrigger>

// ✅ ALSO CORRECT
<DialogTrigger render={<Button variant="outline">Click me</Button>} />
```

## Props

Beyond the slot pattern, only the following components have different props. When using these components following the component specific guide.

### Accordion

There's no `type` prop on the `Accordion` component, use the boolean `multiple` prop instead. The `defaultValue` prop is always array based.

1. Single Mode

```tsx
// ❌ INCORRECT
<Accordion type="single" defaultValue="item-1">
  <AccordionItem value="item-1">
    // ...
  </AccordionItem>
</Accordion>

// ✅ CORRECT
<Accordion defaultValue={["item-1"]}>
  <AccordionItem value="item-1">
    // ...
  </AccordionItem>
</Accordion>
```

2. Multi Mode

```tsx
// ❌ INCORRECT
<Accordion type="multiple" defaultValue={["item-1", "item-2"]}>
  <AccordionItem value="item-1">...</AccordionItem>
  <AccordionItem value="item-2">...</AccordionItem>
</Accordion>

// ✅ CORRECT
<Accordion multiple defaultValue={["item-1", "item-2"]}>
  <AccordionItem value="item-1">...</AccordionItem>
  <AccordionItem value="item-2">...</AccordionItem>
</Accordion>
```

### Button (Special Case)

When rendering a Button as a non-button element (like a Link), you must add `nativeButton={false}`.

```tsx
// ❌ INCORRECT - Radix pattern
import Link from "next/link";

<Button asChild variant="ghost">
  <Link href="/dashboard">Dashboard</Link>
</Button>

// ✅ CORRECT - Base UI pattern
import Link from "next/link";

<Button render={<Link href="/dashboard" />} variant="ghost" nativeButton={false}>
  Dashboard
</Button>
```

### Select 

The `position` prop is replaced with a boolean prop `alignItemWithTrigger` which defaults to true.

```tsx
// ❌ INCORRECT
<SelectContent position="popper">
  // ...
</SelectContent>

// ✅ CORRECT
<SelectContent alignItemWithTrigger={false}>
  // ...
</SelectContent>
```

Overview

This skill enforces Base UI patterns when working with shadcn/ui projects to prevent incorrect Radix UI suggestions. It verifies the project is using Base UI and guides code changes like using the render prop and Base UI–specific prop names. The goal is correct, idiomatic component usage and fewer integration bugs.

How this skill works

First, it checks components.json to confirm the project uses a Base UI style (style field starting with "base-"). It ensures @base-ui/react is installed, then enforces the slot pattern and component-specific prop differences. The skill replaces or flags Radix patterns such as asChild, type= on Accordion, and Radix-specific position props with Base UI equivalents.

When to use it

  • When generating or reviewing shadcn/ui component code in a project that uses Base UI.
  • Before suggesting component wrappers or trigger patterns to avoid Radix-specific solutions.
  • When converting Radix-based examples to Base UI equivalents.
  • During code reviews to ensure consistent Base UI prop usage and patterns.
  • When confirming project dependencies include @base-ui/react before giving code snippets.

Best practices

  • Always verify components.json style starts with "base-" before applying Base UI rules.
  • Use the render prop for all trigger/wrapper components instead of asChild.
  • For Button rendered as non-button elements, set nativeButton={false} when using render.
  • Use Accordion defaultValue as an array and multiple (boolean) instead of type prop.
  • Replace SelectContent position prop with alignItemWithTrigger boolean when needed.

Example use cases

  • Convert a DialogTrigger that used asChild to a render prop with a Button element.
  • Fix an Accordion that incorrectly used type="single" and string defaultValue to array defaultValue.
  • Update a Button wrapping a Next.js Link to use render and nativeButton={false}.
  • Swap SelectContent position="popper" to alignItemWithTrigger={false} in a dropdown.
  • Validate an incoming code suggestion and reject Radix patterns before supplying Base UI code.

FAQ

How do I detect a Base UI project?

Check components.json and ensure the style field starts with "base-" (for example "base-vega").

What if @base-ui/react is not installed?

Install @base-ui/react with your package manager before applying Base UI component patterns.