Make material categories horizontally scrollable
This commit is contained in:
@@ -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}
|
||||||
|
|||||||
Reference in New Issue
Block a user