TourKit
@tour-kit/adoptionComponents

FeatureButton

FeatureButton component: button wrapper that automatically records usage events for the tracked feature on each click

Overview

FeatureButton is a button wrapper that automatically tracks feature usage when clicked. It optionally shows a "new" indicator for unadopted features.

Basic Usage

import { FeatureButton } from '@tour-kit/adoption'

function Toolbar() {
  return (
    <FeatureButton featureId="export" onClick={() => exportData()}>
      Export
    </FeatureButton>
  )
}

Every click automatically tracks usage - no manual trackUsage() calls needed.

Props

Prop

Type

Extends all standard <button> props.

Examples

Basic Button

<FeatureButton featureId="search" onClick={handleSearch}>
  Search
</FeatureButton>

Without New Indicator

<FeatureButton
  featureId="save"
  showNewIndicator={false}
  onClick={handleSave}
>
  Save
</FeatureButton>

Different Variants

<FeatureButton featureId="delete" variant="destructive">
  Delete
</FeatureButton>

<FeatureButton featureId="settings" variant="outline">
  Settings
</FeatureButton>

<FeatureButton featureId="help" variant="ghost" size="sm">
  Help
</FeatureButton>

With Custom Element (asChild)

import { Button } from '@/components/ui/button'

<FeatureButton featureId="export" asChild>
  <Button className="custom-class">
    Export Data
  </Button>
</FeatureButton>

Icon Button

import { Download } from 'lucide-react'

<FeatureButton featureId="download" size="sm" variant="ghost">
  <Download className="h-4 w-4" />
</FeatureButton>

Loading State

function ExportButton() {
  const [loading, setLoading] = useState(false)

  const handleExport = async () => {
    setLoading(true)
    try {
      await exportData()
    } finally {
      setLoading(false)
    }
  }

  return (
    <FeatureButton
      featureId="export"
      onClick={handleExport}
      disabled={loading}
    >
      {loading ? 'Exporting...' : 'Export'}
    </FeatureButton>
  )
}

With Tooltip

import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'

<Tooltip>
  <TooltipTrigger asChild>
    <FeatureButton featureId="shortcuts" variant="ghost" size="sm">
      Ctrl+K
    </FeatureButton>
  </TooltipTrigger>
  <TooltipContent>Keyboard Shortcuts</TooltipContent>
</Tooltip>

New Indicator

The indicator appears as a small red dot when the feature is not adopted:

// Shows red dot if not adopted
<FeatureButton featureId="new-feature">
  Try New Feature
</FeatureButton>

// Hide indicator
<FeatureButton featureId="new-feature" showNewIndicator={false}>
  Try New Feature
</FeatureButton>

The indicator automatically disappears once the feature is adopted.

Click Handling

The button tracks usage before calling your onClick:

<FeatureButton
  featureId="analytics"
  onClick={(e) => {
    // Usage already tracked at this point
    console.log('Button clicked')
  }}
>
  View Analytics
</FeatureButton>

Tracking happens even if onClick is not provided:

<FeatureButton featureId="feature" type="submit">
  Submit Form
</FeatureButton>

Accessibility

The component:

  • Renders a semantic <button> by default
  • Includes aria-label on the new indicator: "New feature"
  • Supports all standard button ARIA attributes
  • Works with keyboard navigation
<FeatureButton
  featureId="feature"
  aria-label="Export data to CSV"
  aria-describedby="export-help"
>
  Export
</FeatureButton>

TypeScript

Fully typed with standard button props:

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

const props: FeatureButtonProps = {
  featureId: 'my-feature',
  onClick: (e: React.MouseEvent<HTMLButtonElement>) => {
    console.log('clicked')
  },
  disabled: false,
  type: 'button',
}

<FeatureButton {...props}>Click</FeatureButton>

Styling

CSS Variables

.feature-button {
  --button-bg: hsl(0 0% 10%);
  --button-text: hsl(0 0% 100%);
  --indicator-color: hsl(0 84% 60%);
}

Custom Classes

<FeatureButton
  featureId="feature"
  className="w-full justify-start"
>
  Full Width Button
</FeatureButton>

Best Practices

  1. Use for feature-specific actions, not generic buttons:
// Good
<FeatureButton featureId="ai-assist" onClick={generateWithAI}>
  Generate with AI
</FeatureButton>

// Bad (too generic)
<FeatureButton featureId="button" onClick={handleClick}>
  Click Me
</FeatureButton>
  1. Provide meaningful feature IDs:
// Good
featureId="pdf-export"

// Bad
featureId="btn-1"
  1. Don't track non-feature actions:
// Good: Feature-specific
<FeatureButton featureId="dark-mode" onClick={toggleDarkMode}>
  Dark Mode
</FeatureButton>

// Bad: Should use regular button
<FeatureButton featureId="close" onClick={closeModal}>
  Close
</FeatureButton>

Next Steps

On this page