---
name: 'working-with-pm-design-kit'
description: 'This skill provides guidance for using the Packmind UI component library (@packmind/ui). It should be used when building or modifying frontend UI with PM-prefixed components, working with Chakra UI in the Packmind codebase, or when questions arise about available components, theming, or layout patterns. Triggers on mentions of PM components, @packmind/ui, Chakra UI usage, design kit, or frontend component implementation.'
---

# Working With the PM Design Kit

## Overview

The Packmind design kit (`@packmind/ui`) is a component library built on top of Chakra UI v3. All components are prefixed with `PM` and provide a consistent, themed API across the application. The source lives in `packages/ui/`.

**Import pattern**: Always import from `@packmind/ui`, never from Chakra UI directly.

```tsx
import { PMButton, PMBox, PMHeading, PMText } from '@packmind/ui';
```

## Component Selection Guide

Before reaching for a raw `<div>` or Chakra primitive, check if a PM component exists. Consult `references/component-catalog.md` for the full inventory organized by category.

### Decision Flow

1. **Need a layout container?** Use `PMBox`, `PMVStack`, `PMHStack`, `PMFlex`, or `PMGrid`.
2. **Need text?** Use `PMHeading` (with `level` prop for semantic h1–h6) or `PMText` (with `variant` and `color`).
3. **Need a button?** Use `PMButton` with the appropriate `variant`: `primary` for main actions, `secondary`/`ghost` for secondary, `danger` for destructive.
4. **Need user input?** Use `PMInput`, `PMTextArea`, `PMSelect`, `PMCheckbox`, `PMSwitch`, or `PMRadioGroup`.
5. **Need feedback?** Use `pmToaster` for transient messages, `PMAlert` for inline messages, `PMConfirmationModal` for destructive confirmations.
6. **Need an overlay?** Use `PMDialog` for modals, `PMPopover` for contextual info, `PMDrawer` for side panels.
7. **Need to show nothing?** Use `PMEmptyState` with title, description, icon, and an action button.
8. **Need loading placeholders?** Use `PMSkeleton` for content areas, `PMSpinner` for inline indicators.
9. **Need a color indicator?** Use `PMColorSwatch` to display a color sample.
10. **No PM wrapper exists?** Check Chakra UI v3 docs, then ask the user before using a raw Chakra component.

## Compound Component Patterns

Several PM components use Chakra's compound pattern with dot notation. Always use the compound API — do not try to reconstruct these with standalone elements.

```tsx
// Dialog
<PMDialog.Root open={isOpen} onOpenChange={setIsOpen}>
  <PMDialog.Backdrop />
  <PMDialog.Positioner>
    <PMDialog.Content>
      <PMDialog.Header>
        <PMDialog.Title>Title</PMDialog.Title>
        <PMDialog.CloseTrigger />
      </PMDialog.Header>
      {/* body */}
    </PMDialog.Content>
  </PMDialog.Positioner>
</PMDialog.Root>

// Accordion
<PMAccordion.Root>
  <PMAccordion.Item value="section-1">
    <PMAccordion.ItemTrigger>Section 1</PMAccordion.ItemTrigger>
    <PMAccordion.ItemContent>Content here</PMAccordion.ItemContent>
  </PMAccordion.Item>
</PMAccordion.Root>

// Timeline
<PMTimeline.Root>
  <PMTimeline.Item>
    <PMTimeline.Separator>
      <PMTimeline.Indicator />
      <PMTimeline.Connector />
    </PMTimeline.Separator>
    <PMTimeline.Content>
      <PMTimeline.Title>Event</PMTimeline.Title>
      <PMTimeline.Description>Details</PMTimeline.Description>
    </PMTimeline.Content>
  </PMTimeline.Item>
</PMTimeline.Root>

// Tabs (compound pattern — preferred for flexible tab layouts)
<PMTabsCompound.Root defaultValue="tab1">
  <PMTabsCompound.List>
    <PMTabsCompound.Trigger value="tab1">First Tab</PMTabsCompound.Trigger>
    <PMTabsCompound.Trigger value="tab2">Second Tab</PMTabsCompound.Trigger>
  </PMTabsCompound.List>
  <PMTabsCompound.Content value="tab1">First content</PMTabsCompound.Content>
  <PMTabsCompound.Content value="tab2">Second content</PMTabsCompound.Content>
</PMTabsCompound.Root>
```

