@@ -40,6 +40,7 @@ interface AnalysisMaiaWinrateBarProps {
4040 displayText : string
4141 labelPositionTop : MotionValue < string >
4242 disabled ?: boolean
43+ variant ?: StockfishEvalBarVariant
4344 className ?: string
4445 bubbleMinWidthPx ?: number
4546 desktopSize ?: 'compact' | 'expanded'
@@ -159,7 +160,7 @@ export const AnalysisStockfishEvalBar: React.FC<
159160 ? isExpandedDesktop
160161 ? 'h-6 min-w-[42px] rounded-full px-2 text-[11px]'
161162 : 'h-5 min-w-[36px] rounded-full px-1.5 text-[10px]'
162- : 'h-4 min- w-[30px ] rounded-full px-1 text-[8px ]'
163+ : 'h-[18px] w-[36px ] rounded-full px-1 text-[9px ]'
163164
164165 return (
165166 < div
@@ -234,23 +235,35 @@ export const AnalysisMaiaWinrateBar: React.FC<AnalysisMaiaWinrateBarProps> = ({
234235 displayText,
235236 labelPositionTop,
236237 disabled = false ,
238+ variant = 'desktop' ,
237239 className,
238240 bubbleMinWidthPx,
239241 desktopSize = 'compact' ,
240242} ) => {
243+ const isDesktop = variant === 'desktop'
241244 const isExpandedDesktop = desktopSize === 'expanded'
245+ const widthClass = isDesktop
246+ ? isExpandedDesktop
247+ ? 'w-[18px]'
248+ : 'w-[16px]'
249+ : 'w-4'
250+ const tickTextClass = isDesktop
251+ ? isExpandedDesktop
252+ ? 'text-[9px]'
253+ : 'text-[8px]'
254+ : 'text-[8px]'
255+ const bubbleClass = isDesktop
256+ ? isExpandedDesktop
257+ ? 'h-6 min-w-[42px] px-2 text-[11px]'
258+ : 'h-5 min-w-[36px] px-1.5 text-[10px]'
259+ : 'h-[18px] w-[36px] rounded-full px-1 text-[9px]'
242260 return (
243261 < div
244- className = { [
245- `relative h-full ${ isExpandedDesktop ? 'w-[18px]' : 'w-[16px]' } ` ,
246- className ,
247- ]
262+ className = { [ `relative h-full ${ widthClass } ` , className ]
248263 . filter ( Boolean )
249264 . join ( ' ' ) }
250265 >
251- < div
252- className = { `relative h-full ${ isExpandedDesktop ? 'w-[18px]' : 'w-[16px]' } ` }
253- >
266+ < div className = { `relative h-full ${ widthClass } ` } >
254267 < div
255268 className = "absolute inset-0 overflow-hidden rounded-[5px] border border-glass-border bg-glass-strong shadow-[0_0_0_1px_rgb(var(--color-backdrop)/0.35)]"
256269 style = { {
@@ -282,12 +295,12 @@ export const AnalysisMaiaWinrateBar: React.FC<AnalysisMaiaWinrateBarProps> = ({
282295 ) ,
283296 ) }
284297 < div
285- className = { `absolute left-1/2 top-0 -translate-x-1/2 font-bold leading-none text-black/90 [text-shadow:0_1px_1px_rgb(255_255_255_/_0.5)] ${ isExpandedDesktop ? 'text-[9px]' : 'text-[8px]' } ` }
298+ className = { `absolute left-1/2 top-0 -translate-x-1/2 font-bold leading-none text-black/90 [text-shadow:0_1px_1px_rgb(255_255_255_/_0.5)] ${ tickTextClass } ` }
286299 >
287300 100
288301 </ div >
289302 < div
290- className = { `absolute bottom-0 left-1/2 -translate-x-1/2 font-bold leading-none text-white/95 [text-shadow:0_1px_1px_rgb(0_0_0_/_0.55)] ${ isExpandedDesktop ? 'text-[9px]' : 'text-[8px]' } ` }
303+ className = { `absolute bottom-0 left-1/2 -translate-x-1/2 font-bold leading-none text-white/95 [text-shadow:0_1px_1px_rgb(0_0_0_/_0.55)] ${ tickTextClass } ` }
291304 >
292305 0
293306 </ div >
@@ -296,11 +309,7 @@ export const AnalysisMaiaWinrateBar: React.FC<AnalysisMaiaWinrateBarProps> = ({
296309 ) : null }
297310 </ div >
298311 < motion . div
299- className = { `absolute left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full border border-black/45 bg-white font-bold leading-none text-black/85 ${
300- isExpandedDesktop
301- ? 'h-6 min-w-[42px] px-2 text-[11px]'
302- : 'h-5 min-w-[36px] px-1.5 text-[10px]'
303- } `}
312+ className = { `absolute left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full border border-black/45 bg-white font-bold leading-none text-black/85 ${ bubbleClass } ` }
304313 style = { {
305314 top : labelPositionTop ,
306315 boxShadow : '0 0 0 2px rgb(255 255 255 / 0.32)' ,
@@ -318,6 +327,7 @@ export const AnalysisMaiaWinrateBar: React.FC<AnalysisMaiaWinrateBarProps> = ({
318327type SegmentConfig = {
319328 key : 'blunder' | 'ok' | 'good'
320329 label : string
330+ mobileLabel ?: string
321331 probability : number
322332 topMoves : { move : string ; probability : number ; label : string } [ ]
323333 badge : string
@@ -376,6 +386,7 @@ export const AnalysisCompactBlunderMeter: React.FC<
376386 {
377387 key : 'blunder' ,
378388 label : 'Blunders' ,
389+ mobileLabel : 'Blunders' ,
379390 probability : data . blunderMoves . probability ,
380391 topMoves : getTopCategoryMoves ( data . blunderMoves . moves ) ,
381392 badge : '??' ,
@@ -387,6 +398,7 @@ export const AnalysisCompactBlunderMeter: React.FC<
387398 {
388399 key : 'ok' ,
389400 label : 'Mistakes' ,
401+ mobileLabel : 'Mistakes' ,
390402 probability : data . okMoves . probability ,
391403 topMoves : getTopCategoryMoves ( data . okMoves . moves ) ,
392404 badge : '?' ,
@@ -398,6 +410,7 @@ export const AnalysisCompactBlunderMeter: React.FC<
398410 {
399411 key : 'good' ,
400412 label : 'Best Moves' ,
413+ mobileLabel : 'Best' ,
401414 probability : data . goodMoves . probability ,
402415 topMoves : getTopCategoryMoves ( data . goodMoves . moves ) ,
403416 badge : '✓' ,
@@ -415,13 +428,13 @@ export const AnalysisCompactBlunderMeter: React.FC<
415428 ? 'h-5 min-w-5 text-[10px]'
416429 : 'h-3.5 min-w-3.5 text-[8px]'
417430 const percentTextClass = isDesktop ? 'text-[11px]' : 'text-[9px]'
418- const metaTextClass = isDesktop ? 'text-xs py-1.5' : 'text-[9px ] py-0 .5'
431+ const metaTextClass = isDesktop ? 'text-xs py-1.5' : 'text-[10px ] py-1 .5'
419432 const playedMoveOutlineOuterInsetClass = isDesktop
420433 ? '-inset-x-[11px] -inset-y-[5px]'
421- : '-inset-x-[7px ] -inset-y-[4px ]'
434+ : '-inset-x-[6px ] -inset-y-[2px ]'
422435 const playedMoveOutlineInnerInsetClass = isDesktop
423436 ? '-inset-x-[8px] -inset-y-[3px]'
424- : '-inset-x-[5px ] -inset-y-[3px ]'
437+ : '-inset-x-[4px ] -inset-y-[1px ]'
425438 const renderTopMoveButton = (
426439 segmentKey : string ,
427440 topMove : { move : string ; probability : number ; label : string } ,
@@ -471,6 +484,26 @@ export const AnalysisCompactBlunderMeter: React.FC<
471484 </ button >
472485 )
473486 }
487+ const renderMobileMoveSequence = (
488+ segmentKey : string ,
489+ moves : { move : string ; probability : number ; label : string } [ ] ,
490+ startIndex = 0 ,
491+ ) =>
492+ moves . map ( ( topMove , index ) => {
493+ const absoluteIndex = startIndex + index
494+ return (
495+ < span
496+ key = { `${ segmentKey } -${ topMove . move } -${ absoluteIndex } ` }
497+ className = "inline-flex min-w-0 items-baseline"
498+ >
499+ { absoluteIndex > 0 ? < span className = "mr-1" > </ span > : null }
500+ { renderTopMoveButton ( segmentKey , topMove ) }
501+ { absoluteIndex < startIndex + moves . length - 1 ? (
502+ < span className = "mr-1" > ,</ span >
503+ ) : null }
504+ </ span >
505+ )
506+ } )
474507
475508 return (
476509 < div
@@ -546,22 +579,48 @@ export const AnalysisCompactBlunderMeter: React.FC<
546579 </ div >
547580 ) : (
548581 < div
549- className = { `flex items-center gap-2.5 whitespace-nowrap font-semibold leading-tight tracking-[0.01em] ${ metaTextClass } ` }
582+ className = { `flex min-h-[38px] items-start gap-2.5 pt-1 font-semibold leading-snug tracking-[0.01em] ${ metaTextClass } ` }
550583 >
551584 { segments . map ( ( segment ) => (
552585 < div
553586 key = { `maia-top-moves-${ segment . key } ` }
554- className = { `min-w-0 flex-1 truncate ${ segment . moveClass } ` }
587+ className = { `flex min-w-0 flex-1 items-start ${ segment . moveClass } ${
588+ segment . key === 'good' ? '-ml-5' : ''
589+ } `}
555590 >
556- { segment . label } :{ ' ' }
557- { segment . topMoves . length
558- ? segment . topMoves . map ( ( topMove , index ) => (
559- < span key = { `${ segment . key } -${ topMove . move } ` } >
560- { index > 0 ? < span > , </ span > : null }
561- { renderTopMoveButton ( segment . key , topMove ) }
591+ < span className = "mr-2 shrink-0 whitespace-nowrap" >
592+ { segment . mobileLabel ?? segment . label } :
593+ </ span >
594+ { segment . topMoves . length ? (
595+ segment . topMoves . length >= 3 ? (
596+ < span className = "flex min-w-0 flex-col gap-0.5 leading-tight" >
597+ < span className = "-mx-[6px] inline-flex min-w-0 items-baseline whitespace-nowrap px-[6px]" >
598+ { renderMobileMoveSequence (
599+ segment . key ,
600+ segment . topMoves . slice ( 0 , 2 ) ,
601+ 0 ,
602+ ) }
603+ </ span >
604+ < span className = "-mx-[6px] inline-flex min-w-0 items-baseline whitespace-nowrap px-[6px]" >
605+ { renderMobileMoveSequence (
606+ segment . key ,
607+ segment . topMoves . slice ( 2 ) ,
608+ 2 ,
609+ ) }
562610 </ span >
563- ) )
564- : '-' }
611+ </ span >
612+ ) : (
613+ < span className = "-mx-[6px] inline-flex min-w-0 items-baseline whitespace-nowrap px-[6px]" >
614+ { renderMobileMoveSequence (
615+ segment . key ,
616+ segment . topMoves ,
617+ 0 ,
618+ ) }
619+ </ span >
620+ )
621+ ) : (
622+ '-'
623+ ) }
565624 </ div >
566625 ) ) }
567626 </ div >
0 commit comments