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.
Follow the installation guide to authenticate the private registry with your HEROUI_PERSONAL_TOKEN, install heroui-native-pro, and wire up HeroUINativeProvider.
This release introduces 5 new components spanning charts, data display, and navigation:
victory-native-powered area chart with Area, AreaRange, and StackedArea compound parts. (Documentation)Anchor / Value / ValueLabel) shared across every cartesian chart. (Documentation)Header, Media, Title, Description, and Content parts. (Documentation)Tabs with Group, ScrollView, Indicator, Item, Label, and Separator compounds. (Documentation)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:
AreaChart.Area, AreaChart.AreaRange, AreaChart.StackedAreacolorClassName (e.g. accent-chart-1, accent-chart-3) with full accent-chart-* token supportanimation="disable-all" prop through AnimationSettingsProvidercurveType (natural, linear, monotoneX, etc.) and per-area animate config for path-interpolated data transitionsLinearGradient composes as a child of AreaChart.Area for gradient fillsuseAreaPath and useStackedAreaPaths hooks re-exported for custom renderingvictory-native stays an optional dependency — only loaded when a chart component is importedUsage:
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.
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:
ChartCrosshair, ChartCrosshair.Anchor, ChartCrosshair.Value, ChartCrosshair.ValueLabelvariant — dashed (themed DashPathEffect) or solid unbroken strokecolor, strokeWidth, and overrideable DashPathEffect via childrenuseChartPressState shared values from victory-native — no React renders on pressx, and clamps to chartBounds via onChartBoundsChangeChartCrosshair.ValueLabel reads a useDerivedValue shared string from context, so label text updates entirely on the UI threadLineChart, BarChart, and AreaChartUsage:
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.
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:
useChartPressState shared values for x and yinnerRadius (default 5) and outerRadius (default 7) for sizinginnerColor and outerColor overrides on top of the themed --color-background halo and --color-chart-3 dotCircle props are forwarded to the inner circle for stroke, opacity, and other effectsChartCrosshair for a complete press-overlay systemUsage:
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.
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:
EmptyState.Header, EmptyState.Media, EmptyState.Title, EmptyState.Description, EmptyState.ContentEmptyState.Media ships default and icon variants (icon variant renders a circular muted surface)EmptyState.Title rendered with accessibilityRole="header" for screen readersContent for header-only states, omit Media for text-only layoutsanimation="disable-all" cascades through AnimationSettingsProvider to every animated descendantUsage:
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.
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:
Segment.Group, Segment.ScrollView, Segment.Indicator, Segment.Item, Segment.Label, Segment.Separatorvalue / onValueChange) and uncontrolled (defaultValue) modes via useControllableStatesize — sm, md, lg cascades padding, indicator radius, and label typography across every partisDisabled cascades from the root through SegmentContext and merges per-item flagsSegment.ScrollView wraps Tabs.ScrollView for horizontally scrollable rows when items overflowSegment.Indicator inherits Tabs animation props (animation, isAnimatedStyleActive) for full Reanimated controlSegment.Separator accepts betweenValues so dividers auto-hide when one of their neighbors is selectedUsage:
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.
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.
The LineChart and BarChart example screens have been migrated to the new ChartCrosshair + ChartIndicator pattern.
Improvements:
chartBounds sourced from onChartBoundsChange for consistent overlay clampingReText bridge — no more in-canvas-only tooltipsThe 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:
handlePressOut now relies on resetProgress() alone to drive the value back to 0cancelAnimation import removed from progress-button.animation.tsLineChart.Tooltip and LineChart.CrosshairLineChart.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" — Themed DashPathEffect rule (default)"solid" — Unbroken strokeWhen 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.
The following documentation pages have been updated to reflect the changes in this release:
useDerivedValue label patternsLineChart.Tooltip and LineChart.Crosshair removed; press-overlay examples migrated to ChartCrosshair + ChartIndicator1.0.0-beta.4
Adds PieChart, RadarChart, WheelPicker, WheelPickerGroup, TimePicker, WheelTimePicker, DateTimePicker, and WheelDateTimePicker, refactors component labels to soft-foreground tokens, and fixes NumberStepper digit jitter plus WheelPicker overscroll and re-render edge cases.
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.