**Key compound components**: `PMDialog`, `PMAccordion`, `PMTimeline`, `PMCarousel`, `PMCopiable`, `PMSelect`, `PMMenu`, `PMTreeView`, `PMTabs`, `PMTabsCompound`.

Always wrap overlays (dialogs, popovers, drawers) inside `PMPortal` to escape stacking context issues.

## Layout Patterns

### Spacing

Use `gap` on stacks/grids for consistent spacing between children — never use margin on individual children to create gaps.

```tsx
<PMVStack gap="4">
  <PMHeading level="h2">Title</PMHeading>
  <PMText>Description</PMText>
</PMVStack>
```

### Full-Height Layouts

For layouts that fill the viewport, use `height="100vh"` on the root, `flex="1"` on the expanding section, and `minHeight={0}` on flex children that need to scroll.

### Grid Layouts

Use `PMGrid` with `gridTemplateColumns` for multi-panel layouts:

```tsx
<PMGrid gridTemplateColumns="minmax(240px, 270px) 1fr minmax(280px, 320px)">
  <PMBox>Sidebar</PMBox>
  <PMBox>Main</PMBox>
  <PMBox>Detail</PMBox>
</PMGrid>
```

### Page Structure

Use `PMPage` for full-page layouts with title, breadcrumbs, actions, and optional sidebar. Use `PMPageSection` for collapsible content sections within a page.

## Typography

### Headings

Use `PMHeading` with the `level` prop for semantic HTML (h1–h6) and `color` for emphasis:

```tsx
<PMHeading level="h1" color="primary">Page Title</PMHeading>
<PMHeading level="h3" color="secondary">Section Title</PMHeading>
```

Available colors: `primary`, `secondary`, `tertiary`, `faded`, `primaryLight`, `secondaryLight`, `tertiaryLight`.

### Body Text

Use `PMText` with `variant` for size and `color` for emphasis:

```tsx
<PMText variant="body" color="primary">Main content</PMText>
<PMText variant="small" color="secondary">Supporting text</PMText>
```

Variants: `body`, `body-important`, `small`, `small-important`.
Colors: `primary`, `secondary`, `tertiary`, `error`, `faded`, `warning`, `success`, `primaryLight`, `secondaryLight`, `tertiaryLight`.

## Theming

Use semantic tokens — never hardcode hex colors or raw Chakra palette values.

### Semantic Token Categories

| Category | Tokens | Usage |
|----------|--------|-------|
| Background | `background.primary`, `.secondary`, `.tertiary`, `.faded` | Surface colors (dark to light) |
| Text | `text.primary`, `.secondary`, `.tertiary`, `.faded`, `.error`, `.warning`, `.success` | Text contrast levels |
| Border | `border.primary`, `.secondary`, `.tertiary` | Border contrast levels |

### Status Colors

Use the semantic color names for status indicators:
- **Success**: `green` palette or `text.success`
- **Error/Danger**: `red` palette or `text.error`
- **Warning**: `orange` palette or `text.warning`
- **Info/Primary**: `blue` palette

```tsx
<PMButton variant="danger">Delete</PMButton>
<PMText color="error">Validation failed</PMText>
<PMBadge colorPalette="green">Active</PMBadge>
```

## Form Patterns

### Input Fields

`PMInput` provides label, error state, and helper text out of the box:

```tsx
<PMInput
  label="Project name"
  value={name}
  onChange={(e) => setName(e.target.value)}
  error={errors.name}
  helperText="Must be unique within the organization"
  maxLength={255}
/>
```

### Form Layout

Group related fields with `PMFormContainer`:

```tsx
<PMFormContainer maxWidth="400px" centered>
  <PMInput label="Name" />
  <PMInput label="Email" />
  <PMButton variant="primary" type="submit">Save</PMButton>
</PMFormContainer>
```

### Validation

Show errors directly on inputs via the `error` prop — this adds a red border and displays the message below the field. Disable submit buttons during async operations with `isLoading`.

