Skip to content

Commit c43a8f8

Browse files
committed
feat(web): display ops button on mouse hover
1 parent 007c966 commit c43a8f8

File tree

4 files changed

+82
-67
lines changed

4 files changed

+82
-67
lines changed

web/src/routes/root/ChatTab/index.jsx

Lines changed: 53 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import styles from "./index.module.css";
22

33
import { useContext, useEffect, useState, useRef } from "react";
4+
import { NavLink } from "react-router-dom";
45
import PropTypes from "prop-types";
56
import Tooltip from "@mui/material/Tooltip";
67
import Icon from "@mui/material/Icon";
@@ -19,10 +20,9 @@ import { ConversationContext } from "@/contexts/conversation";
1920
* @param {Object} chat
2021
* @param {string} chat.id
2122
* @param {string} chat.title
22-
* @param {boolean} isActive whether this chat is active
2323
* @returns
2424
*/
25-
const ChatTab = ({ chat, isActive, onShareClick, onDeleteClick }) => {
25+
const ChatTab = ({ chat, onShareClick, onDeleteClick }) => {
2626
const { dispatch } = useContext(ConversationContext);
2727
const titleRef = useRef(null);
2828
const [titleEditable, setTitleEditable] = useState("false");
@@ -34,7 +34,7 @@ const ChatTab = ({ chat, isActive, onShareClick, onDeleteClick }) => {
3434
}, [titleEditable]);
3535

3636
const handleKeyDown = async (e) => {
37-
// TODO: this will trigger in Chinese IME on OSX
37+
// TODO: this will trigger in Chinese IME on OSX
3838
if (e.key === "Enter") {
3939
e.preventDefault();
4040
await renameChat(titleRef.current.innerText);
@@ -96,7 +96,11 @@ const ChatTab = ({ chat, isActive, onShareClick, onDeleteClick }) => {
9696
};
9797

9898
return (
99-
<>
99+
<NavLink
100+
to={`conversations/${chat.id}`}
101+
className={({ isActive, isPending }) =>
102+
`${styles.sidebarButton} ${isActive ? styles.active : isPending ? styles.pending : ""}`}
103+
>
100104
<Tooltip title={titleRef.current?.innerText}>
101105
{/* contentEditable moves control out of react, so useState won't work correctly.
102106
* I use ref to get the value instead.
@@ -113,53 +117,51 @@ const ChatTab = ({ chat, isActive, onShareClick, onDeleteClick }) => {
113117
{chat.title}
114118
</span>
115119
</Tooltip>
116-
{isActive && (
117-
<Dropdown className={styles.chatOpMenu}>
118-
<DropdownButton className={styles.chatOpMenuIcon}>
119-
<MoreVertIcon />
120-
</DropdownButton>
121-
<DropdownMenu className={styles.chatOpMenuList}>
122-
<li>
123-
<button className={styles.chatOpMenuItem} onClick={flipPin}>
124-
{chat.pinned ?
125-
<>
126-
<Icon baseClassName="material-symbols-outlined">keep_off</Icon>
127-
<span className={styles.chatOpMenuItemText}>Unpin</span>
128-
</> : <>
129-
<Icon baseClassName="material-symbols-outlined">keep</Icon>
130-
<span className={styles.chatOpMenuItemText}>Pin</span>
131-
</>
132-
}
133-
</button>
134-
</li>
135-
<li>
136-
<button className={styles.chatOpMenuItem} onClick={onSummarizeClick}>
137-
<AutoAwesomeIcon />
138-
<span className={styles.chatOpMenuItemText}>Generate title</span>
139-
</button>
140-
</li>
141-
<li>
142-
<button className={styles.chatOpMenuItem} onClick={onUpdateClick}>
143-
<DriveFileRenameOutlineIcon />
144-
<span className={styles.chatOpMenuItemText}>Change title</span>
145-
</button>
146-
</li>
147-
<li>
148-
<button className={styles.chatOpMenuItem} onClick={() => onShareClick(chat.id, chat.title)}>
149-
<ShareIcon />
150-
<span className={styles.chatOpMenuItemText}>Share</span>
151-
</button>
152-
</li>
153-
<li>
154-
<button className={styles.chatOpMenuItem} onClick={() => onDeleteClick(chat.id, titleRef.current?.innerText)}>
155-
<DeleteOutlineIcon />
156-
<span className={styles.chatOpMenuItemText}>Delete</span>
157-
</button>
158-
</li>
159-
</DropdownMenu>
160-
</Dropdown>
161-
)}
162-
</>
120+
<Dropdown className={styles.chatOpMenu}>
121+
<DropdownButton className={styles.chatOpMenuIcon}>
122+
<MoreVertIcon />
123+
</DropdownButton>
124+
<DropdownMenu className={styles.chatOpMenuList}>
125+
<li>
126+
<button className={styles.chatOpMenuItem} onClick={flipPin}>
127+
{chat.pinned ?
128+
<>
129+
<Icon baseClassName="material-symbols-outlined">keep_off</Icon>
130+
<span className={styles.chatOpMenuItemText}>Unpin</span>
131+
</> : <>
132+
<Icon baseClassName="material-symbols-outlined">keep</Icon>
133+
<span className={styles.chatOpMenuItemText}>Pin</span>
134+
</>
135+
}
136+
</button>
137+
</li>
138+
<li>
139+
<button className={styles.chatOpMenuItem} onClick={onSummarizeClick}>
140+
<AutoAwesomeIcon />
141+
<span className={styles.chatOpMenuItemText}>Generate title</span>
142+
</button>
143+
</li>
144+
<li>
145+
<button className={styles.chatOpMenuItem} onClick={onUpdateClick}>
146+
<DriveFileRenameOutlineIcon />
147+
<span className={styles.chatOpMenuItemText}>Change title</span>
148+
</button>
149+
</li>
150+
<li>
151+
<button className={styles.chatOpMenuItem} onClick={() => onShareClick(chat.id, chat.title)}>
152+
<ShareIcon />
153+
<span className={styles.chatOpMenuItemText}>Share</span>
154+
</button>
155+
</li>
156+
<li>
157+
<button className={styles.chatOpMenuItem} onClick={() => onDeleteClick(chat.id, titleRef.current?.innerText)}>
158+
<DeleteOutlineIcon />
159+
<span className={styles.chatOpMenuItemText}>Delete</span>
160+
</button>
161+
</li>
162+
</DropdownMenu>
163+
</Dropdown>
164+
</NavLink>
163165
);
164166
};
165167

web/src/routes/root/ChatTab/index.module.css

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
1+
.sidebarButton {
2+
height: 2rem;
3+
margin: 2px;
4+
padding: 3px;
5+
background-color: var(--bg-primary);
6+
color: var(--text-primary);
7+
border: none;
8+
border-radius: 5px;
9+
transition: ease 0.25s all;
10+
display: flex;
11+
flex-direction: row;
12+
align-items: center;
13+
}
14+
15+
.sidebarButton:hover {
16+
background-color: var(--bg-secondary);
17+
18+
.chatOpMenuIcon {
19+
visibility: visible;
20+
}
21+
}
22+
23+
.sidebarButton.active {
24+
background-color: var(--bg-secondary);
25+
}
26+
127
.chatTitle {
228
margin-left: 5px;
329
/* line-height should be equal to height */
@@ -25,6 +51,7 @@
2551
}
2652

2753
.chatOpMenuIcon {
54+
visibility: hidden;
2855
display: flex;
2956
align-items: center;
3057
justify-content: center;
@@ -38,7 +65,6 @@
3865
background-color: var(--bg-primary);
3966
border: 1px solid var(--border-color);
4067
border-radius: 5px;
41-
position: absolute;
4268
z-index: 1;
4369
padding: 0.5rem;
4470
}

web/src/routes/root/Sidebar/index.jsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import styles from "./index.module.css";
22

33
import { useContext } from "react";
4-
import { Link, NavLink } from "react-router-dom";
4+
import { Link } from "react-router-dom";
55
import PropTypes from "prop-types";
66

77
import AddOutlinedIcon from "@mui/icons-material/AddOutlined";
@@ -31,16 +31,7 @@ const Sidebar = ({ onShareClick, onDeleteClick }) => {
3131
<div key={grp}>
3232
<div className={styles.sidebarDateGroup}>{grp}</div>
3333
{convs.map((conv) => (
34-
<NavLink
35-
key={conv.id}
36-
to={`conversations/${conv.id}`}
37-
className={({ isActive, isPending }) =>
38-
`${styles.sidebarButton} ${isActive ? styles.active : isPending ? styles.pending : ""}`}
39-
>
40-
{({ isActive }) => (
41-
<ChatTab chat={conv} isActive={isActive} onShareClick={onShareClick} onDeleteClick={onDeleteClick} />
42-
)}
43-
</NavLink>
34+
<ChatTab key={conv.id} chat={conv} onShareClick={onShareClick} onDeleteClick={onDeleteClick} />
4435
))}
4536
</div>
4637
]

web/src/routes/root/Sidebar/index.module.css

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,6 @@
4545
background-color: var(--bg-secondary);
4646
}
4747

48-
.sidebarButton.active {
49-
background-color: var(--bg-secondary);
50-
}
51-
5248
.sidebarBottom {
5349
margin-top: auto;
5450
width: 90%;

0 commit comments

Comments
 (0)