App

Kraken

A crypto price screen in the shape Kraken's has: a trace that runs off both edges of the window with no axes at all, a readout that follows the finger, and the two numbers the plot reaches under it. Where the Revolut study is about chrome — native tabs, headers and pickers around a plot — this one is about the plot itself, and it is the reason two things exist in the presentation vocabulary.

The Kraken-style coin screen running on the web, on Android and on iOS, side by side
One trace, three renderers — a repeating canvas pattern on the web, a clipped dot grid on Compose and on SwiftUI — in the appearance you are reading this page in.

The dotted fill

The area under the trace is a grid of dots rather than a wash, and it thins on the way down instead of stopping dead at the bottom of the plot — so the fill has one edge to read, the trace, and the grey rule on the floor is left to be the axis. Both come from one fill on the series style, and all three renderers draw it: a clipped dot grid on the SwiftUI and Compose canvases, a repeating canvas pattern on the web.

tsx
series({
  color: '#f48415',
  id: 'price',
  label: '24H',
  style: {
    fill: fill({
      // A tenth of its strength by the floor, so the paint gathers under the trace.
      fadeTo: 0.12,
      pattern: 'dots',
      spacing: 3.4,
    }),
    // A dot grid wants more opacity than a wash — most of what it covers stays bare.
    fillOpacity: 0.32,
    strokeWidth: 2.4,
  },
  values: range.values,
})
A fill is not a form. Chart.Area still fills by default, because there the fill is the quantity. A fill on the series style is what puts one under a Chart.Line, where it is decoration — which is what let this screen keep the line chart's scrub, reveal and annotations.

The trail scrub

Dragging across the plot lights the trace from its first reading up to the finger and leaves the rest dimmed, so the line reads as the story so far. That is marker.trail — the third selection marker, next to the dot and the window-around-the-reading segment.

tsx
const scrubbing = (labels: readonly string[]) =>
  interaction({
    crosshair: 'x',
    // labels is one time per reading, in data order. The chart draws the one being read.
    crosshairStyle: { color: '#f8b877', labelColor: '#8b8b8b', labels, width: 1 },
    // What the trace fades to past the finger. Everything before it is redrawn at full
    // strength by the trail, so this is only ever seen ahead of the reading.
    dimOpacity: 0.66,
    haptics: true,
    hover: 'nearest',
    marker: marker.trail({ color: '#f48415' }),
    tooltip: false,
  })

The time above the crosshair is drawn by the chart, through crosshairStyle.labels — one string per slot, placed by whichever renderer is drawing the line. It is the one piece of scrub chrome the app hands back: a label pinned to the crosshair has to move with it, and a position that reaches JavaScript through a bridge and returns as a re-render is a frame behind the line beside it. The reading card on the Revolut screen has no such problem, because it sits still.

What it uses

PropTypeDefaultDescription
Chart.Linefeature-charts/kraken-chart.tsxThe price trace: a dotted fill fading to the floor, a grey rule on that floor standing in for the axis, a dashed rule at the latest price, and a haloed point on the last reading.
marker.trailfeature-charts/kraken-chart-style.tsLights the stretch of trace up to the reading and dims the rest, paired with dimOpacity so there is something for it to stand out from.
fillfeature-charts/kraken-chart-style.tsThe dot grid and its fade, resolved per scheme: ink on paper carries at a fraction of what light on black needs, so dark asks for roughly twice the opacity.
crosshairStyle.labelsfeature-charts/kraken-chart-style.tsThe times above the crosshair, one per reading, handed over with the interaction so the label is drawn by whoever draws the line.
useChartScrubapps/example/use-kraken-readout.tsTurns the scrub into the price and the delta above the plot. The change is measured from the window open; the dashed rule sits at the latest price. Two different questions.
Platform fileskraken-coin.ios.tsx · kraken-coin.android.tsxOne screen per platform: SwiftUI through @expo/ui on iOS, Compose on Android, React Native on the web — sharing the data, the theme and the chart.

Split the same way the Revolut study is: the chart, its style, the theme and the generated prices are the shared packages/feature-charts package, and the screen around it — in the example app — is one file per platform. apps/example runs it on a device with yarn ios:example or yarn android:example.

A study, not a product. The screen is built to test the library against a design people already know by heart. It uses generated data, and it is not affiliated with or endorsed by Kraken.