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,30 +132,36 @@ 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
{MATERIAL_CATEGORIES.map((category) => ( className="w-full max-w-full overflow-x-auto overflow-y-hidden"
<button ref={categoryScrollRef}
className={`px-2 font-medium text-[11px] uppercase tracking-[0.12em] transition-all ${ style={{ msOverflowStyle: 'none', scrollbarWidth: 'none' }}
selectedCategory === category >
? 'bg-transparent text-foreground' <div className="flex min-w-max gap-1 pb-1">
: 'bg-transparent text-muted-foreground opacity-70 hover:text-foreground hover:opacity-100' {MATERIAL_CATEGORIES.map((category) => (
}`} <button
key={category} className={`shrink-0 px-2 font-medium text-[11px] uppercase tracking-[0.12em] transition-all ${
onClick={() => { selectedCategory === category
setSelectedCategory(category) ? 'bg-transparent text-foreground'
if (showCustom) { : 'bg-transparent text-muted-foreground opacity-70 hover:text-foreground hover:opacity-100'
setShowCustom(false) }`}
} key={category}
if (category !== 'other') { onClick={() => {
setPaintPanelOpen(false) setSelectedCategory(category)
} if (showCustom) {
}} setShowCustom(false)
type="button" }
> if (category !== 'other') {
{category.charAt(0).toUpperCase() + category.slice(1)} setPaintPanelOpen(false)
</button> }
))} }}
type="button"
>
{category.charAt(0).toUpperCase() + category.slice(1)}
</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"