progress on responsive
This commit is contained in:
34
src/App.tsx
34
src/App.tsx
@ -541,16 +541,16 @@ function App() {
|
||||
<div className="w-screen h-screen flex flex-col bg-black overflow-hidden">
|
||||
{showWarning && <AudioContextWarning onDismiss={handleDismissWarning} />}
|
||||
{showHelp && <HelpModal onClose={() => setShowHelp(false)} />}
|
||||
<header className="bg-black border-b-2 border-white px-2 md:px-6 py-2 md:py-3">
|
||||
<div className="flex flex-col md:flex-row items-start md:items-center gap-2 md:gap-6">
|
||||
<div className="flex items-center justify-between w-full md:w-auto gap-2">
|
||||
<header className="bg-black border-b-2 border-white px-2 lg:px-6 py-2 lg:py-3">
|
||||
<div className="flex flex-col lg:flex-row items-start lg:items-center gap-2 lg:gap-6">
|
||||
<div className="flex items-center justify-between w-full lg:w-auto gap-2">
|
||||
<h1
|
||||
onClick={() => setShowHelp(true)}
|
||||
className="font-mono text-[10px] md:text-sm tracking-[0.3em] text-white flex-shrink-0 cursor-pointer hover:opacity-70 transition-opacity"
|
||||
>
|
||||
BRUITISTE
|
||||
</h1>
|
||||
<div className="flex gap-2 md:hidden">
|
||||
<div className="flex gap-2 lg:hidden">
|
||||
<button
|
||||
onClick={handleStop}
|
||||
disabled={!playing}
|
||||
@ -579,7 +579,7 @@ function App() {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full md:flex-1">
|
||||
<div className="w-full lg:flex-1">
|
||||
<EngineControls
|
||||
values={engineValues}
|
||||
onChange={handleEngineChange}
|
||||
@ -587,35 +587,35 @@ function App() {
|
||||
getMappedLFOs={getMappedLFOs}
|
||||
/>
|
||||
</div>
|
||||
<div className="hidden md:flex gap-2 md:gap-4 flex-shrink-0">
|
||||
<div className="hidden lg:flex gap-2 lg:gap-4 flex-shrink-0">
|
||||
<button
|
||||
onClick={handleStop}
|
||||
disabled={!playing}
|
||||
className="px-2 md:px-6 py-1 md:py-2 bg-black text-white border-2 border-white font-mono text-[9px] md:text-[11px] tracking-[0.2em] hover:bg-white hover:text-black transition-all disabled:opacity-30 disabled:cursor-not-allowed flex items-center gap-1 md:gap-2"
|
||||
className="px-2 lg:px-6 py-1 lg:py-2 bg-black text-white border-2 border-white font-mono text-[9px] lg:text-[11px] tracking-[0.2em] hover:bg-white hover:text-black transition-all disabled:opacity-30 disabled:cursor-not-allowed flex items-center gap-1 lg:gap-2"
|
||||
>
|
||||
<Square size={12} strokeWidth={2} fill="currentColor" className="md:w-[14px] md:h-[14px]" />
|
||||
<Square size={12} strokeWidth={2} fill="currentColor" className="lg:w-[14px] lg:h-[14px]" />
|
||||
<span className="hidden sm:inline">STOP</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={handleRandom}
|
||||
className="px-2 md:px-6 py-1 md:py-2 bg-white text-black font-mono text-[9px] md:text-[11px] tracking-[0.2em] hover:bg-black hover:text-white border-2 border-white transition-all flex items-center gap-1 md:gap-2"
|
||||
className="px-2 lg:px-6 py-1 lg:py-2 bg-white text-black font-mono text-[9px] lg:text-[11px] tracking-[0.2em] hover:bg-black hover:text-white border-2 border-white transition-all flex items-center gap-1 lg:gap-2"
|
||||
>
|
||||
<Dices size={12} strokeWidth={2} className="md:w-[14px] md:h-[14px]" />
|
||||
<Dices size={12} strokeWidth={2} className="lg:w-[14px] lg:h-[14px]" />
|
||||
<span className="hidden sm:inline">RANDOM</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={handleRandomizeAllParams}
|
||||
className="px-2 md:px-6 py-1 md:py-2 bg-white text-black font-mono text-[9px] md:text-[11px] tracking-[0.2em] hover:bg-black hover:text-white border-2 border-white transition-all flex items-center gap-1 md:gap-2"
|
||||
className="px-2 lg:px-6 py-1 lg:py-2 bg-white text-black font-mono text-[9px] lg:text-[11px] tracking-[0.2em] hover:bg-black hover:text-white border-2 border-white transition-all flex items-center gap-1 lg:gap-2"
|
||||
>
|
||||
<Sparkles size={12} strokeWidth={2} className="md:w-[14px] md:h-[14px]" />
|
||||
<Sparkles size={12} strokeWidth={2} className="lg:w-[14px] lg:h-[14px]" />
|
||||
<span className="hidden sm:inline">CHAOS</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={handleDownloadAll}
|
||||
disabled={downloading}
|
||||
className="px-2 md:px-6 py-1 md:py-2 bg-black text-white border-2 border-white font-mono text-[9px] md:text-[11px] tracking-[0.2em] hover:bg-white hover:text-black transition-all disabled:opacity-30 disabled:cursor-not-allowed flex items-center gap-1 md:gap-2"
|
||||
className="px-2 lg:px-6 py-1 lg:py-2 bg-black text-white border-2 border-white font-mono text-[9px] lg:text-[11px] tracking-[0.2em] hover:bg-white hover:text-black transition-all disabled:opacity-30 disabled:cursor-not-allowed flex items-center gap-1 lg:gap-2"
|
||||
>
|
||||
<Archive size={12} strokeWidth={2} className="md:w-[14px] md:h-[14px]" />
|
||||
<Archive size={12} strokeWidth={2} className="lg:w-[14px] lg:h-[14px]" />
|
||||
<span className="hidden sm:inline">{downloading ? 'DOWNLOADING...' : 'PACK'}</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -625,8 +625,8 @@ function App() {
|
||||
<LFOPanel onChange={handleLFOChange} onUpdateDepth={handleUpdateMappingDepth} onRemoveMapping={handleRemoveMapping} />
|
||||
|
||||
<div className="flex-1 flex flex-col overflow-auto bg-white">
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-[1px] bg-white p-[1px]">
|
||||
<div className="col-span-1 md:col-span-4">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-4 gap-[1px] bg-white p-[1px]">
|
||||
<div className="col-span-1 lg:col-span-4">
|
||||
<FormulaEditor
|
||||
formula={customTile.formula}
|
||||
isPlaying={playing === PLAYBACK_ID.CUSTOM}
|
||||
@ -639,7 +639,7 @@ function App() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 grid grid-cols-1 md:grid-cols-4 auto-rows-min gap-[1px] bg-white p-[1px]">
|
||||
<div className="flex-1 grid grid-cols-1 lg:grid-cols-4 auto-rows-min gap-[1px] bg-white p-[1px]">
|
||||
{tiles.map((row, i) =>
|
||||
row.map((tile, j) => {
|
||||
const id = getTileId(i, j)
|
||||
|
||||
@ -16,6 +16,7 @@ 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 [isCollapsed, setIsCollapsed] = useState(false)
|
||||
const randomizeEffect = (effect: typeof EFFECTS[number]) => {
|
||||
effect.parameters.forEach(param => {
|
||||
if (param.id.endsWith('Enable')) return
|
||||
@ -34,9 +35,9 @@ export function EffectsBar({ values, onChange, onMapClick, getMappedLFOs }: Effe
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-black border-t-2 border-white px-2 md:px-6 py-3 md:py-4">
|
||||
<div className="bg-black border-t-2 border-white px-2 lg:px-6 py-3 lg:py-4">
|
||||
{/* Desktop: Grid layout */}
|
||||
<div className="hidden md:grid md:grid-cols-4 md:gap-4">
|
||||
<div className="hidden lg:grid lg:grid-cols-4 lg:gap-4">
|
||||
{EFFECTS.map(effect => {
|
||||
return (
|
||||
<div key={effect.id} className="border-2 border-white p-3">
|
||||
@ -117,14 +118,21 @@ export function EffectsBar({ values, onChange, onMapClick, getMappedLFOs }: Effe
|
||||
</div>
|
||||
|
||||
{/* Mobile: Tabbed layout */}
|
||||
<div className="md:hidden flex flex-col">
|
||||
<div className="lg:hidden flex flex-col">
|
||||
<div className="flex border-2 border-white">
|
||||
{EFFECTS.map(effect => (
|
||||
<button
|
||||
key={effect.id}
|
||||
onClick={() => setActiveTab(effect.id)}
|
||||
onClick={() => {
|
||||
if (activeTab === effect.id && !isCollapsed) {
|
||||
setIsCollapsed(true)
|
||||
} else {
|
||||
setActiveTab(effect.id)
|
||||
setIsCollapsed(false)
|
||||
}
|
||||
}}
|
||||
className={`flex-1 p-2 font-mono text-[9px] tracking-[0.15em] transition-colors ${
|
||||
activeTab === effect.id
|
||||
activeTab === effect.id && !isCollapsed
|
||||
? 'bg-white text-black'
|
||||
: 'bg-black text-white hover:bg-white/10'
|
||||
}`}
|
||||
@ -133,7 +141,7 @@ export function EffectsBar({ values, onChange, onMapClick, getMappedLFOs }: Effe
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
{EFFECTS.map(effect => {
|
||||
{!isCollapsed && EFFECTS.map(effect => {
|
||||
if (activeTab !== effect.id) return null
|
||||
return (
|
||||
<div key={effect.id} className="border-2 border-t-0 border-white p-3">
|
||||
|
||||
@ -55,12 +55,12 @@ export function EngineControls({ values, onChange, onMapClick, getMappedLFOs }:
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={param.id} className="hidden md:flex flex-col gap-1 min-w-[90px] xl:min-w-[100px]">
|
||||
<div key={param.id} className="flex flex-col gap-1 min-w-[70px] flex-1 lg:flex-initial lg:min-w-[90px] xl:min-w-[100px]">
|
||||
<div className="flex justify-between items-baseline gap-1">
|
||||
<label className="font-mono text-[9px] tracking-[0.15em] text-white truncate">
|
||||
<label className="font-mono text-[7px] lg:text-[9px] tracking-[0.1em] lg:tracking-[0.15em] text-white truncate">
|
||||
{param.label.toUpperCase()}
|
||||
</label>
|
||||
<span className="font-mono text-[9px] text-white whitespace-nowrap">
|
||||
<span className="font-mono text-[7px] lg:text-[9px] text-white whitespace-nowrap">
|
||||
{formatValue(param.id, (values[param.id] as number) ?? param.default)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@ -36,7 +36,7 @@ export function LFOPanel({ onChange, onUpdateDepth, onRemoveMapping }: LFOPanelP
|
||||
|
||||
return (
|
||||
<div className="bg-black border-t-2 border-white">
|
||||
<div className="grid grid-cols-2 xl:grid-cols-4 gap-[1px] bg-white p-[1px]">
|
||||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-[1px] bg-white p-[1px]">
|
||||
{lfoConfigs.map(({ key, index }) => {
|
||||
const lfo = lfoValues[key]
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user