Make material categories horizontally scrollable

This commit is contained in:
sudhir
2026-04-24 10:43:38 +05:30
parent 2876f39876
commit a5448a0053
@@ -31,6 +31,7 @@ export function MaterialPicker({
const [showCustom, setShowCustom] = useState<boolean>(!!value?.properties) const [showCustom, setShowCustom] = useState<boolean>(!!value?.properties)
const [selectedCategory, setSelectedCategory] = useState<MaterialCategory>(MATERIAL_CATEGORIES[0]) const [selectedCategory, setSelectedCategory] = useState<MaterialCategory>(MATERIAL_CATEGORIES[0])
const catalogScrollRef = useRef<HTMLDivElement>(null) const catalogScrollRef = useRef<HTMLDivElement>(null)
const categoryScrollRef = useRef<HTMLDivElement>(null)
const catalogItems = const catalogItems =
selectedCategory === 'other' selectedCategory === 'other'
? getMaterialsForCategory('other') ? getMaterialsForCategory('other')
@@ -87,6 +88,27 @@ export function MaterialPicker({
} }
}, [catalogItems.length, onChange, showCustom]) }, [catalogItems.length, onChange, showCustom])
useEffect(() => {
const container = categoryScrollRef.current
if (!container) return
const handleWheel = (event: WheelEvent) => {
const deltaX = event.deltaX
const deltaY = event.deltaY
const nextScrollLeft = container.scrollLeft + deltaX + deltaY
if (nextScrollLeft === container.scrollLeft) return
event.preventDefault()
container.scrollLeft = nextScrollLeft
}
container.addEventListener('wheel', handleWheel, { passive: false })
return () => {
container.removeEventListener('wheel', handleWheel)
}
}, [])
const handleCustomOpen = () => { const handleCustomOpen = () => {
if (disabled) return if (disabled) return
setShowCustom(true) setShowCustom(true)
@@ -110,11 +132,16 @@ export function MaterialPicker({
return ( return (
<div className={`min-w-0 space-y-3 ${disabled ? 'pointer-events-none opacity-50' : ''}`}> <div className={`min-w-0 space-y-3 ${disabled ? 'pointer-events-none opacity-50' : ''}`}>
{(catalogItems.length > 0 || onChange) && ( {(catalogItems.length > 0 || onChange) && (
<div className="min-w-0 space-y-2"> <div className="min-w-0 space-y-1">
<div className="flex flex-wrap gap-1"> <div
className="w-full max-w-full overflow-x-auto overflow-y-hidden"
ref={categoryScrollRef}
style={{ msOverflowStyle: 'none', scrollbarWidth: 'none' }}
>
<div className="flex min-w-max gap-1 pb-1">
{MATERIAL_CATEGORIES.map((category) => ( {MATERIAL_CATEGORIES.map((category) => (
<button <button
className={`px-2 font-medium text-[11px] uppercase tracking-[0.12em] transition-all ${ className={`shrink-0 px-2 font-medium text-[11px] uppercase tracking-[0.12em] transition-all ${
selectedCategory === category selectedCategory === category
? 'bg-transparent text-foreground' ? 'bg-transparent text-foreground'
: 'bg-transparent text-muted-foreground opacity-70 hover:text-foreground hover:opacity-100' : 'bg-transparent text-muted-foreground opacity-70 hover:text-foreground hover:opacity-100'
@@ -135,6 +162,7 @@ export function MaterialPicker({
</button> </button>
))} ))}
</div> </div>
</div>
<div <div
className="w-full max-w-full overflow-x-auto overflow-y-hidden" className="w-full max-w-full overflow-x-auto overflow-y-hidden"
ref={catalogScrollRef} ref={catalogScrollRef}