PercentileSurfaces
Precise linear percentile surfaces for scouting rows, cards, and battle-test recreations. PercentileBar is the primary precision read; PercentilePill is the dense companion for list rows.
Canonical behaviors.
A single player's scouting row rendered as stacked PercentileBars. Every bar carries the same comparison sample; the inversion badge appears on 'Dispossessed' because originalDirection === 'lower'.
Invalid input never paints a fake zero bar. The empty-state primitive renders inside the SVG and the warnings channel receives a named reason.
Dense scouting list built from 14 PercentilePill components. Composition — not a runtime fallback — is how small-card layouts are handled.
RadarChart gives the profile shape, PercentileBar list gives the exact percentiles. Same fixture, two normalization shapes derived from one source row set.
percentileBarRecipes.quiet mutes the track and softens the fill for card-sidebar usage. Callers can still override individual families on top.
Best-practice examples.
Minimal percentile bar
Pass a single metric and a comparison sample. The bar handles sample labeling, tick placement, and the accessible label.
import { PercentileBar } from "@withqwerty/campos-react";
export function ProgPasses({ metric, comparison }) {
return <PercentileBar metric={metric} comparison={comparison} />;
}
Pill row stack
Compose dense scouting rows from PercentilePill. Each pill requires either a comparison sample or an explicit accessibleSampleLabel fallback.
import { PercentilePill, percentilePillRecipes } from "@withqwerty/campos-react";
export function PillRow({ metric, comparison }) {
return (
<PercentilePill
metric={metric}
comparison={comparison}
recipe={percentilePillRecipes.compact}
/>
);
}
Hybrid overview + precision
Pair a RadarChart overview with a PercentileBar list so readers can see both the profile shape and the exact values. The same fixture drives both charts.
import { PercentileBar, RadarChart } from "@withqwerty/campos-react";
export function ScoutingCard({ radarRows, percentileMetrics, comparison }) {
return (
<div className="grid gap-4 md:grid-cols-[1fr_1.2fr]">
<RadarChart rows={radarRows} />
<ul className="space-y-1">
{percentileMetrics.map((metric) => (
<li key={metric.id}>
<PercentileBar metric={metric} comparison={comparison} />
</li>
))}
</ul>
</div>
);
}
Public surface.
| Prop | Type | Default | Description |
|---|---|---|---|
metric | PercentileMetric | — | Single metric packet: id, label, display-scale percentile (higher is always better), optional rawValue/rawValueUnit, and optional originalDirection used to drive the inversion badge and the accessible inversion note. |
comparison | PercentileComparisonSample | — (required on the bar; required-or-fallback on the pill) | Named comparison sample (e.g. 'Big Five League midfielders'). The pill also accepts an accessibleSampleLabel fallback when the sample line is suppressed visually. |
inversionBadgeLabel | string | "lower is better" | Copy shown in the inversion badge when originalDirection === 'lower'. Set to an empty string to hide the visible badge; the inversion note remains in the structured accessibleLabel. |
onWarnings | (warnings: readonly string[]) => void | — | Called on mount when the compute layer returned any warnings (e.g. clamped percentile, weak sample). Components also emit one dev-only console.warn per unique warnings signature. |
track / fill / text / ticks / badges | StyleValue-backed style family | — | First-class styling surfaces that accept constants, object-maps, or callbacks. Constant-only subsets flow through the static export contract for PercentileBar. |
recipe | PercentileBarRecipe | PercentilePillRecipe | — | Named preset (percentileBarRecipes.quiet, percentilePillRecipes.compact). Individual style-family overrides still win at the prop level. |
Create a React component using Campos PercentileBar. Import PercentileBar from @withqwerty/campos-react, keep metric and comparison shaping outside the component, and require an explicit comparison sample label (or an accessibleSampleLabel fallback for PercentilePill).