diff --git a/app/components/chat-list.tsx b/app/components/chat-list.tsx index fb0f740c597..626336afd63 100644 --- a/app/components/chat-list.tsx +++ b/app/components/chat-list.tsx @@ -22,6 +22,7 @@ export function ChatItem(props: { selected: boolean; id: number; index: number; + narrow?: boolean; }) { return ( @@ -35,13 +36,20 @@ export function ChatItem(props: { {...provided.draggableProps} {...provided.dragHandleProps} > -
{props.title}
-
-
- {Locale.ChatItem.ChatItemCount(props.count)} -
-
{props.time}
-
+ {props.narrow ? ( +
{props.count}
+ ) : ( + <> +
{props.title}
+
+
+ {Locale.ChatItem.ChatItemCount(props.count)} +
+
{props.time}
+
+ + )} +
@@ -51,7 +59,7 @@ export function ChatItem(props: { ); } -export function ChatList() { +export function ChatList(props: { narrow?: boolean }) { const [sessions, selectedIndex, selectSession, removeSession, moveSession] = useChatStore((state) => [ state.sessions, @@ -101,7 +109,12 @@ export function ChatList() { navigate(Path.Chat); selectSession(i); }} - onDelete={() => chatStore.deleteSession(i)} + onDelete={() => { + if (!props.narrow || confirm(Locale.Home.DeleteChat)) { + chatStore.deleteSession(i); + } + }} + narrow={props.narrow} /> ))} {provided.placeholder} diff --git a/app/components/home.module.scss b/app/components/home.module.scss index 9bf0d571905..38e755bc57c 100644 --- a/app/components/home.module.scss +++ b/app/components/home.module.scss @@ -50,7 +50,7 @@ flex-direction: column; box-shadow: inset -2px 0px 2px 0px rgb(0, 0, 0, 0.05); position: relative; - transition: width ease 0.1s; + transition: width ease 0.05s; } .sidebar-drag { @@ -126,11 +126,13 @@ .sidebar-title { font-size: 20px; font-weight: bold; + animation: slide-in ease 0.3s; } .sidebar-sub-title { font-size: 12px; font-weight: 400px; + animation: slide-in ease 0.3s; } .sidebar-body { @@ -171,6 +173,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + animation: slide-in ease 0.3s; } .chat-item-delete { @@ -197,6 +200,7 @@ color: rgb(166, 166, 166); font-size: 12px; margin-top: 8px; + animation: slide-in ease 0.3s; } .chat-item-count, @@ -206,6 +210,69 @@ white-space: nowrap; } +.narrow-sidebar { + .sidebar-title, + .sidebar-sub-title { + display: none; + } + .sidebar-logo { + position: relative; + display: flex; + justify-content: center; + } + + .chat-item { + padding: 0; + min-height: 50px; + display: flex; + justify-content: center; + align-items: center; + transition: all ease 0.3s; + + &:hover { + .chat-item-narrow { + transform: scale(0.7) translateX(-50%); + } + } + } + + .chat-item-narrow { + font-weight: bolder; + font-size: 24px; + line-height: 0; + font-weight: lighter; + color: var(--black); + transform: translateX(0); + transition: all ease 0.3s; + opacity: 0.1; + padding: 4px; + } + + .chat-item-delete { + top: 15px; + } + + .chat-item:hover > .chat-item-delete { + opacity: 0.5; + right: 5px; + } + + .sidebar-tail { + flex-direction: column; + align-items: center; + + .sidebar-actions { + flex-direction: column; + align-items: center; + + .sidebar-action { + margin-right: 0; + margin-bottom: 15px; + } + } + } +} + .sidebar-tail { display: flex; justify-content: space-between; diff --git a/app/components/home.tsx b/app/components/home.tsx index 8b5e1d74dfc..123be03a955 100644 --- a/app/components/home.tsx +++ b/app/components/home.tsx @@ -41,7 +41,7 @@ const SideBar = dynamic(async () => (await import("./sidebar")).SideBar, { loading: () => , }); -function useSwitchTheme() { +export function useSwitchTheme() { const config = useChatStore((state) => state.config); useEffect(() => { @@ -83,7 +83,6 @@ const useHasHydrated = () => { }; function WideScreen() { - // setting const config = useChatStore((state) => state.config); return ( @@ -92,9 +91,7 @@ function WideScreen() { config.tightBorder ? styles["tight-container"] : styles.container }`} > -
- -
+
@@ -113,9 +110,7 @@ function MobileScreen() { return (
-
- -
+
@@ -129,8 +124,8 @@ function MobileScreen() { } export function Home() { - useSwitchTheme(); const isMobileScreen = useMobileScreen(); + useSwitchTheme(); if (!useHasHydrated()) { return ; diff --git a/app/components/sidebar.tsx b/app/components/sidebar.tsx index 338dec1931c..71e75f8ab43 100644 --- a/app/components/sidebar.tsx +++ b/app/components/sidebar.tsx @@ -12,14 +12,20 @@ import Locale from "../locales"; import { useChatStore } from "../store"; -import { Path, REPO_URL } from "../constant"; +import { + MAX_SIDEBAR_WIDTH, + MIN_SIDEBAR_WIDTH, + NARROW_SIDEBAR_WIDTH, + Path, + REPO_URL, +} from "../constant"; import { HashRouter as Router, Link, useNavigate } from "react-router-dom"; import { useMobileScreen } from "../utils"; import { ChatList } from "./chat-list"; function useDragSideBar() { - const limit = (x: number) => Math.min(500, Math.max(220, x)); + const limit = (x: number) => Math.min(MAX_SIDEBAR_WIDTH, x); const chatStore = useChatStore(); const startX = useRef(0); @@ -27,7 +33,7 @@ function useDragSideBar() { const lastUpdateTime = useRef(Date.now()); const handleMouseMove = useRef((e: MouseEvent) => { - if (Date.now() < lastUpdateTime.current + 100) { + if (Date.now() < lastUpdateTime.current + 50) { return; } lastUpdateTime.current = Date.now(); @@ -49,29 +55,36 @@ function useDragSideBar() { window.addEventListener("mouseup", handleMouseUp.current); }; const isMobileScreen = useMobileScreen(); + const shouldNarrow = + !isMobileScreen && chatStore.config.sidebarWidth < MIN_SIDEBAR_WIDTH; useEffect(() => { - const sideBarWidth = isMobileScreen - ? "100vw" - : `${limit(chatStore.config.sidebarWidth ?? 300)}px`; + const barWidth = shouldNarrow + ? NARROW_SIDEBAR_WIDTH + : limit(chatStore.config.sidebarWidth ?? 300); + const sideBarWidth = isMobileScreen ? "100vw" : `${barWidth}px`; document.documentElement.style.setProperty("--sidebar-width", sideBarWidth); - }, [chatStore.config.sidebarWidth, isMobileScreen]); + }, [chatStore.config.sidebarWidth, isMobileScreen, shouldNarrow]); return { onDragMouseDown, + shouldNarrow, }; } -export function SideBar(props: { setShowSideBar?: (_: boolean) => void }) { +export function SideBar(props: { className?: string }) { const chatStore = useChatStore(); // drag side bar - const { onDragMouseDown } = useDragSideBar(); + const { onDragMouseDown, shouldNarrow } = useDragSideBar(); const navigate = useNavigate(); - const isMobileScreen = useMobileScreen(); return ( - <> +
ChatGPT Next
@@ -88,10 +101,9 @@ export function SideBar(props: { setShowSideBar?: (_: boolean) => void }) { if (e.target === e.currentTarget) { navigate(Path.Home); } - props.setShowSideBar?.(false); }} > - +
@@ -116,10 +128,9 @@ export function SideBar(props: { setShowSideBar?: (_: boolean) => void }) {
} - text={Locale.Home.NewChat} + text={shouldNarrow ? undefined : Locale.Home.NewChat} onClick={() => { chatStore.newSession(); - props.setShowSideBar?.(false); }} shadow /> @@ -130,6 +141,6 @@ export function SideBar(props: { setShowSideBar?: (_: boolean) => void }) { className={styles["sidebar-drag"]} onMouseDown={(e) => onDragMouseDown(e as any)} >
- +
); } diff --git a/app/constant.ts b/app/constant.ts index 687445462b8..43ae4cc68f1 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -12,3 +12,7 @@ export enum Path { Chat = "/chat", Settings = "/settings", } + +export const MAX_SIDEBAR_WIDTH = 500; +export const MIN_SIDEBAR_WIDTH = 230; +export const NARROW_SIDEBAR_WIDTH = 100;