diff --git a/client/src/components/Chat/Input/Mention.tsx b/client/src/components/Chat/Input/Mention.tsx index ba2821a7f0..516328af24 100644 --- a/client/src/components/Chat/Input/Mention.tsx +++ b/client/src/components/Chat/Input/Mention.tsx @@ -103,15 +103,18 @@ export default function Mention({ }; }, []); + const type = commandChar !== '@' ? 'add-convo' : 'mention'; useEffect(() => { - const currentActiveItem = document.getElementById(`mention-item-${activeIndex}`); + const currentActiveItem = document.getElementById(`${type}-item-${activeIndex}`); currentActiveItem?.scrollIntoView({ behavior: 'instant', block: 'nearest' }); - }, [activeIndex]); + }, [type, activeIndex]); return (
{(matches as MentionOption[]).map((mention, index) => ( { diff --git a/client/src/components/Chat/Input/MentionItem.tsx b/client/src/components/Chat/Input/MentionItem.tsx index 3cc4f19165..c15a51472c 100644 --- a/client/src/components/Chat/Input/MentionItem.tsx +++ b/client/src/components/Chat/Input/MentionItem.tsx @@ -9,37 +9,37 @@ export default function MentionItem({ icon, isActive, description, + type = 'mention', }: { name: string; onClick: () => void; index: number; + type?: 'prompt' | 'mention' | 'add-convo'; icon?: React.ReactNode; isActive?: boolean; description?: string; }) { return ( -
+ ); } diff --git a/client/src/components/Chat/Input/PromptsCommand.tsx b/client/src/components/Chat/Input/PromptsCommand.tsx index 75e106877e..1c03a93f99 100644 --- a/client/src/components/Chat/Input/PromptsCommand.tsx +++ b/client/src/components/Chat/Input/PromptsCommand.tsx @@ -60,7 +60,7 @@ function PromptsCommand({ label: `${group.command ? `/${group.command} - ` : ''}${group.name}: ${ group.oneliner?.length ? group.oneliner : group.productionPrompt?.prompt ?? '' }`, - icon: , + icon: , })); const promptsMap = mapPromptGroups(data); @@ -108,7 +108,7 @@ function PromptsCommand({ } const group = promptsMap[mention.id]; - const hasVariables = detectVariables(group?.productionPrompt?.prompt ?? ''); + const hasVariables = detectVariables(group.productionPrompt?.prompt ?? ''); if (group && hasVariables) { if (e && e.key === 'Tab') { e.preventDefault(); @@ -154,6 +154,8 @@ function PromptsCommand({
( { if (timeoutRef.current) { diff --git a/client/src/hooks/Messages/useMessageScrolling.ts b/client/src/hooks/Messages/useMessageScrolling.ts index 0b79c40ebb..ddb071ff86 100644 --- a/client/src/hooks/Messages/useMessageScrolling.ts +++ b/client/src/hooks/Messages/useMessageScrolling.ts @@ -6,8 +6,8 @@ import useScrollToRef from '~/hooks/useScrollToRef'; import { useChatContext } from '~/Providers'; import store from '~/store'; -const threshold = 0.14; -const debounceRate = 250; +const threshold = 0.85; +const debounceRate = 150; export default function useMessageScrolling(messagesTree?: TMessage[] | null) { const autoScroll = useRecoilValue(store.autoScroll); diff --git a/client/src/hooks/ThemeContext.tsx b/client/src/hooks/ThemeContext.tsx index 8cbff7293e..df516eec4f 100644 --- a/client/src/hooks/ThemeContext.tsx +++ b/client/src/hooks/ThemeContext.tsx @@ -1,8 +1,9 @@ //ThemeContext.js // source: https://plainenglish.io/blog/light-and-dark-mode-in-react-web-application-with-tailwind-css-89674496b942 - +import { useSetRecoilState } from 'recoil'; import React, { createContext, useState, useEffect } from 'react'; import { getInitialTheme, applyFontSize } from '~/utils'; +import store from '~/store'; type ProviderValue = { theme: string; @@ -27,6 +28,7 @@ export const ThemeContext = createContext(defaultContextValue); export const ThemeProvider = ({ initialTheme, children }) => { const [theme, setTheme] = useState(getInitialTheme); + const setFontSize = useSetRecoilState(store.fontSize); const rawSetTheme = (rawTheme: string) => { const root = window.document.documentElement; @@ -54,9 +56,14 @@ export const ThemeProvider = ({ initialTheme, children }) => { useEffect(() => { const fontSize = localStorage.getItem('fontSize'); if (fontSize == null) { + setFontSize('text-base'); + applyFontSize('text-base'); + localStorage.setItem('fontSize', 'text-base'); return; } applyFontSize(JSON.parse(fontSize)); + // Reason: This effect should only run once, and `setFontSize` is a stable function + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); if (initialTheme) { diff --git a/client/src/style.css b/client/src/style.css index 0dd6f6cd45..43f86e9ef8 100644 --- a/client/src/style.css +++ b/client/src/style.css @@ -32,6 +32,7 @@ html { --text-secondary:var(--gray-600); --text-secondary-alt:var(--gray-500); --text-tertiary:var(--gray-500); + --surface-active:var(--gray-100); --surface-primary:var(--white); --surface-primary-alt:var(--white); --surface-primary-contrast:var(--gray-100); @@ -49,6 +50,7 @@ html { --text-secondary:var(--gray-300); --text-secondary-alt:var(--gray-400); --text-tertiary:var(--gray-500); + --surface-active:var(--gray-600); --surface-primary:var(--gray-900); --surface-primary-alt:var(--gray-850); --surface-primary-contrast:var(--gray-850); diff --git a/client/tailwind.config.cjs b/client/tailwind.config.cjs index 41770be8f7..4b1b9a47b5 100644 --- a/client/tailwind.config.cjs +++ b/client/tailwind.config.cjs @@ -68,6 +68,7 @@ module.exports = { 'text-secondary': 'var(--text-secondary)', 'text-secondary-alt': 'var(--text-secondary-alt)', 'text-tertiary': 'var(--text-tertiary)', + 'surface-active': 'var(--surface-active)', 'surface-primary': 'var(--surface-primary)', 'surface-primary-alt': 'var(--surface-primary-alt)', 'surface-primary-contrast': 'var(--surface-primary-contrast)',