Docs
Feature Showcase Interactive

Feature Showcase Interactive

An interactive feature showcase with animated demos and stats. Click features to see detailed information with smooth animations.

Everything you need to succeed

Powerful features designed to help your business grow faster

Lightning Fast Performance

Optimized for speed with sub-50ms response times and 99.9% uptime guarantee

50ms
Response
99.9%
Uptime
10x
Faster

Installation

Install dependencies

npm install framer-motion

Copy and paste the following code into your project.

"use client";
 
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Check, Zap, Shield, TrendingUp, Users, Globe } from "lucide-react";
 
interface Feature {
  id: string;
  icon: React.ElementType;
  title: string;
  description: string;
  stats?: {
    value: string;
    label: string;
  }[];
  color: string;
}
 
interface FeatureShowcaseInteractiveProps {
  title?: string;
  description?: string;
  features: Feature[];
  className?: string;
}
 
export function FeatureShowcaseInteractive({
  title = "Everything you need to succeed",
  description = "Powerful features designed to help your business grow faster",
  features,
  className = "",
}: FeatureShowcaseInteractiveProps) {
  const [activeFeature, setActiveFeature] = useState(0);
 
  const Icon = features[activeFeature].icon;
 
  return (
    <section className={`w-full bg-black py-20 ${className}`}>
      <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
        <div className="mb-16 text-center">
          <h2 className="mb-4 text-4xl font-bold text-white sm:text-5xl">
            {title}
          </h2>
          <p className="mx-auto max-w-2xl text-lg text-zinc-400">
            {description}
          </p>
        </div>
 
        <div className="grid gap-8 lg:grid-cols-2 lg:gap-12">
          <div className="space-y-4">
            {features.map((feature, index) => {
              const Icon = feature.icon;
              const isActive = activeFeature === index;
 
              return (
                <motion.button
                  key={feature.id}
                  onClick={() => setActiveFeature(index)}
                  className={`group relative w-full rounded-2xl border p-6 text-left transition-all duration-300 ${
                    isActive
                      ? "border-white/20 bg-white/5"
                      : "border-zinc-800 bg-zinc-950 hover:border-zinc-700 hover:bg-zinc-900"
                  }`}
                  whileHover={{ scale: 1.02 }}
                  whileTap={{ scale: 0.98 }}
                >
                  {isActive && (
                    <motion.div
                      layoutId="activeFeature"
                      className="absolute inset-0 rounded-2xl border-2"
                      style={{ borderColor: feature.color }}
                      transition={{
                        type: "spring",
                        stiffness: 300,
                        damping: 30,
                      }}
                    />
                  )}
 
                  <div className="relative flex items-start gap-4">
                    <div
                      className={`flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-xl transition-all duration-300 ${
                        isActive
                          ? "shadow-lg"
                          : "bg-zinc-900 group-hover:bg-zinc-800"
                      }`}
                      style={
                        isActive
                          ? {
                              backgroundColor: feature.color,
                              boxShadow: `0 0 30px ${feature.color}40`,
                            }
                          : {}
                      }
                    >
                      <Icon
                        className={`h-6 w-6 ${
                          isActive ? "text-white" : "text-zinc-400"
                        }`}
                      />
                    </div>
 
                    {/* Content */}
                    <div className="flex-1">
                      <h3
                        className={`mb-2 text-lg font-semibold ${
                          isActive ? "text-white" : "text-zinc-300"
                        }`}
                      >
                        {feature.title}
                      </h3>
                      <p
                        className={`text-sm ${
                          isActive ? "text-zinc-400" : "text-zinc-500"
                        }`}
                      >
                        {feature.description}
                      </p>
                    </div>
 
                    {isActive && (
                      <motion.div
                        initial={{ scale: 0 }}
                        animate={{ scale: 1 }}
                        className="flex-shrink-0"
                      >
                        <div
                          className="flex h-6 w-6 items-center justify-center rounded-full"
                          style={{ backgroundColor: feature.color }}
                        >
                          <Check className="h-4 w-4 text-white" />
                        </div>
                      </motion.div>
                    )}
                  </div>
                </motion.button>
              );
            })}
          </div>
 
          <div className="relative">
            <AnimatePresence mode="wait">
              <motion.div
                key={activeFeature}
                initial={{ opacity: 0, y: 20 }}
                animate={{ opacity: 1, y: 0 }}
                exit={{ opacity: 0, y: -20 }}
                transition={{ duration: 0.3 }}
                className="sticky top-8"
              >
                <div className="relative overflow-hidden rounded-2xl border border-zinc-800 bg-zinc-950 p-8">
                  {/* Glow Effect */}
                  <div
                    className="absolute inset-0 opacity-20 blur-3xl"
                    style={{
                      background:
                        `radial-gradient(circle at 50% 50%, ${features[activeFeature].color}, transparent 70%)` as any,
                    }}
                  />
 
                  <div className="relative z-10">
                    {(() => {
                      const ActiveIcon = features[activeFeature].icon;
                      return (
                        <div
                          className="mb-6 inline-flex h-16 w-16 items-center justify-center rounded-2xl shadow-lg"
                          style={
                            {
                              backgroundColor: features[activeFeature].color,
                              boxShadow: `0 0 40px ${features[activeFeature].color}60`,
                            } as React.CSSProperties
                          }
                        >
                          <ActiveIcon className="h-8 w-8 text-white" />
                        </div>
                      );
                    })()}
 
                    <h3 className="mb-3 text-2xl font-bold text-white">
                      {features[activeFeature].title}
                    </h3>
                    <p className="mb-8 text-zinc-400">
                      {features[activeFeature].description}
                    </p>
 
                    {features[activeFeature].stats && (
                      <div className="grid grid-cols-3 gap-4">
                        {features[activeFeature].stats!.map((stat, index) => (
                          <motion.div
                            key={index}
                            initial={{ scale: 0.8, opacity: 0 }}
                            animate={{ scale: 1, opacity: 1 }}
                            transition={{ delay: index * 0.1 }}
                            className="rounded-xl border border-zinc-800 bg-zinc-900/50 p-4 text-center"
                          >
                            <div
                              className="mb-1 text-2xl font-bold"
                              style={{ color: features[activeFeature].color }}
                            >
                              {stat.value}
                            </div>
                            <div className="text-xs text-zinc-500">
                              {stat.label}
                            </div>
                          </motion.div>
                        ))}
                      </div>
                    )}
 
                    <div className="mt-8 space-y-3">
                      {[1, 2, 3].map((item, index) => (
                        <motion.div
                          key={item}
                          initial={{ width: 0 }}
                          animate={{ width: "100%" }}
                          transition={{ delay: index * 0.15, duration: 0.6 }}
                          className="h-2 rounded-full bg-zinc-800"
                        >
                          <motion.div
                            initial={{ width: 0 }}
                            animate={{ width: `${85 - index * 15}%` }}
                            transition={{
                              delay: index * 0.15 + 0.3,
                              duration: 0.8,
                            }}
                            className="h-full rounded-full"
                            style={{
                              background: `linear-gradient(90deg, ${features[activeFeature].color}, ${features[activeFeature].color}80)`,
                            }}
                          />
                        </motion.div>
                      ))}
                    </div>
                  </div>
                </div>
              </motion.div>
            </AnimatePresence>
          </div>
        </div>
      </div>
    </section>
  );
}

