# Quick start

Install the package, render a primitive and style it with its data attributes.

## Install

Install the package. React 19 is a peer dependency.

```bash
pnpm add @logic-ui/react@latest
npm install @logic-ui/react@latest
yarn add @logic-ui/react@latest
bun add @logic-ui/react@latest
```

## Set up the portal root

Popups (dialogs, menus, the lightbox) are portaled to the end of `<body>`.
Give your app's root its own stacking context, so they always show on top of it:

```tsx title="app/layout.tsx"
<body>
  <div className="isolate">{children}</div>
</body>
```

## Render a primitive

Import each component from its own path and put its parts together:

```tsx title="hero.tsx"
"use client";
import * as React from "react";
import { Clipboard } from "@logic-ui/react/clipboard";

export default function ExampleClipboard() {
  return (
    <Clipboard.Root
      value="pnpm add @logic-ui/react"
      className="flex items-center gap-2 rounded-md border border-neutral-200 bg-white py-1 pr-1 pl-3 text-neutral-950 data-copied:border-green-600 dark:border-neutral-800 dark:bg-neutral-950 dark:text-white"
    >
      <code className="font-mono text-sm">pnpm add @logic-ui/react</code>
      <Clipboard.Trigger
        aria-label="Copy the install command"
        className="group relative flex size-8 cursor-pointer items-center justify-center rounded border-none bg-transparent p-0 text-inherit hover:bg-neutral-100 focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:hover:bg-neutral-800 dark:focus-visible:outline-white"
      >
        {/* The copy icon gives way to the check while copied. */}
        <CopyIcon className="group-data-copied:invisible" />
        <Clipboard.Indicator className="absolute inset-0 flex items-center justify-center text-green-600">
          <CheckIcon />
        </Clipboard.Indicator>
      </Clipboard.Trigger>
    </Clipboard.Root>
  );
}

function CopyIcon(props: React.ComponentProps<"svg">) {
  return (
    <svg
      width="16"
      height="16"
      viewBox="0 0 16 16"
      fill="none"
      aria-hidden
      {...props}
    >
      <rect
        x="5"
        y="5"
        width="8.5"
        height="8.5"
        rx="1.5"
        stroke="currentColor"
      />
      <path
        d="M3 10.5V3.5A1 1 0 0 1 4 2.5h6.5"
        stroke="currentColor"
        strokeLinecap="round"
      />
    </svg>
  );
}

function CheckIcon(props: React.ComponentProps<"svg">) {
  return (
    <svg
      width="16"
      height="16"
      viewBox="0 0 16 16"
      fill="none"
      aria-hidden
      {...props}
    >
      <path
        d="M3.5 8.5 6.5 11.5 12.5 4.5"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </svg>
  );
}
```

## Style it

Parts render no styles of their own. Each one takes `className` and `style`, and exposes its
state as `data-*` attributes to style it with:

```tsx title="Style the copied state"
<Clipboard.Trigger className="text-neutral-500 data-copied:text-green-600">
  Copy
</Clipboard.Trigger>
```

Every page lists the data attributes and CSS variables of each part in its API reference.

## Change the element

The `render` prop replaces the element a part renders, or composes it with one of your
components. The part's props and behaviour are merged into it:

```tsx title="Compose your own button"
<Clipboard.Trigger render={<MyButton variant="ghost" />}>
  Copy
</Clipboard.Trigger>
```

## Import other components

Every component has its own path in the same package:

```tsx title="Import from one package"
import { Dialog } from "@logic-ui/react/dialog";
import { Menu } from "@logic-ui/react/menu";
import { useRender } from "@logic-ui/react/use-render";
```

## Migrate from Base UI

Logic UI re-exports every public Base UI entry point under the same path, so it can replace
`@base-ui/react` in an existing app. There are two ways to do it.

### Keep your imports

Alias `@base-ui/react` to Logic UI in `package.json`, then reinstall. Every
`import … from "@base-ui/react/…"` keeps working and now resolves to Logic UI, and so do the
libraries in your app that depend on Base UI:

```json title="package.json"
{
  "dependencies": {
    "@base-ui/react": "npm:@logic-ui/react@0.4.0"
  }
}
```

Logic UI's own components are then imported through the same alias:

```tsx title="Import a Logic UI component"
import { Clipboard } from "@base-ui/react/clipboard";
```

### Switch your imports

Or remove `@base-ui/react`, install `@logic-ui/react`, and replace the package name in your
imports:

```bash
pnpm remove @base-ui/react
pnpm add @logic-ui/react
```

```tsx title="Change the imports"
// Before
import { Dialog } from "@base-ui/react/dialog";
// After
import { Dialog } from "@logic-ui/react/dialog";
```

Either way, check which Base UI version your Logic UI release is built on in the
[changelog](/docs/changelog). `@base-ui/react/internals/*` is private API and is not
re-exported.
