Bit Archaeology
Bit-level visualisation for the moment a single integer turns out to secretly carry multiple sub-fields. Pass the packed integer as value and a flat array of segments — each { label, offset, width } — and the component renders one bit box per bit (MSB on the left, LSB on the right), then paints a coloured overlay per segment, labelled with the field name and its decoded decimal value.
Generic over the underlying protocol — works equally well for an 8-bit network header, a packed RGBA pixel, a bit-set instruction encoding, a packed FEN board square, or any "this integer secretly carries N sub-fields" demonstration.
Installation
npx shadcn@latest add https://craftbits.dev/r/bit-archaeology.jsonUsage
import { BitArchaeology } from "@craft-bits/core";
<BitArchaeology
value={0b10_101_100}
segments={[
{ label: "FLAGS", offset: 6, width: 2 },
{ label: "OP", offset: 3, width: 3 },
{ label: "PAYLOAD", offset: 0, width: 3 },
]}
/>Show the decimal weight of each bit under the bit row — useful when teaching bit significance:
<BitArchaeology value={172} segments={segments} showWeights />Override per-segment tones rather than letting the palette rotate:
<BitArchaeology
value={172}
segments={[
{ label: "FLAGS", offset: 6, width: 2, tone: "warning" },
{ label: "OP", offset: 3, width: 3, tone: "accent" },
{ label: "PAYLOAD", offset: 0, width: 3, tone: "success" },
]}
/>Understanding the component
- MSB on the left. Bit rows render in human-readable order — bit
bitCount - 1on the far left, bit0on the far right. The component readsvalueas an unsigned integer; negative inputs are interpreted via JavaScript's unsigned-right-shift semantics. - Segments are LSB-anchored.
offsetis the LSB position of the field (offset: 0is the rightmost bit), andwidthis how many consecutive bits the field owns. Overlapping segments are allowed; the last entry in the array wins for a given bit. - Decoded values. Each segment extracts its decimal value and renders it inside the segment pill. Pass
showSegmentValues={false}to hide the decoded numbers and label the fields only. - Tones rotate by default. Adjacent segments receive different tones from a five-colour rotation (
accent,success,warning,error,default) so neighbouring fields read as visually distinct without any work from the caller. Pass atoneper segment to override. - Bits without a segment. Any bit that no segment claims renders as a neutral chip — useful for "reserved" / "padding" bits in a real protocol header.
- Bit weights.
showWeightsprints the bit's decimal weight (128,64,32, ...) under each bit box. Off by default so the bit row stays compact. - Reduced motion. The staggered bit enter animation collapses to instant under
prefers-reduced-motion: reduce.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | required | The packed integer to dissect. Read as an unsigned bitCount-bit value. |
segments | BitArchaeologySegment[] | required | Bit ranges to decode and label. |
bitCount | number | 8 | Total number of bits to render. Clamped to 1..31. |
showWeights | boolean | false | Show the decimal weight of each bit under the bit row. |
showSegmentValues | boolean | true | Show the decoded decimal value inside each segment overlay. |
transition | Transition | SPRINGS.smooth | Override the enter transition. Reduced-motion users snap regardless. |
className | string | — | Merged onto the root via cn(). |
Accessibility
- The component root carries
role="group"and anaria-labelledbypointing at an off-screen<span>that summarises the packed integer, its binary form, and the decoded value of every segment. - Every bit and segment overlay exposes
data-position,data-bit,data-owned, anddata-toneattributes so consumer apps can hook custom styles or assistive tooling without re-reading the DOM. - Tone is never the only signal — segment values are printed numerically inside the overlay, so colourblind users see the magnitude even when the highlight colour is hard to discriminate.
- Motion respects
prefers-reduced-motion: reduce— the staggered bit enter animation collapses to instant.
Credits
- Extracted from:
algoflashcards(src/lessons/primitives/construction/BitArchaeology.tsx). The source was a multi-phase "reverse the crime" puzzle (evidence gathering → operator deduction → mask construction → verification). The library extract keeps only the underlying visualisation primitive — a packed integer rendered as a bit row with labelled segment overlays — and lets the caller compose any puzzle or reducer-driven scoring on top.