fix: Workshop mobile layout + navigation from all modes
Mobile: - Workshop nav tabs full-width, hide logo, hide hero header - Search/sort/share go full-width stacked - Tags scroll horizontally - Share button large and prominent - Patch cards single column, shorter previews - Auth modal fits mobile viewport Navigation: - Workshop button in Sandbox hamburger menu (mobile) - Workshop tab in WorldMap mobile tab bar - GameApp passes onWorkshop prop through to WorldMap Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -354,6 +354,11 @@ export default function App({ onSwitchToGame, onSwitchToWorkshop }) {
|
|||||||
🎮 Chiptune Demo
|
🎮 Chiptune Demo
|
||||||
</button>
|
</button>
|
||||||
<button className="toolbar-btn" onClick={() => { handleClearCanvas(); setMenuOpen(false); }}>🗑 Limpiar</button>
|
<button className="toolbar-btn" onClick={() => { handleClearCanvas(); setMenuOpen(false); }}>🗑 Limpiar</button>
|
||||||
|
{onSwitchToWorkshop && (
|
||||||
|
<button className="toolbar-btn" onClick={() => { setMenuOpen(false); onSwitchToWorkshop(); }} style={{ color: 'var(--accent)' }}>
|
||||||
|
🎵 Workshop
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { WORLD_12 } from './levels/world12.js';
|
|||||||
|
|
||||||
const allWorlds = [WORLD_1, WORLD_2, WORLD_3, WORLD_4, WORLD_5, WORLD_6, WORLD_7, WORLD_8, WORLD_9, WORLD_10, WORLD_11, WORLD_12];
|
const allWorlds = [WORLD_1, WORLD_2, WORLD_3, WORLD_4, WORLD_5, WORLD_6, WORLD_7, WORLD_8, WORLD_9, WORLD_10, WORLD_11, WORLD_12];
|
||||||
|
|
||||||
export default function GameApp({ onSwitchToSandbox }) {
|
export default function GameApp({ onSwitchToSandbox, onSwitchToWorkshop }) {
|
||||||
const [view, setView] = useState('map');
|
const [view, setView] = useState('map');
|
||||||
const [currentLevel, setCurrentLevel] = useState(null);
|
const [currentLevel, setCurrentLevel] = useState(null);
|
||||||
const [currentLevelIndex, setCurrentLevelIndex] = useState(0);
|
const [currentLevelIndex, setCurrentLevelIndex] = useState(0);
|
||||||
@@ -78,6 +78,7 @@ export default function GameApp({ onSwitchToSandbox }) {
|
|||||||
<WorldMap
|
<WorldMap
|
||||||
onSelectLevel={handleSelectLevel}
|
onSelectLevel={handleSelectLevel}
|
||||||
onSandbox={onSwitchToSandbox}
|
onSandbox={onSwitchToSandbox}
|
||||||
|
onWorkshop={onSwitchToWorkshop}
|
||||||
onAdmin={() => setShowAdmin(true)}
|
onAdmin={() => setShowAdmin(true)}
|
||||||
/>
|
/>
|
||||||
{showAdmin && (
|
{showAdmin && (
|
||||||
|
|||||||
@@ -45,10 +45,11 @@ function isWorldUnlocked(world) {
|
|||||||
const MOBILE_TABS = [
|
const MOBILE_TABS = [
|
||||||
{ id: 'game', label: 'JUEGO', icon: '🎮' },
|
{ id: 'game', label: 'JUEGO', icon: '🎮' },
|
||||||
{ id: 'sandbox', label: 'SANDBOX', icon: '🎛' },
|
{ id: 'sandbox', label: 'SANDBOX', icon: '🎛' },
|
||||||
|
{ id: 'workshop', label: 'WORKSHOP', icon: '🎵' },
|
||||||
{ id: 'config', label: 'CONFIG', icon: '⚙' },
|
{ id: 'config', label: 'CONFIG', icon: '⚙' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function WorldMap({ onSelectLevel, onSandbox, onAdmin }) {
|
export default function WorldMap({ onSelectLevel, onSandbox, onAdmin, onWorkshop }) {
|
||||||
const totalStars = getTotalStars();
|
const totalStars = getTotalStars();
|
||||||
const maxStars = getMaxStars();
|
const maxStars = getMaxStars();
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
@@ -236,6 +237,7 @@ export default function WorldMap({ onSelectLevel, onSandbox, onAdmin }) {
|
|||||||
activeTab="game"
|
activeTab="game"
|
||||||
onTabChange={(id) => {
|
onTabChange={(id) => {
|
||||||
if (id === 'sandbox') onSandbox?.();
|
if (id === 'sandbox') onSandbox?.();
|
||||||
|
if (id === 'workshop') onWorkshop?.();
|
||||||
if (id === 'config') onAdmin?.();
|
if (id === 'config') onAdmin?.();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1006,11 +1006,24 @@ input, textarea, [contenteditable] { -webkit-user-select: text; user-select: tex
|
|||||||
.ws-load-btn:hover { background: var(--accent); color: #000; border-color: var(--accent); }
|
.ws-load-btn:hover { background: var(--accent); color: #000; border-color: var(--accent); }
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.ws-page { padding: 16px; gap: 16px; }
|
.ws-page { padding: 12px; gap: 12px; height: 100dvh; }
|
||||||
|
.ws-nav { flex-wrap: wrap; gap: 8px; padding: 0 0 12px; }
|
||||||
|
.ws-nav-logo { display: none; }
|
||||||
|
.ws-nav-tabs { width: 100%; gap: 2px; }
|
||||||
|
.ws-nav-tab { flex: 1; text-align: center; font-size: 12px; padding: 8px 4px; }
|
||||||
|
.ws-header { display: none; }
|
||||||
.ws-title { font-size: 22px; }
|
.ws-title { font-size: 22px; }
|
||||||
.ws-toolbar { flex-direction: column; }
|
.ws-toolbar { flex-direction: column; gap: 8px; }
|
||||||
.ws-tags { overflow-x: auto; flex-wrap: nowrap; }
|
.ws-search { min-width: unset; }
|
||||||
.ws-grid { grid-template-columns: 1fr; }
|
.ws-tags { overflow-x: auto; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; }
|
||||||
|
.ws-sort { width: 100%; }
|
||||||
|
.ws-share-btn { width: 100%; text-align: center; padding: 12px; font-size: 14px; }
|
||||||
|
.ws-grid { grid-template-columns: 1fr; gap: 10px; }
|
||||||
|
.ws-card-preview { height: 60px; }
|
||||||
|
.ws-card-body { padding: 10px 12px; }
|
||||||
|
.user-badge { padding: 4px 8px; }
|
||||||
|
.login-btn { padding: 6px 12px; }
|
||||||
|
.auth-card { padding: 24px 20px; max-height: 90vh; overflow-y: auto; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===== Fullscreen Keyboard ===== */
|
/* ===== Fullscreen Keyboard ===== */
|
||||||
|
|||||||
Reference in New Issue
Block a user