## Feedback Patterns

### Toasts (Transient Notifications)

```tsx
import { pmToaster } from '@packmind/ui';

pmToaster.create({
  type: 'success',        // 'success' | 'error' | 'warning' | 'info' | 'loading'
  title: 'Saved',
  description: 'Your changes have been saved.',
  closable: true,
  action: { label: 'Undo', onClick: handleUndo },  // optional
});
```

### Confirmation Modals (Destructive Actions)

```tsx
<PMConfirmationModal
  trigger={<PMButton variant="danger">Delete</PMButton>}
  title="Delete project?"
  message="This action cannot be undone."
  confirmText="Delete"
  confirmColorScheme="red"
  onConfirm={handleDelete}
  isLoading={isDeleting}
/>
```

### Inline Alerts

```tsx
<PMAlert.Root status="warning">
  <PMAlert.Indicator />
  <PMAlert.Title>Attention</PMAlert.Title>
  <PMAlert.Description>This feature is in beta.</PMAlert.Description>
</PMAlert.Root>
```

### Empty States

```tsx
<PMEmptyState
  title="No standards yet"
  description="Create your first coding standard to get started."
  icon={<LuInbox />}
>
  <PMButton variant="primary">Create Standard</PMButton>
</PMEmptyState>
```

## Icons

Icons come from `react-icons/lu` (Lucide icon set). Import with the `Lu` prefix:

```tsx
import { LuTrash2, LuPlus, LuChevronDown } from 'react-icons/lu';

<PMButton><LuPlus /> Add Item</PMButton>
<PMIconButton variant="ghost"><LuTrash2 /></PMIconButton>
```

Control size via `fontSize` or `size` props on the icon element.

## Responsive Design

Use Chakra's responsive object syntax with breakpoints `base`, `sm`, `md`, `lg`, `xl`:

```tsx
<PMBox
  display={{ base: 'none', md: 'flex' }}
  width={{ base: '100%', lg: '60%' }}
  padding={{ base: '4', md: '6' }}
/>
```

Mobile-first approach: `base` styles apply to all sizes, then override at larger breakpoints.

## Button Variant Guide

| Variant | Usage |
|---------|-------|
| `primary` | Main action on the page (one per view) |
| `secondary` | Important but not primary actions |
| `tertiary` | Low-emphasis actions |
| `outline` | Alternative to secondary with border emphasis |
| `ghost` | Minimal actions (toolbar buttons, inline actions) |
| `success` | Positive confirmations |
| `warning` | Caution-required actions |
| `danger` | Destructive actions (delete, remove) |

## Hooks

`@packmind/ui` exports several hooks for common UI patterns:

### useTableSort

Manages sorting state for `PMTable`. Returns `sortKey`, `sortDirection`, `handleSort`, and `getSortDirection`:

```tsx
import { useTableSort } from '@packmind/ui';

const { sortKey, sortDirection, handleSort, getSortDirection } = useTableSort({
  defaultSortKey: 'name',
  defaultSortDirection: 'asc',
});

<PMTable columns={columns} data={data} onSort={handleSort} />
```

### Chakra Re-exports

- **pmUseFilter** — Chakra's `useFilter` for filtering collections
- **pmUseListCollection** — Chakra's `useListCollection` for managing list data (useful with `PMSelect`, `PMCombobox`)
- **pmUseToken** — Chakra's `useToken` for accessing design tokens programmatically

```tsx
import { pmUseToken, pmUseListCollection } from '@packmind/ui';
```

## Anti-Patterns

- **Do not** import from `@chakra-ui/react` directly — always use `@packmind/ui` wrappers.
- **Do not** use inline styles or hardcoded colors — use semantic tokens and component props.
- **Do not** create custom modal/overlay implementations — use `PMDialog`, `PMDrawer`, or `PMPopover` with `PMPortal`.
- **Do not** build custom loading indicators — use `PMSkeleton` or `PMSpinner`.
- **Do not** use `as="h1"` on headings — use the `level` prop on `PMHeading` for semantic HTML.

## Resources

### references/

- `component-catalog.md` — Full inventory of all PM components and hooks with props, organized by category.