npm package: @jaydixit/experimental-mode
Description: A memorialized implementation of the experimental mode pattern from If Then Canonical - complete solution for prototyping and comparing UI variants.
Author: Jay Dixit
Latest version: 1.0.6

# @jaydixit/experimental-mode

> A memorialized implementation of the experimental mode pattern from **If Then Canonical** - a complete solution for prototyping and comparing UI variants in production applications.

## Overview

This package provides everything needed to implement A/B variant testing UI in your applications. Born from the "perfect implementation" in If Then Canonical's identity timeline, it offers:

- **URL-flag detection** - `?experimental=true` enables experimental mode
- **Keyboard-driven cycling** - Option-X cycles through variants (customizable)
- **React hooks** - `useExperimentalMode` provides full state management
- **Styled components** - Beautiful navigation and instruction panels (styles injected automatically)
- **Variant metadata** - WHAT/WHY/TEST/ASK instructions for each variant

**⚠️ IMPORTANT:** This package handles keyboard shortcuts (Option-X) automatically. Do NOT add custom keyboard event listeners for variant cycling - duplicate handlers will cause conflicts.

## Installation

```bash
npm install @jaydixit/experimental-mode
```

## Quick Start

```tsx
import { useExperimentalMode } from '@jaydixit/experimental-mode/react'
import { VariantNavigation, InstructionsBox, parseInstructionString } from '@jaydixit/experimental-mode'

function App() {
  const experimentalMode = useExperimentalMode({
    variants: [
      {
        key: 'baseline',
        label: 'Baseline',
        description: 'WHAT: Original design with standard spacing | WHY: Proven layout users know | TO TEST: Navigate and verify all features work | ASK: Is this still the best default?',
      },
      {
        key: 'compact',
        label: 'Compact',
        description: 'WHAT: Tighter spacing and smaller typography | WHY: Fit more content on screen | TO TEST: Check readability and clickability | ASK: Does density help or hurt?',
      },
    ],
    defaultKey: 'baseline',
    experimentalDefaultKey: 'compact',
  })

  // Option-X automatically cycles variants - no manual keyboard handling needed!

  const activeVariant = experimentalMode.variants.find(v => v.key === experimentalMode.activeKey)
  const instructions = activeVariant?.description ? parseInstructionString(activeVariant.description) : null

  return (
    <div data-experimental-variant={experimentalMode.activeKey}>
      {experimentalMode.enabled && (
        <div className="variant-switcher">
          <VariantNavigation
            variants={experimentalMode.variants}
            activeKey={experimentalMode.activeKey}
            onSelect={experimentalMode.setActiveKey}
          />
          {instructions && <InstructionsBox instructions={instructions} />}
        </div>
      )}

      {/* Your app content */}
    </div>
  )
}
```

### Add variant-specific CSS:

```css
/* Default styles */
.content {
  padding: 24px;
  font-size: 16px;
}

/* Compact variant */
[data-experimental-variant="compact"] .content {
  padding: 12px;
  font-size: 14px;
}
```

## Core Concepts

### URL Flag

Visit `yourapp.com?experimental=true` to enable experimental mode. The active variant persists in the URL.

### Variant Metadata

Each variant should describe:
- **WHAT**: What changes in this variant
- **WHY**: The hypothesis or goal
- **TO TEST**: How to evaluate it
- **ASK**: Questions to answer

Format: `"WHAT: ... | WHY: ... | TO TEST: ... | ASK: ..."`

### Keyboard Control

- **Option-X** (Alt-X): Cycle forward through variants
- Handled automatically by the package
- Customizable via `cycleHotkey` option

## API Reference

### `useExperimentalMode(options)`

React hook that manages experimental mode state.

**Options:**
- `variants` - Array of variant objects with `key`, `label`, `description`
- `defaultKey` - Variant to use when experimental mode is OFF
- `experimentalDefaultKey` - Variant to use when experimental mode is ON
- `paramName` - URL param name (default: `"experimental"`)
- `paramValue` - URL param value to enable (default: `"true"`)
- `cycleHotkey` - Hotkey config (default: `{ code: 'KeyX', altKey: true }`)

**Returns:**
- `enabled` - Whether experimental mode is active
- `activeKey` - Current variant key
- `variants` - Array of variants
- `setActiveKey(key)` - Switch to a specific variant
- `cycleVariant()` - Cycle to next variant (rarely needed - keyboard does this)

### Components

#### `<VariantNavigation>`

Pill-style navigation for switching variants.

**Props:**
- `variants` - Array of variant objects
- `activeKey` - Currently active variant key
- `onSelect(key)` - Called when user clicks a variant
- `className` - Optional additional CSS class

#### `<InstructionsBox>`

Displays WHAT/WHY/TEST/ASK instructions in a formatted grid.

**Props:**
- `instructions` - Object with `what`, `why`, `toTest`, `ask` strings
- `className` - Optional additional CSS class

#### `parseInstructionString(description)`

Utility to parse pipe-delimited description into instruction object.

