---
name: skills/octopus-design-system
description: >
  Use when building or modifying UI components: adding components, composing forms, displaying
  data, showing feedback/messaging, or working with overlays. Triggers on imports from
  @octopusdeploy/design-system-components or @octopusdeploy/design-system-octopus-components,
  or whenever the user asks to build, fix, or style UI elements using the Octopus design system.

metadata:
  sources:
    - definition-of-ready.md
---

# Octopus Design System

## Overview

The Octopus Design System provides a constrained set of components for building UI in the Octopus
Deploy portal. It is an **internal** design system — not general-purpose — so components are
deliberately opinionated. The goal is consistency and accessibility, not flexibility.

Components come from two packages:
- `@octopusdeploy/design-system-components` — core components
- `@octopusdeploy/design-system-octopus-components` — Octopus-specific extensions (Avatar, Form
  field variants, Status, Tabs, FilterSearchBox) which is not published and only consumable from the Octopus monorepo.

## Setup requirements

**All design system components require three providers, in this order (outermost first):**
```tsx
import {
  Theme,
  PageTitleProvider,
  OctopusRoutingProvider,
} from "@octopusdeploy/design-system-components";

<Theme>
  <PageTitleProvider>
    <OctopusRoutingProvider>
      {/* app */}
    </OctopusRoutingProvider>
  </PageTitleProvider>
</Theme>
```
`Theme` must be the outermost. Without all three, components will fail silently or throw context errors.

**The design system package is client-only.** It accesses `document` at module evaluation time and will crash in SSR.
In Next.js, any file that imports from the design system must either declare `"use client"` at the top or be loaded
via `next/dynamic` with `ssr: false`.

**Portal-rendered components need tokens at `:root`.** `Theme` scopes its CSS variables to a wrapper `div`,
not `:root`. Components that render at `document.body` — `Drawer`, `Dialog`, `Popover` — are outside that
div and cannot resolve design system tokens unless those tokens are also injected at `:root`. Ensure your theme setup
covers this if you use any of those components.

**Consuming apps are not required to use Emotion.** Emotion is an internal implementation detail of the design system.
Consumers may use any styling mechanism: Tailwind, CSS modules, inline styles, Radix, shadcn, etc. Do not
add Emotion as a consumer dependency.

**If you need MUI directly, declare it as an explicit direct dependency.** Do not rely on it as a transitive
dep from the design system. It is not reachable under pnpm or strict bun, and it is an internal implementation
detail that may change.

## Core Principles

**Always prefer design system components over custom HTML/CSS.**
Never write custom styled `<div>`, `<button>`, `<input>`, or other HTML elements when a design
system component exists. Do not reach for Emotion, inline styles, Tailwind or any other styling mechanism 
to build something the design system already provides.

**Never pass `className` or `style` to components.**
Modern design system components do not accept `className` or `style` props. If you see them in a
component's API, that property is deprecated. There is no escape hatch for custom styling — find
the right component or variant instead. This is intentional.

**Never add external margin to components.**
Components do not own their surrounding space. Layout is the consumer's responsibility. Use layout
components or spacing utilities at the page/section level, not inside component props.

**Use the most constrained composition model available.**
In order of preference:
1. Use the component's defined props and variants
2. Typed slot objects — strongly typed interfaces that enforce exactly what props the slot accepts,
   giving the component full control over the underlying element (most constrained slot pattern)
3. `React.ReactElement<SpecificProps>` — provides some typing but is inherently flexible; use only
   when a typed slot object is not sufficient
4. Custom hooks — when shared logic is needed across a component boundary, expose it as a hook that
   consumers call and pass results in as props; prefer this over render props
5. `React.ReactNode` and render props are effectively equivalent in flexibility — both are
   last-resort escape hatches for migration scenarios only; avoid in new code as we would much prefer
   to capture the variants as opposed to opening the API and allowing everything.

The design system does not currently use compound components. When a slot pattern is needed,
prefer typed slot objects over any of the more open alternatives above.

**Check for deprecated components before using anything.**
See `rules/deprecated.md` for the full list. Never use a `Deprecated*` or `Legacy*` component
in new code. Always migrate to the replacement. 

**Ensure accessibility.**
Components that have no visible label require an `accessibleName` prop. This is enforced as a
required prop in those cases. See `rules/accessibility.md`.

## Component Selection Guide

| Use case | Component | Package |
|---|---|---|
| Primary / secondary / destructive action | `Button` | design-system-components |
| Icon-only action | `IconButton` | design-system-components |
| Copy text to clipboard | `CopyToClipboardButton` | design-system-components |
| Navigation link | `Link` | design-system-components |
| Boolean instant toggle | `Switch` | design-system-components |
| Text input | `TextField` | design-system-components |
| Number input | `NumberField` | design-system-components |
| Select / dropdown | `Select` | design-system-octopus-components |
| Multi-step form | `Stepper` + `StepCard` | design-system-components |
| Progress indication | `Progress` / `ProgressTracker` | design-system-components |
| Tabbed content | `Tab` + `Tabs` | design-system-components |
| Page layout | `Page` components | design-system-components |
| Data grid | `DataTable` | design-system-components |
| Sortable list | `SortableList` | design-system-components |
| User / space / project avatar | `Avatar` | design-system-octopus-components |
| Entity status | `Status` | design-system-octopus-components |
| Search with filter | `FilterSearchBox` | design-system-octopus-components |
| Informational message | `Callout` / `QuietCallout` / `InlineMessage` | design-system-components |
| Actionable message | `ActionableCallout` | design-system-components |
| Toast notification | `Notification` / `InlineSnackbar` | design-system-components |
| Modal/overlay | `Dialog` | design-system-components |
| Side panel | `Drawer` | design-system-components |
| Contextual popup | `Popover` | design-system-components |
| Dropdown menu | `Menu` / `MenuItems` | design-system-components |
| Label/tag | `Badge` / `Chip` / `Tag` | design-system-components |
| Tooltip | `Tooltip` | design-system-components |
| Collapsible content | `Collapse` | design-system-components |
| Breadcrumb trail | `Breadcrumbs` | design-system-components |
| Pagination | `Pagination` | design-system-components |
| Loading skeleton | `SkeletonHeaders` | design-system-components |
| Scrollable area | `ScrollArea` | design-system-components |

## Detailed Rules

- Deprecated components and their replacements → `rules/deprecated.md`
- Form components and patterns → `rules/forms.md`
- Feedback and messaging components → `rules/feedback.md`
- Overlays: Dialog, Drawer, Popover, Menu → `rules/overlays.md`
- Navigation and page layouts → `rules/navigation.md`
- Accessibility patterns → `rules/accessibility.md`

## Figma Code Connect

Apply these rules **only if an MCP tool named "figma" or "figma-mcp" is available** in the current session, otherwise skip.

- Always use Figma Code Connect mappings when available when implementing components.
- Remove any `CodeConnectSnippet` wrapper elements from generated code.
