Native

iOS and Android

Zyplot ships an Expo module that draws with the platform's own graphics stack — Swift Charts on iOS, Jetpack Compose Canvas on Android — behind the same Chart namespace the web renderer exposes. There is no WebView.

Installation

The same single package you installed for the web carries the native code; autolinking picks it up. Rebuild the native project after adding it. These are native modules, so Expo Go cannot load them: use a development build.

tsx
yarn add @hzblj/zyplot

npx expo prebuild
npx expo run:ios
npx expo run:android
iOS 17 and newer. Swift Charts features used by the renderer require a deployment target of 17.0. Set it with expo-build-properties if your app targets something lower.

Import from @hzblj/zyplot and the correct renderer is picked per platform — the same source builds for web, iOS and Android.

tsx
import { Chart } from '@hzblj/zyplot'

export function Revenue() {
  return (
    <Chart.Line
      categories={['Jan', 'Feb', 'Mar']}
      format={{ prefix: '$' }}
      series={[{ id: 'revenue', label: 'Revenue', values: [42, 56, 51] }]}
    />
  )
}

Platform-specific files

A few forms exist on one platform only, because the underlying renderer has a mark the other has no honest equivalent for. They are not on the shared namespace — reaching for one would type-check and then render nothing on the platform that lacks it.

Instead, give the component one file per platform and let Metro choose. Write the shared parts once, import the platform entry point in the file that is already committed to that platform, and drop the Platform.OS branches entirely.

tsx
forecast.ios.tsx      imports @hzblj/zyplot/ios
forecast.android.tsx  imports @hzblj/zyplot/android
forecast.tsx          optional web or fallback version
tsx
// forecast.ios.tsx
import { Chart } from '@hzblj/zyplot/ios'

export const Forecast = ({ bands }: ForecastProps) => (
  <Chart.Range data={bands} height={300} />
)
tsx
// forecast.android.tsx
import { Chart } from '@hzblj/zyplot/android'

export const Forecast = ({ bands }: ForecastProps) => (
  <Chart.Lollipop data={bands.map(toPoint)} height={300} />
)

The call site imports ./forecast with no extension and never learns which one it got. This is the same convention Expo's own UI packages use.

Keep a base file for TypeScript. tsc does not know about platform extensions, so ./forecast needs a plain forecast.tsx to resolve to. It doubles as the web version, or returns null if the component is native-only.

Chart coverage

All twenty-one shared chart kinds render on both native platforms, and each platform adds two of its own. The props are the same ones documented under Charts.

PropTypeDefaultDescription
Cartesianweb · iOS · AndroidLine, Area, Bar, StackedBar, TimeSeries, Sparkline, Scatter, Histogram.
Radial and flowweb · iOS · AndroidPie, Gauge, Meter, Radar, Sunburst, Treemap, Funnel, Sankey.
Statistical and financeweb · iOS · AndroidCandlestick, Boxplot, DivergingBar, Dumbbell, Heatmap.
iOS extensionsiOS onlyChart.Range and Chart.Rule, built on Swift Charts marks with no web equivalent.
Android extensionsAndroid onlyChart.Waterfall and Chart.Lollipop, with no web equivalent.

Differences from web

PropTypeDefaultDescription
classNameweb onlyNative charts have no DOM node to style. Use height and plot instead.
textureweb onlyPattern fills answer forced-colors and print, which a native chart never meets. Not part of the native props — the compiler rejects it rather than the renderer ignoring it.
skeletonweb onlyNative has no custom skeleton slot; isLoading draws the platform spinner.
colorModeshared"system"Per chart on native: there is no cascade to inherit through, so Chart.Provider scopes surface and theme but not the color mode.
interactionsharedDelivered through onInteraction on both platforms, with haptics available natively.
labelssharedBoxplot terminology is honoured natively too — the tooltip shows the five-number summary in your wording.