mirror of
https://github.com/Mintplex-Labs/anything-llm.git
synced 2024-11-15 02:50:10 +01:00
Add more styling options
Add sponsor text at bottom Support dynamic container height Loading animations
This commit is contained in:
parent
d1664f3042
commit
a727235195
@ -66,9 +66,18 @@ REQUIRED data attributes:
|
||||
|
||||
- `data-greeting` — Default text message to be shown when chat is opened and no previous message history is found.
|
||||
|
||||
- `data-no-sponsor` — Setting this attribute to anything will hide the custom or default sponsor at the bottom of an open chat window.
|
||||
|
||||
- `data-sponsor-link` — A clickable link in the sponsor section in the footer of an open chat window.
|
||||
|
||||
- `data-sponsor-text` — The text displays in sponsor text in the footer of an open chat window.
|
||||
|
||||
|
||||
**Behavior Overrides**
|
||||
- `data-open-on-load` — Once loaded, open the chat as default. It can still be closed by the user.
|
||||
|
||||
- `data-support-email` — Shows a support email that the user can used to draft an email via the "three dot" menu in the top right. Option will not appear if it is not set.
|
||||
|
||||
|
||||
### `<iframe>` tag HTML embed
|
||||
_work in progress_
|
||||
|
@ -27,9 +27,9 @@ export default function App() {
|
||||
width: isChatOpen ? 320 : "auto",
|
||||
height: isChatOpen ? "93vh" : "auto",
|
||||
}}
|
||||
className={`transition-all duration-300 ease-in-out ${
|
||||
className={`${
|
||||
isChatOpen
|
||||
? "max-w-md p-4 bg-white rounded-lg border shadow-lg w-72"
|
||||
? "max-w-md px-4 py-2 bg-white rounded-lg border shadow-lg w-72"
|
||||
: "w-16 h-16 rounded-full"
|
||||
}`}
|
||||
>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import HistoricalMessage from "./HistoricalMessage";
|
||||
import PromptReply from "./PromptReply";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { ArrowDown } from "@phosphor-icons/react";
|
||||
import { ArrowDown, CircleNotch } from "@phosphor-icons/react";
|
||||
import debounce from "lodash.debounce";
|
||||
|
||||
export default function ChatHistory({ settings = {}, history = [] }) {
|
||||
@ -46,10 +46,7 @@ export default function ChatHistory({ settings = {}, history = [] }) {
|
||||
|
||||
if (history.length === 0) {
|
||||
return (
|
||||
<div
|
||||
style={{ height: "85vh", paddingBottom: 100, paddingTop: 5 }}
|
||||
className="bg-gray-100 rounded-lg px-2 h-full mt-2 gap-y-2 overflow-y-scroll flex flex-col justify-start no-scroll"
|
||||
>
|
||||
<div className="h-full max-h-[82vh] pb-[100px] pt-[5px] bg-gray-100 rounded-lg px-2 h-full mt-2 gap-y-2 overflow-y-scroll flex flex-col justify-start no-scroll">
|
||||
<div className="flex h-full flex-col items-center justify-center">
|
||||
<p className="text-slate-400 text-sm font-base py-4 text-center">
|
||||
{settings?.greeting ?? "Send a chat to get started!"}
|
||||
@ -61,8 +58,7 @@ export default function ChatHistory({ settings = {}, history = [] }) {
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{ height: "85vh", paddingBottom: 100, paddingTop: 5 }}
|
||||
className="bg-gray-100 rounded-lg px-2 h-full mt-2 gap-y-2 overflow-y-scroll flex flex-col justify-start no-scroll"
|
||||
className="h-full max-h-[82vh] pb-[100px] pt-[5px] bg-gray-100 rounded-lg px-2 h-full mt-2 gap-y-2 overflow-y-scroll flex flex-col justify-start no-scroll"
|
||||
id="chat-history"
|
||||
ref={chatHistoryRef}
|
||||
>
|
||||
@ -98,7 +94,7 @@ export default function ChatHistory({ settings = {}, history = [] }) {
|
||||
);
|
||||
})}
|
||||
{!isAtBottom && (
|
||||
<div className="fixed bottom-[8rem] right-[3rem] z-50 cursor-pointer animate-pulse">
|
||||
<div className="fixed bottom-[10rem] right-[3rem] z-50 cursor-pointer animate-pulse">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="p-1 rounded-full border border-white/10 bg-white/10 hover:bg-white/20 hover:text-white">
|
||||
<ArrowDown
|
||||
@ -113,3 +109,15 @@ export default function ChatHistory({ settings = {}, history = [] }) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ChatHistoryLoading() {
|
||||
return (
|
||||
<div className="h-full w-full relative">
|
||||
<div className="h-full max-h-[82vh] pb-[100px] pt-[5px] bg-gray-100 rounded-lg px-2 h-full mt-2 gap-y-2 overflow-y-scroll flex flex-col justify-start no-scroll">
|
||||
<div className="flex h-full flex-col items-center justify-center">
|
||||
<CircleNotch size={14} className="text-slate-400 animate-spin" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -33,15 +33,12 @@ export default function PromptInput({
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{ bottom: 25 }}
|
||||
className="w-full fixed md:absolute left-0 z-10 flex justify-center items-center"
|
||||
>
|
||||
<div className="w-full absolute left-0 bottom-[5px] z-10 flex justify-center items-center">
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className="flex flex-col gap-y-1 rounded-t-lg md:w-3/4 w-full mx-auto max-w-xl"
|
||||
className="flex flex-col gap-y-1 rounded-t-lg w-full items-center justify-center"
|
||||
>
|
||||
<div className="flex items-center rounded-lg md:mb-4">
|
||||
<div className="flex items-center rounded-lg">
|
||||
<div className="bg-white border border-white/50 rounded-2xl flex flex-col px-4 overflow-hidden">
|
||||
<div className="flex items-center w-full">
|
||||
<textarea
|
||||
|
@ -76,7 +76,7 @@ export default function ChatContainer({
|
||||
}, [loadingResponse, chatHistory]);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="h-full w-full relative">
|
||||
<ChatHistory settings={settings} history={chatHistory} />
|
||||
<PromptInput
|
||||
settings={settings}
|
||||
@ -86,6 +86,6 @@ export default function ChatContainer({
|
||||
inputDisabled={loadingResponse}
|
||||
buttonDisabled={loadingResponse}
|
||||
/>
|
||||
</React.Fragment>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,11 @@
|
||||
import AnythingLLMLogo from "@/assets/anything-llm-dark.png";
|
||||
import ChatService from "@/models/chatService";
|
||||
import { DotsThreeOutlineVertical, Lightning, X } from "@phosphor-icons/react";
|
||||
import {
|
||||
DotsThreeOutlineVertical,
|
||||
Envelope,
|
||||
Lightning,
|
||||
X,
|
||||
} from "@phosphor-icons/react";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function ChatWindowHeader({
|
||||
@ -46,15 +51,19 @@ export default function ChatWindowHeader({
|
||||
<X size={18} />
|
||||
</button>
|
||||
</div>
|
||||
<OptionsMenu showing={showingOptions} resetChat={handleChatReset} />
|
||||
<OptionsMenu
|
||||
settings={settings}
|
||||
showing={showingOptions}
|
||||
resetChat={handleChatReset}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function OptionsMenu({ showing, resetChat }) {
|
||||
function OptionsMenu({ settings, showing, resetChat }) {
|
||||
if (!showing) return null;
|
||||
return (
|
||||
<div className="absolute bg-white flex flex-col gap-y-2 rounded-lg shadow-lg border border-gray-300 top-[3vh] right-[1vw] max-w-[150px]">
|
||||
<div className="absolute z-10 bg-white flex flex-col gap-y-1 rounded-lg shadow-lg border border-gray-300 top-[23px] right-[20px] max-w-[150px]">
|
||||
<button
|
||||
onClick={resetChat}
|
||||
className="flex items-center gap-x-1 hover:bg-gray-100 text-sm text-gray-700 p-2 rounded-lg"
|
||||
@ -62,6 +71,22 @@ function OptionsMenu({ showing, resetChat }) {
|
||||
<Lightning size={14} />
|
||||
<p>Reset Chat</p>
|
||||
</button>
|
||||
<ContactSupport email={settings.supportEmail} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ContactSupport({ email = null }) {
|
||||
if (!email) return null;
|
||||
|
||||
const subject = `Inquiry from ${window.location.origin}`;
|
||||
return (
|
||||
<a
|
||||
href={`mailto:${email}?Subject=${encodeURIComponent(subject)}`}
|
||||
className="flex items-center gap-x-1 hover:bg-gray-100 text-sm text-gray-700 p-2 rounded-lg"
|
||||
>
|
||||
<Envelope size={14} />
|
||||
<p>Email support</p>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ import ChatWindowHeader from "./Header";
|
||||
import SessionId from "../SessionId";
|
||||
import useChatHistory from "@/hooks/chat/useChatHistory";
|
||||
import ChatContainer from "./ChatContainer";
|
||||
import Sponsor from "../Sponsor";
|
||||
import { ChatHistoryLoading } from "./ChatContainer/ChatHistory";
|
||||
|
||||
export default function ChatWindow({ closeChat, settings, sessionId }) {
|
||||
const { chatHistory, setChatHistory, loading } = useChatHistory(
|
||||
@ -9,10 +11,28 @@ export default function ChatWindow({ closeChat, settings, sessionId }) {
|
||||
sessionId
|
||||
);
|
||||
|
||||
if (loading) return null;
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<ChatWindowHeader
|
||||
sessionId={sessionId}
|
||||
settings={settings}
|
||||
iconUrl={settings.brandImageUrl}
|
||||
closeChat={closeChat}
|
||||
setChatHistory={setChatHistory}
|
||||
/>
|
||||
<ChatHistoryLoading />
|
||||
<div className="pt-4 pb-2 h-fit gap-y-1">
|
||||
<SessionId />
|
||||
<Sponsor settings={settings} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
setEventDelegatorForCodeSnippets();
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-col h-full">
|
||||
<ChatWindowHeader
|
||||
sessionId={sessionId}
|
||||
settings={settings}
|
||||
@ -25,7 +45,10 @@ export default function ChatWindow({ closeChat, settings, sessionId }) {
|
||||
settings={settings}
|
||||
knownHistory={chatHistory}
|
||||
/>
|
||||
<SessionId />
|
||||
<div className="pt-4 pb-2 h-fit gap-y-1">
|
||||
<SessionId />
|
||||
<Sponsor settings={settings} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
16
embed/src/components/Sponsor/index.jsx
Normal file
16
embed/src/components/Sponsor/index.jsx
Normal file
@ -0,0 +1,16 @@
|
||||
export default function Sponsor({ settings }) {
|
||||
if (!!settings.noSponsor) return null;
|
||||
|
||||
return (
|
||||
<div className="flex w-full items-center justify-center">
|
||||
<a
|
||||
href={settings.sponsorLink ?? "#"}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="text-xs text-gray-300 hover:text-blue-300 hover:underline"
|
||||
>
|
||||
{settings.sponsorText}
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -17,9 +17,13 @@ const DEFAULT_SETTINGS = {
|
||||
buttonColor: "#262626", // must be hex color code
|
||||
userBgColor: "#2C2F35", // user text bubble color
|
||||
assistantBgColor: "#2563eb", // assistant text bubble color
|
||||
noSponsor: null, // Shows sponsor in footer of chat
|
||||
sponsorText: "Powered by AnythingLLM", // default sponsor text
|
||||
sponsorLink: "https://useanything.com", // default sponsor link
|
||||
|
||||
// behaviors
|
||||
openOnLoad: "off", // or "on"
|
||||
supportEmail: null, // string of email for contact
|
||||
};
|
||||
|
||||
export default function useGetScriptAttributes() {
|
||||
|
Loading…
Reference in New Issue
Block a user