Rank
Order, filter, and truncate a candidate set. Two modes that answer different questions.
LIVE DEMO →order a page of a feedRank takes candidates your code already has and puts them in order. Typeahead is not a separate primitive — it is Rank with take.
compete — one Choice over the candidates
Probabilities sum to one, so something always wins even when nothing fits. Right for "which one did they mean": a command palette, a typeahead, a next-action menu.
<Rank
items={candidates}
idOf={(c) => c.id}
labelOf={(c) => c.label}
mode="compete"
take={4}
pinTop={2}
ask="Which of these commands did the user mean by what they typed in `query`?"
>
{(ranked) => ranked.map(({ item, score, pinned }) => <Row key={item.id} … />)}
</Rank>grade — one Score per candidate
Each item gets its own Score question, fanned out into the same request. Those scores are comparable across items and across requests, which compete mode cannot be: a per-page Choice re-normalizes, so page two cannot be ranked against page one.
<Rank
items={cards}
idOf={(c) => c.id}
labelOf={(c) => c.title}
mode="grade"
levels={['Unrelated', 'Same area', 'Clearly useful', 'Exactly what they need']}
minScore={0.5}
ask="How well does the card in `data.item` match what the person has been doing, per `recent`?"
>
{(ranked) => …}
</Rank>Choosing a mode
Shaping the result in code
- pinTop holds the leading items in place. Reordering a menu fights muscle memory.
- take truncates after ranking.
- minScore drops weak matches, in grade mode only.
- Changing any of these re-derives from the answer already in hand and spends no new request — the evidence and the question have not changed.