Feature Chip

Minimal metadata token with an independent icon hover and soft selected bloom.

Add to your project

Pick the way you like to build.

Let your AI assistant add it

Copy this prompt and paste it into the AI tool building your site.

# Integrate this UI component

Add this component to my project.

1. Install any missing dependencies.
2. Make sure Tailwind CSS is set up and scans the new file.
3. Prefer passing props over editing the component source — changing the component itself may break it.
4. Adjust colors, size, and layout via props or wrapper classes to match my project. You know my codebase better than this snippet does.

## Component source

```tsx
'use client';

import { AnimatePresence, motion } from 'framer-motion';
import { useState, type ReactNode } from 'react';

// ---------------------------------------------------------------------------
// Props
// ---------------------------------------------------------------------------
//
// icon          Leading mark — node or string
// label         Chip text
// tooltip       Optional hint revealed on hover/focus
// selected      Active / selected state with soft bloom
// tone          neutral | accent
// interactive   Enables click / keyboard selection feel
// onClick       Selection handler
// className     Styles for the outer shell
//
type FeatureChipProps = {
  icon?: ReactNode;
  label?: string;
  tooltip?: string;
  selected?: boolean;
  tone?: 'neutral' | 'accent';
  interactive?: boolean;
  onClick?: () => void;
  className?: string;
};

const DEFAULT_ICON = (
  <svg viewBox='0 0 16 16' className='h-3.5 w-3.5' aria-hidden>
    <path
      d='M8 1.5l1.2 3.4H13l-2.9 2.1 1.1 3.5L8 8.7 4.8 10.5l1.1-3.5L3 4.9h3.8L8 1.5z'
      fill='none'
      stroke='currentColor'
      strokeWidth='1.2'
      strokeLinejoin='round'
    />
  </svg>
);

export default function FeatureChip({
  icon = DEFAULT_ICON,
  label = 'Realtime sync',
  tooltip,
  selected = false,
  tone = 'neutral',
  interactive = true,
  onClick,
  className = '',
}: FeatureChipProps) {
  const [hovered, setHovered] = useState(false);
  const isAccent = tone === 'accent' || selected;

  const shell = [
    'relative inline-flex items-center gap-2 rounded-full border px-3 py-1.5 text-xs font-medium tracking-wide shadow-[0_1px_2px_rgba(0,0,0,0.03)] backdrop-blur-md transition-[background-color,border-color,box-shadow,color] duration-300',
    isAccent
      ? 'border-violet-200/80 bg-violet-50/80 text-violet-900 shadow-[0_0_0_1px_rgba(167,139,250,0.15),0_8px_20px_rgba(139,92,246,0.08)]'
      : 'border-gray-200/80 bg-white/70 text-gray-700 hover:border-gray-300 hover:bg-white',
    interactive ? 'cursor-pointer' : 'cursor-default',
    className,
  ]
    .filter(Boolean)
    .join(' ');

  return (
    <motion.button
      type='button'
      className={shell}
      onClick={interactive ? onClick : undefined}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      onFocus={() => setHovered(true)}
      onBlur={() => setHovered(false)}
      initial={{ opacity: 0, y: 6 }}
      animate={{ opacity: 1, y: 0 }}
      whileHover={interactive ? { y: -1 } : undefined}
      whileTap={interactive ? { scale: 0.98 } : undefined}
      transition={{ duration: 0.35, ease: [0.22, 1, 0.36, 1] }}
      aria-pressed={interactive ? selected : undefined}
    >
      <motion.span
        className='inline-flex text-current'
        animate={hovered ? { rotate: [-2, 2, 0], y: -1 } : { rotate: 0, y: 0 }}
        transition={{ type: 'spring', stiffness: 360, damping: 16 }}
      >
        {icon}
      </motion.span>
      <span>{label}</span>

      <AnimatePresence>
        {tooltip && hovered ? (
          <motion.span
            role='tooltip'
            className='pointer-events-none absolute -top-9 left-1/2 z-10 -translate-x-1/2 whitespace-nowrap rounded-md bg-gray-900/90 px-2 py-1 text-[10px] font-medium tracking-wide text-white shadow-lg backdrop-blur-xs'
            initial={{ opacity: 0, y: 4, filter: 'blur(3px)' }}
            animate={{ opacity: 1, y: 0, filter: 'blur(0px)' }}
            exit={{ opacity: 0, y: 2, filter: 'blur(3px)' }}
            transition={{ duration: 0.2 }}
          >
            {tooltip}
          </motion.span>
        ) : null}
      </AnimatePresence>
    </motion.button>
  );
}

```

Works with your AI tools

ClaudeClaude*
CodexCodex*
LovableLovable
Base44Base44
Figma MakeFigma Make
ReplitReplit*
CursorCursor*
v0v0

* Compatible with most projects that use the default React/Next.js framework.

Built With

ReactTailwind CSSFramer Motion

Props

PropTypeDescription
iconReactNodeLeading mark — node or string
labelstringChip text
tooltipstringOptional hint revealed on hover/focus
selectedbooleanActive state with a soft bloom
tone'neutral' | 'accent'Color treatment
interactivebooleanEnables click / keyboard selection
onClick() => voidSelection handler
classNamestringStyles for the outer shell

More Product Components

Slackconnected

Sculptural app mark in a precise tile — muted to full color with a near-imperceptible lift.