index.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import Link from "next/link";
  2. type IntegrationCardProps = {
  3. href: string;
  4. icon: React.ReactNode;
  5. title: string;
  6. description: string;
  7. colorScheme?: "blue" | "green" | "purple" | "yellow";
  8. external?: boolean;
  9. showArrow?: boolean;
  10. };
  11. const colorClasses = {
  12. blue: {
  13. bg: "bg-blue-100 dark:bg-blue-900",
  14. text: "text-blue-600 dark:text-blue-400",
  15. hoverText: "group-hover:text-blue-600 dark:group-hover:text-blue-400",
  16. },
  17. green: {
  18. bg: "bg-green-100 dark:bg-green-900",
  19. text: "text-green-600 dark:text-green-400",
  20. hoverText: "group-hover:text-green-600 dark:group-hover:text-green-400",
  21. },
  22. purple: {
  23. bg: "bg-purple-100 dark:bg-purple-900",
  24. text: "text-purple-600 dark:text-purple-400",
  25. hoverText: "group-hover:text-purple-600 dark:group-hover:text-purple-400",
  26. },
  27. yellow: {
  28. bg: "bg-yellow-100 dark:bg-yellow-900",
  29. text: "text-yellow-600 dark:text-yellow-400",
  30. hoverText: "group-hover:text-yellow-600 dark:group-hover:text-yellow-400",
  31. },
  32. };
  33. export function IntegrationCard({
  34. href,
  35. icon,
  36. title,
  37. description,
  38. colorScheme = "blue",
  39. external,
  40. showArrow = true,
  41. }: IntegrationCardProps) {
  42. const colors = colorClasses[colorScheme];
  43. const Wrapper = external ? "a" : Link;
  44. const wrapperProps = external
  45. ? { href, target: "_blank", rel: "noopener noreferrer" }
  46. : { href };
  47. return (
  48. <Wrapper
  49. {...(wrapperProps as
  50. | { href: string }
  51. | { href: string; target: string; rel: string })}
  52. className="not-prose group no-underline grid h-full grid-rows-[auto_1fr] gap-3 rounded-xl border bg-[var(--color-fd-card)] border-[var(--color-fd-border)] p-5 md:p-6 shadow-sm outline-none transition-colors hover:border-[var(--color-fd-accent)] focus-visible:ring-2 focus-visible:ring-[var(--color-fd-accent)]"
  53. aria-label={title}
  54. >
  55. <div className="flex items-center gap-3">
  56. <div
  57. className={`flex h-8 w-8 items-center justify-center rounded-md ${colors.bg}`}
  58. >
  59. <div className={`h-4 w-4 ${colors.text}`}>{icon}</div>
  60. </div>
  61. <h3
  62. className={`m-0 text-base font-semibold text-[var(--color-fd-foreground)] ${colors.hoverText}`}
  63. >
  64. {title}
  65. </h3>
  66. {showArrow && (
  67. <span
  68. className="ml-auto translate-x-0 opacity-0 transition-all duration-200 ease-out group-hover:translate-x-1 group-hover:opacity-100"
  69. aria-hidden="true"
  70. >
  71. </span>
  72. )}
  73. </div>
  74. <p className="m-0 text-sm text-[var(--color-fd-muted-foreground)] line-clamp-2">
  75. {description}
  76. </p>
  77. </Wrapper>
  78. );
  79. }