diff --git a/components/Icons/GoBackTiny.tsx b/components/Icons/GoBackTiny.tsx new file mode 100644 index 00000000..5c9dd161 --- /dev/null +++ b/components/Icons/GoBackTiny.tsx @@ -0,0 +1,21 @@ +import { Props } from "./Props"; + +export const GoBackTiny = (props: Props) => { + return ( + + + + ); +}; diff --git a/components/Mention.tsx b/components/Mention.tsx index c2c9f343..6b61eeb3 100644 --- a/components/Mention.tsx +++ b/components/Mention.tsx @@ -9,6 +9,9 @@ import { callRPC } from "app/api/rpc/client"; import { ArrowRightTiny } from "components/Icons/ArrowRightTiny"; import { GoBackSmall } from "components/Icons/GoBackSmall"; import { SearchTiny } from "components/Icons/SearchTiny"; +import { CloseTiny } from "./Icons/CloseTiny"; +import { GoToArrow } from "./Icons/GoToArrow"; +import { GoBackTiny } from "./Icons/GoBackTiny"; export function MentionAutocomplete(props: { open: boolean; @@ -18,6 +21,7 @@ export function MentionAutocomplete(props: { coords: { top: number; left: number } | null; }) { const [searchQuery, setSearchQuery] = useState(""); + const [noResults, setNoResults] = useState(false); const inputRef = useRef(null); const contentRef = useRef(null); @@ -48,9 +52,23 @@ export function MentionAutocomplete(props: { setSearchQuery(""); setScope({ type: "default" }); setSuggestionIndex(0); + setNoResults(false); } }, [props.open, setScope, setSuggestionIndex]); + // Handle timeout for showing "No results found" + useEffect(() => { + if (searchQuery && suggestions.length === 0) { + setNoResults(false); + const timer = setTimeout(() => { + setNoResults(true); + }, 2000); + return () => clearTimeout(timer); + } else { + setNoResults(false); + } + }, [searchQuery, suggestions.length]); + // Handle keyboard navigation const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Escape") { @@ -120,14 +138,23 @@ export function MentionAutocomplete(props: { if (!props.open || !props.coords) return null; - const getHeader = (type: Mention["type"]) => { + const getHeader = (type: Mention["type"], scope?: MentionScope) => { switch (type) { case "did": return "People"; case "publication": return "Publications"; case "post": - return "Posts"; + if (scope) { + return ( + { + handleScopeChange({ type: "default" }); + }} + /> + ); + } else return "Posts"; } }; @@ -164,26 +191,13 @@ export function MentionAutocomplete(props: { max-h-(--radix-popover-content-available-height) overflow-y-scroll`} > - {/* Search input */} -
- {scope.type === "publication" && ( - - )} - {scope.type === "publication" && ( - - {scope.name} - - )} + {/* Dropdown Header */} +
{ @@ -197,24 +211,27 @@ export function MentionAutocomplete(props: { ? "Search posts..." : "Search people & publications..." } - className="flex-1 min-w-0 bg-transparent border-none outline-none text-sm placeholder:text-tertiary" + className="flex-1 w-full min-w-0 bg-transparent border-none outline-none text-sm placeholder:text-tertiary" />
{sortedSuggestions.length === 0 ? ( -
+
{searchQuery - ? "No results found" + ? noResults + ? "No results found..." + : "Searching..." : scope.type === "publication" - ? "Type to search posts" - : "Type to search"} + ? "Start typing to search posts" + : "Start typing to search people and publications"}
) : (
    {sortedSuggestions.map((result, index) => { const prevResult = sortedSuggestions[index - 1]; const showHeader = - prevResult && prevResult.type !== result.type; + index === 0 || + (prevResult && prevResult.type !== result.type); return ( )}
    - {getHeader(result.type)} + {getHeader(result.type, scope)}
    )} @@ -389,6 +406,27 @@ const PostResult = (props: { ); }; +const ScopeHeader = (props: { + scope: MentionScope; + handleScopeChange: () => void; +}) => { + if (props.scope.type === "default") return; + if (props.scope.type === "publication") + return ( + + ); +}; + export type Mention = | { type: "did"; handle: string; did: string; displayName?: string } | { type: "publication"; uri: string; name: string }