General

Build an AI Chatbot in React JS & CSS

Unlock the Power of Chatbots with React. Chatbots have become an integral part of our digital lives, from assisting with shopping to providing instant answers. Building a chatbot may seem daunting, but with React.js and CSS, you can create a sophisticated and functional AI chatbot in just a few steps.

Through this process, you’ll gain hands-on experience with essential concepts such as:

  • Building reusable components
  • Managing state and user interactions
  • Integrating APIs for seamless functionality

By the end, you’ll have a sleek, functional chatbot to enhance your projects and a deeper understanding of React.js and CSS.”

In this step-by-step guide, we’ll create a dynamic AI-powered chatbot using React JS and CSS, leveraging the free Google Gemini API for intelligent responses. You’ll learn how to tailor the chatbot to work seamlessly with your own data, making it a valuable asset for your portfolio.

By completing this project, you’ll gain a practical, real-world example of AI-driven development, perfect for showcasing your skills in today’s AI-centric landscape. Plus, you can easily integrate this chatbot into your website, application, or client projects.

Looking for a JavaScript challenge? Check out our companion blog post to build the same AI chatbot using vanilla JavaScript, complete with advanced features like file uploads and emoji pickers. This is an excellent opportunity to hone your JavaScript skills and develop a practical, functional project.”

Why Build an AI Chatbot in React JS?

Building an AI-powered chatbot with React.js and CSS is a rewarding project that goes beyond just having fun. It’s an opportunity to develop in-demand skills and gain hands-on experience with:

  • React Fundamentals: Master components, state management, and hooks.
  • AI Integration: Harness the power of the Gemini API for dynamic, AI-driven responses.
  • Web Services: Learn to interact with APIs, handle asynchronous operations, and manage data fetching.

By completing this project, you’ll have a portfolio-worthy chatbot that showcases your skills and can be used in real-world applications. Enhance your resume, impress potential employers, and take your development skills to the next level.”

Setting Up the Project

Create a Project Folder:

  • Make a new folder, for instance, “chatbot-reactjs”. (Or any name you feel good with)
  • Open this folder in your VS Code editor. (Or any code editor)

Initialize the Project:

Open your terminal by pressing Ctrl + J and then use Vite to create a new React app with this command:

npm create vite@latest ./ -- --template react

Install necessary dependencies and start the development server:

npm install
npm run dev

If your project is running in your browser, congratulations! You’ve successfully set up your chat app. Now, let’s move on to modifying folders and files.

Modify folder and CSS Files:

  • Remove the default assets folder and App.css file.
  • Replace the content of index.css with the provided CSS code.
/* Importing Google Fonts - Inter */
@import url('https://fonts.googleapis.com/css2?family=Inter:opsz,[email protected],100..900&display=swap');

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Inter", sans-serif;
}

body {
  width: 100%;
  min-height: 100vh;
  background: linear-gradient(#F4F0FF, #DACDFF);
}

#chatbot-toggler {
  position: fixed;
  bottom: 30px;
  right: 35px;
  border: none;
  height: 50px;
  width: 50px;
  display: flex;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: #6D4FC2;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
  transition: all 0.2s ease;
}

.container.show-chatbot #chatbot-toggler {
  transform: rotate(90deg);
}

#chatbot-toggler span {
  color: #fff;
  position: absolute;
}

#chatbot-toggler span:last-child,
.container.show-chatbot #chatbot-toggler span:first-child {
  opacity: 0;
}

.container.show-chatbot #chatbot-toggler span:last-child {
  opacity: 1;
}

.chatbot-popup {
  position: fixed;
  width: 420px;
  opacity: 0;
  right: 35px;
  bottom: 90px;
  pointer-events: none;
  transform: scale(0.2);
  overflow: hidden;
  background: #fff;
  border-radius: 15px;
  transform-origin: bottom right;
  box-shadow: 0 0 128px 0 rgba(0, 0, 0, 0.1),
    0 32px 64px -48px rgba(0, 0, 0, 0.5);
  transition: all 0.1s ease;
}

.container.show-chatbot .chatbot-popup {
  opacity: 1;
  pointer-events: auto;
  transform: scale(1);
}

.chatbot-popup .chat-header {
  display: flex;
  padding: 15px 22px;
  align-items: center;
  background: #6D4FC2;
  justify-content: space-between;
}

.chat-header .header-info {
  display: flex;
  gap: 10px;
  align-items: center;
}

.header-info svg {
  width: 35px;
  height: 35px;
  flex-shrink: 0;
  padding: 6px;
  fill: #6D4FC2;
  background: #fff;
  border-radius: 50%;
}

