# Components

UI component references. Import from `@tailor-platform/app-shell`.

## Routing Helpers

`Link`, `useNavigate`, `useParams`, `useSearchParams`, `useLocation` — all re-exported from `@tailor-platform/app-shell` (not `react-router` directly).

## Button / Link

> Full API reference: https://raw.githubusercontent.com/tailor-platform/app-shell/refs/heads/main/docs/components/button.md

Use the `render` prop for polymorphic rendering (not Radix `asChild`):

```tsx
import { Button, Link } from "@tailor-platform/app-shell";

<Button render={<Link to="create" />}>Create</Button>
```

Variants: `default` | `destructive` | `outline` | `secondary` | `ghost` | `link`. Sizes: `default` | `sm` | `lg` | `icon` | `xs`.

## Badge

> Full API reference: https://raw.githubusercontent.com/tailor-platform/app-shell/refs/heads/main/docs/components/badge.md

Status labels:

```tsx
import { Badge } from "@tailor-platform/app-shell";

<Badge variant="success">Active</Badge>
```

Variants: `default` | `success` | `warning` | `neutral` | `error` | `destructive`.

## Table

> Full API reference: https://raw.githubusercontent.com/tailor-platform/app-shell/refs/heads/main/docs/components/table.md

Semantic HTML table sub-components. `Table.Root` wraps `<table>` in a scrollable container.

```tsx
import { Table } from "@tailor-platform/app-shell";

<Table.Root>
  <Table.Header>
    <Table.Row>
      <Table.Head>Name</Table.Head>
      <Table.Head>Email</Table.Head>
      <Table.Head>Role</Table.Head>
    </Table.Row>
  </Table.Header>
  <Table.Body>
    {items.map((item) => (
      <Table.Row key={item.id}>
        <Table.Cell>{item.name}</Table.Cell>
        <Table.Cell>{item.email}</Table.Cell>
        <Table.Cell>{item.role}</Table.Cell>
      </Table.Row>
    ))}
  </Table.Body>
</Table.Root>
```

Sub-components: `Root`, `Header`, `Body`, `Footer`, `Row`, `Head`, `Cell`, `Caption`. All accept `className` and their standard HTML element props.

- **`Table.Root`** — `containerClassName` for the outer scrollable `<div>`, `className` for the inner `<table>`.
- **`Table.Footer`** — use for totals rows (`<Table.Cell colSpan={2}>Total</Table.Cell>`).
- **`Table.Caption`** — accessible table description.
- **Constrained scroll** — `containerClassName="astw:max-h-64 astw:overflow-y-auto"` for fixed-height tables.

## Tooltip

> Full API reference: https://raw.githubusercontent.com/tailor-platform/app-shell/refs/heads/main/docs/components/tooltip.md

```tsx
import { Tooltip, Button } from "@tailor-platform/app-shell";

<Tooltip.Root>
  <Tooltip.Trigger render={<Button variant="ghost" size="icon" />}>
    <InfoIcon />
  </Tooltip.Trigger>
  <Tooltip.Content>Helpful information</Tooltip.Content>
</Tooltip.Root>
```

## MetricCard

> Full API reference: https://raw.githubusercontent.com/tailor-platform/app-shell/refs/heads/main/docs/components/metric-card.md

KPI card for dashboards.

```tsx
import { MetricCard } from "@tailor-platform/app-shell";
import { DollarSign } from "lucide-react";

<MetricCard
  title="Net total payment"
  value="$1,500.00"
  trend={{ direction: "up", value: "+5%" }}
  description="vs last month"
  icon={<DollarSign />}
/>
```

## Card

> Full API reference: https://raw.githubusercontent.com/tailor-platform/app-shell/refs/heads/main/docs/components/card.md

General-purpose container. Compound API:

```tsx
import { Card, Button } from "@tailor-platform/app-shell";

<Card.Root>
  <Card.Header title="Recent Orders" description="Last 7 days">
    <Button size="sm" variant="outline">View all</Button>
  </Card.Header>
  <Card.Content>
    {/* any content */}
  </Card.Content>
</Card.Root>
```

## Dialog

> Full API reference: https://raw.githubusercontent.com/tailor-platform/app-shell/refs/heads/main/docs/components/dialog.md

Modal dialog with a compound component API. Use for confirmations, forms, or any blocking interaction.

### Basic Usage

```tsx
import { Dialog, Button } from "@tailor-platform/app-shell";

<Dialog.Root>
  <Dialog.Trigger render={<Button />}>Open</Dialog.Trigger>
  <Dialog.Content>
    <Dialog.Header>
      <Dialog.Title>Confirm Action</Dialog.Title>
      <Dialog.Description>Are you sure you want to proceed?</Dialog.Description>
    </Dialog.Header>
    <Dialog.Footer>
      <Dialog.Close render={<Button variant="outline" />}>Cancel</Dialog.Close>
      <Button>Confirm</Button>
    </Dialog.Footer>
  </Dialog.Content>
</Dialog.Root>
```

### Controlled Usage

```tsx
const [open, setOpen] = useState(false);

<Dialog.Root open={open} onOpenChange={setOpen}>
  <Dialog.Trigger render={<Button variant="outline" />}>Open Dialog</Dialog.Trigger>
  <Dialog.Content>
    <Dialog.Header>
      <Dialog.Title>Settings</Dialog.Title>
    </Dialog.Header>
    <Dialog.Footer>
      <Button onClick={() => setOpen(false)}>Done</Button>
    </Dialog.Footer>
  </Dialog.Content>
</Dialog.Root>;
```

### Delete Confirmation Example

A common pattern in detail pages — pair with `ActionPanel` items:

