Integration Badge

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

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 { motion } from 'framer-motion';
import { useState, type ReactNode } from 'react';

// ---------------------------------------------------------------------------
// Props
// ---------------------------------------------------------------------------
//
// logo        Image URL for the app mark
// name        Integration name
// status      Optional status chip: connected | available | beta
// href        Optional link wrapper
// size        sm | md | lg
// monochrome  Start muted; color on hover (default true)
// className   Styles for the outer shell
//
type IntegrationBadgeProps = {
  logo?: string;
  name?: string;
  status?: 'connected' | 'available' | 'beta';
  href?: string;
  size?: 'sm' | 'md' | 'lg';
  monochrome?: boolean;
  className?: string;
};

const SIZE = {
  sm: { tile: 28, pad: 'px-2 py-1.5 gap-2', text: 'text-xs' },
  md: { tile: 34, pad: 'px-2.5 py-2 gap-2.5', text: 'text-sm' },
  lg: { tile: 40, pad: 'px-3 py-2.5 gap-3', text: 'text-sm' },
};

const STATUS = {
  connected: 'text-emerald-600',
  available: 'text-gray-400',
  beta: 'text-amber-600',
};

function SlackLogo({ className = '' }: { className?: string }) {
  return (
    <svg viewBox='0 0 24 24' className={className} aria-hidden>
      <path
        fill='#E01E5A'
        d='M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zm1.271 0a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313z'
      />
      <path
        fill='#36C5F0'
        d='M8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zm0 1.271a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312z'
      />
      <path
        fill='#2EB67D'
        d='M18.956 8.834a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zm-1.27 0a2.528 2.528 0 0 1-2.523 2.521 2.528 2.528 0 0 1-2.52-2.521V2.522A2.528 2.528 0 0 1 15.163 0a2.528 2.528 0 0 1 2.523 2.522v6.312z'
      />
      <path
        fill='#ECB22E'
        d='M15.163 18.956a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.163 24a2.527 2.527 0 0 1-2.523-2.522v-2.522h2.523zm0-1.27a2.527 2.527 0 0 1-2.523-2.523 2.527 2.527 0 0 1 2.523-2.52h6.315A2.528 2.528 0 0 1 24 15.163a2.528 2.528 0 0 1-2.522 2.523h-6.315z'
      />
    </svg>
  );
}

export default function IntegrationBadge({
  logo,
  name = 'Slack',
  status,
  href,
  size = 'md',
  monochrome = true,
  className = '',
}: IntegrationBadgeProps) {
  const s = SIZE[size];
  const [logoFailed, setLogoFailed] = useState(false);
  const showRemoteLogo = Boolean(logo) && !logoFailed;

  const markClass = [
    'h-[58%] w-[58%] transition-[filter,transform] duration-500 group-hover:scale-105 group-hover:grayscale-0',
    monochrome ? 'grayscale' : '',
  ].join(' ');

  let mark: ReactNode = <SlackLogo className={markClass} />;
  if (showRemoteLogo) {
    mark = (
      <img
        src={logo}
        alt=''
        className={[markClass, 'object-contain'].join(' ')}
        onError={() => setLogoFailed(true)}
      />
    );
  }

  const body = (
    <>
      <span
        className='relative flex shrink-0 items-center justify-center overflow-hidden rounded-xl border border-gray-200/80 bg-white shadow-[0_1px_2px_rgba(0,0,0,0.04)]'
        style={{ width: s.tile, height: s.tile }}
      >
        {mark}
      </span>

      <span className='min-w-0'>
        <span
          className={[
            'block truncate font-medium tracking-wide text-gray-800',
            s.text,
          ].join(' ')}
        >
          {name}
        </span>
        {status ? (
          <span
            className={[
              'block text-[10px] font-medium uppercase tracking-[0.12em]',
              STATUS[status],
            ].join(' ')}
          >
            {status}
          </span>
        ) : null}
      </span>
    </>
  );

  const shell = [
    'group inline-flex items-center rounded-2xl border border-gray-200/70 bg-white/60 shadow-[0_1px_2px_rgba(0,0,0,0.03)] backdrop-blur-md transition-[transform,box-shadow,border-color,background-color] duration-300 hover:-translate-y-0.5 hover:border-gray-300 hover:bg-white hover:shadow-[0_8px_24px_rgba(0,0,0,0.06)]',
    s.pad,
    className,
  ]
    .filter(Boolean)
    .join(' ');

  return (
    <motion.div
      initial={{ opacity: 0, y: 8 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.4, ease: [0.22, 1, 0.36, 1] }}
    >
      {href ? (
        <a href={href} className={shell}>
          {body}
        </a>
      ) : (
        <div className={shell}>{body}</div>
      )}
    </motion.div>
  );
}

```

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
logostringImage URL for the app mark
namestringIntegration name
status'connected' | 'available' | 'beta'Optional status chip
hrefstringOptional link wrapper
size'sm' | 'md' | 'lg'Badge size
monochromebooleanStart muted and reveal color on hover
classNamestringStyles for the outer shell

More Product Components

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