client/web: scroll exit node dropdown to top on search

When search input changes, reset the scroll to the top of the
dropdown list.

Updates #10261

Signed-off-by: Sonia Appasamy <sonia@tailscale.com>
This commit is contained in:
Sonia Appasamy 2023-11-27 12:26:18 -05:00 committed by Sonia Appasamy
parent d5d84f1a68
commit b247435d66

View File

@ -1,5 +1,5 @@
import cx from "classnames" import cx from "classnames"
import React, { useCallback, useMemo, useState } from "react" import React, { useCallback, useMemo, useRef, useState } from "react"
import { ReactComponent as Check } from "src/assets/icons/check.svg" import { ReactComponent as Check } from "src/assets/icons/check.svg"
import { ReactComponent as ChevronDown } from "src/assets/icons/chevron-down.svg" import { ReactComponent as ChevronDown } from "src/assets/icons/chevron-down.svg"
import useExitNodes, { import useExitNodes, {
@ -212,6 +212,7 @@ function ExitNodeSelectorInner({
}) { }) {
const [filter, setFilter] = useState<string>("") const [filter, setFilter] = useState<string>("")
const { data: exitNodes } = useExitNodes(node.TailnetName, filter) const { data: exitNodes } = useExitNodes(node.TailnetName, filter)
const listRef = useRef<HTMLDivElement>(null)
const hasNodes = useMemo( const hasNodes = useMemo(
() => exitNodes.find((n) => n.nodes.length > 0), () => exitNodes.find((n) => n.nodes.length > 0),
@ -228,10 +229,17 @@ function ExitNodeSelectorInner({
autoCapitalize="off" autoCapitalize="off"
placeholder="Search exit nodes…" placeholder="Search exit nodes…"
value={filter} value={filter}
onChange={(e) => setFilter(e.target.value)} onChange={(e) => {
// Jump list to top when search value changes.
listRef.current?.scrollTo(0, 0)
setFilter(e.target.value)
}}
/> />
{/* TODO(sonia): use loading spinner when loading useExitNodes */} {/* TODO(sonia): use loading spinner when loading useExitNodes */}
<div className="pt-1 border-t border-gray-200 max-h-64 overflow-y-scroll"> <div
ref={listRef}
className="pt-1 border-t border-gray-200 max-h-64 overflow-y-scroll"
>
{hasNodes ? ( {hasNodes ? (
exitNodes.map( exitNodes.map(
(group) => (group) =>