.header-info .logo-text {
  color: #fff;
  font-weight: 600;
  font-size: 1.31rem;
  letter-spacing: 0.02rem;
}

.chat-header button {
  border: none;
  height: 40px;
  width: 40px;
  color: #fff;
  cursor: pointer;
  padding-top: 2px;
  margin-right: -10px;
  font-size: 1.9rem;
  border-radius: 50%;
  background: none;
  transition: 0.2s ease;
}

.chat-header button:hover {
  background: #593bab;
}

.chat-body {
  display: flex;
  flex-direction: column;
  gap: 20px;
  height: 460px;
  overflow-y: auto;
  margin-bottom: 82px;
  padding: 25px 22px;
  scrollbar-width: thin;
  scrollbar-color: #DDD3F9 transparent;
}

.chat-body .message {
  display: flex;
  gap: 11px;
  align-items: center;
}

.chat-body .message svg {
  width: 35px;
  height: 35px;
  flex-shrink: 0;
  padding: 6px;
  fill: #fff;
  align-self: flex-end;
  margin-bottom: 2px;
  background: #6D4FC2;
  border-radius: 50%;
}

.chat-body .message .message-text {
  padding: 12px 16px;
  max-width: 75%;
  font-size: 0.95rem;
  word-wrap: break-word;
  white-space: pre-line;
}

.chat-body .message.error .message-text {
  color: #ff0000;
}

.chat-body .bot-message .message-text {
  background: #F6F2FF;
  border-radius: 13px 13px 13px 3px;
}

.chat-body .user-message {
  flex-direction: column;
  align-items: flex-end;
}

.chat-body .user-message .message-text {
  color: #fff;
  background: #6D4FC2;
  border-radius: 13px 13px 3px 13px;
}

.chat-footer {
  position: absolute;
  bottom: 0;
  width: 100%;
  background: #fff;
  padding: 15px 22px 20px;
}

.chat-footer .chat-form {
  display: flex;
  align-items: center;
  position: relative;
  background: #fff;
  border-radius: 32px;
  outline: 1px solid #CCCCE5;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.06);
}

.chat-form:focus-within {
  outline: 2px solid #6D4FC2;
}

.chat-form .message-input {
  width: 100%;
  height: 47px;
  border: none;
  outline: none;
  font-size: 0.95rem;
  padding: 0 17px;
  background: none;
}

.chat-form #send-message {
  height: 35px;
  width: 35px;
  border: none;
  flex-shrink: 0;
  color: #fff;
  cursor: pointer;
  display: none;
  margin-right: 6px;
  background: #6D4FC2;
  border-radius: 50%;
  font-size: 1.15rem;
  transition: 0.2s ease;
}

.chat-form .message-input:valid~#send-message {
  display: block;
}

.chat-form #send-message:hover {
  background: #593bab;
}

/* Responsive media query for mobile screens */
@media (max-width: 520px) {
  #chatbot-toggler {
    right: 20px;
    bottom: 20px;
  }

  .chatbot-popup {
    right: 0;
    bottom: 0;
    height: 100%;
    border-radius: 0;
    width: 100%;
  }

  .chatbot-popup .chat-header {
    padding: 12px 15px;
  }

  .chat-body {
    height: calc(90% - 55px);
    padding: 25px 15px;
  }

  .chat-footer {
    padding: 10px 15px 15px;
  }
}

Step 1: Set Up Your Component Files
In the src directory of your project, create a new folder named components. Inside this folder, create the following three files:

  • ChatbotIcon.jsx
  • ChatForm.jsx
  • ChatMessage.jsx

These files will serve as the building blocks for your chatbot’s user interface.

Step 2: Define Component Layout and Functionality
Add the respective code to each of the newly created files:

  • In components/ChatbotIcon.jsx, add the code to render the chatbot’s SVG icon.
  • In components/ChatForm.jsx, add the code to define the chat form’s layout and functionality.
  • In components/ChatMessage.jsx, add the code to define the chat message’s layout and functionality.

By adding the necessary code to each file, you’ll begin to bring your chatbot to life.

