🔄 feat: chat direction (LTR-RTL) (#3260)

* feat: chat direction

* fix: FileRow

* feat: smooth trigger transition
This commit is contained in:
Marco Beretta 2024-07-17 16:08:13 +02:00 committed by GitHub
parent d5782ac66c
commit 237a0de8b6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 145 additions and 111 deletions

View file

@ -0,0 +1,32 @@
import { memo } from 'react';
import * as Tabs from '@radix-ui/react-tabs';
import { SettingsTabValues } from 'librechat-data-provider';
import SendMessageKeyEnter from './EnterToSend';
import ShowCodeSwitch from './ShowCodeSwitch';
import { ForkSettings } from './ForkSettings';
import ChatDirection from './ChatDirection';
import SaveDraft from './SaveDraft';
function Chat() {
return (
<Tabs.Content value={SettingsTabValues.CHAT} role="tabpanel" className="md: w-full">
<div className="flex flex-col gap-3 text-sm text-black dark:text-gray-50">
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-600">
<SendMessageKeyEnter />
</div>
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-600">
<ChatDirection />
</div>
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-600">
<ShowCodeSwitch />
</div>
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-600">
<SaveDraft />
</div>
<ForkSettings />
</div>
</Tabs.Content>
);
}
export default memo(Chat);

View file

@ -0,0 +1,31 @@
import React from 'react';
import { useRecoilState } from 'recoil';
import { useLocalize } from '~/hooks';
import store from '~/store';
const ChatDirection = () => {
const [direction, setDirection] = useRecoilState(store.chatDirection);
const localize = useLocalize();
const toggleChatDirection = () => {
setDirection((prev) => (prev === 'LTR' ? 'RTL' : 'LTR'));
};
return (
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<span>{localize('com_nav_chat_direction')}</span>
</div>
<label
onClick={toggleChatDirection}
data-testid="chatDirection"
className="btn btn-neutral relative"
style={{ userSelect: 'none' }}
>
{direction.toLowerCase()}
</label>
</div>
);
};
export default ChatDirection;

View file

@ -0,0 +1,37 @@
import { useRecoilState } from 'recoil';
import HoverCardSettings from '../HoverCardSettings';
import { Switch } from '~/components/ui/Switch';
import useLocalize from '~/hooks/useLocalize';
import store from '~/store';
export default function SendMessageKeyEnter({
onCheckedChange,
}: {
onCheckedChange?: (value: boolean) => void;
}) {
const [enterToSend, setEnterToSend] = useRecoilState<boolean>(store.enterToSend);
const localize = useLocalize();
const handleCheckedChange = (value: boolean) => {
setEnterToSend(value);
if (onCheckedChange) {
onCheckedChange(value);
}
};
return (
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<div>{localize('com_nav_enter_to_send')}</div>
<HoverCardSettings side="bottom" text="com_nav_info_enter_to_send" />
</div>
<Switch
id="enterToSend"
checked={enterToSend}
onCheckedChange={handleCheckedChange}
className="ml-4 mt-2"
data-testid="enterToSend"
/>
</div>
);
}

View file

@ -0,0 +1,67 @@
import { useRecoilState } from 'recoil';
import HoverCardSettings from '../HoverCardSettings';
import { ForkOptions } from 'librechat-data-provider';
import { Dropdown, Switch } from '~/components/ui';
import { useLocalize } from '~/hooks';
import store from '~/store';
export const ForkSettings = () => {
const localize = useLocalize();
const [forkSetting, setForkSetting] = useRecoilState(store.forkSetting);
const [splitAtTarget, setSplitAtTarget] = useRecoilState(store.splitAtTarget);
const [remember, setRemember] = useRecoilState<boolean>(store.rememberForkOption);
const forkOptions = [
{ value: ForkOptions.DIRECT_PATH, display: localize('com_ui_fork_visible') },
{ value: ForkOptions.INCLUDE_BRANCHES, display: localize('com_ui_fork_branches') },
{ value: ForkOptions.TARGET_LEVEL, display: localize('com_ui_fork_all_target') },
];
return (
<>
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-600">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<div>{localize('com_ui_fork_change_default')}</div>
<HoverCardSettings side="bottom" text="com_nav_info_fork_change_default" />
</div>
<Dropdown
value={forkSetting}
onChange={setForkSetting}
options={forkOptions}
sizeClasses="w-[200px]"
anchor="bottom start"
testId="fork-setting-dropdown"
/>
</div>
</div>
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-600">
<div className="flex items-center justify-between">
<div> {localize('com_ui_fork_default')} </div>
<Switch
id="rememberForkOption"
checked={remember}
onCheckedChange={setRemember}
className="ml-4 mt-2"
data-testid="rememberForkOption"
/>
</div>
</div>
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-600">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<div>{localize('com_ui_fork_split_target_setting')}</div>
<HoverCardSettings side="bottom" text="com_nav_info_fork_split_target_setting" />
</div>
<Switch
id="splitAtTarget"
checked={splitAtTarget}
onCheckedChange={setSplitAtTarget}
className="ml-4 mt-2"
data-testid="splitAtTarget"
/>
</div>
</div>
</>
);
};

View file

@ -0,0 +1,37 @@
import { useRecoilState } from 'recoil';
import HoverCardSettings from '../HoverCardSettings';
import { Switch } from '~/components/ui';
import useLocalize from '~/hooks/useLocalize';
import store from '~/store';
export default function SaveDraft({
onCheckedChange,
}: {
onCheckedChange?: (value: boolean) => void;
}) {
const [saveDrafts, setSaveDrafts] = useRecoilState<boolean>(store.saveDrafts);
const localize = useLocalize();
const handleCheckedChange = (value: boolean) => {
setSaveDrafts(value);
if (onCheckedChange) {
onCheckedChange(value);
}
};
return (
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<div>{localize('com_nav_save_drafts')}</div>
<HoverCardSettings side="bottom" text="com_nav_info_save_draft" />
</div>
<Switch
id="saveDrafts"
checked={saveDrafts}
onCheckedChange={handleCheckedChange}
className="ml-4 mt-2"
data-testid="saveDrafts"
/>
</div>
);
}

View file

@ -0,0 +1,34 @@
import { useRecoilState } from 'recoil';
import HoverCardSettings from '../HoverCardSettings';
import { Switch } from '~/components/ui';
import { useLocalize } from '~/hooks';
import store from '~/store';
export default function ShowCodeSwitch({
onCheckedChange,
}: {
onCheckedChange?: (value: boolean) => void;
}) {
const [showCode, setShowCode] = useRecoilState<boolean>(store.showCode);
const localize = useLocalize();
const handleCheckedChange = (value: boolean) => {
setShowCode(value);
if (onCheckedChange) {
onCheckedChange(value);
}
};
return (
<div className="flex items-center justify-between">
<div> {localize('com_nav_show_code')} </div>
<Switch
id="showCode"
checked={showCode}
onCheckedChange={handleCheckedChange}
className="ml-4 mt-2"
data-testid="showCode"
/>
</div>
);
}