progress on responsive

This commit is contained in:
2025-10-06 10:56:46 +02:00
parent ef50cc9918
commit a4a26333b3
8 changed files with 261 additions and 108 deletions

View File

@ -1,4 +1,5 @@
import { Dices } from 'lucide-react'
import { useState } from 'react'
import { Dices, ChevronDown } from 'lucide-react'
import { Slider } from './Slider'
import { Switch } from './Switch'
import { Dropdown } from './Dropdown'
@ -13,6 +14,8 @@ interface EffectsBarProps {
}
export function EffectsBar({ values, onChange, onMapClick, getMappedLFOs }: EffectsBarProps) {
const [expandedEffect, setExpandedEffect] = useState<string | null>(null)
const [activeTab, setActiveTab] = useState<string>(EFFECTS[0].id)
const randomizeEffect = (effect: typeof EFFECTS[number]) => {
effect.parameters.forEach(param => {
if (param.id.endsWith('Enable')) return
@ -31,8 +34,9 @@ export function EffectsBar({ values, onChange, onMapClick, getMappedLFOs }: Effe
}
return (
<div className="bg-black border-t-2 border-white px-6 py-4">
<div className="grid grid-cols-4 gap-4">
<div className="bg-black border-t-2 border-white px-2 md:px-6 py-3 md:py-4">
{/* Desktop: Grid layout */}
<div className="hidden md:grid md:grid-cols-4 md:gap-4">
{EFFECTS.map(effect => {
return (
<div key={effect.id} className="border-2 border-white p-3">
@ -111,6 +115,100 @@ export function EffectsBar({ values, onChange, onMapClick, getMappedLFOs }: Effe
)
})}
</div>
{/* Mobile: Tabbed layout */}
<div className="md:hidden flex flex-col">
<div className="flex border-2 border-white">
{EFFECTS.map(effect => (
<button
key={effect.id}
onClick={() => setActiveTab(effect.id)}
className={`flex-1 p-2 font-mono text-[9px] tracking-[0.15em] transition-colors ${
activeTab === effect.id
? 'bg-white text-black'
: 'bg-black text-white hover:bg-white/10'
}`}
>
{effect.name.toUpperCase()}
</button>
))}
</div>
{EFFECTS.map(effect => {
if (activeTab !== effect.id) return null
return (
<div key={effect.id} className="border-2 border-t-0 border-white p-3">
<div className="flex items-center justify-between mb-3">
<div className="flex items-center gap-2">
<button
onClick={() => randomizeEffect(effect)}
className="p-1 text-white hover:bg-white hover:text-black transition-colors"
>
<Dices size={14} strokeWidth={2} />
</button>
</div>
{effect.bypassable && (
<Switch
checked={!values[`${effect.id}Bypass`]}
onChange={(checked) => onChange(`${effect.id}Bypass`, !checked)}
label={values[`${effect.id}Bypass`] ? 'OFF' : 'ON'}
/>
)}
</div>
<div className="flex flex-col gap-3">
{effect.parameters.map(param => {
if (param.options) {
return (
<Dropdown
key={param.id}
label={param.label}
value={values[param.id] as string ?? param.default as string}
options={param.options}
onChange={(value) => onChange(param.id, value)}
/>
)
}
const isSwitch = param.min === 0 && param.max === 1 && param.step === 1
if (isSwitch) {
return (
<div key={param.id} className="flex flex-col gap-1 mt-2">
<div className="flex items-center justify-between">
<span className="font-mono text-[9px] tracking-[0.15em] text-white">
{param.label.toUpperCase()}
</span>
<Switch
checked={Boolean(values[param.id])}
onChange={(checked) => onChange(param.id, checked ? 1 : 0)}
label={values[param.id] ? 'ON' : 'OFF'}
/>
</div>
</div>
)
}
return (
<Slider
key={param.id}
label={param.label}
value={values[param.id] as number ?? param.default as number}
min={param.min}
max={param.max}
step={param.step}
unit={param.unit}
onChange={(value) => onChange(param.id, value)}
valueId={param.id}
paramId={param.id}
onMapClick={onMapClick}
mappedLFOs={getMappedLFOs ? getMappedLFOs(param.id) : []}
/>
)
})}
</div>
</div>
)
})}
</div>
</div>
)
}