const ChatbotIcon = () => {
  return (
    <svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 1024 1024">
      <path d="M738.3 287.6H285.7c-59 0-106.8 47.8-106.8 106.8v303.1c0 59 47.8 106.8 106.8 106.8h81.5v111.1c0 .7.8 1.1 1.4.7l166.9-110.6 41.8-.8h117.4l43.6-.4c59 0 106.8-47.8 106.8-106.8V394.5c0-59-47.8-106.9-106.8-106.9zM351.7 448.2c0-29.5 23.9-53.5 53.5-53.5s53.5 23.9 53.5 53.5-23.9 53.5-53.5 53.5-53.5-23.9-53.5-53.5zm157.9 267.1c-67.8 0-123.8-47.5-132.3-109h264.6c-8.6 61.5-64.5 109-132.3 109zm110-213.7c-29.5 0-53.5-23.9-53.5-53.5s23.9-53.5 53.5-53.5 53.5 23.9 53.5 53.5-23.9 53.5-53.5 53.5zM867.2 644.5V453.1h26.5c19.4 0 35.1 15.7 35.1 35.1v121.1c0 19.4-15.7 35.1-35.1 35.1h-26.5zM95.2 609.4V488.2c0-19.4 15.7-35.1 35.1-35.1h26.5v191.3h-26.5c-19.4 0-35.1-15.7-35.1-35.1zM561.5 149.6c0 23.4-15.6 43.3-36.9 49.7v44.9h-30v-44.9c-21.4-6.5-36.9-26.3-36.9-49.7 0-28.6 23.3-51.9 51.9-51.9s51.9 23.3 51.9 51.9z" />
    </svg>
  );
};

export default ChatbotIcon;

In components/ChatForm.jsx, add the code to create the chat form. It will handle form submission, update the component’s state with user input, and call the generateBotResponse function to fetch responses from the API.

import { useRef } from "react";

const ChatForm = ({ chatHistory, setChatHistory, generateBotResponse }) => {
  const inputRef = useRef();

  const handleFormSubmit = (e) => {
    e.preventDefault();
    const userMessage = inputRef.current.value.trim();
    if (!userMessage) return;
    inputRef.current.value = "";

    // Update chat history with the user's message
    setChatHistory((history) => [...history, { role: "user", text: userMessage }]);

    // Delay 600 ms before showing "Thinking..." and generating response
    setTimeout(() => {
      // Add a "Thinking..." placeholder for the bot's response
      setChatHistory((history) => [...history, { role: "model", text: "Thinking..." }]);

      // Call the function to generate the bot's response
      generateBotResponse([...chatHistory, { role: "user", text: `Using the details provided above, please address this query: ${userMessage}` }]);
    }, 600);
  };

  return (
    <form onSubmit={handleFormSubmit} className="chat-form">
      <input ref={inputRef} placeholder="Message..." className="message-input" required />
      <button type="submit" id="send-message" className="material-symbols-rounded">
        arrow_upward
      </button>
    </form>
  );
};

export default ChatForm;

In components/ChatMessage.jsx, add the code to display chat messages. Differentiate between user messages and bot replies with the unique class name for stylings.

import ChatbotIcon from "./ChatbotIcon";

const ChatMessage = ({ chat }) => {
  return (
    !chat.hideInChat && (
      <div className={`message ${chat.role === "model" ? "bot" : "user"}-message ${chat.isError ? "error" : ""}`}>
        {chat.role === "model" && <ChatbotIcon />}
        <p className="message-text">{chat.text}</p>
      </div>
    )
  );
};

export default ChatMessage;

Next, create a companyInfo.js file inside the src, outside of the components folder.

// Dummy company information for chabot
export const companyInfo = `
Introduction:
I'm your friendly Aroma Beans Coffee chatbot, here to assist you with anything you need related to our coffee shop! Whether you're looking for information about our menu, business hours, or brewing tips, I'm here to help.

Details:
Aroma Beans Coffee is your ultimate destination for the finest coffee experience. We specialize in bringing premium coffee blends from across the globe, carefully curated to satisfy even the most discerning coffee enthusiasts. Whether you're a fan of single-origin beans or enjoy exploring bold, unique blends, Aroma Beans Coffee promises to elevate your coffee moments.

Located in the heart of Brew City, California, our café and roastery provide a cozy, welcoming atmosphere for coffee lovers to relax, work, or connect. Visit us at 123 Coffee Lane, Brew City, CA 90210. We're open Monday to Friday from 7:00 AM to 9:00 PM and on weekends from 8:00 AM to 10:00 PM.

Stay connected with us through our vibrant social media community. Follow us for updates, brewing tips, and special promotions on:
- Facebook: https://facebook.com/aromabeanscoffee
- Instagram: https://instagram.com/aromabeanscoffee
- Twitter: https://twitter.com/aromabeansco
- LinkedIn: https://linkedin.com/company/aromabeanscoffee

For inquiries, feel free to reach out via email at [email protected] or call us at +1 (555) 123-4567.

Our website, https://www.aromabeanscoffee.com, offers a seamless shopping experience for coffee beans, accessories, and subscriptions. Learn about our unique blends, explore brewing guides, and subscribe to receive fresh coffee delivered to your doorstep.

Menu:
- Signature Coffee:
  - Espresso Shot - $3.50
  - Cappuccino - $4.00
  - Latte (Classic/Vanilla/Caramel) - $4.50
  - Mocha - $5.00
- Specialty Brews:
  - Cold Brew - $4.50
  - Nitro Cold Brew - $5.50
  - Single-Origin Pour Over - $5.00
- Seasonal Favorites:
  - Pumpkin Spice Latte - $5.50
  - Peppermint Mocha - $5.50
- Tea & Alternatives:
  - Matcha Latte - $5.00
  - Chai Latte - $4.50
  - Hot Chocolate - $4.00
- Snacks & Pastries:
  - Croissant (Butter/Almond) - $3.50
  - Muffins (Blueberry/Chocolate Chip) - $3.00
  - Avocado Toast - $6.00
  - Bagel with Cream Cheese - $4.00

At Aroma Beans Coffee, we believe in creating moments worth savoring. Whether you're stopping by for your morning pick-me-up or indulging in an afternoon treat, we've got something special for everyone.
`;

