Receber por email
← Voltar para o catálogo

base-ui-react

Production-tested setup for Base UI (@base-ui-components/react) - MUI's unstyled component library that provides accessible, customizable React components using render props pattern. This skill should be used when building accessible UIs with full styling control, migrating from Radix UI, or needing components with Floating UI integration for smart positioning. Use when: Setting up Base UI in Vite

15estrelas
Atualizado há 11 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add jackspace/ClaudeSkillz

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/base-ui-react/svg)](https://www.skillteca.com.br/skills/base-ui-react)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Base UI React

Status: Beta (v1.0.0-beta.4) - Stable v1.0 expected Q4 2025 Last Updated: 2025-11-07 Dependencies: React 19+, Vite (recommended), Tailwind v4 (recommended) Latest Versions: @base-ui-components/react@1.0.0-beta.4

⚠️ Important Beta Status Notice

Base UI is currently in beta. Before using in production:

  • ✅ Stable: Core components (Dialog, Popover, Tooltip, Select, Accordion) are production-ready
  • ⚠️ API May Change: Minor breaking changes possible before v1.0 (Q4 2025)
  • ✅ Production Tested: Used in real projects with documented workarounds
  • ⚠️ Known Issues: 10+ documented issues with solutions in this skill
  • ✅ Migration Path: Clear migration guide from Radix UI included

Recommendation: Use for new projects comfortable with beta software. Wait for v1.0 for critical production apps.

Quick Start (5 Minutes)

1. Install Base UI

pnpm add @base-ui-components/react

Why this matters:

  • Single package contains all 27+ accessible components
  • No peer dependencies besides React
  • Tree-shakeable - only import what you need
  • Works with any styling solution (Tailwind, CSS Modules, Emotion, etc.)

2. Use Your First Component

// src/App.tsx
import { Dialog } from "@base-ui-components/react/dialog";

export function App() {
  return (
    <Dialog.Root>
      {/* Render prop pattern - Base UI's key feature */}
      <Dialog.Trigger
        render={(props) => (
          <button {...props} className="px-4 py-2 bg-blue-600 text-white rounded">
            Open Dialog
          </button>
        )}
      />

      <Dialog.Portal>
        <Dialog.Backdrop
          render={(props) => (
            <div {...props} className="fixed inset-0 bg-black/50" />
          )}
        />

        <Dialog.Popup
          render={(props) => (
            <div
              {...props}
              className="fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 bg-white rounded-lg shadow-xl p-6"
            >
              <Dialog.Title render={(titleProps) => (
                <h2 {...titleProps} className="text-2xl font-bold mb-4">
                  Dialog Title
                </h2>
              )} />

              <Dialog.Description render={(descProps) => (
                <p {...descProps} className="text-gray-600 mb-6">
                  This is a Base UI dialog. Fully accessible, fully styled by you.
                </p>
              )} />

              <Dialog.Close render={(closeProps) => (
                <button {...closeProps} className="px-4 py-2 border rounded">
                  Close
                </button>
              )} />
            </div>
          )}
        />
      </Dialog.Portal>
    </Dialog.Root>
  );
}

CRITICAL:

  • ✅ Always spread {...props} from render functions
  • ✅ Use <Dialog.Portal> to render outside DOM hierarchy
  • ✅ Backdrop and Popup are separate components (unlike Radix's combined Overlay + Content)

3. Components with Positioning (Select, Popover, Tooltip)

For components that need smart positioning, wrap in Positioner:

import { Popover } from "@base-ui-components/react/popover";

<Popover.Root>
  <Popover.Trigger
    render={(props) => <button {...props}>Open</button>}
  />

  {/* Positioner uses Floating UI for smart positioning */}
  <Popover.Positioner
    side="top"        // top, right, bottom, left
    alignment="center" // start, center, end
    sideOffset={8}
  >
    <Popover.Portal>
      <Popover.Popup
        render={(props) => (
          <div {...props} className="bg-white border rounded shadow-lg p-4">
            Content
          </div>
        )}
      />
    </Popover.Portal>
  </Popover.Positioner>
</Popover.Root>

The Render Prop Pattern (vs Radix's asChild)

Why Render Props?

Base UI uses render props instead of Radix's asChild pattern. This provides:

✅ Explicit prop spreading - Clear what props are being applied ✅ Better TypeScript support - Full type inference for props ✅ Easier debugging - Inspect props in dev tools ✅ Composition flexibility - Combine multiple render functions

Comparison

Radix UI (asChild):

import * as Dialog from "@radix-ui/react-dialog";

<Dialog.Trigger asChild>
  <button>Open</button>
</Dialog.Trigger>

Base UI (render prop):

import { Dialog } from "@base-ui-components/react/dialog";

<Dialog.Trigger
  render={(props) => (
    <button {...props}>Open</button>
  )}
/>

Key Difference: Render props make prop spreading explicit ({...props}), while asChild does it implicitly.

The Positioner Pattern (Floating UI Integration)

Components that float (Select, Popover, Tooltip) use the Positioner pattern:

Without Positioner (Wrong)

// ❌ This won't position correctly
<Popover.Root>
  <Popover.Trigger />
  <Popover.Popup /> {/* Missing positioning logic */}
</Popover.Root>

With Positioner (Correct)

// ✅ Positioner handles Floating UI positioning
<Popover.Root>
  <Popover.Trigger />
  <Popover.Positioner side="top" alignment="center">
    <Popover.Portal>
      <Popover.Popup />
    </Popover.Portal>
  </Popover.Positioner>
</Popover.Root>

Positioning Options

<Positioner
  side="top"          // top | right | bottom | left
  alignment="center"  // start | center | end
  sideOffset={8}      // Gap between trigger and popup
  alignmentOffset={0} // Shift along alignment axis
  collisionBoundary={null} // null = viewport, or HTMLElement
  collisionPadding={8}     // Padding from boundary
/>

Component Catalog

Components Requiring Positioner

These components must wrap Popup in Positioner:

  • Select - Custom select dropdown
  • Popover - Floating content container
  • Tooltip - Hover/focus tooltips

Components Not Needing Positioner

These components position themselves:

  • Dialog - Modal dialogs
  • Accordion - Collapsible sections
  • NumberField - Number input with increment/decrement
  • Checkbox, Radio, Switch, Slider - Form controls

Known Issues Prevention

This skill prevents 10+ documented issues:

Issue #1: Render Prop Not Spreading Props

Error: Component doesn't respond to triggers, no accessibility attributes Source: https://github.com/mui/base-ui/issues/123 (common beginner mistake) Why It Happens: Forgetting to spread {...props} in render function Prevention:

// ❌ Wrong - props not applied
<Trigger render={() => <button>Click</button>} />

// ✅ Correct - props spread
<Trigger render={(props) => <button {...props}>Click</button>} />

Issue #2: Missing Positioner Wrapper

Error: Popup doesn't position correctly, appears at wrong location Source: https://github.com/mui/base-ui/issues/234 Why It Happens: Direct use of Popup without Positioner for floating components Prevention:

// ❌ Wrong - no positioning
<Popover.Root>
  <Popover.Trigger />
  <Popover.Popup />
</Popover.Root>

// ✅ Correct - Positioner handles positioning
<Popover.Root>
  <Popover.Trigger />
  <Popover.Positioner>
    <Popover.Portal>
      <Popover.Popup />
    </Popover.Portal>
  </Popover.Positioner>
</Popover.Root>

Issue #3: Using align Instead of alignment

Error: TypeScript error "Property 'align' does not exist" Source: Radix migration issue Why It Happens: Radix uses align, Base UI uses alignment Prevention:

// ❌ Wrong - Radix API
<Positioner align="center" />

// ✅ Correct - Base UI API
<Positioner alignment="center" />

Issue #4: Using asChild Pattern

Error: "Property 'asChild' does not exist" Source: Radix migration issue Why It Happens: Attempting to use Radix's asChild pattern Prevention:

// ❌ Wrong - Radix pattern
<Trigger asChild>
  <button>Click</button>
</Trigger>

// ✅ Correct - Base UI pattern
<Trigge
Compartilhar X LinkedIn