--- title: Gemini Clone description: Open-source Gemini clone in React with a centered greeting over an ambient glow, a single-row pill composer, avatar-free assistant replies, and disabled, ready, and stop send states. --- import { Gemini } from "@/components/examples/gemini";
## Overview The Gemini Clone shows how to restyle assistant-ui to match Google Gemini's current interface. The empty state centers a single-line greeting over a soft blue glow, and a single-row pill composer is shared by both the empty and chat states. Assistant replies render as full-width markdown with no avatar, and user turns sit in a rounded grey bubble. ## Features - **Centered greeting**: one "How can I help you today?" headline, centered over a blurred radial glow. - **Single-row composer**: a 32px pill that holds the `+` menu, the input, the model picker, the mic, and send on one line. - **Combined `+` menu**: "Add photos & files" sits next to the Deep Research, Canvas, Create image, and Guided Learning tools. - **Model picker**: Fast and Thinking, each with a short description and a check mark on the active model. - **Send states**: a disabled grey arrow when empty, a blue arrow when ready, and a stop square while a response streams. - **Avatar-free replies**: assistant messages are full-width markdown, with the action bar revealed on hover. - **Grey user bubble**: a `rounded-3xl` warm-grey bubble, right-aligned, with copy and edit actions on hover. ## Quick Start ```bash npx assistant-ui add thread ``` ## Code The empty and chat states render the same `Composer`. It is a flex column: an optional attachment row on top, then a single action row with the input as the `flex-1` middle and the controls bottom-aligned around it. ```tsx import { AuiIf, ComposerPrimitive, ThreadPrimitive, } from "@assistant-ui/react"; export const Gemini = () => ( s.thread.isEmpty}> !s.thread.isEmpty}> ); const Composer = () => ( s.composer.attachments.length > 0}>
); ``` ### Send states The trailing slot swaps between Send and Cancel with `AuiIf`. `ComposerPrimitive.Send` disables itself while the composer is empty, so the disabled, ready, and running looks are all driven by state instead of manual class toggling: ```tsx {/* Send: disabled grey when empty, blue when there is text */} !s.thread.isRunning}> {/* Cancel: stop square while a response streams */} s.thread.isRunning}> ``` ### Combined `+` menu The `+` button opens one menu for both attachments and tools. `ComposerPrimitive.AddAttachment` is rendered as the first item through the `render` prop, so picking it opens the file dialog and closes the menu: ```tsx import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; }> Add photos & files Deep Research Canvas {/* Create image, Guided Learning ... */} ``` ### Ambient glow The empty state places a single blurred ellipse behind the greeting and composer. It is decorative, so it is `pointer-events-none` and `aria-hidden`: ```tsx
``` ### Color palette | Element | Light | Dark | | ------------------ | --------------------- | --------- | | Background | `#fdfcfc` | `#131314` | | Composer surface | `#ffffff` | `#1e1f20` | | Primary text | `#1f1f1f` | `#e3e3e3` | | Muted text & icons | `#444746` | `#c4c7c5` | | User bubble | `#f2f0f0` | `#333537` | | Send (ready) | `#d3e3fd` | `#1f3760` | | Ambient glow | `#a9d1fb` | `#1d4068` | ### Messages Assistant replies have no avatar; the markdown spans the full content width and the action bar (feedback, copy, regenerate, more) fades in on hover. User turns sit in a rounded grey bubble, right-aligned, with copy and edit actions to its left: ```tsx
``` ## Source