mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Merge pull request #1803 from Infisical/misc/improved-select-path-component-ux-1
misc: added handling of input focus to select path component
This commit is contained in:
@@ -31,6 +31,7 @@ export const SecretPathInput = ({
|
|||||||
const [inputValue, setInputValue] = useState(propValue ?? "");
|
const [inputValue, setInputValue] = useState(propValue ?? "");
|
||||||
const [secretPath, setSecretPath] = useState("/");
|
const [secretPath, setSecretPath] = useState("/");
|
||||||
const [suggestions, setSuggestions] = useState<string[]>([]);
|
const [suggestions, setSuggestions] = useState<string[]>([]);
|
||||||
|
const [isInputFocused, setIsInputFocus] = useState(false);
|
||||||
const [highlightedIndex, setHighlightedIndex] = useState(-1);
|
const [highlightedIndex, setHighlightedIndex] = useState(-1);
|
||||||
const debouncedInputValue = useDebounce(inputValue, 200);
|
const debouncedInputValue = useDebounce(inputValue, 200);
|
||||||
|
|
||||||
@@ -55,7 +56,9 @@ export const SecretPathInput = ({
|
|||||||
) {
|
) {
|
||||||
setSecretPath(debouncedInputValue);
|
setSecretPath(debouncedInputValue);
|
||||||
}
|
}
|
||||||
|
}, [debouncedInputValue]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
// filter suggestions based on matching
|
// filter suggestions based on matching
|
||||||
const searchFragment = debouncedInputValue.split("/").pop() || "";
|
const searchFragment = debouncedInputValue.split("/").pop() || "";
|
||||||
const filteredSuggestions = folders
|
const filteredSuggestions = folders
|
||||||
@@ -65,7 +68,7 @@ export const SecretPathInput = ({
|
|||||||
.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
||||||
|
|
||||||
setSuggestions(filteredSuggestions);
|
setSuggestions(filteredSuggestions);
|
||||||
}, [debouncedInputValue]);
|
}, [debouncedInputValue, folders]);
|
||||||
|
|
||||||
const handleSuggestionSelect = (selectedIndex: number) => {
|
const handleSuggestionSelect = (selectedIndex: number) => {
|
||||||
if (!suggestions[selectedIndex]) {
|
if (!suggestions[selectedIndex]) {
|
||||||
@@ -75,7 +78,7 @@ export const SecretPathInput = ({
|
|||||||
const validPaths = inputValue.split("/");
|
const validPaths = inputValue.split("/");
|
||||||
validPaths.pop();
|
validPaths.pop();
|
||||||
|
|
||||||
const newValue = `${validPaths.join("/")}/${suggestions[selectedIndex]}`;
|
const newValue = `${validPaths.join("/")}/${suggestions[selectedIndex]}/`;
|
||||||
onChange?.(newValue);
|
onChange?.(newValue);
|
||||||
setInputValue(newValue);
|
setInputValue(newValue);
|
||||||
setSecretPath(newValue);
|
setSecretPath(newValue);
|
||||||
@@ -108,7 +111,7 @@ export const SecretPathInput = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover.Root
|
<Popover.Root
|
||||||
open={suggestions.length > 0 && inputValue.length > 1}
|
open={suggestions.length > 0 && isInputFocused}
|
||||||
onOpenChange={() => {
|
onOpenChange={() => {
|
||||||
setHighlightedIndex(-1);
|
setHighlightedIndex(-1);
|
||||||
}}
|
}}
|
||||||
@@ -119,6 +122,8 @@ export const SecretPathInput = ({
|
|||||||
type="text"
|
type="text"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
|
onFocus={() => setIsInputFocus(true)}
|
||||||
|
onBlur={() => setIsInputFocus(false)}
|
||||||
value={inputValue}
|
value={inputValue}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className={containerClassName}
|
className={containerClassName}
|
||||||
@@ -150,8 +155,9 @@ export const SecretPathInput = ({
|
|||||||
key={`secret-reference-secret-${i + 1}`}
|
key={`secret-reference-secret-${i + 1}`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`${highlightedIndex === i ? "bg-gray-600" : ""
|
className={`${
|
||||||
} text-md relative mb-0.5 flex w-full cursor-pointer select-none items-center justify-between rounded-md px-2 py-1 outline-none transition-all hover:bg-mineshaft-500 data-[highlighted]:bg-mineshaft-500`}
|
highlightedIndex === i ? "bg-gray-600" : ""
|
||||||
|
} text-md relative mb-0.5 flex w-full cursor-pointer select-none items-center justify-between rounded-md px-2 py-1 outline-none transition-all hover:bg-mineshaft-500 data-[highlighted]:bg-mineshaft-500`}
|
||||||
>
|
>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<div className="flex items-center text-yellow-700">
|
<div className="flex items-center text-yellow-700">
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export const useGetFoldersByEnv = ({
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
return [...names];
|
return [...names];
|
||||||
}, [(folders || []).map((folder) => folder.data)]);
|
}, [...(folders || []).map((folder) => folder.data)]);
|
||||||
|
|
||||||
const isFolderPresentInEnv = useCallback(
|
const isFolderPresentInEnv = useCallback(
|
||||||
(name: string, env: string) => {
|
(name: string, env: string) => {
|
||||||
@@ -91,7 +91,7 @@ export const useGetFoldersByEnv = ({
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
[(folders || []).map((folder) => folder.data)]
|
[...(folders || []).map((folder) => folder.data)]
|
||||||
);
|
);
|
||||||
|
|
||||||
const getFolderByNameAndEnv = useCallback(
|
const getFolderByNameAndEnv = useCallback(
|
||||||
|
|||||||
Reference in New Issue
Block a user