1- import { useState , useCallback } from 'react'
1+ import { useState , useCallback , useEffect } from 'react'
22import type { MusicStyle , MusicResult , ParseResult } from '../core/index'
33import { parseCode , mapCodeToMusic } from '../core/index'
44import Visualizer from '../components/Visualizer'
@@ -216,7 +216,19 @@ const STYLES: { value: MusicStyle; label: string; emoji: string }[] = [
216216 { value : 'lofi' , label : 'Lo-Fi' , emoji : '☕' } ,
217217]
218218
219+ function useIsMobile ( ) {
220+ const [ isMobile , setIsMobile ] = useState ( false )
221+ useEffect ( ( ) => {
222+ const check = ( ) => setIsMobile ( window . innerWidth < 768 )
223+ check ( )
224+ window . addEventListener ( 'resize' , check )
225+ return ( ) => window . removeEventListener ( 'resize' , check )
226+ } , [ ] )
227+ return isMobile
228+ }
229+
219230export default function Home ( ) {
231+ const isMobile = useIsMobile ( )
220232 const [ code , setCode ] = useState ( SAMPLE_CODES . python )
221233 const [ language , setLanguage ] = useState ( 'python' )
222234 const [ style , setStyle ] = useState < MusicStyle > ( 'piano' )
@@ -357,7 +369,7 @@ export default function Home() {
357369 } } >
358370 { /* Header */ }
359371 < header style = { {
360- padding : '16px 24px' ,
372+ padding : isMobile ? '12px 16px' : '16px 24px' ,
361373 display : 'flex' ,
362374 alignItems : 'center' ,
363375 justifyContent : 'space-between' ,
@@ -367,36 +379,38 @@ export default function Home() {
367379 position : 'sticky' ,
368380 top : 0 ,
369381 zIndex : 100 ,
382+ flexWrap : isMobile ? 'wrap' : 'nowrap' ,
383+ gap : 8 ,
370384 } } >
371- < div style = { { display : 'flex' , alignItems : 'center' , gap : 12 } } >
372- < span style = { { fontSize : 28 } } > 🎵</ span >
385+ < div style = { { display : 'flex' , alignItems : 'center' , gap : isMobile ? 8 : 12 } } >
386+ < span style = { { fontSize : isMobile ? 22 : 28 } } > 🎵</ span >
373387 < div >
374388 < h1 style = { {
375389 margin : 0 ,
376- fontSize : 22 ,
390+ fontSize : isMobile ? 18 : 22 ,
377391 fontWeight : 700 ,
378392 background : 'linear-gradient(135deg, #6366f1, #ec4899)' ,
379393 WebkitBackgroundClip : 'text' ,
380394 WebkitTextFillColor : 'transparent' ,
381395 } } >
382396 CodeBeats
383397 </ h1 >
384- < p style = { { margin : 0 , fontSize : 12 , color : '#94a3b8' } } > Hear what your code sounds like</ p >
398+ < p style = { { margin : 0 , fontSize : isMobile ? 10 : 12 , color : '#94a3b8' } } > Hear what your code sounds like</ p >
385399 </ div >
386400 </ div >
387- < div style = { { display : 'flex' , gap : 8 , flexWrap : 'wrap' } } >
401+ < div style = { { display : 'flex' , gap : 6 , flexWrap : 'wrap' } } >
388402 { [ 'python' , 'javascript' , 'rust' , 'c' ] . map ( lang => (
389403 < button
390404 key = { lang }
391405 onClick = { ( ) => handleSampleCode ( lang ) }
392406 style = { {
393- padding : '6px 14px' ,
407+ padding : isMobile ? '4px 10px' : '6px 14px' ,
394408 border : language === lang ? '1px solid #6366f1' : '1px solid rgba(99, 102, 241, 0.3)' ,
395409 borderRadius : 20 ,
396410 background : language === lang ? 'rgba(99, 102, 241, 0.2)' : 'transparent' ,
397411 color : language === lang ? '#a5b4fc' : '#94a3b8' ,
398412 cursor : 'pointer' ,
399- fontSize : 13 ,
413+ fontSize : isMobile ? 11 : 13 ,
400414 fontFamily : 'monospace' ,
401415 transition : 'all 0.2s' ,
402416 } }
@@ -409,15 +423,15 @@ export default function Home() {
409423
410424 < div style = { {
411425 display : 'grid' ,
412- gridTemplateColumns : '1fr 1fr' ,
413- gap : 16 ,
414- padding : 16 ,
426+ gridTemplateColumns : isMobile ? '1fr' : '1fr 1fr' ,
427+ gap : isMobile ? 10 : 16 ,
428+ padding : isMobile ? 10 : 16 ,
415429 maxWidth : 1400 ,
416430 margin : '0 auto' ,
417- minHeight : 'calc(100vh - 70px)' ,
431+ minHeight : isMobile ? 'auto' : 'calc(100vh - 70px)' ,
418432 } } >
419433 { /* Left: Code Editor */ }
420- < div style = { { display : 'flex' , flexDirection : 'column' , gap : 12 , maxHeight : 'calc(100vh - 100px)' , overflow : 'hidden' } } >
434+ < div style = { { display : 'flex' , flexDirection : 'column' , gap : isMobile ? 8 : 12 , maxHeight : isMobile ? 'none' : 'calc(100vh - 100px)' , overflow : 'hidden' } } >
421435 < div style = { {
422436 background : 'rgba(15, 15, 35, 0.8)' ,
423437 borderRadius : 12 ,
@@ -454,13 +468,13 @@ export default function Home() {
454468 border : 'none' ,
455469 color : '#e2e8f0' ,
456470 fontFamily : '"Fira Code", "Cascadia Code", "JetBrains Mono", monospace' ,
457- fontSize : 13 ,
471+ fontSize : isMobile ? 11 : 13 ,
458472 lineHeight : 1.6 ,
459- padding : 16 ,
473+ padding : isMobile ? 10 : 16 ,
460474 resize : 'none' ,
461475 outline : 'none' ,
462476 tabSize : 2 ,
463- maxHeight : '50vh' ,
477+ maxHeight : isMobile ? '35vh' : '50vh' ,
464478 overflowY : 'auto' ,
465479 } }
466480 />
@@ -471,24 +485,24 @@ export default function Home() {
471485 background : 'rgba(15, 15, 35, 0.8)' ,
472486 borderRadius : 12 ,
473487 border : '1px solid rgba(99, 102, 241, 0.15)' ,
474- padding : 12 ,
488+ padding : isMobile ? 8 : 12 ,
475489 } } >
476- < div style = { { fontSize : 12 , color : '#94a3b8' , marginBottom : 8 , fontWeight : 600 } } >
490+ < div style = { { fontSize : 11 , color : '#94a3b8' , marginBottom : 6 , fontWeight : 600 } } >
477491 MUSIC STYLE
478492 </ div >
479- < div style = { { display : 'flex' , gap : 6 , flexWrap : 'wrap' } } >
493+ < div style = { { display : 'flex' , gap : 4 , flexWrap : 'wrap' } } >
480494 { STYLES . map ( s => (
481495 < button
482496 key = { s . value }
483497 onClick = { ( ) => handleStyleChange ( s . value ) }
484498 style = { {
485- padding : '6px 12px' ,
499+ padding : isMobile ? '4px 8px' : '6px 12px' ,
486500 border : style === s . value ? '1px solid #6366f1' : '1px solid rgba(99, 102, 241, 0.2)' ,
487501 borderRadius : 8 ,
488502 background : style === s . value ? 'rgba(99, 102, 241, 0.2)' : 'rgba(255,255,255,0.03)' ,
489503 color : style === s . value ? '#a5b4fc' : '#94a3b8' ,
490504 cursor : 'pointer' ,
491- fontSize : 12 ,
505+ fontSize : isMobile ? 10 : 12 ,
492506 transition : 'all 0.2s' ,
493507 } }
494508 >
@@ -503,26 +517,27 @@ export default function Home() {
503517 background : 'rgba(15, 15, 35, 0.8)' ,
504518 borderRadius : 12 ,
505519 border : '1px solid rgba(99, 102, 241, 0.15)' ,
506- padding : 16 ,
520+ padding : isMobile ? 10 : 16 ,
507521 display : 'flex' ,
508522 alignItems : 'center' ,
509- gap : 12 ,
523+ gap : isMobile ? 8 : 12 ,
524+ flexWrap : isMobile ? 'wrap' : 'nowrap' ,
510525 } } >
511526 < button
512527 onClick = { handlePlay }
513528 style = { {
514- padding : '10px 24px' ,
529+ padding : isMobile ? '8px 18px' : '10px 24px' ,
515530 border : 'none' ,
516531 borderRadius : 8 ,
517532 background : isPlaying
518533 ? 'linear-gradient(135deg, #ef4444, #dc2626)'
519534 : 'linear-gradient(135deg, #6366f1, #8b5cf6)' ,
520535 color : 'white' ,
521536 cursor : 'pointer' ,
522- fontSize : 14 ,
537+ fontSize : isMobile ? 13 : 14 ,
523538 fontWeight : 600 ,
524539 transition : 'all 0.2s' ,
525- minWidth : 100 ,
540+ minWidth : isMobile ? 80 : 100 ,
526541 } }
527542 >
528543 { isPlaying ? '⏹ Stop' : '▶ Play' }
@@ -531,21 +546,21 @@ export default function Home() {
531546 < button
532547 onClick = { handleAnalyze }
533548 style = { {
534- padding : '10px 20px' ,
549+ padding : isMobile ? '8px 14px' : '10px 20px' ,
535550 border : '1px solid rgba(99, 102, 241, 0.3)' ,
536551 borderRadius : 8 ,
537552 background : 'rgba(99, 102, 241, 0.1)' ,
538553 color : '#a5b4fc' ,
539554 cursor : 'pointer' ,
540- fontSize : 14 ,
555+ fontSize : isMobile ? 12 : 14 ,
541556 transition : 'all 0.2s' ,
542557 } }
543558 >
544559 🔍 Analyze
545560 </ button >
546561
547- < div style = { { flex : 1 , display : 'flex' , alignItems : 'center' , gap : 8 } } >
548- < span style = { { fontSize : 16 } } > 🔊</ span >
562+ < div style = { { flex : 1 , display : 'flex' , alignItems : 'center' , gap : 8 , minWidth : isMobile ? '100%' : 'auto' } } >
563+ < span style = { { fontSize : 14 } } > 🔊</ span >
549564 < input
550565 type = "range"
551566 min = "0"
@@ -561,13 +576,13 @@ export default function Home() {
561576 < button
562577 onClick = { handleShare }
563578 style = { {
564- padding : '10px 16px' ,
579+ padding : isMobile ? '8px 12px' : '10px 16px' ,
565580 border : '1px solid rgba(99, 102, 241, 0.3)' ,
566581 borderRadius : 8 ,
567582 background : 'rgba(99, 102, 241, 0.1)' ,
568583 color : '#a5b4fc' ,
569584 cursor : 'pointer' ,
570- fontSize : 14 ,
585+ fontSize : isMobile ? 12 : 14 ,
571586 } }
572587 >
573588 📤 Share
@@ -577,15 +592,15 @@ export default function Home() {
577592 </ div >
578593
579594 { /* Right: Visualizer + Info */ }
580- < div style = { { display : 'flex' , flexDirection : 'column' , gap : 12 } } >
595+ < div style = { { display : 'flex' , flexDirection : 'column' , gap : isMobile ? 8 : 12 } } >
581596 { /* Visualizer */ }
582597 < div style = { {
583598 background : 'rgba(15, 15, 35, 0.8)' ,
584599 borderRadius : 12 ,
585600 border : '1px solid rgba(99, 102, 241, 0.15)' ,
586601 overflow : 'hidden' ,
587602 flex : 1 ,
588- minHeight : 300 ,
603+ minHeight : isMobile ? 200 : 300 ,
589604 } } >
590605 < Visualizer
591606 music = { music }
@@ -601,15 +616,15 @@ export default function Home() {
601616 background : 'rgba(15, 15, 35, 0.8)' ,
602617 borderRadius : 12 ,
603618 border : '1px solid rgba(99, 102, 241, 0.15)' ,
604- padding : 16 ,
619+ padding : isMobile ? 10 : 16 ,
605620 } } >
606- < div style = { { fontSize : 12 , color : '#94a3b8' , marginBottom : 10 , fontWeight : 600 } } >
621+ < div style = { { fontSize : 11 , color : '#94a3b8' , marginBottom : 8 , fontWeight : 600 } } >
607622 CODE ANALYSIS
608623 </ div >
609624 < div style = { {
610625 display : 'grid' ,
611- gridTemplateColumns : 'repeat(4, 1fr)' ,
612- gap : 8 ,
626+ gridTemplateColumns : isMobile ? 'repeat(4, 1fr)' : 'repeat(4, 1fr)' ,
627+ gap : isMobile ? 4 : 8 ,
613628 } } >
614629 { [
615630 { label : 'Functions' , value : parseResult . stats . functions , emoji : '🎵' } ,
@@ -624,12 +639,12 @@ export default function Home() {
624639 < div key = { stat . label } style = { {
625640 background : 'rgba(99, 102, 241, 0.08)' ,
626641 borderRadius : 8 ,
627- padding : '8px 10px' ,
642+ padding : isMobile ? '6px 4px' : '8px 10px' ,
628643 textAlign : 'center' ,
629644 } } >
630- < div style = { { fontSize : 18 } } > { stat . emoji } </ div >
631- < div style = { { fontSize : 18 , fontWeight : 700 , color : '#e2e8f0' } } > { stat . value } </ div >
632- < div style = { { fontSize : 10 , color : '#94a3b8' } } > { stat . label } </ div >
645+ < div style = { { fontSize : isMobile ? 14 : 18 } } > { stat . emoji } </ div >
646+ < div style = { { fontSize : isMobile ? 14 : 18 , fontWeight : 700 , color : '#e2e8f0' } } > { stat . value } </ div >
647+ < div style = { { fontSize : isMobile ? 8 : 10 , color : '#94a3b8' } } > { stat . label } </ div >
633648 </ div >
634649 ) ) }
635650 </ div >
@@ -642,12 +657,12 @@ export default function Home() {
642657 background : 'rgba(15, 15, 35, 0.8)' ,
643658 borderRadius : 12 ,
644659 border : '1px solid rgba(99, 102, 241, 0.15)' ,
645- padding : 16 ,
660+ padding : isMobile ? 10 : 16 ,
646661 } } >
647- < div style = { { fontSize : 12 , color : '#94a3b8' , marginBottom : 10 , fontWeight : 600 } } >
662+ < div style = { { fontSize : 11 , color : '#94a3b8' , marginBottom : 8 , fontWeight : 600 } } >
648663 MUSIC INFO
649664 </ div >
650- < div style = { { display : 'flex' , gap : 16 , flexWrap : 'wrap' } } >
665+ < div style = { { display : 'flex' , gap : isMobile ? 8 : 16 , flexWrap : 'wrap' , fontSize : isMobile ? 11 : 13 } } >
651666 < span style = { { color : '#a5b4fc' , fontFamily : 'monospace' } } >
652667 🎼 { music . key } { music . scale }
653668 </ span >
@@ -667,7 +682,7 @@ export default function Home() {
667682
668683 { /* Section Timeline */ }
669684 < div style = { {
670- marginTop : 12 ,
685+ marginTop : isMobile ? 8 : 12 ,
671686 display : 'flex' ,
672687 gap : 2 ,
673688 overflow : 'hidden' ,
@@ -680,7 +695,7 @@ export default function Home() {
680695 onClick = { ( ) => setActiveSectionIndex ( idx ) }
681696 style = { {
682697 flex : section . notes . length || 1 ,
683- height : 24 ,
698+ height : isMobile ? 18 : 24 ,
684699 background : idx === activeSectionIndex
685700 ? 'linear-gradient(135deg, #6366f1, #ec4899)'
686701 : 'rgba(99, 102, 241, 0.2)' ,
0 commit comments