11import React , { memo , useMemo } from 'react' ;
2- import { View , StyleSheet } from 'react-native' ;
2+ import { View , StyleSheet , ViewStyle } from 'react-native' ;
33import {
44 Text ,
55 TextVariant ,
@@ -33,9 +33,6 @@ interface LivePriceHeaderProps {
3333const styleSheet = ( ) =>
3434 StyleSheet . create ( {
3535 container : {
36- flexDirection : 'row' ,
37- alignItems : 'baseline' ,
38- gap : 6 ,
3936 // Allow the row to shrink within a constrained parent so long prices or
4037 // larger system font sizes don't overflow adjacent content.
4138 flexShrink : 1 ,
@@ -45,6 +42,19 @@ const styleSheet = () =>
4542 } ,
4643 } ) ;
4744
45+ // Compact header keeps the change inline with the price; the prominent header
46+ // stacks the change below the price (matches the asset overview screen).
47+ const inlineLayout : ViewStyle = {
48+ flexDirection : 'row' ,
49+ alignItems : 'baseline' ,
50+ gap : 6 ,
51+ } ;
52+ const stackedLayout : ViewStyle = {
53+ flexDirection : 'column' ,
54+ alignItems : 'flex-start' ,
55+ gap : 2 ,
56+ } ;
57+
4858/**
4959 * Component that displays live price and change for header
5060 * Uses currentPrice prop from candle stream, subscribes to price stream for 24h change only
@@ -58,11 +68,12 @@ const LivePriceHeader: React.FC<LivePriceHeaderProps> = ({
5868 size = 'default' ,
5969} ) => {
6070 const isLarge = size === 'large' ;
61- const priceVariant = isLarge ? TextVariant . HeadingLg : TextVariant . BodySm ;
71+ const priceVariant = isLarge ? TextVariant . DisplayLg : TextVariant . BodySm ;
6272 const priceColor = isLarge
6373 ? TextColor . TextDefault
6474 : TextColor . TextAlternative ;
65- const changeVariant = isLarge ? TextVariant . BodyMd : TextVariant . BodySm ;
75+ const changeVariant = TextVariant . BodySm ;
76+ // Match the asset overview screen, which uses a medium-weight change line.
6677 const changeFontWeight = isLarge ? FontWeight . Medium : FontWeight . Regular ;
6778 const { styles } = useStyles ( styleSheet , { } ) ;
6879 // Subscribe to price stream only for 24h change percentage
@@ -107,6 +118,18 @@ const LivePriceHeader: React.FC<LivePriceHeaderProps> = ({
107118 }
108119 } , [ currentPrice ] ) ;
109120
121+ // Absolute 24h change derived from the current price and the 24h percentage
122+ // (the price stream only exposes the percentage). prevPrice = current / (1 + pct/100).
123+ const absoluteChange = useMemo ( ( ) => {
124+ if ( displayChange === null ) return null ;
125+ if ( ! currentPrice || currentPrice <= 0 || ! Number . isFinite ( currentPrice ) ) {
126+ return null ;
127+ }
128+ const previousPrice = currentPrice / ( 1 + displayChange / 100 ) ;
129+ if ( ! Number . isFinite ( previousPrice ) ) return null ;
130+ return currentPrice - previousPrice ;
131+ } , [ currentPrice , displayChange ] ) ;
132+
110133 const formattedChange = useMemo ( ( ) => {
111134 // If displayChange is null, we're still loading - show loading indicator
112135 if ( displayChange === null ) {
@@ -118,14 +141,30 @@ const LivePriceHeader: React.FC<LivePriceHeaderProps> = ({
118141 }
119142
120143 try {
121- return formatPercentage ( displayChange . toString ( ) ) ;
144+ const percentage = formatPercentage ( displayChange . toString ( ) ) ;
145+
146+ // Compact header stays percentage-only; the prominent header mirrors the
147+ // asset overview screen by showing the absolute change and percentage,
148+ // e.g. "+$3.57 (+0.21%)".
149+ if ( ! isLarge || absoluteChange === null ) {
150+ return percentage ;
151+ }
152+
153+ const sign = absoluteChange > 0 ? '+' : absoluteChange < 0 ? '-' : '' ;
154+ const formattedAbsoluteChange = formatPerpsFiat (
155+ Math . abs ( absoluteChange ) ,
156+ {
157+ ranges : PRICE_RANGES_UNIVERSAL ,
158+ } ,
159+ ) ;
160+ return `${ sign } ${ formattedAbsoluteChange } (${ percentage } )` ;
122161 } catch {
123162 return PERPS_CONSTANTS . FallbackPercentageDisplay ;
124163 }
125- } , [ currentPrice , displayChange ] ) ;
164+ } , [ currentPrice , displayChange , isLarge , absoluteChange ] ) ;
126165
127166 return (
128- < View style = { styles . container } >
167+ < View style = { [ styles . container , isLarge ? stackedLayout : inlineLayout ] } >
129168 < Text
130169 variant = { priceVariant }
131170 color = { priceColor }
0 commit comments