Introduction
An enterprise-grade primitive library built on composability principles and Figma variables, delivering an opinionated yet flexible design system for PMI.
Welcome to Catalyst 2.0
Catalyst 2.0 is a comprehensive library of reusable, production-ready primitives designed to establish clear standards and accelerate development across PMI's digital ecosystem. Built with composability at its core and synchronized with Figma variables, our design system provides an opinionated foundation while maintaining the flexibility required for diverse product needs.
Powered by TailwindCSS and architected on Radix UI primitives, Catalyst delivers accessibility, consistency, and performance by default.
Objectives
Catalyst 2.0 is designed to streamline the design and development process, ensuring visual and functional consistency across projects while accelerating time-to-market for new features and products. By leveraging this design system, teams can focus on solving complex user problems rather than reinventing foundational interface patterns.
As a single source of truth for designers and developers, Catalyst establishes a unified language and shared vocabulary that enables seamless cross-functional collaboration. The system is architected to reduce cognitive load, enhance accessibility standards, and deliver superior user experiences across all PMI digital properties.
Design Philosophy
Our approach aligns with Radix UI's core vision, which serves as the architectural foundation of our primitive system. We prioritize the use of proven, accessible primitives as building blocks, effectively combining the robustness and accessibility guarantees of Radix with the rapid styling capabilities of TailwindCSS.
Catalyst 2.0 primitives are thoughtfully enhanced Radix primitives, enriched with PMI-specific design tokens and styling conventions. They inherit the comprehensive accessibility features, keyboard navigation support, and ARIA compliance of Radix, while maintaining full extensibility through standard className overrides. This architectural approach ensures the design system remains adaptable and scalable, capable of meeting evolving project requirements without compromising on quality or consistency.
System Words Glossary
A reference for key terms used consistently across Catalyst documentation:
| Term | Definition |
|---|---|
| Primitive | A headless, unstyled Radix UI primitive that provides accessibility and behavior without visual opinions. |
| Catalyst primitive | A styled, CVA-powered wrapper around a Radix primitive. Adds design tokens, variants, and Tailwind classes. |
| CVA | class-variance-authority — the library used to define primitive variants (size, color, variant) as composable class sets. |
| Variant | A named CVA dimension (e.g. variant, size, color) that maps prop values to Tailwind class strings. |
asChild | A Radix UI Slot pattern. When true, the primitive merges its props onto its child element instead of rendering its own DOM node. |
| Slot | The Radix UI primitive (@radix-ui/react-slot) used internally to implement asChild behaviour. |
| Design Token | A named value from the Tailwind theme (e.g. text-off-black, bg-accent) that maps to a brand-approved colour, size, or spacing value. |
| Data Attribute | A data-* HTML attribute used for styling states (e.g. data-disabled, data-orientation) without JavaScript class toggling. |
| Compound primitive | A set of related sub-primitives exported together (e.g. CarouselRoot, CarouselContent, CarouselItem) that share context and compose into a single UI pattern. |
cn() | A utility that merges Tailwind class strings, resolving conflicts via tailwind-merge. Used in every Catalyst primitive. |
| Marketing Variant | A primitive implementation optimised for public-facing, brand-led pages. Lives in primitive/marketing/. |
| Product Variant | A primitive implementation optimised for dense, functional UI (dashboards, forms). Lives in primitive/product/. |
Primitive Hierarchy
The diagram below shows how Catalyst layers on top of browser primitives and external libraries:
Browser / HTML
└── Radix UI Primitives ← Headless accessibility & behaviour (focus, ARIA, keyboard)
└── Catalyst Primitives ← CVA variants, design tokens, Tailwind classes
└── Catalyst Patterns ← Pre-composed combinations (e.g. ProductCardCarousel)
└── Consumer App ← Your product or marketing pageWhat each layer owns
| Layer | Owns |
|---|---|
| Browser / HTML | DOM, native events, baseline accessibility |
| Radix UI | ARIA roles, keyboard navigation, focus management, asChild / Slot |
| Catalyst primitives | Visual variants, design tokens, responsive behaviour, data attributes |
| Catalyst Patterns | Opinionated compositions of multiple primitives for common use cases |
| Consumer App | Content, layout, business logic |
"Last Resort" Philosophy
Catalyst is intentionally composable but opinionated. Before reaching for lower-level escape hatches, work through this decision hierarchy:
1. Use the Catalyst primitive as-is (Preferred)
Catalyst primitives cover the vast majority of design system use cases. Start here.
<Badge variant="soft" color="success" size="md">New</Badge>2. Use CVA variant props
If the default appearance isn't right, check the variant table first. Most visual differences are already modelled as props.
<Button variant="outline" size="lg">Learn more</Button>3. Use className for one-off overrides
For minor layout or spacing adjustments not worth adding as a variant, pass className. Tailwind Merge will resolve conflicts.
<Badge className="mt-2">Custom spacing</Badge>4. Use asChild to change the rendered element
When you need a different HTML element or want to compose with a router <Link>, use asChild to delegate rendering.
<Button asChild>
<a href="/docs">Read the docs</a>
</Button>5. Access the underlying Radix primitive directly.
If Catalyst's abstraction is genuinely insufficient, you can import the Radix primitive directly and style it yourself. Take ownership of accessibility, keyboard navigation, and design token alignment when you do this.
import * as RadixDialog from '@radix-ui/react-dialog';
// You are now responsible for ARIA, focus trapping, tokens, and variants.Last resort warning: Bypassing Catalyst primitives means opting out of design system guarantees — visual consistency, accessibility compliance, and future upgrade compatibility. Prefer composing with provided primitives wherever possible. If you find yourself repeatedly needing an escape hatch, consider raising a PBI to extend the primitive.