feat(category): dynamic dropdown item height
This commit is contained in:
parent
4bf84cd9a6
commit
836d5b76e1
@ -1,6 +1,7 @@
|
||||
import _ from 'lodash'
|
||||
import { Event, kinds, nip19, UnsignedEvent } from 'nostr-tools'
|
||||
import React, {
|
||||
CSSProperties,
|
||||
Fragment,
|
||||
useCallback,
|
||||
useEffect,
|
||||
@ -10,7 +11,7 @@ import React, {
|
||||
} from 'react'
|
||||
import { Link, useLocation, useNavigate } from 'react-router-dom'
|
||||
import { toast } from 'react-toastify'
|
||||
import { FixedSizeList as List } from 'react-window'
|
||||
import { VariableSizeList, FixedSizeList } from 'react-window'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { T_TAG_VALUE } from '../constants'
|
||||
import { useAppSelector, useGames, useNDKContext } from '../hooks'
|
||||
@ -865,7 +866,7 @@ const GameDropdown = ({
|
||||
</svg>
|
||||
</button>
|
||||
<div className='dropdown-menu dropdownMainMenu dropdownMainMenuAlt'>
|
||||
<List
|
||||
<FixedSizeList
|
||||
height={500}
|
||||
width={'100%'}
|
||||
itemCount={filteredOptions.length}
|
||||
@ -887,7 +888,7 @@ const GameDropdown = ({
|
||||
{filteredOptions[index].label}
|
||||
</div>
|
||||
)}
|
||||
</List>
|
||||
</FixedSizeList>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -992,6 +993,70 @@ export const CategoryAutocomplete = ({
|
||||
}))
|
||||
}, [selectedCategories, setFormState])
|
||||
|
||||
const listRef = useRef<VariableSizeList>(null)
|
||||
const rowHeights = useRef<{ [index: number]: number }>({})
|
||||
const setRowHeight = (index: number, size: number) => {
|
||||
rowHeights.current = { ...rowHeights.current, [index]: size }
|
||||
if (listRef.current) {
|
||||
listRef.current.resetAfterIndex(index)
|
||||
}
|
||||
}
|
||||
const getRowHeight = (index: number) => {
|
||||
return (rowHeights.current[index] || 35) + 8
|
||||
}
|
||||
|
||||
const Row = ({ index, style }: { index: number; style: CSSProperties }) => {
|
||||
const rowRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const rowElement = rowRef.current
|
||||
if (!rowElement) return
|
||||
const updateHeight = () => {
|
||||
const height = Math.max(rowElement.scrollHeight, 35)
|
||||
setRowHeight(index, height)
|
||||
}
|
||||
const observer = new ResizeObserver(() => {
|
||||
updateHeight()
|
||||
})
|
||||
observer.observe(rowElement)
|
||||
updateHeight()
|
||||
return () => {
|
||||
observer.disconnect()
|
||||
}
|
||||
}, [index])
|
||||
|
||||
if (!filteredOptions) return null
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={rowRef}
|
||||
style={style}
|
||||
className='dropdown-item dropdownMainMenuItem'
|
||||
onClick={() => handleSelect(filteredOptions[index])}
|
||||
>
|
||||
{capitalizeEachWord(filteredOptions[index].hierarchy)}
|
||||
{selectedCategories.some(
|
||||
(cat) => cat.hierarchy === filteredOptions[index].hierarchy
|
||||
) && (
|
||||
<button
|
||||
className='btn btnMain btnMainInsideField btnMainRemove'
|
||||
onClick={() => handleRemove(filteredOptions[index])}
|
||||
>
|
||||
<svg
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
viewBox='-32 0 512 512'
|
||||
width='1em'
|
||||
height='1em'
|
||||
fill='currentColor'
|
||||
>
|
||||
<path d='M323.3 32.01H188.7C172.3 32.01 160 44.31 160 60.73V96.01H32C14.33 96.01 0 110.3 0 128S14.33 160 32 160H480c17.67 0 32-14.33 32-32.01S497.7 96.01 480 96.01H352v-35.28C352 44.31 339.7 32.01 323.3 32.01zM64.9 477.5C66.5 492.3 79.31 504 94.72 504H417.3c15.41 0 28.22-11.72 29.81-26.5L480 192.2H32L64.9 477.5z'></path>
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='inputLabelWrapperMain'>
|
||||
<label className='form-label labelMain'>Categories</label>
|
||||
@ -1025,43 +1090,22 @@ export const CategoryAutocomplete = ({
|
||||
|
||||
<div className='dropdown-menu dropdownMainMenu dropdownMainMenuAlt'>
|
||||
{filteredOptions && filteredOptions.length > 0 ? (
|
||||
<List
|
||||
<VariableSizeList
|
||||
ref={listRef}
|
||||
height={500}
|
||||
width={'100%'}
|
||||
itemCount={filteredOptions.length}
|
||||
itemSize={getRowHeight}
|
||||
>
|
||||
{Row}
|
||||
</VariableSizeList>
|
||||
) : (
|
||||
<FixedSizeList
|
||||
height={500}
|
||||
width={'100%'}
|
||||
itemCount={1}
|
||||
itemSize={35}
|
||||
>
|
||||
{({ index, style }) => (
|
||||
<div
|
||||
style={style}
|
||||
className='dropdown-item dropdownMainMenuItem'
|
||||
onClick={() => handleSelect(filteredOptions[index])}
|
||||
>
|
||||
{capitalizeEachWord(filteredOptions[index].hierarchy)}
|
||||
{selectedCategories.some(
|
||||
(cat) =>
|
||||
cat.hierarchy === filteredOptions[index].hierarchy
|
||||
) && (
|
||||
<button
|
||||
className='btn btnMain btnMainInsideField btnMainRemove'
|
||||
onClick={() => handleRemove(filteredOptions[index])}
|
||||
>
|
||||
<svg
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
viewBox='-32 0 512 512'
|
||||
width='1em'
|
||||
height='1em'
|
||||
fill='currentColor'
|
||||
>
|
||||
<path d='M323.3 32.01H188.7C172.3 32.01 160 44.31 160 60.73V96.01H32C14.33 96.01 0 110.3 0 128S14.33 160 32 160H480c17.67 0 32-14.33 32-32.01S497.7 96.01 480 96.01H352v-35.28C352 44.31 339.7 32.01 323.3 32.01zM64.9 477.5C66.5 492.3 79.31 504 94.72 504H417.3c15.41 0 28.22-11.72 29.81-26.5L480 192.2H32L64.9 477.5z'></path>
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</List>
|
||||
) : (
|
||||
<List height={500} width={'100%'} itemCount={1} itemSize={35}>
|
||||
{({ index, style }) => (
|
||||
<div
|
||||
style={style}
|
||||
@ -1093,7 +1137,7 @@ export const CategoryAutocomplete = ({
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</List>
|
||||
</FixedSizeList>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@ -1103,8 +1147,9 @@ export const CategoryAutocomplete = ({
|
||||
{LTags.map((hierarchy) => {
|
||||
const heirarchicalCategories = hierarchy.split(`:`)
|
||||
const categories = heirarchicalCategories
|
||||
.map<React.ReactNode>((c: string) => (
|
||||
.map<React.ReactNode>((c, i) => (
|
||||
<Link
|
||||
key={`category-${i}`}
|
||||
to={{
|
||||
pathname: getGamePageRoute(game),
|
||||
search: `c=${c}`
|
||||
@ -1114,9 +1159,12 @@ export const CategoryAutocomplete = ({
|
||||
<p>{capitalizeEachWord(c)}</p>
|
||||
</Link>
|
||||
))
|
||||
.reduce((prev, curr) => [
|
||||
.reduce((prev, curr, i) => [
|
||||
prev,
|
||||
<div className='IBMSMSMBSSCategoriesBoxSeparator'>
|
||||
<div
|
||||
key={`separator-${i}`}
|
||||
className='IBMSMSMBSSCategoriesBoxSeparator'
|
||||
>
|
||||
<p>></p>
|
||||
</div>,
|
||||
curr
|
||||
|
@ -298,7 +298,7 @@ h6 {
|
||||
}
|
||||
|
||||
.dropdownMainMenuItem {
|
||||
transition: ease 0.4s;
|
||||
transition: background ease 0.4s, color ease 0.4s;
|
||||
background: linear-gradient(
|
||||
rgba(255, 255, 255, 0.03),
|
||||
rgba(255, 255, 255, 0.03)
|
||||
@ -319,7 +319,7 @@ h6 {
|
||||
}
|
||||
|
||||
.dropdownMainMenuItem:hover {
|
||||
transition: ease 0.4s;
|
||||
transition: background ease 0.4s, color ease 0.4s;
|
||||
background: linear-gradient(
|
||||
rgba(255, 255, 255, 0.05),
|
||||
rgba(255, 255, 255, 0.05)
|
||||
|
Loading…
x
Reference in New Issue
Block a user