SplitTemplateCard.tsx2.5 KBView on GitHub
import { Check } from 'lucide-react';
import { Switch } from '@/components/ui/switch';
import { cn } from '@/lib/utils';

interface SplitTemplateCardProps {
  /** Card title — the inbox this template creates. */
  name: string;
  /** Whether the matching inbox exists on the account. */
  isApplied: boolean;
  onClick: () => void;
  /**
   * Layout-toggle templates ("Important + Other") read as a switch rather than a
   * tick: they turn a mode on, they do not add a tab.
   */
  isToggle?: boolean;
  /** Tailwind `border-t-*` accent that gives each category its colour. */
  accentClassName?: string;
  /** Optional blurb under the title. Omitted where the options speak for themselves. */
  description?: string;
  /** Extra controls under the card body (the Gmail-important checkbox, VIP form). */
  children?: React.ReactNode;
  className?: string;
}

/**
 * A sub-inbox template card.
 *
 * Shared by the inbox's own Edit dialog and by onboarding so the two cannot drift:
 * the picker a user meets during setup is the same picker they come back to.
 */
export function SplitTemplateCard({
  name,
  isApplied,
  onClick,
  isToggle = false,
  accentClassName,
  description,
  children,
  className,
}: SplitTemplateCardProps) {
  return (
    <div
      className={cn(
        'border-border bg-background hover:border-foreground/30 flex flex-col rounded-md border border-t-4 text-left transition-colors',
        accentClassName,
        (isApplied || isToggle) && 'bg-sunken',
        className,
      )}
    >
      <button
        type="button"
        onClick={onClick}
        className="flex flex-1 cursor-pointer flex-col items-start text-left"
      >
        <div className="w-full space-y-2 p-3">
          <p className="flex items-center gap-1.5 text-sm font-medium">
            <span className="flex-1">{name}</span>
            {isToggle ? (
              <Switch
                aria-hidden
                tabIndex={-1}
                checked={isApplied}
                className="pointer-events-none"
              />
            ) : (
              isApplied && <Check className="h-3.5 w-3.5 text-emerald-600" />
            )}
          </p>
          {/* min-h keeps a row of cards aligned when their blurbs run to different
              line counts. Absent entirely when there is no blurb at all. */}
          {description && (
            <p className="text-muted-foreground min-h-[40px] text-xs">{description}</p>
          )}
        </div>
      </button>
      {children}
    </div>
  );
}