logoassistant-ui

Perplexity Clone

Dark theme with cyan accents for a Perplexity look and feel

What do you want to know?

Overview

The Perplexity Clone demonstrates how to customize assistant-ui to match Perplexity's search-focused interface. This example features their distinctive forced dark theme with cyan accents, large welcome typography, and answer-focused response formatting.

Features

  • Forced Dark Theme: Consistent #1a1a1a background regardless of system preference
  • Cyan Accent: Signature #20b8cd for interactive elements
  • Search-First Design: Large welcome text with prominent input
  • Answer Format: Responses prefixed with sparkle icon and "Answer" heading
  • Layered Surfaces: Multiple dark shades for depth (#1a1a1a, #242424, #3a3a3a)
  • Attachment Support: File uploads with paperclip icon

Quick Start

npx assistant-ui add thread

Code

The Perplexity clone uses a dark theme with cyan accents:

import {
  ThreadPrimitive,
  ComposerPrimitive,
  MessagePrimitive,
} from "@assistant-ui/react";

export const Thread = () => {
  return (
    <ThreadPrimitive.Root
      className="dark h-full bg-[#1a1a1a] text-[#f5f5f5]"
      style={{ ["--thread-max-width"]: "42rem" }}
    >
      <ThreadPrimitive.Empty>
        <div className="flex h-full w-full items-center justify-center">
          <div className="flex w-full max-w-[var(--thread-max-width)] flex-col gap-12">
            <p className="text-4xl text-[#f5f5f5] md:text-5xl">
              What do you want to know?
            </p>
            <ComposerPrimitive.Root className="rounded-xl border border-[#3a3a3a] bg-[#242424] focus-within:border-[#20b8cd] focus-within:ring-1 focus-within:ring-[#20b8cd]/30">
              <ComposerPrimitive.Input
                placeholder="Ask anything..."
                className="text-[#f5f5f5] text-lg placeholder:text-[#808080]"
              />
              <ComposerPrimitive.Send className="rounded-full bg-[#20b8cd] text-[#1a1a1a] hover:bg-[#1aa3b5]">
                <ArrowRightIcon />
              </ComposerPrimitive.Send>
            </ComposerPrimitive.Root>
          </div>
        </div>
      </ThreadPrimitive.Empty>

      <ThreadPrimitive.Viewport>
        <ThreadPrimitive.Messages components={{ UserMessage, AssistantMessage }} />
        <Composer />
      </ThreadPrimitive.Viewport>
    </ThreadPrimitive.Root>
  );
};

const AssistantMessage = () => (
  <MessagePrimitive.Root className="max-w-[var(--thread-max-width)]">
    <h1 className="mb-4 inline-flex items-center gap-2 text-2xl text-[#20b8cd]">
      <SparkleIcon /> Answer
    </h1>
    <MessagePrimitive.Parts components={{ Text: MarkdownText }} />
  </MessagePrimitive.Root>
);

Color Palette

ElementColor
Background#1a1a1a
Surface#242424
Border#3a3a3a
Text#f5f5f5
Muted text#808080, #a0a0a0
Accent (cyan)#20b8cd
Accent hover#1aa3b5

Styling Details

  • Focus Ring: focus-within:border-[#20b8cd] focus-within:ring-1 focus-within:ring-[#20b8cd]/30
  • CSS Variable: --thread-max-width: 42rem for consistent content width
  • Welcome: Large text-4xl md:text-5xl for impact
  • Follow-up Composer: Rounded pill with rounded-full in follow-up mode
  • Answer Heading: Cyan text with sparkle icon prefix

Source

View full source on GitHub