1.0.0-beta.3
Adds AreaChart, ChartCrosshair, ChartIndicator, EmptyState, and Segment components, unifies press-driven overlays across cartesian charts, removes LineChart.Tooltip and LineChart.Crosshair, and cleans up ProgressButton press-out handling.
The third beta of HeroUI Native Pro lands five new components — AreaChart, ChartCrosshair, ChartIndicator, EmptyState, and Segment — and unifies press-driven UI across every cartesian chart. LineChart and BarChart now share the same standalone crosshair and indicator primitives.
Try It on Your Device
Installation
Follow the installation guide to authenticate the private registry with your HEROUI_PERSONAL_TOKEN, install heroui-native-pro, and wire up HeroUINativeProvider.
What's New
New Components
This release introduces 5 new components spanning charts, data display, and navigation:
- AreaChart:
victory-native-powered area chart withArea,AreaRange, andStackedAreacompound parts. (Documentation) - ChartCrosshair: Skia vertical rule with an RN tooltip overlay (
Anchor/Value/ValueLabel) shared across every cartesian chart. (Documentation) - ChartIndicator: Themed Skia double-dot marker (outer halo + inner dot) for press-driven point markers. (Documentation)
- EmptyState: Compound primitive for empty / zero-state messaging with
Header,Media,Title,Description, andContentparts. (Documentation) - Segment: Segmented control built on
TabswithGroup,ScrollView,Indicator,Item,Label, andSeparatorcompounds. (Documentation)
AreaChart
A Skia-accelerated area chart for visualizing trends, stacked contributions, and confidence bands. Built on victory-native and wrapped in a themed outer View, with the same compound, theming, and animation cascade conventions as LineChart and BarChart. Pair it with ChartCrosshair and ChartIndicator to add press-driven overlays.
Features:
- Compound parts —
AreaChart.Area,AreaChart.AreaRange,AreaChart.StackedArea - Themed fills via Uniwind
colorClassName(e.g.accent-chart-1,accent-chart-3) with fullaccent-chart-*token support - Built-in draw-on animation, gated by the cascading
animation="disable-all"prop throughAnimationSettingsProvider - Configurable
curveType(natural,linear,monotoneX, etc.) and per-areaanimateconfig for path-interpolated data transitions - Skia
LinearGradientcomposes as a child ofAreaChart.Areafor gradient fills useAreaPathanduseStackedAreaPathshooks re-exported for custom renderingvictory-nativestays an optional dependency — only loaded when a chart component is imported
Usage:
import { AreaChart } from "heroui-native-pro";
const DATA = [
{ month: "Jan", revenue: 120 },
{ month: "Feb", revenue: 180 },
{ month: "Mar", revenue: 150 },
];
export function Example() {
return (
<AreaChart
data={DATA}
xKey="month"
yKeys={["revenue"]}
wrapperClassName="h-48"
>
{({ points, chartBounds }) => (
<AreaChart.Area
points={points.revenue}
y0={chartBounds.bottom}
/>
)}
</AreaChart>
);
}For complete documentation and examples, see the AreaChart component page.
ChartCrosshair
A vertical rule and tooltip overlay that highlight the pressed point on a chart. The Skia rule renders inside the chart canvas, while a sibling React Native overlay (ChartCrosshair.Value) hosts the tooltip pill — measured, centered, and clamped against chartBounds, with a label that updates on the UI thread via an internal ReText (read-only Reanimated TextInput) bridge.
Features:
- Compound parts —
ChartCrosshair,ChartCrosshair.Anchor,ChartCrosshair.Value,ChartCrosshair.ValueLabel variant—dashed(themedDashPathEffect) orsolidunbroken stroke- Custom
color,strokeWidth, and overrideableDashPathEffectvia children - Driven by
useChartPressStateshared values fromvictory-native— no React renders on press - React Native value pill rendered outside the Skia canvas: auto-measures its own width, centers on
x, and clamps tochartBoundsviaonChartBoundsChange ChartCrosshair.ValueLabelreads auseDerivedValueshared string from context, so label text updates entirely on the UI thread- Works uniformly across
LineChart,BarChart, andAreaChart
Usage:
import { LineChart, ChartCrosshair, ChartIndicator } from "heroui-native-pro";
import { useChartPressState } from "victory-native";
import { useDerivedValue } from "react-native-reanimated";
export function Example() {
const { state, isActive } = useChartPressState({
x: "" as string,
y: { revenue: 0 },
});
const value = useDerivedValue(
() => `$${state.y.revenue.value.value.toFixed(0)}`
);
return (
<ChartCrosshair.Anchor>
<LineChart
data={DATA}
xKey="month"
yKeys={["revenue"]}
chartPressState={state}
wrapperClassName="h-48"
>
{({ points, chartBounds }) => (
<>
<LineChart.Line points={points.revenue} />
{isActive ? (
<>
<ChartCrosshair
x={state.x.position}
top={chartBounds.top}
bottom={chartBounds.bottom}
/>
<ChartIndicator
x={state.x.position}
y={state.y.revenue.position}
/>
</>
) : null}
</>
)}
</LineChart>
<ChartCrosshair.Value value={value}>
<ChartCrosshair.ValueLabel />
</ChartCrosshair.Value>
</ChartCrosshair.Anchor>
);
}For complete documentation and examples, see the ChartCrosshair component page.
ChartIndicator
A themed Skia double-dot marker — outer halo plus inner dot — that follows the pressed point on a chart. Drop-in primitive that pairs with ChartCrosshair (or stands alone) for line, area, and bar press interactions.
Features:
- Driven by
useChartPressStateshared values forxandy innerRadius(default5) andouterRadius(default7) for sizinginnerColorandouterColoroverrides on top of the themed--color-backgroundhalo and--color-chart-3dot- Extra Skia
Circleprops are forwarded to the inner circle for stroke, opacity, and other effects - Renders inside the chart canvas alongside
ChartCrosshairfor a complete press-overlay system
Usage:
import { LineChart, ChartIndicator } from "heroui-native-pro";
import { useChartPressState } from "victory-native";
export function Example() {
const { state, isActive } = useChartPressState({
x: 0,
y: { value: 0 },
});
return (
<LineChart
data={DATA}
xKey="day"
yKeys={["value"]}
chartPressState={state}
wrapperClassName="h-48"
>
{({ points }) => (
<>
<LineChart.Line points={points.value} />
{isActive ? (
<ChartIndicator
x={state.x.position}
y={state.y.value.position}
/>
) : null}
</>
)}
</LineChart>
);
}For complete documentation and examples, see the ChartIndicator component page.
EmptyState
A placeholder for empty views with an optional icon, title, description, and call-to-action area. Use it for empty inboxes, no-search-results screens, first-run states, or any zero-data UI that previously had to be hand-rolled.
Features:
- Compound parts —
EmptyState.Header,EmptyState.Media,EmptyState.Title,EmptyState.Description,EmptyState.Content EmptyState.Mediashipsdefaultandiconvariants (icon variant renders a circular muted surface)EmptyState.Titlerendered withaccessibilityRole="header"for screen readers- All sub-components are optional — drop
Contentfor header-only states, omitMediafor text-only layouts - Root
animation="disable-all"cascades throughAnimationSettingsProviderto every animated descendant
Usage:
import { Button, EmptyState } from "heroui-native-pro";
import { BellIcon } from "lucide-react-native";
export function Example() {
return (
<EmptyState>
<EmptyState.Header>
<EmptyState.Media variant="icon">
<BellIcon size={20} />
</EmptyState.Media>
<EmptyState.Title>No notifications yet</EmptyState.Title>
<EmptyState.Description>
New activity will show up here as it happens.
</EmptyState.Description>
</EmptyState.Header>
<EmptyState.Content>
<Button variant="outline">Refresh</Button>
</EmptyState.Content>
</EmptyState>
);
}For complete documentation and examples, see the EmptyState component page.
Segment
A segmented control for toggling between a small set of mutually exclusive options. Built on top of HeroUI Native's Tabs (variant="primary") so style overrides and animation hooks (useTabsMeasurements, useTabsTrigger) stay consistent with the underlying primitive.
Features:
- Compound parts —
Segment.Group,Segment.ScrollView,Segment.Indicator,Segment.Item,Segment.Label,Segment.Separator - Controlled (
value/onValueChange) and uncontrolled (defaultValue) modes viauseControllableState size—sm,md,lgcascades padding, indicator radius, and label typography across every partisDisabledcascades from the root throughSegmentContextand merges per-item flagsSegment.ScrollViewwrapsTabs.ScrollViewfor horizontally scrollable rows when items overflowSegment.Indicatorinherits Tabs animation props (animation,isAnimatedStyleActive) for full Reanimated controlSegment.SeparatoracceptsbetweenValuesso dividers auto-hide when one of their neighbors is selected
Usage:
import { Segment } from "heroui-native-pro";
export function Example() {
return (
<Segment defaultValue="dashboard">
<Segment.Group>
<Segment.Indicator />
<Segment.Item value="dashboard">
<Segment.Label>Dashboard</Segment.Label>
</Segment.Item>
<Segment.Separator betweenValues={["dashboard", "analytics"]} />
<Segment.Item value="analytics">
<Segment.Label>Analytics</Segment.Label>
</Segment.Item>
</Segment.Group>
</Segment>
);
}For complete documentation and examples, see the Segment component page.
Unified Chart Press Overlays
ChartCrosshair and ChartIndicator are now standalone primitives that work uniformly across every cartesian chart. Previously, LineChart shipped its own bundled LineChart.Tooltip and LineChart.Crosshair Skia compounds; there was no equivalent for BarChart or AreaChart, and no React Native overlay label that could sit on top of the Skia canvas.
Supported components:
The new pattern reads chartBounds from onChartBoundsChange and threads useChartPressState shared values through both Skia primitives and the RN value overlay — so press-driven UI is one mental model for every chart in the library.
Component Improvements
LineChart and BarChart Migration
The LineChart and BarChart example screens have been migrated to the new ChartCrosshair + ChartIndicator pattern.
Improvements:
- Press-driven crosshair, indicator dot, and tooltip pill now share the same primitives across both charts
chartBoundssourced fromonChartBoundsChangefor consistent overlay clamping- React Native value labels render on top of the Skia canvas via the new
ReTextbridge — no more in-canvas-only tooltips - Component docs updated in lockstep with the new APIs
ProgressButton Press-Out Cleanup
The ProgressButton handlePressOut flow has been simplified. The redundant cancelAnimation(progress) call has been removed — resetProgress() already supersedes any in-flight animation by assigning a new withSpring value to progress, making the explicit cancel unnecessary.
Improvements:
handlePressOutnow relies onresetProgress()alone to drive the value back to0- Unused
cancelAnimationimport removed fromprogress-button.animation.ts - No visual or behavioral change for consumers — reset still runs as a spring (or instantly when animations are disabled)
⚠️ Breaking Changes
Removed LineChart.Tooltip and LineChart.Crosshair
LineChart.Tooltip and LineChart.Crosshair have been removed in favor of the new standalone ChartCrosshair and ChartIndicator exports from heroui-native-pro. The new primitives accept the same x / y / top / bottom props and the same useChartPressState wiring, so the migration is a like-for-like replacement.
Migration:
Replace LineChart.Tooltip with ChartIndicator, and LineChart.Crosshair with ChartCrosshair. For React Native value labels, wrap the chart in ChartCrosshair.Anchor and render ChartCrosshair.Value (with ChartCrosshair.ValueLabel) as a sibling.
// Before
import { LineChart } from "heroui-native-pro";
import { useChartPressState } from "victory-native";
const { state, isActive } = useChartPressState({
x: 0,
y: { value: 0 },
});
<LineChart
data={DATA}
xKey="day"
yKeys={["value"]}
chartPressState={state}
>
{({ points, chartBounds }) => (
<>
<LineChart.Line points={points.value} />
{isActive ? (
<>
<LineChart.Crosshair
x={state.x.position}
top={chartBounds.top}
bottom={chartBounds.bottom}
/>
<LineChart.Tooltip
x={state.x.position}
y={state.y.value.position}
/>
</>
) : null}
</>
)}
</LineChart>
// After
import {
LineChart,
ChartCrosshair,
ChartIndicator,
} from "heroui-native-pro";
import { useChartPressState } from "victory-native";
import { useDerivedValue } from "react-native-reanimated";
const { state, isActive } = useChartPressState({
x: "" as string,
y: { value: 0 },
});
const label = useDerivedValue(
() => `${state.y.value.value.value.toFixed(0)}`
);
<ChartCrosshair.Anchor>
<LineChart
data={DATA}
xKey="day"
yKeys={["value"]}
chartPressState={state}
>
{({ points, chartBounds }) => (
<>
<LineChart.Line points={points.value} />
{isActive ? (
<>
<ChartCrosshair
x={state.x.position}
top={chartBounds.top}
bottom={chartBounds.bottom}
/>
<ChartIndicator
x={state.x.position}
y={state.y.value.position}
/>
</>
) : null}
</>
)}
</LineChart>
<ChartCrosshair.Value value={label}>
<ChartCrosshair.ValueLabel />
</ChartCrosshair.Value>
</ChartCrosshair.Anchor>;Available crosshair variants:
"dashed"— ThemedDashPathEffectrule (default)"solid"— Unbroken stroke
When using ChartCrosshair.Anchor, the wrapped chart's wrapperClassName must not contain padding (e.g. p-*, px-*, py-*) — the anchor measures positions in the chart's native coordinate space, so any padding offsets the chart relative to the anchor and breaks centering / clamping of ChartCrosshair.Value. Apply spacing on a parent container instead.
Updated Documentation
The following documentation pages have been updated to reflect the changes in this release:
- AreaChart — New component page with basic, gradient, curve type, animated, stacked, and area-range examples
- ChartCrosshair — New component page covering the Skia rule, RN value overlay, dashed / solid variants, and
useDerivedValuelabel patterns - ChartIndicator — New component page covering basic usage, custom radii, custom colors, and forwarded Skia props
- EmptyState — New component page with header, icon media, action, and animation-cascade examples
- Segment — New component page covering controlled / uncontrolled selection, sizes, scrollable layouts, separators, and disabled cascading
- LineChart —
LineChart.TooltipandLineChart.Crosshairremoved; press-overlay examples migrated toChartCrosshair+ChartIndicator
Links
Crypto Wallet v1.0.0
First HeroUI Native Pro template — a fully-built mobile crypto wallet with portfolio, assets, and transaction views.
1.0.0-beta.2
Adds Badge, ProgressBar, ProgressCircle, ToggleButton, ToggleButtonGroup, BarChart, and Widget components, fixes calendar year picker sync after nav-button paging, locks date picker trigger variants, and launches the HeroUI Native Pro Figma library.