feat: Improve PageAssistSelect component

This commit enhances the `PageAssistSelect` component with the following improvements:

- Adds a `ref` to the options container to automatically scroll to the selected option when the dropdown is opened.
- Fixes an issue where the `selectedOption` was not being correctly determined when the `options` array was updated.
- Improves the rendering of the selected option, ensuring that the loading state, placeholder, and selected option are displayed correctly.
- Adds a `data-value` attribute to the option elements to facilitate scrolling to the selected option.

These changes improve the overall user experience and functionality of the `PageAssistSelect` component.
This commit is contained in:
n4ze3m 2024-11-16 19:33:04 +05:30
parent c4d9e3aeed
commit 726d3e3427

View File

@ -43,6 +43,7 @@ export const PageAssistSelect: React.FC<SelectProps> = ({
const [searchTerm, setSearchTerm] = useState("") const [searchTerm, setSearchTerm] = useState("")
const [filteredOptions, setFilteredOptions] = useState<SelectOption[]>([]) const [filteredOptions, setFilteredOptions] = useState<SelectOption[]>([])
const containerRef = useRef<HTMLDivElement>(null) const containerRef = useRef<HTMLDivElement>(null)
const optionsContainerRef = useRef<HTMLDivElement>(null)
const [activeIndex, setActiveIndex] = useState(-1) const [activeIndex, setActiveIndex] = useState(-1)
useEffect(() => { useEffect(() => {
@ -59,6 +60,21 @@ export const PageAssistSelect: React.FC<SelectProps> = ({
return () => document.removeEventListener("mousedown", handleClickOutside) return () => document.removeEventListener("mousedown", handleClickOutside)
}, []) }, [])
useEffect(() => {
try {
if (isOpen && optionsContainerRef.current && value) {
const selectedOptionElement = optionsContainerRef.current.querySelector(
`[data-value="${value}"]`
)
if (selectedOptionElement) {
selectedOptionElement.scrollIntoView({ block: "nearest" })
}
}
} catch (error) {
console.error("Error scrolling to selected option:", error)
}
}, [isOpen, value])
useEffect(() => { useEffect(() => {
if (!options) return if (!options) return
@ -193,7 +209,7 @@ export const PageAssistSelect: React.FC<SelectProps> = ({
const selectedOption = useMemo(() => { const selectedOption = useMemo(() => {
if (!value || !options) return null if (!value || !options) return null
return options?.find(opt => opt.value === value) return options?.find((opt) => opt.value === value)
}, [value, options]) }, [value, options])
if (!options) { if (!options) {
@ -221,7 +237,13 @@ export const PageAssistSelect: React.FC<SelectProps> = ({
className={`${defaultSelectClass} ${className}`}> className={`${defaultSelectClass} ${className}`}>
<span className="!truncate flex items-center gap-2 "> <span className="!truncate flex items-center gap-2 ">
{isLoading && <LoadingIndicator />} {isLoading && <LoadingIndicator />}
{isLoading ? loadingText : selectedOption ? selectedOption.label : <span className="dark:text-gray-400 text-sm">{placeholder}</span>} {isLoading ? (
loadingText
) : selectedOption ? (
selectedOption.label
) : (
<span className="dark:text-gray-400 text-sm">{placeholder}</span>
)}
</span> </span>
<ChevronDown <ChevronDown
aria-hidden="true" aria-hidden="true"
@ -247,7 +269,10 @@ export const PageAssistSelect: React.FC<SelectProps> = ({
disabled={isLoading} disabled={isLoading}
aria-label="Search options" aria-label="Search options"
/> />
<Search aria-hidden="true" className="absolute left-2 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" /> <Search
aria-hidden="true"
className="absolute left-2 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400"
/>
{onRefresh && ( {onRefresh && (
<button <button
onClick={handleRefresh} onClick={handleRefresh}
@ -265,7 +290,9 @@ export const PageAssistSelect: React.FC<SelectProps> = ({
</div> </div>
</div> </div>
<div className="max-h-60 overflow-y-auto custom-scrollbar"> <div
ref={optionsContainerRef}
className="max-h-60 overflow-y-auto custom-scrollbar">
{isLoading ? ( {isLoading ? (
<div className="p-4 text-center text-gray-500 flex items-center justify-center gap-2"> <div className="p-4 text-center text-gray-500 flex items-center justify-center gap-2">
<LoadingIndicator /> <LoadingIndicator />
@ -281,6 +308,7 @@ export const PageAssistSelect: React.FC<SelectProps> = ({
key={option.value} key={option.value}
role="option" role="option"
aria-selected={value === option.value} aria-selected={value === option.value}
data-value={option.value}
onClick={() => { onClick={() => {
onChange(option) onChange(option)
setIsOpen(false) setIsOpen(false)