for-legacy-web/src/components/navigation/SearchAutoComplete.tsx

123 lines
3.6 KiB
TypeScript

import styled from "styled-components/macro";
import { User } from "revolt.js";
import { AutoCompleteState } from "../common/AutoComplete";
import UserIcon from "../common/user/UserIcon";
const Base = styled.div`
position: absolute;
top: 100%;
left: 0;
right: 0;
margin-top: 4px;
background: var(--primary-background);
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
z-index: 1001;
overflow: hidden;
max-height: 200px;
overflow-y: auto;
@media (max-width: 768px) {
margin-top: 8px;
max-height: 250px;
border-radius: 10px;
}
button {
width: 100%;
gap: 8px;
padding: 8px 12px;
border: none;
display: flex;
font-size: 14px;
cursor: pointer;
align-items: center;
flex-direction: row;
font-family: inherit;
background: transparent;
color: var(--foreground);
text-align: left;
transition: background 0.15s ease;
&:hover,
&.active {
background: var(--secondary-background);
}
span {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
@media (max-width: 768px) {
padding: 14px 16px;
font-size: 15px;
gap: 12px;
/* Add touch feedback for mobile */
&:active {
background: var(--secondary-background);
transform: scale(0.98);
}
}
}
`;
interface Props {
state: AutoCompleteState;
setState: (state: AutoCompleteState) => void;
onClick: (userId: string, username: string) => void;
}
export default function SearchAutoComplete({ state, setState, onClick }: Props) {
if (state.type !== "user") return null;
// Detect if we're on mobile
const isMobile = window.innerWidth <= 768;
const iconSize = isMobile ? 24 : 20;
return (
<Base>
{state.matches.length > 0 ? (
state.matches.map((user, i) => (
<button
key={user._id}
className={i === state.selected ? "active" : ""}
onMouseEnter={() =>
(i !== state.selected || !state.within) &&
setState({
...state,
selected: i,
within: true,
})
}
onMouseLeave={() =>
state.within &&
setState({
...state,
within: false,
})
}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
onClick(user._id, user.username);
}}>
<UserIcon size={iconSize} target={user} status={true} />
<span>{user.username}</span>
</button>
))
) : (
<div style={{
padding: isMobile ? "16px" : "12px",
textAlign: "center",
color: "var(--tertiary-foreground)",
fontSize: isMobile ? "14px" : "13px"
}}>
No users found
</div>
)}
</Base>
);
}