npm package: @projectdiscoveryio/pd-design-system
Description: A modern design system built with React, TypeScript, Tailwind CSS, shadcn/ui, and Radix UI
Author: ProjectDiscovery
Latest version: 0.0.3

# PD Design System

A modern, production-ready design system built with **React**, **TypeScript**, **Tailwind CSS**, **shadcn/ui**, and **Radix UI primitives**.

## 🚀 Features

- ✅ **React 18 & 19** with TypeScript
- ✅ **Tailwind CSS** for styling
- ✅ **TypeScript-based Design Tokens** with auto-generated CSS
- ✅ **shadcn/ui** components (customizable)
- ✅ **Radix UI** primitives for accessibility
- ✅ **Storybook 8** for component documentation
- ✅ **Tree-shakeable** ESM/CJS builds
- ✅ **Type-safe** with full TypeScript support
- ✅ **Dark mode** support built-in
- ✅ **CVA** (Class Variance Authority) for component variants

## 📦 Installation

### From npm (Recommended)

```bash
npm install @projectdiscovery/pd-design-system
# or
yarn add @projectdiscovery/pd-design-system
# or
pnpm add @projectdiscovery/pd-design-system
```

### Local Development / Git

```bash
# From local directory
npm install file:../path/to/pd-design-system

# From GitHub
npm install git+https://github.com/projectdiscovery/pd-design-system.git
```

### Setup Tailwind CSS

Since this design system uses Tailwind CSS, you need to configure it in your consuming application:

**1. Install Tailwind CSS** (if not already installed):

```bash
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
```

**2. Update your `tailwind.config.js`**:

```js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,ts,jsx,tsx}",
    // 🔥 IMPORTANT: Include design system components
    "./node_modules/@projectdiscovery/pd-design-system/dist/**/*.{js,mjs}",
  ],
  darkMode: "class", // 🔥 REQUIRED for theme switching
  theme: {
    extend: {},
  },
  plugins: [],
};
```

**3. Import the design system styles** in your main CSS/entry file:

```css
/* app/globals.css or src/index.css */
@import "@projectdiscovery/pd-design-system/styles.css";
```

Or import in your main TypeScript/JavaScript file:

```typescript
// main.tsx or App.tsx
import "@projectdiscovery/pd-design-system/styles.css";
```

## 🎨 Usage

### Step 1: Wrap with ThemeProvider (REQUIRED)

```tsx
// app/layout.tsx or App.tsx
import { ThemeProvider } from "@projectdiscovery/pd-design-system";
import "@projectdiscovery/pd-design-system/styles.css";

export default function App() {
  return (
    <ThemeProvider>
      <YourApp />
    </ThemeProvider>
  );
}
```

### Step 2: Use Components with Type-Safe Colors

```tsx
import {
  Button,
  Card,
  CardHeader,
  CardTitle,
  CardContent,
  Input,
} from "@projectdiscovery/pd-design-system";

function MyComponent() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Welcome</CardTitle>
      </CardHeader>
      <CardContent>
        <Input placeholder="Enter your name" />

        {/* Use built-in variants */}
        <Button variant="default">Submit</Button>

        {/* Or use custom colors from theme (with autocomplete!) */}
        <Button bgColor="green">Success</Button>
        <Button bgColor="colors.blue.600">Custom Blue</Button>
      </CardContent>
    </Card>
  );
}
```

### Button Usage

```tsx
import { Button } from "@projectdiscovery/pd-design-system";

{/* Built-in variants */}
<Button variant="default">Default</Button>
<Button variant="destructive">Delete</Button>
<Button variant="success">Success</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>

{/* Custom colors from theme (TypeScript autocomplete!) */}
<Button bgColor="green">Green Button</Button>
<Button bgColor="red">Red Button</Button>
<Button bgColor="colors.blue.700">Deep Blue</Button>

{/* Sizes */}
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>

{/* ❌ className is NOT available (design system controls styling) */}
<Button className="custom">Won't work</Button>
```

### Card Component

```tsx
import {
  Card,
  CardHeader,
  CardTitle,
  CardDescription,
  CardContent,
  CardFooter,
  Button,
} from "@projectdiscovery/pd-design-system";

<Card>
  <CardHeader>
    <CardTitle>Card Title</CardTitle>
    <CardDescription>Card description goes here</CardDescription>
  </CardHeader>
  <CardContent>
    <p>Card content</p>
  </CardContent>
  <CardFooter>
    <Button>Action</Button>
  </CardFooter>
</Card>;
```

### Input Component

```tsx
import { Input } from "@projectdiscovery/pd-design-system";

<Input type="email" placeholder="Enter email" />
<Input type="password" placeholder="Password" disabled />
```

## 🎨 Design Tokens

This design system uses **TypeScript-based design tokens** with automatic CSS generation. All colors and semantic tokens are defined in TypeScript for type safety and maintainability.

### Working with Tokens

```bash
# Generate CSS from TypeScript tokens
npm run generate-tokens

# Tokens are auto-generated before build
npm run build
```

**Key files:**

