Histogram Chart
Interaction highlights
•
HistogramBinSummary via onBinFocus / onBinBlur so external UI can react to the active bin.•
Pointer metadata now includes cumulative counts, density ratios, and percentile—ideal for shared popovers.
Examples
(6)Properties
(62)Playground
Loading demo…
import
{
HistogramChart
}
from
'@platform-blocks/charts'
;
import
{
SESSION_DURATIONS
}
from
'./data'
;
export
function
Demo
(
)
{
return
(
<HistogramChart
title
=
"Session duration distribution"
subtitle
=
"Product analytics cohort"
height
=
{
280
}
data
=
{
SESSION_DURATIONS
}
bins
=
{
10
}
showDensity
densityThickness
=
{
3
}
densityColor
=
"#12B886"
barGap
=
{
0.15
}
tooltip
=
{
{
show
:
true
,
formatter
:
(
bin
)
=>
`${bin.count} sessions between ${bin.start}-${bin.end} min`
,
}
}
valueFormatter
=
{
(
count
,
bin
)
=>
`${count} • ${bin.density.toFixed(2)} pdf`
}
enableCrosshair
liveTooltip
/>
)
;
}
Loading demo…
import
{
HistogramChart
}
from
'@platform-blocks/charts'
;
import
{
CONTRACT_LENGTHS
,
median
}
from
'./data'
;
export
function
Demo
(
)
{
return
(
<HistogramChart
title
=
"Customer contract length distribution"
subtitle
=
"Used to calibrate retention and renewal strategy"
height
=
{
320
}
data
=
{
CONTRACT_LENGTHS
}
bins
=
{
12
}
binMethod
=
"sturges"
density
=
{
false
}
showDensity
=
{
false
}
barOpacity
=
{
0.82
}
rangeHighlights
=
{
[
{
id
:
'core-subscription'
,
start
:
12
,
end
:
24
,
color
:
'#22C55E'
,
opacity
:
0.14
}
]
}
annotations
=
{
[
{
id
:
'one-year'
,
shape
:
'vertical-line'
,
x
:
12
,
color
:
'#22C55E'
,
label
:
'1 year'
,
}
,
{
id
:
'two-year'
,
shape
:
'vertical-line'
,
x
:
24
,
color
:
'#15803D'
,
label
:
'2 years'
,
}
,
{
id
:
'median'
,
shape
:
'vertical-line'
,
x
:
median
,
color
:
'#F97316'
,
label
:
`Median ${median} mo`
,
}
,
]
}
xAxis
=
{
{
title
:
'Contract length (months)'
,
}
}
yAxis
=
{
{
title
:
'Customer accounts'
,
labelFormatter
:
(
value
)
=>
`${value.toFixed(0)}`
,
}
}
grid
=
{
{
show
:
true
}
}
tooltip
=
{
{
show
:
true
,
formatter
:
(
bin
)
=>
`${bin.count} accounts between ${bin.start.toFixed(0)}–${bin.end.toFixed(0)} months`
,
}
}
valueFormatter
=
{
(
count
)
=>
`${count} customers`
}
/>
)
;
}
Loading demo…
import
{
HistogramChart
}
from
'@platform-blocks/charts'
;
import
{
TENURE_YEARS
,
medianTenure
}
from
'./data'
;
export
function
Demo
(
)
{
return
(
<HistogramChart
title
=
"Employee tenure distribution"
subtitle
=
"Helps spot retention risks and succession depth"
height
=
{
320
}
data
=
{
TENURE_YEARS
}
bins
=
{
12
}
binMethod
=
"sqrt"
showDensity
densityThickness
=
{
2.5
}
densityColor
=
"#22C55E"
barOpacity
=
{
0.8
}
rangeHighlights
=
{
[
{
id
:
'new-hires'
,
start
:
0
,
end
:
1.5
,
color
:
'#FACC15'
,
opacity
:
0.18
}
,
{
id
:
'veterans'
,
start
:
8
,
end
:
15
,
color
:
'#22C55E'
,
opacity
:
0.12
}
,
]
}
annotations
=
{
[
{
id
:
'median-tenure'
,
shape
:
'vertical-line'
,
x
:
Number
(
medianTenure
.
toFixed
(
2
)
)
,
color
:
'#F97316'
,
label
:
`Median ${medianTenure.toFixed(1)} yrs`
,
}
,
]
}
xAxis
=
{
{
title
:
'Tenure (years)'
,
labelFormatter
:
(
value
)
=>
`${value.toFixed(1)} yrs`
,
}
}
yAxis
=
{
{
title
:
'Probability density'
,
labelFormatter
:
(
value
)
=>
value
.
toFixed
(
2
)
,
}
}
grid
=
{
{
show
:
true
}
}
tooltip
=
{
{
show
:
true
,
formatter
:
(
bin
)
=>
`${bin.count} teammates between ${bin.start.toFixed(1)}–${bin.end.toFixed(1)} years`
,
}
}
valueFormatter
=
{
(
count
,
bin
)
=>
`${count} people · pdf ${bin.density.toFixed(3)}`
}
/>
)
;
}
Loading demo…
import
{
useState
}
from
'react'
;
import
{
View
,
Text
}
from
'react-native'
;
import
{
HistogramChart
,
HistogramBinSummary
}
from
'@platform-blocks/charts'
;
import
{
AVERAGE_LOAD
,
LOAD_TIMES
,
SLO_TARGET
}
from
'./data'
;
export
function
Demo
(
)
{
const
[
focusedBin
,
setFocusedBin
]
=
useState
<HistogramBinSummary
|
null
>
(
null
)
;
return
(
<View
>
<HistogramChart
title
=
"Page load time distribution"
subtitle
=
"Week after performance optimization rollout"
height
=
{
340
}
data
=
{
LOAD_TIMES
}
bins
=
{
14
}
binMethod
=
"fd"
showDensity
densityThickness
=
{
3
}
barOpacity
=
{
0.78
}
densityColor
=
"#12B886"
rangeHighlights
=
{
[
{
id
:
'slo-window'
,
start
:
0
,
end
:
SLO_TARGET
,
color
:
'#38BDF8'
,
opacity
:
0.12
}
]
}
annotations
=
{
[
{
id
:
'slo-target'
,
shape
:
'vertical-line'
,
x
:
SLO_TARGET
,
color
:
'#0EA5E9'
,
label
:
'SLO 2.5s'
,
}
,
{
id
:
'avg-load'
,
shape
:
'vertical-line'
,
x
:
Number
(
AVERAGE_LOAD
.
toFixed
(
2
)
)
,
color
:
'#F97316'
,
label
:
`Avg ${AVERAGE_LOAD.toFixed(2)}s`
,
}
,
]
}
xAxis
=
{
{
title
:
'Page load time (seconds)'
,
labelFormatter
:
(
value
)
=>
`${value.toFixed(1)}s`
,
}
}
yAxis
=
{
{
title
:
'Probability density'
,
labelFormatter
:
(
value
)
=>
value
.
toFixed
(
2
)
,
}
}
grid
=
{
{
show
:
true
}
}
tooltip
=
{
{
show
:
true
,
formatter
:
(
bin
)
=>
`${bin.count} page views between ${bin.start.toFixed(1)}–${bin.end.toFixed(1)}s`
,
}
}
valueFormatter
=
{
(
count
,
bin
)
=>
`${count} views · pdf ${bin.density.toFixed(3)}`
}
onBinFocus
=
{
(
summary
)
=>
setFocusedBin
(
summary
)
}
onBinBlur
=
{
(
)
=>
setFocusedBin
(
null
)
}
/>
<View
style
=
{
{
paddingHorizontal
:
4
,
marginTop
:
12
}
}
>
{
focusedBin
?
(
<Text
style
=
{
{
fontSize
:
13
,
color
:
'#3F3F46'
}
}
>
{
`${focusedBin.count} loads between ${focusedBin.start.toFixed(2)}–${focusedBin.end.toFixed(2)}s · percentile ${(focusedBin.percentile * 100).toFixed(1)}% · cumulative ${(focusedBin.cumulativeDensityRatio * 100).toFixed(1)}% density`
}
</Text
>
)
:
(
<Text
style
=
{
{
fontSize
:
13
,
color
:
'#52525B'
}
}
>
Hover
a bar to highlight its percentile and cumulative share of traffic
.
</Text
>
)
}
</View
>
</View
>
)
;
}
Loading demo…
import
{
HistogramChart
}
from
'@platform-blocks/charts'
;
import
{
BATTERY_VOLTAGES
,
REPLACEMENT_THRESHOLD
,
TARGET_VOLTAGE
}
from
'./data'
;
export
function
Demo
(
)
{
return
(
<HistogramChart
title
=
"Sensor battery voltage after firmware upgrade"
subtitle
=
"Monitoring pack health across deployed field units"
height
=
{
320
}
data
=
{
BATTERY_VOLTAGES
}
bins
=
{
12
}
binMethod
=
"sturges"
showDensity
densityThickness
=
{
2.8
}
densityColor
=
"#34D399"
barOpacity
=
{
0.78
}
rangeHighlights
=
{
[
{
id
:
'low-voltage'
,
start
:
3.0
,
end
:
REPLACEMENT_THRESHOLD
,
color
:
'#EF4444'
,
opacity
:
0.14
}
,
{
id
:
'target-band'
,
start
:
TARGET_VOLTAGE
,
end
:
4.1
,
color
:
'#22C55E'
,
opacity
:
0.12
}
,
]
}
annotations
=
{
[
{
id
:
'replacement-line'
,
shape
:
'vertical-line'
,
x
:
REPLACEMENT_THRESHOLD
,
color
:
'#DC2626'
,
label
:
'Replace below 3.5V'
,
}
,
{
id
:
'target-line'
,
shape
:
'vertical-line'
,
x
:
TARGET_VOLTAGE
,
color
:
'#16A34A'
,
label
:
'Target 3.9V+'
,
}
,
]
}
xAxis
=
{
{
title
:
'Voltage (V)'
,
labelFormatter
:
(
value
)
=>
`${value.toFixed(2)}V`
,
}
}
yAxis
=
{
{
title
:
'Probability density'
,
labelFormatter
:
(
value
)
=>
value
.
toFixed
(
2
)
,
}
}
grid
=
{
{
show
:
true
}
}
tooltip
=
{
{
show
:
true
,
formatter
:
(
bin
)
=>
`${bin.count} sensors between ${bin.start.toFixed(2)}–${bin.end.toFixed(2)}V`
,
}
}
valueFormatter
=
{
(
count
,
bin
)
=>
`${count} sensors · pdf ${bin.density.toFixed(3)}`
}
/>
)
;
}
Loading demo…
import
{
HistogramChart
}
from
'@platform-blocks/charts'
;
import
{
REVIEW_THRESHOLD
,
TRANSACTION_AMOUNTS
}
from
'./data'
;
export
function
Demo
(
)
{
return
(
<HistogramChart
title
=
"Transaction amount distribution"
subtitle
=
"Identifying anomalous high-value purchases"
height
=
{
320
}
data
=
{
TRANSACTION_AMOUNTS
}
bins
=
{
16
}
binMethod
=
"fd"
showDensity
barOpacity
=
{
0.76
}
densityColor
=
"#0EA5E9"
rangeHighlights
=
{
[
{
id
:
'high-risk-window'
,
start
:
900
,
end
:
1400
,
color
:
'#EF4444'
,
opacity
:
0.12
}
,
]
}
annotations
=
{
[
{
id
:
'manual-review'
,
shape
:
'vertical-line'
,
x
:
REVIEW_THRESHOLD
,
color
:
'#DC2626'
,
label
:
'Manual review starts'
,
}
,
]
}
xAxis
=
{
{
title
:
'Transaction amount (USD)'
,
labelFormatter
:
(
value
)
=>
`$${value.toFixed(0)}`
,
}
}
yAxis
=
{
{
title
:
'Probability density'
,
labelFormatter
:
(
value
)
=>
value
.
toFixed
(
3
)
,
}
}
grid
=
{
{
show
:
true
}
}
tooltip
=
{
{
show
:
true
,
formatter
:
(
bin
)
=>
`${bin.count} orders between $${bin.start.toFixed(0)}–$${bin.end.toFixed(0)}`
,
}
}
valueFormatter
=
{
(
count
,
bin
)
=>
`${count} orders · pdf ${bin.density.toFixed(3)}`
}
/>
)
;
}
</>
react-ui-library
100+ accessible, themeable components that work seamlessly across iOS, Android, and Web.
A Platform Blocks product.
Quick Links
Resources