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 [filteredOptions, setFilteredOptions] = useState<SelectOption[]>([])
const containerRef = useRef<HTMLDivElement>(null)
const optionsContainerRef = useRef<HTMLDivElement>(null)
const [activeIndex, setActiveIndex] = useState(-1)
useEffect(() => {
@ -59,6 +60,21 @@ export const PageAssistSelect: React.FC<SelectProps> = ({
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(() => {
if (!options) return
@ -193,7 +209,7 @@ export const PageAssistSelect: React.FC<SelectProps> = ({
const selectedOption = useMemo(() => {
if (!value || !options) return null
return options?.find(opt => opt.value === value)
return options?.find((opt) => opt.value === value)
}, [value, options])
if (!options) {
@ -221,7 +237,13 @@ export const PageAssistSelect: React.FC<SelectProps> = ({
className={`${defaultSelectClass} ${className}`}>
<span className="!truncate flex items-center gap-2 ">
{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>
<ChevronDown
aria-hidden="true"
@ -247,7 +269,10 @@ export const PageAssistSelect: React.FC<SelectProps> = ({
disabled={isLoading}
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 && (
<button
onClick={handleRefresh}
@ -265,7 +290,9 @@ export const PageAssistSelect: React.FC<SelectProps> = ({
</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 ? (
<div className="p-4 text-center text-gray-500 flex items-center justify-center gap-2">
<LoadingIndicator />
@ -281,6 +308,7 @@ export const PageAssistSelect: React.FC<SelectProps> = ({
key={option.value}
role="option"
aria-selected={value === option.value}
data-value={option.value}
onClick={() => {
onChange(option)
setIsOpen(false)