Skip to main content

Grid Cards

A modern bento-style grid layout with shader backgrounds, AI chat input, marquee integrations, and real-time collaboration cursors.

GridReactFramer MotionTailwind CSSShaders
CSSTailwind

Manual

Create a file and paste the following code into it.

src/components/ai-card.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { motion } from "motion/react";
import { User } from "@phosphor-icons/react";

function GenerateButton() {
  return (
    <motion.button
      className="
        relative flex shrink-0 items-center gap-2 overflow-hidden
        rounded-full px-6 py-4
        bg-gradient-to-b from-sky-300/90 to-sky-500/90
        text-[14px] font-semibold text-white
        shadow-[0_0_18px_2px_rgba(56,189,248,0.35)]
      "
      animate={{
        boxShadow: [
          "0 0 18px 2px rgba(56,189,248,0.35)",
          "0 0 28px 6px rgba(56,189,248,0.5)",
          "0 0 18px 2px rgba(56,189,248,0.35)",
        ],
      }}
      transition={{ duration: 2.4, repeat: Infinity, ease: "easeInOut" }}
    >
      Generate
      <span className="flex items-center gap-0.5 rounded-full bg-white/20 px-1.5 py-0.5 text-[11px] font-medium">
        Enter
        <svg
          width="10"
          height="10"
          viewBox="0 0 10 10"
          fill="none"
          className="opacity-80"
        >
          <path
            d="M8 2v3.5H2.5M2.5 5.5 1 7l1.5 1.5"
            stroke="currentColor"
            strokeWidth="1.3"
            strokeLinecap="round"
            strokeLinejoin="round"
          />
        </svg>
      </span>
    </motion.button>
  );
}

const MESSAGE_PARTS = [
  { text: "Hey, Can you help ", highlight: false },
  { text: "me improve", highlight: true },
  { text: " the ", highlight: false },
  { text: "membership signup flow", highlight: true },
  { text: " with an ", highlight: false },
  { text: "extra step?", highlight: true },
];

function MessageBubble() {
  return (
    <div className="rounded-2xl bg-white/[0.06] px-5 py-4 ring-1 ring-white/[0.09]">
      <p className="text-left text-[15px] leading-7 text-white/40">
        {MESSAGE_PARTS.map((part, i) =>
          part.highlight ? (
            <span key={i} className="font-semibold text-white">
              {part.text}
            </span>
          ) : (
            <span key={i}>{part.text}</span>
          ),
        )}
      </p>
    </div>
  );
}

function InputRow() {
  return (
    <div className="mt-3 flex items-center justify-between rounded-full bg-white/[0.04] pr-2 py-2 pl-5 ring-1 ring-white/[0.08]">
      <span className="text-[14px] text-white/20 line-clamp-1">
        Ask anything
      </span>
      <GenerateButton />
    </div>
  );
}

function AiCard() {
  return (
    <div className="absolute inset-x-6 top-8 z-10">
      <div className="mb-3 flex justify-end">
        <div className="flex size-12 items-center justify-center rounded-full bg-white/[0.07] ring-1 ring-white/10">
          <User weight="duotone" size={20} className="text-white/50" />
        </div>
      </div>

      <MessageBubble />
      <InputRow />
    </div>
  );
}

export default AiCard;

Update the import paths to match your project setup.

Similar components

Bento Grid

Infinite Grid With Framer Motion

Max

Elastic Grid Scroll

Resource details

PublishedMarch 18, 2026
CategoryGrid
ReactFramer MotionTailwind CSSShaders