Skip to content

Commit

Permalink
feat: add AI chat widget (#256)
Browse files Browse the repository at this point in the history
* feat: add ChatButton component to homepage features

* style: update chat button and iframe styles

* refactor: move chat button functionality to separate module

* feat: add query parameter to chat iframe source

* refactor: improve chat iframe display and container styling
  • Loading branch information
HashCookie committed Aug 2, 2024
1 parent 4577082 commit 669be00
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
"react/no-unknown-property": [
"error",
{
"ignore": ["scrolling"]
"ignore": ["scrolling","fill"]
}
]
}
Expand Down
51 changes: 51 additions & 0 deletions src/ChatWidget/ChatButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, {useState} from "react";
import {chatButton, chatButtonOpen, chatIframe, chatIframeContainer, closeIcon} from "./chatStyles";

function ChatButton() {
const [isChatOpen, setIsChatOpen] = useState(false);
const [isHovered, setIsHovered] = useState(false);

const handleClick = () => {
setIsChatOpen(!isChatOpen);
};

return (
<div>
<button
style={{
...chatButton,
...(isChatOpen ? chatButtonOpen : {}),
...(isHovered ? {backgroundColor: "#2E2A57"} : {}),
}}
onClick={handleClick}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
{isChatOpen ? (
<span style={closeIcon}>×</span>
) : (
<>
<svg style={{marginRight: "5px"}} viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24">
<g transform="scale(-1, 1) translate(-1024, 0)">
<path
d="M1002.7 448C1002.7 212.4 783 21.3 512 21.3S21.3 212.4 21.3 448c0 194.7 149.9 358.9 354.8 410.1-21.1 66.9-77.4 123.2-77.4 123.2s548.8-34.3 677.6-395c17.1-43.4 26.4-89.9 26.4-138.3z"
fill="#ffffff"
></path>
</g>
</svg>
Chat with AI
</>
)}
</button>
<div style={{...chatIframeContainer, display: isChatOpen ? "flex" : "none"}}>
<iframe
src="https://ai.casbin.com/?isRaw=1"
title="Chat with AI"
style={chatIframe}
></iframe>
</div>
</div>
);
}

export default ChatButton;
49 changes: 49 additions & 0 deletions src/ChatWidget/chatStyles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
export const chatButton = {
position: "fixed",
bottom: "20px",
right: "20px",
backgroundColor: "#403B79",
color: "white",
border: "none",
borderRadius: "50px",
padding: "10px 20px",
boxShadow: "0 2px 10px rgba(0, 0, 0, 0.1)",
cursor: "pointer",
zIndex: 1000,
display: "flex",
alignItems: "center",
fontWeight: "bold",
fontSize: "16px",
transition: "all 0.3s ease",
};

export const chatButtonOpen = {
borderRadius: "50%",
width: "50px",
height: "50px",
padding: 0,
justifyContent: "center",
};

export const closeIcon = {
fontSize: "50px",
fontWeight: "100",
lineHeight: 1,
};

export const chatIframeContainer = {
position: "fixed",
bottom: "80px",
right: "20px",
width: "min(500px, calc(100vw - 40px))",
height: "min(600px, calc(100vh - 100px))",
borderRadius: "10px",
zIndex: 1001,
flexDirection: "column",
overflow: "hidden",
};

export const chatIframe = {
width: "100%",
height: "100%",
};
13 changes: 13 additions & 0 deletions src/ChatWidget/chatWidget.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";
import ReactDOM from "react-dom";
import ChatButton from "./ChatButton";

export function initChatWidget(targetElement) {
if (typeof window !== "undefined" && targetElement) {
const chatContainer = document.createElement("div");
targetElement.appendChild(chatContainer);
ReactDOM.render(<ChatButton />, chatContainer);
}
}

export {ChatButton};
8 changes: 7 additions & 1 deletion src/components/HomepageFeatures/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React from "react";
import React, {useEffect} from "react";
import clsx from "clsx";
import styles from "./styles.module.css";
import Translate from "@docusaurus/Translate";
import {useColorMode} from "@docusaurus/theme-common";
import {initChatWidget} from "../../ChatWidget/chatWidget";

const FeatureList = [
{
Expand Down Expand Up @@ -69,6 +70,11 @@ function Feature({title, path, description}) {
}

export default function HomepageFeatures() {

useEffect(() => {
initChatWidget(document.body);
}, []);

return (
<section className={styles.features}>
<div className="container">
Expand Down

0 comments on commit 669be00

Please sign in to comment.