TourKit
@tour-kit/adoption

TypeScript Types

TypeScript types for FeatureConfig, AdoptionState, NudgeRule, UsageThreshold, and the @tour-kit/adoption API surface

Core Types

Feature

interface Feature {
  id: string
  name: string
  trigger: FeatureTrigger
  adoptionCriteria?: AdoptionCriteria
  resources?: FeatureResources
  priority?: number
  category?: string
  description?: string
  premium?: boolean
}

Prop

Type

FeatureTrigger

type FeatureTrigger =
  | string // CSS selector
  | { event: string } // Custom event
  | { callback: () => boolean } // Programmatic check

Examples:

// CSS selector (click tracking)
trigger: '#dark-mode-toggle'
trigger: '[data-feature="export"]'

// Custom event
trigger: { event: 'export:complete' }
trigger: { event: 'ai:generated' }

// Callback (polled every 1s)
trigger: { callback: () => document.fullscreenElement !== null }

AdoptionCriteria

interface AdoptionCriteria {
  minUses?: number // default: 3
  recencyDays?: number // default: 30
  custom?: (usage: FeatureUsage) => boolean
}

Prop

Type

FeatureResources

interface FeatureResources {
  tourId?: string
  hintIds?: string[]
}

Prop

Type

FeatureUsage

interface FeatureUsage {
  featureId: string
  firstUsed: string | null // ISO date string
  lastUsed: string | null // ISO date string
  useCount: number
  status: AdoptionStatus
}

Prop

Type

AdoptionStatus

type AdoptionStatus = 'not_started' | 'exploring' | 'adopted' | 'churned'
  • not_started: Never used
  • exploring: Used, but below minUses
  • adopted: Meets adoption criteria
  • churned: Was adopted, now inactive (exceeds recencyDays)

FeatureWithUsage

interface FeatureWithUsage extends Feature {
  usage: FeatureUsage
}

Combines feature definition with current usage state.

Provider Types

AdoptionProviderProps

interface AdoptionProviderProps {
  children: React.ReactNode
  features: Feature[]
  storage?: StorageConfig
  nudge?: NudgeConfig
  userId?: string
  onAdoption?: (feature: Feature) => void
  onChurn?: (feature: Feature) => void
  onNudge?: (feature: Feature, action: 'shown' | 'clicked' | 'dismissed') => void
}

StorageConfig

type StorageConfig =
  | { type: 'localStorage'; key?: string }
  | { type: 'memory' }
  | { type: 'custom'; adapter: StorageAdapter }

StorageAdapter

interface StorageAdapter {
  getItem(key: string): Promise<string | null> | string | null
  setItem(key: string, value: string): Promise<void> | void
  removeItem(key: string): Promise<void> | void
}

NudgeConfig

interface NudgeConfig {
  enabled?: boolean // default: true
  initialDelay?: number // default: 5000
  cooldown?: number // default: 86400000 (24h)
  maxPerSession?: number // default: 3
  maxFeatures?: number // default: 1
}

Hook Return Types

UseFeatureReturn

interface UseFeatureReturn {
  feature: Feature | null
  usage: FeatureUsage
  isAdopted: boolean
  status: AdoptionStatus
  useCount: number
  trackUsage: () => void
}

AdoptionStats

interface AdoptionStats {
  features: FeatureWithUsage[]
  adoptionRate: number
  adoptedCount: number
  totalCount: number
  byStatus: Record<AdoptionStatus, FeatureWithUsage[]>
  byCategory: Record<string, { adopted: number; total: number; rate: number }>
}

UseNudgeReturn

interface UseNudgeReturn {
  pendingNudges: Feature[]
  hasNudges: boolean
  showNudge: (featureId: string) => void
  dismissNudge: (featureId: string) => void
  snoozeNudge: (featureId: string, durationMs: number) => void
  handleNudgeClick: (featureId: string) => void
}

Component Prop Types

AdoptionNudgeProps

interface AdoptionNudgeProps extends React.ComponentPropsWithoutRef<'div'> {
  render?: (props: NudgeRenderProps) => React.ReactNode
  delay?: number
  position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
  size?: 'sm' | 'md' | 'lg'
  asChild?: boolean
}

NudgeRenderProps

interface NudgeRenderProps {
  feature: Feature
  onDismiss: () => void
  onSnooze: (durationMs: number) => void
  onClick: () => void
}

FeatureButtonProps

interface FeatureButtonProps extends React.ComponentPropsWithoutRef<'button'> {
  featureId: string
  showNewIndicator?: boolean
  variant?: 'default' | 'secondary' | 'outline' | 'ghost' | 'destructive'
  size?: 'sm' | 'md' | 'lg'
  asChild?: boolean
}

NewFeatureBadgeProps

interface NewFeatureBadgeProps extends React.ComponentPropsWithoutRef<'span'> {
  featureId: string
  text?: string
  variant?: 'default' | 'secondary' | 'outline' | 'destructive'
  size?: 'sm' | 'md' | 'lg'
}

Dashboard Component Types

AdoptionDashboardProps

interface AdoptionDashboardProps {
  showFilters?: boolean
  showStats?: boolean
  showChart?: boolean
  showTable?: boolean
  className?: string
}

AdoptionStatCardProps

interface AdoptionStatCardProps {
  title: string
  value: string | number
  description?: string
  trend?: number
  trendLabel?: string
  icon?: React.ReactNode
  variant?: 'default' | 'success' | 'warning' | 'danger'
  size?: 'sm' | 'md' | 'lg'
}

AdoptionTableProps

interface AdoptionTableProps {
  sortBy?: 'name' | 'status' | 'useCount' | 'lastUsed' | 'category'
  sortOrder?: 'asc' | 'desc'
  showCategory?: boolean
  showPriority?: boolean
  features?: FeatureWithUsage[]
  onRowClick?: (feature: FeatureWithUsage) => void
  className?: string
}

AdoptionCategoryChartProps

interface AdoptionCategoryChartProps {
  showPercentages?: boolean
  highlightCategory?: string
  orientation?: 'horizontal' | 'vertical'
  className?: string
}

AdoptionStatusBadgeProps

interface AdoptionStatusBadgeProps {
  status: AdoptionStatus
  size?: 'sm' | 'md' | 'lg'
  showIcon?: boolean
  className?: string
}

AdoptionFiltersProps

interface AdoptionFiltersProps {
  filters: AdoptionFiltersState
  onChange: (filters: AdoptionFiltersState) => void
  categories?: string[]
  className?: string
}

AdoptionFiltersState

interface AdoptionFiltersState {
  status: AdoptionStatus | 'all'
  category: string | 'all'
  search: string
}

Usage Examples

Typed Feature Array

import type { Feature } from '@tour-kit/adoption'

const features: Feature[] = [
  {
    id: 'dark-mode',
    name: 'Dark Mode',
    trigger: '#dark-mode-toggle',
    category: 'customization',
    adoptionCriteria: {
      minUses: 3,
      recencyDays: 30,
    },
  },
]

Typed Hook Usage

import { useFeature, type UseFeatureReturn } from '@tour-kit/adoption'

function Component() {
  const feature: UseFeatureReturn = useFeature('my-feature')

  feature.trackUsage() // ✓ Type-safe
  feature.isAdopted // ✓ Type-safe
}

Typed Component Props

import type { FeatureButtonProps } from '@tour-kit/adoption'

const buttonProps: FeatureButtonProps = {
  featureId: 'export',
  variant: 'default',
  onClick: () => console.log('clicked'),
}

Next Steps

On this page