```tsx
function DeleteConfirmation({ onDelete }: { onDelete: () => void }) {
  return (
    <Dialog.Root>
      <Dialog.Trigger render={<Button variant="destructive" />}>Delete</Dialog.Trigger>
      <Dialog.Content>
        <Dialog.Header>
          <Dialog.Title>Delete Order</Dialog.Title>
          <Dialog.Description>
            This action cannot be undone. The order will be permanently deleted.
          </Dialog.Description>
        </Dialog.Header>
        <Dialog.Footer>
          <Dialog.Close render={<Button variant="outline" />}>Cancel</Dialog.Close>
          <Button variant="destructive" onClick={onDelete}>Delete</Button>
        </Dialog.Footer>
      </Dialog.Content>
    </Dialog.Root>
  );
}
```

## Menu

> Full API reference: https://raw.githubusercontent.com/tailor-platform/app-shell/refs/heads/main/docs/components/menu.md

Dropdown menu with a compound component API. Supports checkbox/radio items, groups, separators, and nested sub-menus.

### Basic Usage

```tsx
import { Menu } from "@tailor-platform/app-shell";

<Menu.Root>
  <Menu.Trigger>Open menu</Menu.Trigger>
  <Menu.Content>
    <Menu.Item>Edit</Menu.Item>
    <Menu.Item>Duplicate</Menu.Item>
    <Menu.Separator />
    <Menu.Item>Delete</Menu.Item>
  </Menu.Content>
</Menu.Root>
```

### Context Menu Example

Common pattern for row actions in tables or detail pages. Uses fragment collocation:

```tsx
import { Menu, Button, useNavigate } from "@tailor-platform/app-shell";
import { EllipsisVertical } from "lucide-react";
import { type FragmentOf, readFragment } from "@/graphql";

function OrderActions({ order }: { order: FragmentOf<typeof OrderActionsFragment> }) {
  const data = readFragment(OrderActionsFragment, order);
  const navigate = useNavigate();

  return (
    <Menu.Root>
      <Menu.Trigger>
        <Button variant="ghost" size="icon">
          <EllipsisVertical />
        </Button>
      </Menu.Trigger>
      <Menu.Content>
        <Menu.Item onSelect={() => navigate(`/orders/${data.id}`)}>View</Menu.Item>
        <Menu.Item onSelect={() => navigate(`/orders/${data.id}/edit`)}>Edit</Menu.Item>
        <Menu.Separator />
        <Menu.Item onSelect={() => handleDelete(data.id)}>Delete</Menu.Item>
      </Menu.Content>
    </Menu.Root>
  );
}
```

### Grouped Items

```tsx
<Menu.Root>
  <Menu.Trigger>Actions</Menu.Trigger>
  <Menu.Content>
    <Menu.Group>
      <Menu.GroupLabel>File</Menu.GroupLabel>
      <Menu.Item>New</Menu.Item>
      <Menu.Item>Open</Menu.Item>
    </Menu.Group>
    <Menu.Separator />
    <Menu.Group>
      <Menu.GroupLabel>Edit</Menu.GroupLabel>
      <Menu.Item>Cut</Menu.Item>
      <Menu.Item>Copy</Menu.Item>
    </Menu.Group>
  </Menu.Content>
</Menu.Root>
```

## Sheet

> Full API reference: https://raw.githubusercontent.com/tailor-platform/app-shell/refs/heads/main/docs/components/sheet.md

Slide-in panel from any edge of the screen. Backed by Base UI's Drawer primitive with native swipe-to-dismiss on touch devices. Use for filters, settings, or non-modal workflows where a full dialog is too heavy.

### Basic Usage

```tsx
import { Sheet, Button } from "@tailor-platform/app-shell";

<Sheet.Root side="right">
  <Sheet.Trigger render={<Button />}>Open Settings</Sheet.Trigger>
  <Sheet.Content>
    <Sheet.Header>
      <Sheet.Title>Settings</Sheet.Title>
      <Sheet.Description>Manage your preferences.</Sheet.Description>
    </Sheet.Header>
    {/* Sheet body content */}
    <Sheet.Footer>
      <Sheet.Close render={<Button variant="outline" />}>Close</Sheet.Close>
    </Sheet.Footer>
  </Sheet.Content>
</Sheet.Root>
```

### Filter Panel Example

```tsx
import { Sheet, Button, Input } from "@tailor-platform/app-shell";

function FilterPanel() {
  return (
    <Sheet.Root side="right">
      <Sheet.Trigger render={<Button variant="outline" />}>Filters</Sheet.Trigger>
      <Sheet.Content>
        <Sheet.Header>
          <Sheet.Title>Filter Orders</Sheet.Title>
          <Sheet.Description>Narrow down orders by criteria.</Sheet.Description>
        </Sheet.Header>
        <div className="astw:p-4 astw:flex astw:flex-col astw:gap-4">
          <Input placeholder="Customer name" />
          <Input placeholder="Order number" />
        </div>
        <Sheet.Footer>
          <Sheet.Close render={<Button variant="outline" />}>Clear</Sheet.Close>
          <Button>Apply Filters</Button>
        </Sheet.Footer>
      </Sheet.Content>
    </Sheet.Root>
  );
}
```

### Controlled Usage

```tsx
const [open, setOpen] = useState(false);

<Sheet.Root side="right" open={open} onOpenChange={setOpen}>
  <Sheet.Trigger render={<Button />}>Open</Sheet.Trigger>
  <Sheet.Content>
    <Sheet.Header>
      <Sheet.Title>Filters</Sheet.Title>
    </Sheet.Header>
    <Sheet.Footer>
      <Button onClick={() => setOpen(false)}>Apply</Button>
    </Sheet.Footer>
  </Sheet.Content>
</Sheet.Root>;
```