Update the import paths to match your project setup.

Features

  • Interactive selection - Click features to see details
  • Smooth animations - Framer Motion powered transitions
  • Stats display - Show key metrics for each feature
  • Color-coded - Each feature has its own color theme
  • Progress bars - Animated visual demos
  • Glow effects - Dynamic background glows
  • Active indicators - Clear visual feedback
  • Responsive - Stacks on mobile devices
  • Customizable - Easy to modify colors and content
  • TypeScript support - Full type safety

Usage

Basic Usage

import FeatureShowcaseInteractive from "@/components/ui/feature-showcase-interactive";
import {Zap, Shield, TrendingUp} from "lucide-react";
 
const features = [
  {
    id: "performance",
    icon: Zap,
    title: "Lightning Fast",
    description: "Optimized for speed",
    color: "#f59e0b",
    stats: [
      {value: "50ms", label: "Response"},
      {value: "99.9%", label: "Uptime"},
    ],
  },
  // ... more features
];
 
export default function Page() {
  return <FeatureShowcaseInteractive features={features} />;
}

Custom Title and Description

<FeatureShowcaseInteractive
  title="Why Choose Us"
  description="Features that make us stand out"
  features={features}
/>

Without Stats

const features = [
  {
    id: "feature1",
    icon: Zap,
    title: "Feature Title",
    description: "Feature description",
    color: "#f59e0b",
    // No stats property
  },
];

Props

FeatureShowcaseInteractiveProps

PropTypeDefaultDescription
featuresFeature[]RequiredArray of feature objects
titlestring"Everything you need..."Section title
descriptionstring"Powerful features..."Section description
classNamestring""Additional CSS classes

Feature

PropTypeRequiredDescription
idstringYesUnique identifier
iconReact.ElementTypeYesLucide icon component
titlestringYesFeature title
descriptionstringYesFeature description
colorstringYesHex color code
statsStat[]NoOptional stats array

Stat

PropTypeRequiredDescription
valuestringYesStat value (e.g., "50ms")
labelstringYesStat label (e.g., "Response")

TypeScript Interface

interface Feature {
  id: string;
  icon: React.ElementType;
  title: string;
  description: string;
  stats?: {
    value: string;
    label: string;
  }[];
  color: string;
}
 
interface FeatureShowcaseInteractiveProps {
  title?: string;
  description?: string;
  features: Feature[];
  className?: string;
}

Use Cases

Perfect for:

  • SaaS landing pages
  • Product feature pages
  • Platform showcases
  • Service descriptions
  • Tool comparisons
  • Capability highlights
  • Technology demos
  • Solution pages

Customization

Change Animation Speed

// In the component, adjust transition durations
transition={{ duration: 0.5 }} // Change from 0.3

Add More Stats

stats: [
  {value: "50ms", label: "Response"},
  {value: "99.9%", label: "Uptime"},
  {value: "10x", label: "Faster"},
  {value: "24/7", label: "Support"}, // Add more
];

Custom Progress Bars

// Modify the visual demo section
{[1, 2, 3, 4].map((item, index) => ( // Add more bars
  // ... progress bar code
))}

Remove Glow Effect

// Remove or comment out this div
<div
  className="absolute inset-0 opacity-20 blur-3xl"
  style={{...}}
/>