Skip to content

Commit a303eb0

Browse files
committed
Add avatar to user autocomplete
1 parent 94e97d2 commit a303eb0

File tree

2 files changed

+45
-16
lines changed

2 files changed

+45
-16
lines changed

packages/app/src/app/components/Overlay/Overlay.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export const Overlay: React.FC<IOverlayProps> = ({
8686

8787
useEffect(() => {
8888
const handleEscape = (e: KeyboardEvent) => {
89-
if (e.keyCode === ESC) {
89+
if (!e.defaultPrevented && e.keyCode === ESC) {
9090
handleClose();
9191
}
9292
};

packages/app/src/app/pages/Sandbox/Editor/Header/Collaborators/UserSearchInput.tsx

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,53 @@ import Downshift, { DownshiftProps } from 'downshift';
33
import css from '@styled-system/css';
44
import { Input, List, ListAction } from '@codesandbox/components';
55

6+
type User = {
7+
id: string;
8+
username: string;
9+
avatar_url: string;
10+
};
11+
612
interface IUserAutoComplete {
713
inputValue: string;
814
children: (answer: {
9-
users: string[];
15+
users: User[];
1016
loading: boolean;
1117
error: Error | null;
1218
}) => JSX.Element;
1319
}
1420

1521
const UserAutoComplete = ({ inputValue, children }: IUserAutoComplete) => {
16-
const [users, setUsers] = React.useState<string[]>([]);
22+
const [users, setUsers] = React.useState<User[]>([]);
1723
const [loading, setLoading] = React.useState<boolean>(true);
1824
const [error, setError] = React.useState<Error | null>(null);
1925
useEffect(() => {
2026
setLoading(true);
2127
setError(null);
28+
29+
let timeoutId: number;
30+
2231
if (inputValue.length > 2 && !inputValue.includes('@')) {
23-
fetch(`/api/v1/users/search?username=${inputValue}`)
24-
.then(x => x.json())
25-
.then(x => {
26-
setUsers(x.map(user => user.username));
27-
setLoading(false);
28-
})
29-
.catch(e => {
30-
setError(e);
31-
});
32+
// Small debounce
33+
timeoutId = window.setTimeout(() => {
34+
fetch(`/api/v1/users/search?username=${inputValue}`)
35+
.then(x => x.json())
36+
.then(x => {
37+
setUsers(x);
38+
setLoading(false);
39+
})
40+
.catch(e => {
41+
setError(e);
42+
});
43+
}, 300);
3244
} else {
3345
setUsers([]);
3446
}
47+
48+
return () => {
49+
if (timeoutId) {
50+
clearTimeout(timeoutId);
51+
}
52+
};
3553
}, [inputValue]);
3654

3755
return children({ users, loading, error });
@@ -98,15 +116,26 @@ export const UserSearchInput = ({
98116
>
99117
{users.map((item, index) => (
100118
<ListAction
101-
key={item}
119+
key={item.id}
102120
isActive={highlightedIndex === index}
103121
{...getItemProps({
104-
item,
122+
item: item.username,
105123
index,
106-
isSelected: selectedItem === item,
124+
isSelected: selectedItem === item.username,
107125
})}
108126
>
109-
{item}
127+
<img
128+
alt={item.username}
129+
css={css({
130+
borderRadius: 2,
131+
marginRight: 2,
132+
paddingY: 1,
133+
})}
134+
width={24}
135+
height={24}
136+
src={item.avatar_url}
137+
/>{' '}
138+
{item.username}
110139
</ListAction>
111140
))}
112141
</List>

0 commit comments

Comments
 (0)