@@ -4,6 +4,7 @@ import type {
44 BigNumberAggregationType ,
55 BigNumberConfiguration ,
66} from "~/components/metrics/QueryWidget" ;
7+ import { AnimatedNumber } from "../AnimatedNumber" ;
78import { Spinner } from "../Spinner" ;
89import { Paragraph } from "../Paragraph" ;
910
@@ -79,42 +80,45 @@ function aggregateValues(values: number[], aggregation: BigNumberAggregationType
7980}
8081
8182/**
82- * Formats a number for display as a big number with abbreviation (K/M/B suffixes).
83+ * Computes the display value and unit suffix for abbreviated display.
84+ * Returns the divided-down number (e.g. 1.5 for 1500) and the suffix (e.g. "K"),
85+ * along with the appropriate decimal places for formatting.
8386 */
84- function formatBigNumberAbbreviated ( value : number ) : { formatted : string ; unitSuffix ?: string } {
87+ function abbreviateValue ( value : number ) : {
88+ displayValue : number ;
89+ unitSuffix ?: string ;
90+ decimalPlaces : number ;
91+ } {
8592 if ( Math . abs ( value ) >= 1_000_000_000 ) {
8693 const v = value / 1_000_000_000 ;
87- return { formatted : v % 1 === 0 ? v . toFixed ( 0 ) : v . toFixed ( 1 ) , unitSuffix : "B" } ;
94+ return { displayValue : v , unitSuffix : "B" , decimalPlaces : v % 1 === 0 ? 0 : 1 } ;
8895 }
8996 if ( Math . abs ( value ) >= 1_000_000 ) {
9097 const v = value / 1_000_000 ;
91- return { formatted : v % 1 === 0 ? v . toFixed ( 0 ) : v . toFixed ( 1 ) , unitSuffix : "M" } ;
98+ return { displayValue : v , unitSuffix : "M" , decimalPlaces : v % 1 === 0 ? 0 : 1 } ;
9299 }
93100 if ( Math . abs ( value ) >= 1_000 ) {
94101 const v = value / 1_000 ;
95- return { formatted : v % 1 === 0 ? v . toFixed ( 0 ) : v . toFixed ( 1 ) , unitSuffix : "K" } ;
102+ return { displayValue : v , unitSuffix : "K" , decimalPlaces : v % 1 === 0 ? 0 : 1 } ;
96103 }
97- return { formatted : formatPlainNumber ( value ) } ;
104+ return { displayValue : value , decimalPlaces : getDecimalPlaces ( value ) } ;
98105}
99106
100107/**
101- * Formats a number for display without abbreviation .
108+ * Determines decimal places for plain (non-abbreviated) display .
102109 */
103- function formatPlainNumber ( value : number ) : string {
104- if ( Number . isInteger ( value ) ) {
105- return value . toLocaleString ( ) ;
106- }
107- if ( Math . abs ( value ) < 0.01 ) {
108- return value . toFixed ( 4 ) ;
109- }
110- if ( Math . abs ( value ) < 1 ) {
111- return value . toFixed ( 3 ) ;
112- }
113- return value . toFixed ( 2 ) ;
110+ function getDecimalPlaces ( value : number ) : number {
111+ if ( Number . isInteger ( value ) ) return 0 ;
112+ const abs = Math . abs ( value ) ;
113+ if ( abs >= 100 ) return 0 ;
114+ if ( abs >= 10 ) return 1 ;
115+ if ( abs >= 1 ) return 2 ;
116+ if ( abs >= 0.01 ) return 3 ;
117+ return 4 ;
114118}
115119
116120export function BigNumberCard ( { rows, columns, config, isLoading = false } : BigNumberCardProps ) {
117- const { column, aggregation, sortDirection, abbreviate = false , prefix, suffix } = config ;
121+ const { column, aggregation, sortDirection, abbreviate = true , prefix, suffix } = config ;
118122
119123 const result = useMemo ( ( ) => {
120124 if ( rows . length === 0 ) return null ;
@@ -127,38 +131,38 @@ export function BigNumberCard({ rows, columns, config, isLoading = false }: BigN
127131
128132 if ( isLoading ) {
129133 return (
130- < div className = "flex h-full items-center justify-center p-6 " >
134+ < div className = "grid h-full place- items-center [container-type:size] " >
131135 < Spinner className = "size-6" />
132136 </ div >
133137 ) ;
134138 }
135139
136140 if ( result === null ) {
137141 return (
138- < div className = "flex h-full items-center justify-center p-6 " >
142+ < div className = "grid h-full place- items-center [container-type:size] " >
139143 < Paragraph variant = "small" className = "text-text-dimmed" >
140144 No data to display
141145 </ Paragraph >
142146 </ div >
143147 ) ;
144148 }
145149
146- const { formatted , unitSuffix } = abbreviate
147- ? formatBigNumberAbbreviated ( result )
148- : { formatted : formatPlainNumber ( result ) , unitSuffix : undefined } ;
150+ const { displayValue , unitSuffix, decimalPlaces } = abbreviate
151+ ? abbreviateValue ( result )
152+ : { displayValue : result , unitSuffix : undefined , decimalPlaces : getDecimalPlaces ( result ) } ;
149153
150154 return (
151- < div className = "flex h-full items-center justify-center p-6 " >
152- < div className = "text-[3.75rem] font-normal tabular-nums leading-none text-text-bright " >
153- < div className = "flex items-baseline gap-1 " >
155+ < div className = "h-full w-full [container-type:size] " >
156+ < div className = "grid h-full w-full place-items-center " >
157+ < div className = "flex items-baseline gap-[0.15em] whitespace-nowrap font-normal tabular-nums leading-none text-text-bright text-[clamp(24px,12cqw,96px)] " >
154158 { prefix && < span > { prefix } </ span > }
155- { formatted }
159+ < AnimatedNumber value = { displayValue } decimalPlaces = { decimalPlaces } />
156160 { ( unitSuffix || suffix ) && (
157- < div className = "text-2xl text-text-dimmed" >
161+ < span className = "text-[0.4em] text-text-dimmed" >
158162 { unitSuffix }
159163 { unitSuffix && suffix ? " " : "" }
160164 { suffix }
161- </ div >
165+ </ span >
162166 ) }
163167 </ div >
164168 </ div >
0 commit comments