11import clsx from 'clsx' ;
2+ import './contribution-graph.css' ;
23
34interface Props {
45 caption ?: string ;
@@ -13,19 +14,20 @@ const monthFormat = new Intl.DateTimeFormat('en-US', { month: 'short', timeZone:
1314const monthFormatFull = new Intl . DateTimeFormat ( 'en-US' , { month : 'long' , timeZone : 'UTC' } ) . format ;
1415
1516export function ContributionGraph ( props : Props ) {
16- const totals = props . contributions [ 0 ] ! . reduce ( ( memo , [ , , inRange ] , i ) => {
17- memo . push ( [
18- props . contributions . reduce ( ( memo , weekday ) => {
19- if ( ! weekday [ i ] ) {
20- return memo ;
21- }
22- return memo + weekday [ i ] ! [ 1 ] ;
23- } , 0 ) ,
24- inRange ,
25- ] ) ;
26- return memo ;
27- } , [ ] as Array < [ number , boolean ] > ) ;
28- const max = Math . max ( ...totals . map ( ( [ t ] ) => t ) ) ;
17+ const totals =
18+ props . contributions [ 0 ] ?. reduce ( ( memo , [ , , inRange ] , i ) => {
19+ memo . push ( [
20+ props . contributions . reduce ( ( memo , weekday ) => {
21+ if ( ! weekday [ i ] ) {
22+ return memo ;
23+ }
24+ return memo + weekday [ i ] ! [ 1 ] ;
25+ } , 0 ) ,
26+ inRange ,
27+ ] ) ;
28+ return memo ;
29+ } , [ ] as Array < [ number , boolean ] > ) ?? [ ] ;
30+ const max = Math . max ( ...totals . map ( ( [ t ] ) => t ) , 6 ) ;
2931
3032 const months = props . contributions [ 0 ] ! . reduce ( ( memo , [ day ] ) => {
3133 if ( day . getMonth ( ) === memo [ memo . length - 1 ] ?. date . getMonth ( ) ) {
@@ -37,17 +39,17 @@ export function ContributionGraph(props: Props) {
3739 } , [ ] as Array < { colSpan : number ; date : Date } > ) ;
3840
3941 return (
40- < div class = "not-prose overflow-scroll text-[10px] leading-none" >
41- < table class = "mb-4 min-w-min max-w-full border-separate border-spacing-[2px]" >
42- { props . caption ? < caption class = "text-black dark:text-white" > { props . caption } </ caption > : null }
42+ < div class = "contribution-graph not-prose overflow-scroll text-[10px] leading-none" >
43+ < table >
44+ { props . caption ? < caption > { props . caption } </ caption > : null }
4345 < thead >
4446 < tr >
4547 < th > </ th >
4648 { months . map ( ( { colSpan, date } ) =>
4749 colSpan < 3 ? (
4850 < th colSpan = { colSpan } />
4951 ) : (
50- < th role = "columnheader" class = "text-left text-gray-600 dark:text-gray-400" colSpan = { colSpan } >
52+ < th role = "columnheader" colSpan = { colSpan } >
5153 < span aria-hidden > { monthFormat ( date ) } </ span >
5254 < span class = "sr-only" > { monthFormatFull ( date ) } </ span >
5355 </ th >
@@ -59,7 +61,7 @@ export function ContributionGraph(props: Props) {
5961 { props . contributions . map ( ( dayOfWeek , w ) => {
6062 return (
6163 < tr >
62- < th role = "rowheader" class = "h-2 w-6 overflow-hidden p-0 pe-1 text-end text-gray-600 dark:text-gray-400" >
64+ < th role = "rowheader" >
6365 { ! ( w % 2 ) || w === 7 ? null : (
6466 < >
6567 < span class = "sr-only" > { dayFullFormat ( dayOfWeek [ 0 ] ! [ 0 ] ) } </ span >
@@ -70,10 +72,7 @@ export function ContributionGraph(props: Props) {
7072 { dayOfWeek . map ( ( [ day , contributions , inRange ] ) => {
7173 const title = `${ contributions } contributions on ${ formatter ( day ) } ` ;
7274 return (
73- < td
74- class = { clsx ( 'h-2 w-2 rounded-[0.5px] sm:h-3 sm:w-3' , opacity [ contributions ] , getColor ( inRange ) ) }
75- title = { title }
76- >
75+ < td class = { clsx ( 'day' , opacity [ contributions ] , getColor ( inRange ) ) } title = { title } >
7776 < div class = "h-2 w-2" />
7877 < span class = "sr-only" > { title } </ span >
7978 </ td >
@@ -84,39 +83,36 @@ export function ContributionGraph(props: Props) {
8483 } ) }
8584 </ tbody >
8685 </ table >
87- < table class = "mb-4 min-w-min max-w-full border-separate border-spacing-[2px]" >
88- < caption class = "text-black dark:text-white" > Number of contributions by week</ caption >
89- < tr role = "presentation" >
90- < td class = "w-6 overflow-hidden p-0 pe-1" />
91- { totals . map ( ( [ value , inRange ] ) => {
92- return (
93- < td class = "w-2 rounded-[0.5px] p-0 sm:w-3" >
94- < div class = "flex h-20 flex-col justify-end" >
95- < div
96- style = { { 'flex-basis' : `${ Math . ceil ( ( value / max ) * 100 ) } %` } }
97- class = { clsx (
98- 'w-2 shrink rounded-sm sm:w-3' ,
99- opacity [ Math . floor ( ( value / max ) * 10 ) ] ,
100- getColor ( inRange )
101- ) }
102- />
103- </ div >
86+ < table >
87+ < caption > Number of contributions by week</ caption >
88+ < tbody >
89+ < tr role = "presentation" >
90+ < th role = "rowheader" />
91+ { totals . map ( ( [ value , inRange ] ) => {
92+ return (
93+ < td class = "total-bar-cell" >
94+ < div class = "total-bar-container" >
95+ < div
96+ style = { { 'flex-basis' : `${ Math . ceil ( ( value / max ) * 100 ) } %` } }
97+ class = { clsx ( 'total-bar' , opacity [ Math . floor ( ( value / max ) * 10 ) ] , getColor ( inRange ) ) }
98+ />
99+ </ div >
100+ </ td >
101+ ) ;
102+ } ) }
103+ </ tr >
104+ < tr >
105+ < th role = "rowheader" >
106+ < span aria-hidden > Tot.</ span >
107+ < span class = "sr-only" > Total</ span >
108+ </ th >
109+ { totals . map ( ( [ value ] ) => (
110+ < td class = "total-bar-cell" >
111+ < span class = "total" > { value } </ span >
104112 </ td >
105- ) ;
106- } ) }
107- </ tr >
108- < tr >
109- < td class = "w-6 overflow-hidden pe-1" >
110- < span class = "sr-only" > Total</ span >
111- </ td >
112- { totals . map ( ( value ) => (
113- < td class = "p-0" >
114- < span class = "h-4 shrink-0 text-[9px] leading-none text-black writing-vertical-lr dark:text-white" >
115- { value }
116- </ span >
117- </ td >
118- ) ) }
119- </ tr >
113+ ) ) }
114+ </ tr >
115+ </ tbody >
120116 </ table >
121117 </ div >
122118 ) ;
@@ -127,7 +123,7 @@ function weekInRange(week: number, range: [number, number] = [-1, 1000]) {
127123}
128124
129125function getColor ( inRange : boolean ) {
130- return inRange ? 'bg-teal-500 p-0 dark:bg-teal-300 ' : 'bg-slate-300 p-0 dark:bg-slate-700 ' ;
126+ return inRange ? 'in-range ' : '' ;
131127}
132128function randomInt ( min : number , max : number ) {
133129 return Math . floor ( Math . random ( ) * ( max - min ) + min ) ;
0 commit comments