Finally, update the content of src/App.jsx with the provided code.

import { useEffect, useRef, useState } from "react";
import ChatbotIcon from "./components/ChatbotIcon";
import ChatForm from "./components/ChatForm";
import ChatMessage from "./components/ChatMessage";
import { companyInfo } from "./companyInfo";

const App = () => {
  const chatBodyRef = useRef();
  const [showChatbot, setShowChatbot] = useState(false);
  const [chatHistory, setChatHistory] = useState([
    {
      hideInChat: true,
      role: "model",
      text: companyInfo,
    },
  ]);

  const generateBotResponse = async (history) => {
    // Helper function to update chat history
    const updateHistory = (text, isError = false) => {
      setChatHistory((prev) => [...prev.filter((msg) => msg.text != "Thinking..."), { role: "model", text, isError }]);
    };

    // Format chat history for API request
    history = history.map(({ role, text }) => ({ role, parts: [{ text }] }));

    const requestOptions = {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ contents: history }),
    };

    try {
      // Make the API call to get the bot's response
      const response = await fetch(import.meta.env.VITE_API_URL, requestOptions);
      const data = await response.json();
      if (!response.ok) throw new Error(data?.error.message || "Something went wrong!");

      // Clean and update chat history with bot's response
      const apiResponseText = data.candidates[0].content.parts[0].text.replace(/\*\*(.*?)\*\*/g, "$1").trim();
      updateHistory(apiResponseText);
    } catch (error) {
      // Update chat history with the error message
      updateHistory(error.message, true);
    }
  };

  useEffect(() => {
    // Auto-scroll whenever chat history updates
    chatBodyRef.current.scrollTo({ top: chatBodyRef.current.scrollHeight, behavior: "smooth" });
  }, [chatHistory]);

  return (
    <div className={`container ${showChatbot ? "show-chatbot" : ""}`}>
      <button onClick={() => setShowChatbot((prev) => !prev)} id="chatbot-toggler">
        <span className="material-symbols-rounded">mode_comment</span>
        <span className="material-symbols-rounded">close</span>
      </button>

      <div className="chatbot-popup">
        {/* Chatbot Header */}
        <div className="chat-header">
          <div className="header-info">
            <ChatbotIcon />
            <h2 className="logo-text">Chatbot</h2>
          </div>
          <button onClick={() => setShowChatbot((prev) => !prev)} className="material-symbols-rounded">
            keyboard_arrow_down
          </button>
        </div>

        {/* Chatbot Body */}
        <div ref={chatBodyRef} className="chat-body">
          <div className="message bot-message">
            <ChatbotIcon />
            <p className="message-text">
              Hey there  <br /> How can I help you today?
            </p>
          </div>

          {/* Render the chat history dynamically */}
          {chatHistory.map((chat, index) => (
            <ChatMessage key={index} chat={chat} />
          ))}
        </div>

        {/* Chatbot Footer */}
        <div className="chat-footer">
          <ChatForm chatHistory={chatHistory} setChatHistory={setChatHistory} generateBotResponse={generateBotResponse} />
        </div>
      </div>
    </div>
  );
};

export default App;

Important: Your chatbot won’t generate responses until it’s connected to the Gemini API. Sign up for a free API key from Google AI Studio. Once you have your key, create a .env file.

VITE_API_URL=https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=YOUR-API-KEY-HERE

Related posts

Fully Functioning Contact Us Form in PHP

Bankygold7904

How to customize Django Jazzmine Admin

Bankygold7904

All in one File and Video Downloader Source Code

Bankygold7904

Leave a Comment