Skip to content

Getting started

Terminal window
npm install @data-profile/fingerprint

react (18 or 19) is a peer dependency, and the only one: your app provides it. The package is ESM only.

Everything below is one file: one dimension (genre), six books, one of them with no genre.

Running the code below: first-fingerprint.tsx
first-fingerprint.tsx
import type { FingerprintDimension, FingerprintItem } from "@data-profile/fingerprint";
import {
FingerprintCanvas,
FingerprintLegend,
useFingerprint,
} from "@data-profile/fingerprint/react";
import "@data-profile/fingerprint/styles.css";
const dimensions: FingerprintDimension[] = [
{
id: "genre",
label: "Genre",
categories: [
{ id: "fiction", label: "Fiction" },
{ id: "poetry", label: "Poetry" },
{ id: "history", label: "History" },
],
},
];
const items: FingerprintItem[] = [
{ id: "b1", values: { genre: "fiction" } },
{ id: "b2", values: { genre: "poetry" } },
{ id: "b3", values: { genre: "fiction" } },
{ id: "b4", values: { genre: "history" } },
{ id: "b5", values: { genre: "fiction" } },
{ id: "b6", values: { genre: null } }, // unknown: drawn, in its own category
];
export default function FirstFingerprint() {
const fp = useFingerprint({ items, dimensions, unit: "books" });
return (
<div style={{ maxWidth: 420 }}>
<FingerprintCanvas {...fp.canvasProps} title="My library" />
{fp.layout.legends.map((group) => (
<FingerprintLegend key={group.dimensionId} {...fp.legendProps(group)} />
))}
</div>
);
}
  • useFingerprint lays the items out and holds the selection. Its canvasProps carry the layout, its description, the selection and the unit; legendProps(group) carries one legend group and the same selection. Choose a legend entry or a mark and both follow.
  • The unknown book is drawn, last, in a category of its own. Nothing is dropped.
  • The faint ridges show while a collection is too small for its marks alone to read as a fingerprint, and fade as it fills.

The canvas is an SVG that fills its container’s width. The stylesheet is optional: it styles the legend, the list and the view switch, and everything works without it.

Treat the items array as immutable: the layout caches work against the array you pass, so a changed collection should be a new array, as React state usually is.