🪟 fix+feat: General UI Enhancements (#2619)

* feat: Minor design changes to mimic OpenAI's latest login page

* fix: Optimize ThemeSelector for mobile

* fix: Use a svg for the logo for transperency in dark mode

* feat: Update styles for Registration

* feat: Update error colors for login & registration

* fix: remove medium font

* wip: Dropdown menu

* feat: Update dropdown to match ChatGPT

* feat: Improve rounding and padding

* feat: Add UI Updates to RequestPasswordReset, PasswordRest and increase width for theme dropdown

* fix: Modify the My Files modal's width to not touch the screen

* feat: fix scrolling for dropdown, and make border width lighter

* feat: Match popup menu design to OpenAI (p1/2)

* fix+feat: fix dark mode, add user email, add lighter borders

* fix: Add border color on focus of chat input.

* feat: Move Export Conversation to a seperate button (testing)

* fix: Properly center Login, Registration, Reset Password Flow

* fix: Border colors on dark mode for settings modal

* feat: Improve wording for settings menu

* fix: Optimize settings modal for mobile and fix height for modal

* feat: Optimize for desktop

* fix: make TooltipTrigger asChild of button, improve settings mobile responsiveness

* feat: Handle dropdowns properly
TODO: Make height dynamic, fix dark mode colors

* fix: input styles
fix: make endpoint icon smaller

* feat: Update UI to Match ChatGPT Style

- Updated the dropdown styles to match the aesthetic of ChatGPT.
- Decreased spacing within the conversation area for cleanliness.
- Replaced the current archive icon with the ChatGPT's icon.

* fix: fix colors for EditMenuButton & ArchiveButton for dark mode and light mode

* fix: ui fixes

* fix: Fix Conversation UI Bugs

* fix: transparency of HoverToggle to make buttons not visible

* fix: dark mode HoverToggle & compress menu item spacing

* fix: responsiveness of export icon

* fix: first mentionitem is set to always be highlighted

* fix: improve hover state to text instead of bg

* feat: Update icons to ChatGPT Style

* fix: dark mode hover for PanelFileCell

* fix: change navlinks z-index to 100

* fix: hover states for DataTable

* feat: Move ExportButton to seperate component

* chore: remove unused imports
This commit is contained in:
Anirudh 2024-05-10 03:16:16 +05:30 committed by GitHub
parent d73ea8e1f2
commit 8f20fb28e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 716 additions and 469 deletions

View file

@ -0,0 +1,71 @@
import React from 'react';
import { useState } from 'react';
import { useLocation } from 'react-router-dom';
import type { TConversation } from 'librechat-data-provider';
import { Download } from 'lucide-react';
import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '~/components/ui';
import { useLocalize } from '~/hooks';
import { ExportModal } from '../Nav';
import { useRecoilValue } from 'recoil';
import store from '~/store';
function ExportButton() {
const localize = useLocalize();
const location = useLocation();
const [showExports, setShowExports] = useState(false);
const activeConvo = useRecoilValue(store.conversationByIndex(0));
const globalConvo = useRecoilValue(store.conversation) ?? ({} as TConversation);
let conversation: TConversation | null | undefined;
if (location.state?.from?.pathname.includes('/chat')) {
conversation = globalConvo;
} else {
conversation = activeConvo;
}
const clickHandler = () => {
if (exportable) {
setShowExports(true);
}
};
const exportable =
conversation &&
conversation.conversationId &&
conversation.conversationId !== 'new' &&
conversation.conversationId !== 'search';
return (
<>
{exportable && (
<div className="flex gap-1 gap-2 pr-1">
<TooltipProvider delayDuration={50}>
<Tooltip>
<TooltipTrigger asChild>
<button
className="btn btn-neutral btn-small relative flex h-9 w-9 items-center justify-center whitespace-nowrap rounded-lg"
onClick={clickHandler}
>
<div className="flex w-full items-center justify-center gap-2">
<Download size={16} />
</div>
</button>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={5}>
{localize('com_nav_export_conversation')}
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
)}
{showExports && (
<ExportModal open={showExports} onOpenChange={setShowExports} conversation={conversation} />
)}
</>
);
}
export default ExportButton;

View file

@ -5,6 +5,7 @@ import { useGetStartupConfig } from 'librechat-data-provider/react-query';
import type { ContextType } from '~/common';
import { EndpointsMenu, ModelSpecsMenu, PresetsMenu, HeaderNewChat } from './Menus';
import HeaderOptions from './Input/HeaderOptions';
import ExportButton from './ExportButton';
const defaultInterface = getConfigDefaults().interface;
@ -19,12 +20,15 @@ export default function Header() {
return (
<div className="sticky top-0 z-10 flex h-14 w-full items-center justify-between bg-white p-2 font-semibold dark:bg-gray-800 dark:text-white">
<div className="hide-scrollbar flex items-center gap-2 overflow-x-auto">
{!navVisible && <HeaderNewChat />}
{interfaceConfig.endpointsMenu && <EndpointsMenu />}
{modelSpecs?.length > 0 && <ModelSpecsMenu modelSpecs={modelSpecs} />}
{<HeaderOptions interfaceConfig={interfaceConfig} />}
{interfaceConfig.presets && <PresetsMenu />}
<div className="hide-scrollbar flex w-full items-center justify-between gap-2 overflow-x-auto">
<div className="flex items-center gap-2">
{!navVisible && <HeaderNewChat />}
{interfaceConfig.endpointsMenu && <EndpointsMenu />}
{modelSpecs?.length > 0 && <ModelSpecsMenu modelSpecs={modelSpecs} />}
{<HeaderOptions interfaceConfig={interfaceConfig} />}
{interfaceConfig.presets && <PresetsMenu />}
</div>
<ExportButton />
</div>
{/* Empty div for spacing */}
<div />

View file

@ -100,7 +100,7 @@ const ChatForm = ({ index = 0 }) => {
{showMentionPopover && (
<Mention setShowMentionPopover={setShowMentionPopover} textAreaRef={textAreaRef} />
)}
<div className="[&:has(textarea:focus)]:border-token-border-xheavy border-token-border-medium bg-token-main-surface-primary relative flex w-full flex-grow flex-col overflow-hidden rounded-2xl border dark:border-gray-600 dark:text-white [&:has(textarea:focus)]:shadow-[0_2px_6px_rgba(0,0,0,.05)] dark:[&:has(textarea:focus)]:border-gray-500">
<div className="bg-token-main-surface-primary relative flex w-full flex-grow flex-col overflow-hidden rounded-2xl border dark:border-gray-600 dark:text-white [&:has(textarea:focus)]:border-gray-300 [&:has(textarea:focus)]:shadow-[0_2px_6px_rgba(0,0,0,.05)] dark:[&:has(textarea:focus)]:border-gray-500">
<FileRow
files={files}
setFiles={setFiles}

View file

@ -27,7 +27,9 @@ export default function Files({ open, onOpenChange }) {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className={cn('overflow-x-auto shadow-2xl dark:bg-gray-700 dark:text-white')}>
<DialogContent
className={cn('w-11/12 overflow-x-auto shadow-2xl dark:bg-gray-700 dark:text-white')}
>
<DialogHeader>
<DialogTitle className="text-lg font-medium leading-6 text-gray-900 dark:text-gray-200">
{localize('com_nav_my_files')}

View file

@ -220,7 +220,7 @@ export default function DataTable<TData, TValue>({ columns, data }: DataTablePro
)}
</div>
<Button
className="dark:border-gray-500"
className="dark:border-gray-500 dark:hover:bg-gray-600"
variant="outline"
size="sm"
onClick={() => table.previousPage()}
@ -229,7 +229,7 @@ export default function DataTable<TData, TValue>({ columns, data }: DataTablePro
{localize('com_ui_prev')}
</Button>
<Button
className="dark:border-gray-500"
className="dark:border-gray-500 dark:hover:bg-gray-600"
variant="outline"
size="sm"
onClick={() => table.nextPage()}

View file

@ -22,7 +22,6 @@ export default function MentionItem({
<div
className={cn(
'hover:bg-token-main-surface-secondary text-token-text-primary bg-token-main-surface-secondary group flex h-10 items-center gap-2 rounded-lg px-2 text-sm font-medium dark:hover:bg-gray-600',
index === 0 ? 'dark:bg-gray-600' : '',
isActive ? 'dark:bg-gray-600' : '',
)}
>

View file

@ -66,7 +66,7 @@ export default function OptionsPopover({
{presetsDisabled ? null : (
<Button
type="button"
className="h-auto w-[150px] justify-start rounded-md border-2 border-gray-300/50 bg-transparent px-2 py-1 text-xs font-medium font-normal text-black hover:bg-gray-100 hover:text-black focus:ring-1 focus:ring-green-500/90 dark:border-gray-500/50 dark:bg-transparent dark:text-white dark:hover:bg-gray-600 dark:focus:ring-green-500"
className="h-auto w-[150px] justify-start rounded-md border border-gray-300/50 bg-transparent px-2 py-1 text-xs font-medium font-normal text-black hover:bg-gray-100 hover:text-black focus:ring-1 focus:ring-green-500/90 dark:border-gray-500/50 dark:bg-transparent dark:text-white dark:hover:bg-gray-600 dark:focus:ring-green-500"
onClick={saveAsPreset}
>
<Save className="mr-1 w-[14px]" />

View file

@ -44,12 +44,7 @@ export default function Landing({ Header }: { Header?: ReactNode }) {
<div className="relative h-full">
<div className="absolute left-0 right-0">{Header && Header}</div>
<div className="flex h-full flex-col items-center justify-center">
<div
className={cn(
'relative h-[72px] w-[72px]',
assistantName && avatar ? 'mb-0' : 'mb-3',
)}
>
<div className={cn('relative h-12 w-12', assistantName && avatar ? 'mb-0' : 'mb-3')}>
<ConvoIcon
conversation={conversation}
assistantMap={assistantMap}

View file

@ -118,7 +118,7 @@ const MenuItem: FC<MenuItemProps> = ({
'invisible flex gap-x-1 group-hover:visible',
selected ? 'visible' : '',
expiryTime
? 'w-full rounded-lg p-2 hover:bg-gray-200 dark:hover:bg-gray-600'
? 'w-full rounded-lg p-2 hover:text-gray-400 dark:hover:text-gray-400'
: '',
)}
onClick={(e) => {