Icon Button Tooltips (#1451)

- add tooltips to footer buttons to clear ambiguity on what they might mean
- Updated Generic OpenAI connector to not have a ton of inputs in one row
This commit is contained in:
Timothy Carambat 2024-05-18 21:29:23 -07:00 committed by GitHub
parent 9ace0e67e6
commit 396e04b0cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 183 additions and 130 deletions

2
frontend/.gitignore vendored
View File

@ -9,10 +9,8 @@ lerna-debug.log*
node_modules node_modules
dist dist
lib
dist-ssr dist-ssr
*.local *.local
!frontend/components/lib
# Editor directories and files # Editor directories and files
.vscode/* .vscode/*

View File

@ -14,6 +14,8 @@ import {
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import SettingsButton from "../SettingsButton"; import SettingsButton from "../SettingsButton";
import { isMobile } from "react-device-detect"; import { isMobile } from "react-device-detect";
import { Tooltip } from "react-tooltip";
import { v4 } from "uuid";
export const MAX_ICONS = 3; export const MAX_ICONS = 3;
export const ICON_COMPONENTS = { export const ICON_COMPONENTS = {
@ -47,36 +49,48 @@ export default function Footer() {
return ( return (
<div className="flex justify-center mb-2"> <div className="flex justify-center mb-2">
<div className="flex space-x-4"> <div className="flex space-x-4">
<a <ToolTipWrapper id="open-github">
href={paths.github()} <a
target="_blank" href={paths.github()}
rel="noreferrer" target="_blank"
className="transition-all duration-300 p-2 rounded-full text-white bg-sidebar-button hover:bg-menu-item-selected-gradient hover:border-slate-100 hover:border-opacity-50 border-transparent border" rel="noreferrer"
aria-label="Find us on Github" className="transition-all duration-300 p-2 rounded-full text-white bg-sidebar-button hover:bg-menu-item-selected-gradient hover:border-slate-100 hover:border-opacity-50 border-transparent border"
> aria-label="Find us on Github"
<GithubLogo weight="fill" className="h-5 w-5 " /> data-tooltip-id="open-github"
</a> data-tooltip-content="View source code on Github"
<a >
href={paths.docs()} <GithubLogo weight="fill" className="h-5 w-5 " />
target="_blank" </a>
rel="noreferrer" </ToolTipWrapper>
className="transition-all duration-300 p-2 rounded-full text-white bg-sidebar-button hover:bg-menu-item-selected-gradient hover:border-slate-100 hover:border-opacity-50 border-transparent border" <ToolTipWrapper id="open-documentation">
aria-label="Docs" <a
> href={paths.docs()}
<BookOpen weight="fill" className="h-5 w-5 " /> target="_blank"
</a> rel="noreferrer"
<a className="w-fit transition-all duration-300 p-2 rounded-full text-white bg-sidebar-button hover:bg-menu-item-selected-gradient hover:border-slate-100 hover:border-opacity-50 border-transparent border"
href={paths.discord()} aria-label="Docs"
target="_blank" data-tooltip-id="open-documentation"
rel="noreferrer" data-tooltip-content="Open AnythingLLM help docs"
className="transition-all duration-300 p-2 rounded-full text-white bg-sidebar-button hover:bg-menu-item-selected-gradient hover:border-slate-100 hover:border-opacity-50 border-transparent border" >
aria-label="Join our Discord server" <BookOpen weight="fill" className="h-5 w-5 " />
> </a>
<DiscordLogo </ToolTipWrapper>
weight="fill" <ToolTipWrapper id="open-discord">
className="h-5 w-5 stroke-slate-200 group-hover:stroke-slate-200" <a
/> href={paths.discord()}
</a> target="_blank"
rel="noreferrer"
className="transition-all duration-300 p-2 rounded-full text-white bg-sidebar-button hover:bg-menu-item-selected-gradient hover:border-slate-100 hover:border-opacity-50 border-transparent border"
aria-label="Join our Discord server"
data-tooltip-id="open-discord"
data-tooltip-content="Join the AnythingLLM Discord"
>
<DiscordLogo
weight="fill"
className="h-5 w-5 stroke-slate-200 group-hover:stroke-slate-200"
/>
</a>
</ToolTipWrapper>
{!isMobile && <SettingsButton />} {!isMobile && <SettingsButton />}
</div> </div>
</div> </div>
@ -105,3 +119,17 @@ export default function Footer() {
</div> </div>
); );
} }
export function ToolTipWrapper({ id = v4(), children }) {
return (
<div className="flex w-fit">
{children}
<Tooltip
id={id}
place="top"
delayShow={300}
className="tooltip !text-xs z-99"
/>
</div>
);
}

View File

@ -1,80 +1,84 @@
export default function GenericOpenAiOptions({ settings }) { export default function GenericOpenAiOptions({ settings }) {
return ( return (
<div className="flex gap-4 flex-wrap"> <div className="flex flex-col gap-y-4">
<div className="flex flex-col w-60"> <div className="flex gap-4 flex-wrap">
<label className="text-white text-sm font-semibold block mb-4"> <div className="flex flex-col w-60">
Base URL <label className="text-white text-sm font-semibold block mb-4">
</label> Base URL
<input </label>
type="url" <input
name="GenericOpenAiBasePath" type="url"
className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5" name="GenericOpenAiBasePath"
placeholder="eg: https://proxy.openai.com" className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5"
defaultValue={settings?.GenericOpenAiBasePath} placeholder="eg: https://proxy.openai.com"
required={true} defaultValue={settings?.GenericOpenAiBasePath}
autoComplete="off" required={true}
spellCheck={false} autoComplete="off"
/> spellCheck={false}
/>
</div>
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-4">
API Key
</label>
<input
type="password"
name="GenericOpenAiKey"
className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5"
placeholder="Generic service API Key"
defaultValue={settings?.GenericOpenAiKey ? "*".repeat(20) : ""}
required={false}
autoComplete="off"
spellCheck={false}
/>
</div>
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-4">
Chat Model Name
</label>
<input
type="text"
name="GenericOpenAiModelPref"
className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5"
placeholder="Model id used for chat requests"
defaultValue={settings?.GenericOpenAiModelPref}
required={true}
autoComplete="off"
/>
</div>
</div> </div>
<div className="flex flex-col w-60"> <div className="flex gap-x-4 flex-wrap">
<label className="text-white text-sm font-semibold block mb-4"> <div className="flex flex-col w-60">
API Key <label className="text-white text-sm font-semibold block mb-4">
</label> Token context window
<input </label>
type="password" <input
name="GenericOpenAiKey" type="number"
className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5" name="GenericOpenAiTokenLimit"
placeholder="Generic service API Key" className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5"
defaultValue={settings?.GenericOpenAiKey ? "*".repeat(20) : ""} placeholder="Content window limit (eg: 4096)"
required={false} min={1}
autoComplete="off" onScroll={(e) => e.target.blur()}
spellCheck={false} defaultValue={settings?.GenericOpenAiTokenLimit}
/> required={true}
</div> autoComplete="off"
<div className="flex flex-col w-60"> />
<label className="text-white text-sm font-semibold block mb-4"> </div>
Chat Model Name <div className="flex flex-col w-60">
</label> <label className="text-white text-sm font-semibold block mb-4">
<input Max Tokens
type="text" </label>
name="GenericOpenAiModelPref" <input
className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5" type="number"
placeholder="Model id used for chat requests" name="GenericOpenAiMaxTokens"
defaultValue={settings?.GenericOpenAiModelPref} className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5"
required={true} placeholder="Max tokens per request (eg: 1024)"
autoComplete="off" min={1}
/> defaultValue={settings?.GenericOpenAiMaxTokens || 1024}
</div> required={true}
<div className="flex flex-col w-60"> autoComplete="off"
<label className="text-white text-sm font-semibold block mb-4"> />
Token context window </div>
</label>
<input
type="number"
name="GenericOpenAiTokenLimit"
className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5"
placeholder="Content window limit (eg: 4096)"
min={1}
onScroll={(e) => e.target.blur()}
defaultValue={settings?.GenericOpenAiTokenLimit}
required={true}
autoComplete="off"
/>
</div>
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-4">
Max Tokens
</label>
<input
type="number"
name="GenericOpenAiMaxTokens"
className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5"
placeholder="Max tokens per request (eg: 1024)"
min={1}
defaultValue={settings?.GenericOpenAiMaxTokens || 1024}
required={true}
autoComplete="off"
/>
</div> </div>
</div> </div>
); );

View File

@ -3,6 +3,7 @@ import paths from "@/utils/paths";
import { ArrowUUpLeft, Wrench } from "@phosphor-icons/react"; import { ArrowUUpLeft, Wrench } from "@phosphor-icons/react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useMatch } from "react-router-dom"; import { useMatch } from "react-router-dom";
import { ToolTipWrapper } from "../Footer";
export default function SettingsButton() { export default function SettingsButton() {
const isInSettings = !!useMatch("/settings/*"); const isInSettings = !!useMatch("/settings/*");
@ -12,22 +13,32 @@ export default function SettingsButton() {
if (isInSettings) if (isInSettings)
return ( return (
<Link <ToolTipWrapper id="go-home">
to={paths.home()} <Link
className="transition-all duration-300 p-2 rounded-full text-white bg-sidebar-button hover:bg-menu-item-selected-gradient hover:border-slate-100 hover:border-opacity-50 border-transparent border" to={paths.home()}
aria-label="Home" className="transition-all duration-300 p-2 rounded-full text-white bg-sidebar-button hover:bg-menu-item-selected-gradient hover:border-slate-100 hover:border-opacity-50 border-transparent border"
> aria-label="Home"
<ArrowUUpLeft className="h-5 w-5" weight="fill" /> data-tooltip-id="go-home"
</Link> data-tooltip-content="Back to workspaces"
>
<ArrowUUpLeft className="h-5 w-5" weight="fill" />
</Link>
</ToolTipWrapper>
); );
return ( return (
<Link <ToolTipWrapper id="open-settings">
to={!!user?.role ? paths.settings.system() : paths.settings.appearance()} <Link
className="transition-all duration-300 p-2 rounded-full text-white bg-sidebar-button hover:bg-menu-item-selected-gradient hover:border-slate-100 hover:border-opacity-50 border-transparent border" to={
aria-label="Settings" !!user?.role ? paths.settings.system() : paths.settings.appearance()
> }
<Wrench className="h-5 w-5" weight="fill" /> className="transition-all duration-300 p-2 rounded-full text-white bg-sidebar-button hover:bg-menu-item-selected-gradient hover:border-slate-100 hover:border-opacity-50 border-transparent border"
</Link> aria-label="Settings"
data-tooltip-id="open-settings"
data-tooltip-content="Open settings"
>
<Wrench className="h-5 w-5" weight="fill" />
</Link>
</ToolTipWrapper>
); );
} }

View File

@ -329,7 +329,7 @@ const SidebarOptions = ({ user = null }) => (
<Option <Option
href={paths.settings.embedSetup()} href={paths.settings.embedSetup()}
childLinks={[paths.settings.embedChats()]} childLinks={[paths.settings.embedChats()]}
btnText="Embedded Chat" btnText="Chat Embed Widgets"
icon={<CodeBlock className="h-5 w-5 flex-shrink-0" />} icon={<CodeBlock className="h-5 w-5 flex-shrink-0" />}
user={user} user={user}
flex={true} flex={true}
@ -338,7 +338,7 @@ const SidebarOptions = ({ user = null }) => (
<> <>
<Option <Option
href={paths.settings.embedChats()} href={paths.settings.embedChats()}
btnText="Embedded Chat History" btnText="Chat Embed History"
icon={<Barcode className="h-5 w-5 flex-shrink-0" />} icon={<Barcode className="h-5 w-5 flex-shrink-0" />}
user={user} user={user}
flex={true} flex={true}

View File

@ -12,6 +12,7 @@ import AvailableAgentsButton, {
} from "./AgentMenu"; } from "./AgentMenu";
import TextSizeButton from "./TextSizeMenu"; import TextSizeButton from "./TextSizeMenu";
import SpeechToText from "./SpeechToText"; import SpeechToText from "./SpeechToText";
import { Tooltip } from "react-tooltip";
export const PROMPT_INPUT_EVENT = "set_prompt_input"; export const PROMPT_INPUT_EVENT = "set_prompt_input";
export default function PromptInput({ export default function PromptInput({
@ -134,14 +135,25 @@ export default function PromptInput({
{buttonDisabled ? ( {buttonDisabled ? (
<StopGenerationButton /> <StopGenerationButton />
) : ( ) : (
<button <>
ref={formRef} <button
type="submit" ref={formRef}
className="inline-flex justify-center rounded-2xl cursor-pointer text-white/60 hover:text-white group ml-4" type="submit"
> className="inline-flex justify-center rounded-2xl cursor-pointer text-white/60 hover:text-white group ml-4"
<PaperPlaneRight className="w-7 h-7 my-3" weight="fill" /> data-tooltip-id="send-prompt"
<span className="sr-only">Send message</span> data-tooltip-content="Send prompt message to workspace"
</button> aria-label="Send prompt message to workspace"
>
<PaperPlaneRight className="w-7 h-7 my-3" weight="fill" />
<span className="sr-only">Send message</span>
</button>
<Tooltip
id="send-prompt"
place="bottom"
delayShow={300}
className="tooltip !text-xs z-99"
/>
</>
)} )}
</div> </div>
<div className="flex justify-between py-3.5"> <div className="flex justify-between py-3.5">