```ts
const instructions = parseInstructionString(
  "WHAT: New layout | WHY: Better UX | TO TEST: Click everything | ASK: Is it faster?"
)
// Returns: { what: "New layout", why: "Better UX", toTest: "Click everything", ask: "Is it faster?" }
```

## Styling

All component styles are automatically injected into the page. No CSS imports needed!

The package uses hardened styles with `!important` to prevent conflicts with your app's global CSS.

### Customizing Wrapper

You typically wrap the components in a sticky container:

```css
.variant-switcher {
  position: sticky;
  top: 80px; /* Below your header */
  z-index: 9999;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  margin: 24px auto;
  width: min(880px, 100%);
  padding: 0 24px;
}
```

## Advanced Usage

### Custom Hotkey

```tsx
const experimentalMode = useExperimentalMode({
  variants: [...],
  cycleHotkey: { code: 'KeyE', metaKey: true }, // Cmd-E instead
})
```

### Programmatic Control

```tsx
// Switch to specific variant
experimentalMode.setActiveKey('compact')

// Cycle to next variant (keyboard does this automatically)
experimentalMode.cycleVariant()
```

### Disable Hotkey

```tsx
const experimentalMode = useExperimentalMode({
  variants: [...],
  cycleHotkey: null, // No keyboard shortcut
})
```

## Example: Calendar App

See how this pattern was used in If Then Canonical:

```tsx
const experimentalMode = useExperimentalMode({
  variants: [
    { key: 'default', label: 'Default UI', description: '...' },
    { key: 'compact', label: 'Compact View', description: '...' },
    { key: 'modern', label: 'Modern UI', description: '...' },
    { key: 'minimal', label: 'Minimal UI', description: '...' },
  ],
  defaultKey: 'default',
  experimentalDefaultKey: 'modern',
})
```

Then in CSS:
```css
[data-experimental-variant="modern"] .day-cell {
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1));
  border-radius: 12px;
  backdrop-filter: blur(10px);
}
```

## Best Practices

1. **Keep variants focused** - Test one concept per variant
2. **Document thoroughly** - Write clear WHAT/WHY/TEST/ASK
3. **Use semantic keys** - `'compact'` not `'variant-2'`
4. **Style with data attributes** - `[data-experimental-variant="..."]` in CSS
5. **No custom keyboard handlers** - Let the package handle Option-X
6. **Sticky positioning** - Keep navigation visible while scrolling
7. **Test all variants** - Cycle through and verify each works

## Common Pitfalls

❌ **Don't** add your own keyboard event listener for cycling:
```tsx
// WRONG - Will conflict with package
window.addEventListener('keydown', (e) => {
  if (e.altKey && e.code === 'KeyX') {
    experimentalMode.cycleVariant()
  }
})
```

❌ **Don't** override button styles globally without excluding package buttons:
```css
/* WRONG - Will break navigation buttons */
button {
  background: blue;
}

/* RIGHT - Exclude package buttons */
button:not(.variant-nav__button) {
  background: blue;
}
```

✅ **Do** let the package handle keyboard shortcuts automatically

✅ **Do** use `data-experimental-variant` for styling variants

## How This Compares to Other Tools

Based on a search by Claude Sonnet 4.5, this package fills a unique niche in the ecosystem. However, there may be other tools that weren't discovered in that search:

### Feature Flag Libraries (LaunchDarkly, Unleash, Split.io, PostHog, Prefab)
- **What they do**: Boolean flags, percentage rollouts, user segmentation, analytics
- **Gap**: Focused on *measuring performance* with cohorts and analytics, not rapid visual comparison
- **This package**: Built for *designer/developer visual comparison* with keyboard shortcuts and zero analytics overhead

### A/B Testing Platforms (VWO, Optimizely, Google Optimize, Maze)
- **What they do**: Statistical A/B testing with user cohorts and metrics tracking
- **Gap**: Require analytics setup and are meant for measuring outcomes, not rapid iteration
- **This package**: Instant switching for design review without any analytics infrastructure

### React Feature Flag Libraries (react-feature-flags, feature-switch)
- **What they do**: Simple boolean feature flags in React
- **Gap**: No UI for switching, no variant metadata, no keyboard shortcuts, no styling support
- **This package**: Complete UI solution with navigation, instructions, and developer experience

### Design Tools (Figma, Storybook variants)
- **What they do**: Compare designs before implementation
- **Gap**: Not in the actual production app with real data and state
- **This package**: Works in the live app with real interactions and data

### What This Package Is For

✅ Showing stakeholders live variants side-by-side
✅ Rapid designer iteration with keyboard shortcuts
✅ Internal testing of UI approaches with real data
✅ Documenting design decisions (WHAT/WHY/TEST/ASK)

### What This Package Is NOT For

❌ Analytics-driven A/B testing (use LaunchDarkly)
❌ User cohort segmentation (use Optimizely)
❌ Design mockup comparison (use Figma)

**In short**: This package is purpose-built for rapid visual prototyping and comparison in production apps, without the overhead of analytics infrastructure.

## License

MIT © Jay Dixit

## Credits

Memorialized from the experimental mode implementation in **If Then Canonical**, which provided the perfect blueprint for this pattern.