@@ -68,7 +68,7 @@ const CHART_CONFIG = {
6868 statCardHeight : '33px' ,
6969 width : '100%' ,
7070 overviewMaxHeight : 179 ,
71- completionMaxHeight : 60 ,
71+ completionMaxHeight : 118 ,
7272 } ,
7373
7474 aspectRatio : {
@@ -88,7 +88,7 @@ const CHART_CONFIG = {
8888 } ,
8989
9090 bar : {
91- thickness : 54 ,
91+ thickness : 118 ,
9292 borderRadius : 5 ,
9393 borderWidth : 3 ,
9494 } ,
@@ -140,17 +140,45 @@ const getCSSProperty = (element: HTMLElement, propertyName: string): string => {
140140 return getComputedStyle ( element ) . getPropertyValue ( propertyName ) . trim ( ) ;
141141} ;
142142
143- const getAnimationConfig = ( ) : { duration : 0 } | undefined => {
143+ const shouldReduceMotion = ( ) : boolean => {
144144 const wrapper = document . querySelector ( '[data-tutor-theme]' ) || document . documentElement ;
145145 const motion = wrapper . getAttribute ( 'data-tutor-motion' ) ;
146+ return (
147+ motion === 'reduce' ||
148+ ( ( ! motion || motion === 'auto' ) && window . matchMedia ( '(prefers-reduced-motion: reduce)' ) . matches )
149+ ) ;
150+ } ;
146151
147- if ( motion === 'reduce' ) {
152+ const getAnimationConfig = ( ) : { duration : 0 } | undefined => {
153+ if ( shouldReduceMotion ( ) ) {
148154 return { duration : 0 } ;
149155 }
150- if ( ( ! motion || motion === 'auto' ) && window . matchMedia ( '(prefers-reduced-motion: reduce)' ) . matches ) {
156+ return undefined ;
157+ } ;
158+
159+ const getCompletionChartAnimation = ( ) : { duration : 0 } | Record < string , unknown > => {
160+ if ( shouldReduceMotion ( ) ) {
151161 return { duration : 0 } ;
152162 }
153- return undefined ;
163+
164+ return {
165+ base : { duration : 0 } ,
166+ x : {
167+ from : ( ctx : Record < string , unknown > ) => {
168+ const chart = ctx . chart as {
169+ scales : { x : { getPixelForValue : ( v : number ) => number } } ;
170+ data : { datasets : Array < { data : Array < number > } > } ;
171+ } ;
172+ const dataIndex = ctx . dataIndex as number ;
173+ const datasetIndex = ctx . datasetIndex as number ;
174+ let cumulative = 0 ;
175+ for ( let i = 0 ; i < datasetIndex ; i ++ ) {
176+ cumulative += chart . data . datasets [ i ] . data [ dataIndex ] || 0 ;
177+ }
178+ return chart . scales . x . getPixelForValue ( cumulative ) ;
179+ } ,
180+ } ,
181+ } ;
154182} ;
155183
156184const createChart = ( canvas : HTMLCanvasElement , config : ChartConfiguration ) : void => {
@@ -791,6 +819,9 @@ export const courseCompletionChart = (data: CourseCompletionChartData) => ({
791819 const chartColors = [ colors . enrolled , colors . completed , colors . in_progress , colors . inactive , colors . cancelled ] ;
792820 const dataKeys : CourseCompletionChartDataKey [ ] = [ 'enrolled' , 'completed' , 'in_progress' , 'inactive' , 'cancelled' ] ;
793821
822+ const lastNonZeroIndex = chartData . reduce ( ( last , value , i ) => ( value > 0 ? i : last ) , - 1 ) ;
823+ const firstNonZeroIndex = chartData . findIndex ( ( value ) => value > 0 ) ;
824+
794825 return {
795826 type : 'bar' ,
796827 data : {
@@ -800,20 +831,29 @@ export const courseCompletionChart = (data: CourseCompletionChartData) => ({
800831 backgroundColor : chartColors [ index ] ,
801832 barThickness : CHART_CONFIG . bar . thickness ,
802833 borderRadius : {
803- bottomLeft : index === 0 ? CHART_CONFIG . bar . borderRadius : 0 ,
804- topLeft : index === 0 ? CHART_CONFIG . bar . borderRadius : 0 ,
805- bottomRight : index === chartData . length - 1 ? CHART_CONFIG . bar . borderRadius : 0 ,
806- topRight : index === chartData . length - 1 ? CHART_CONFIG . bar . borderRadius : 0 ,
834+ bottomLeft : index === ( firstNonZeroIndex > - 1 ? firstNonZeroIndex : 0 ) ? CHART_CONFIG . bar . borderRadius : 0 ,
835+ topLeft : index === ( firstNonZeroIndex > - 1 ? firstNonZeroIndex : 0 ) ? CHART_CONFIG . bar . borderRadius : 0 ,
836+ bottomRight :
837+ index === ( lastNonZeroIndex > - 1 ? lastNonZeroIndex : chartData . length - 1 )
838+ ? CHART_CONFIG . bar . borderRadius
839+ : 0 ,
840+ topRight :
841+ index === ( lastNonZeroIndex > - 1 ? lastNonZeroIndex : chartData . length - 1 )
842+ ? CHART_CONFIG . bar . borderRadius
843+ : 0 ,
807844 } ,
808845 borderSkipped : false ,
809846 borderWidth : {
810- right : index === chartData . length - 1 ? 0 : CHART_CONFIG . bar . borderWidth ,
847+ right :
848+ index === ( lastNonZeroIndex > - 1 ? lastNonZeroIndex : chartData . length - 1 )
849+ ? 0
850+ : CHART_CONFIG . bar . borderWidth ,
811851 } ,
812852 borderColor : getCSSProperty ( this . $refs . canvas , '--tutor-surface-l1' ) ,
813853 } ) ) ,
814854 } ,
815855 options : {
816- animation : getAnimationConfig ( ) ,
856+ animation : getCompletionChartAnimation ( ) ,
817857 indexAxis : 'y' ,
818858 responsive : CHART_CONFIG . common . responsive ,
819859 maintainAspectRatio : false ,
0 commit comments