- `src/lib/tokens/primitives.ts` - Color scales (100-950)
- `src/lib/tokens/semantic.ts` - Semantic tokens (border, content, background)
- `src/styles/globals.css` - Auto-generated CSS variables (don't edit directly!)

📖 **Documentation:**

- [THEME_USAGE.md](./THEME_USAGE.md) - 📖 **How to use theme object (START HERE!)**
- [TOKENS.md](./TOKENS.md) - Token usage guide
- [TOKEN_WORKFLOW.md](./TOKEN_WORKFLOW.md) - How to update tokens
- [src/lib/tokens/README.md](./src/lib/tokens/README.md) - Technical details

### Using Tokens

**With Theme Object** (Recommended for dynamic styling):

```tsx
import { theme } from "@projectdiscovery/pd-design-system";

// Full TypeScript autocomplete!
<div
  style={{
    backgroundColor: theme.background.primary,
    color: theme.content.primary,
    border: `1px solid ${theme.border.blue}`,
  }}
/>;

// Access any token with autocomplete
const brandColor = theme.colors.blue[600]; // "#004BFF"
```

**With Tailwind Classes** (Recommended for static styling):

```tsx
<div className="bg-background-primary text-content-primary border-border-blue" />
```

**Direct Token Access**:

```tsx
import { blue, borderTokens } from "@projectdiscovery/pd-design-system";

const color = blue[500]; // "#3772FF"
const borderColor = borderTokens.light.primary;
```

## 🛠️ Development

### Prerequisites

- Node.js 18+
- npm/yarn/pnpm

### Setup

```bash
# Install dependencies
npm install

# Generate CSS tokens from TypeScript
npm run generate-tokens

# Start Storybook (component development & documentation)
npm run storybook

# Build the library (auto-generates tokens first)
npm run build

# Type check
npm run type-check

# Lint
npm run lint
```

## 📚 Storybook

Run Storybook to see all components with interactive examples:

```bash
npm run storybook
```

This will start Storybook at `http://localhost:6006`

### 🎨 Custom Storybook Theme

Our Storybook is **styled with PD Design System**! The entire Storybook UI uses:

- Custom theme matching your design tokens
- Welcome page built with PD components
- Dark mode support
- Branded documentation

See [STORYBOOK.md](./STORYBOOK.md) for customization details.

## 🏗️ Project Structure

```
pd-ds/
├── src/
│   ├── components/
│   │   ├── Button/
│   │   │   ├── Button.tsx
│   │   │   ├── Button.stories.tsx
│   │   │   └── index.ts
│   │   ├── Card/
│   │   ├── Input/
│   │   └── ...
│   ├── lib/
│   │   ├── tokens/            # 🎨 TypeScript design tokens
│   │   │   ├── primitives.ts  # Color scales
│   │   │   ├── semantic.ts    # Semantic tokens
│   │   │   ├── generate-css.ts
│   │   │   ├── types.ts
│   │   │   └── index.ts
│   │   └── utils.ts           # Utility functions (cn, etc.)
│   ├── styles/
│   │   └── globals.css        # ⚠️ Auto-generated CSS variables
│   └── index.ts               # Main export file
├── scripts/
│   └── generate-css-tokens.ts # CSS generation script
├── .storybook/                # Storybook configuration
├── components.json            # shadcn/ui configuration
├── tailwind.config.js         # Tailwind configuration (uses TS tokens)
├── tsconfig.json              # TypeScript configuration
├── tsup.config.ts             # Build configuration
└── package.json
```

## 🎨 Adding shadcn/ui Components

To add more shadcn/ui components to this design system:

```bash
npx shadcn@latest add [component-name]
```

Example:

```bash
npx shadcn@latest add dialog
npx shadcn@latest add dropdown-menu
npx shadcn@latest add select
```

The components will be added to `src/components/` and you can customize them as needed.

## 🌗 Dark Mode

The design system has built-in dark mode support. To enable dark mode in your app:

```tsx
// Add the 'dark' class to your root element
<html className="dark">{/* Your app */}</html>
```

Or toggle it dynamically:

```tsx
function ThemeToggle() {
  const [isDark, setIsDark] = useState(false);

  useEffect(() => {
    if (isDark) {
      document.documentElement.classList.add("dark");
    } else {
      document.documentElement.classList.remove("dark");
    }
  }, [isDark]);

  return <button onClick={() => setIsDark(!isDark)}>Toggle Theme</button>;
}
```

## 📝 Customization

### Using the `cn` utility

All components use the `cn` utility for className merging:

```tsx
import { Button, cn } from "@projectdiscovery/pd-design-system";

<Button className={cn("my-custom-class", someCondition && "conditional-class")}>
  Click me
</Button>;
```

### Extending Components

You can extend components by wrapping them:

```tsx
import { Button, type ButtonProps } from "@projectdiscovery/pd-design-system";

interface MyButtonProps extends ButtonProps {
  isLoading?: boolean;
}

export function MyButton({ isLoading, children, ...props }: MyButtonProps) {
  return (
    <Button {...props} disabled={isLoading || props.disabled}>
      {isLoading ? "Loading..." : children}
    </Button>
  );
}
```

## 📦 Publishing

### To npm:

```bash
# 1. Build the library
npm run build

# 2. Update version
npm version patch|minor|major

# 3. Publish
npm publish
```

### To private registry:

Update `package.json`:

```json
{
  "publishConfig": {
    "registry": "https://your-private-registry.com"
  }
}
```

## 🤝 Contributing

1. Add new components to `src/components/[ComponentName]/`
2. Include TypeScript types
3. Write Storybook stories
4. Export from `src/index.ts`
5. Update this README

## 📄 License

MIT

## 🔗 Links

- [Storybook](http://localhost:6006)
- [shadcn/ui](https://ui.shadcn.com)
- [Radix UI](https://www.radix-ui.com)
- [Tailwind CSS](https://tailwindcss.com)

---

Built with ❤️ using React, TypeScript, and Tailwind CSS