Stats Bar

Statistics bar display

Marketing BlockSocial Proof

Overview

Renders a centered row of metric values separated by vertical dividers. Numeric values animate from 0 to their target using a count-up animation that activates when the component enters the viewport. String values are displayed as-is.

Usage

import { StatsBar } from '@leanicon/web-builder-library'

Default

10000Happy customers
99Uptime
50Team members
12Years of experience

With prefix & suffix

10000+Happy customers
99%Uptime
$50MRevenue processed
4.9/5Average rating

String values

String values are displayed immediately without count-up animation.

24/7Support availability
A+Security rating
SOC 2Compliance
99.99%SLA guarantee

Slide-up animation

0+Happy customers
0%Uptime
0Team members
0Years of experience

Fade animation

0+Happy customers
0%Uptime
0Team members
0Years of experience

Scale animation

0+Happy customers
0%Uptime
0Team members
0Years of experience

Dark mode

10000+Happy customers
99%Uptime
50Team members
12Years of experience

Props

Prop

Type

Default

Description

metrics

MetricItem[]

—

Array of metric objects to display

animation

{ metrics?: AnimationConfig }

—

Animation configuration for metrics

colorScheme

"light" | "dark"

—

Force light or dark mode

iconPosition

"left" | "above" | "right"

"left"

Where every metric's icon sits

className

string

—

Additional CSS classes on root

MetricItem

Prop

Type

Description

icon

ReactNode?

Decorative icon beside the value. Optional per metric

value

string | number

Metric value — numeric values get count-up animation

label

string

Description below the value

prefix

string?

Text before the value (e.g. "$", "~")

suffix

string?

Text after the value (e.g. "+", "%", "/5")

icon takes a node, not an icon name. In the CMS the editor stores a kebab-case lucide name (shield-check) and the block adapter resolves it with resolveIcon() before it reaches this component — that keeps lucide's icon map out of the client bundle. Rendering it is guarded, so a metric without an icon is spaced exactly as it was before, and a bar may mix the two.

Icon size and position

Position is a prop on the bar, not on the metric — one setting for all of them, because icons in different places within one bar read as a mistake. Size is not a prop: the adapter bakes it into the icon's own className before the node reaches this component, since that is where resolveIcon() runs.

Both come from ./icon-layout.ts, a directive-free module the server adapter and this client component both import. In the CMS they are the stats-bar block's Icon position and Icon size fields.

Size

Class

Rendered

sm

h-5 w-5

20px

md

h-6 w-6

24px

lg

h-8 w-8

32px — default

xl

h-10 w-10

40px

AnimationConfig

Prop

Type

Default

Description

type

"fade" | "slide-up" | "slide-down" | "scale" | "none"

—

Animation type

duration

number

0.5

Duration in seconds

delay

number

0

Initial delay in seconds

stagger

number

0

Delay between children in seconds

once

boolean

true

Trigger animation only once

Notes

  • Count-up animation triggers once when 20% of the component is visible (uses IntersectionObserver via useInView).
  • Count-up duration is 1.5 seconds.
  • String value fields are displayed immediately without animation.
  • Respects prefers-reduced-motion — animations are skipped for users who prefer reduced motion.
  • Metrics are separated by a left border (md:border-l) from the second onward, so the dividers appear only once the bar is laid out in a row.
  • Dark mode: pass colorScheme="dark" or place inside a .dark ancestor.

Props

NameTypeDefaultRequiredDescription
metricsMetricItem[]—Yes
animationStatsBarAnimation—No
colorSchemeenum—No
iconPositionenumleftNoWhere each metric's icon sits relative to its value. Bar-wide, not per metric.
classNamestring—No