Use useDeferredValue for search dropdown rendering
Defer rendering of bestiary suggestions and player character matches in ActionBar so the input stays responsive as the bestiary grows. Keyboard navigation and selection logic still use the latest values. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,12 @@ import {
|
||||
Plus,
|
||||
Users,
|
||||
} from "lucide-react";
|
||||
import { type FormEvent, type RefObject, useState } from "react";
|
||||
import {
|
||||
type FormEvent,
|
||||
type RefObject,
|
||||
useDeferredValue,
|
||||
useState,
|
||||
} from "react";
|
||||
import type { SearchResult } from "../hooks/use-bestiary.js";
|
||||
import { cn } from "../lib/utils.js";
|
||||
import { D20Icon } from "./d20-icon.js";
|
||||
@@ -270,6 +275,8 @@ export function ActionBar({
|
||||
const [nameInput, setNameInput] = useState("");
|
||||
const [suggestions, setSuggestions] = useState<SearchResult[]>([]);
|
||||
const [pcMatches, setPcMatches] = useState<PlayerCharacter[]>([]);
|
||||
const deferredSuggestions = useDeferredValue(suggestions);
|
||||
const deferredPcMatches = useDeferredValue(pcMatches);
|
||||
const [suggestionIndex, setSuggestionIndex] = useState(-1);
|
||||
const [queued, setQueued] = useState<QueuedCreature | null>(null);
|
||||
const [customInit, setCustomInit] = useState("");
|
||||
@@ -394,7 +401,8 @@ export function ActionBar({
|
||||
}
|
||||
};
|
||||
|
||||
const hasSuggestions = suggestions.length > 0 || pcMatches.length > 0;
|
||||
const hasSuggestions =
|
||||
deferredSuggestions.length > 0 || deferredPcMatches.length > 0;
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (!hasSuggestions) return;
|
||||
@@ -495,10 +503,10 @@ export function ActionBar({
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
{browseMode && suggestions.length > 0 && (
|
||||
{browseMode && deferredSuggestions.length > 0 && (
|
||||
<div className="absolute bottom-full z-50 mb-1 w-full rounded-md border border-border bg-card shadow-lg">
|
||||
<ul className="max-h-48 overflow-y-auto py-1">
|
||||
{suggestions.map((result, i) => (
|
||||
{deferredSuggestions.map((result, i) => (
|
||||
<li key={creatureKey(result)}>
|
||||
<button
|
||||
type="button"
|
||||
@@ -524,8 +532,8 @@ export function ActionBar({
|
||||
{!browseMode && hasSuggestions && (
|
||||
<AddModeSuggestions
|
||||
nameInput={nameInput}
|
||||
suggestions={suggestions}
|
||||
pcMatches={pcMatches}
|
||||
suggestions={deferredSuggestions}
|
||||
pcMatches={deferredPcMatches}
|
||||
suggestionIndex={suggestionIndex}
|
||||
queued={queued}
|
||||
onDismiss={dismissSuggestions}
|
||||
|
||||
Reference in New Issue
Block a user