# Distribution bar

Package: @commenda/pathfinder@0.1.0
Page: /docs/components/distribution-bar
Figma: https://www.figma.com/design/dn7BkGYEfIyP0o2zfesfVh/The-System?node-id=876-2

```tsx
import {
  DistributionBar,
  type DistributionSegment,
} from '@commenda/pathfinder/distribution-bar';

const segments: readonly DistributionSegment[] = [
  { id: 'holding', label: 'Commenda Holding LLC', value: 32, color: '1' },
  { id: 'tushar', label: 'Tushar Shudeesh', value: 18.5, color: '2' },
  { id: 'horizon', label: 'Horizon Ventures Pte. Ltd.', value: 15, color: '3' },
  { id: 'priya', label: 'Priya Sharma', value: 14, color: '4' },
  { id: 'daniel', label: 'Daniel Kim', value: 9.5, color: '5' },
  { id: 'elena', label: 'Elena Petrova', value: 6, color: '6' },
  {
    id: 'other-a',
    label: 'Aleksandra Wiśniewska-Kowalczyk',
    value: 3,
    color: '1',
  },
  { id: 'other-b', label: 'Jo', value: 2, color: '2' },
];

export const DistributionBarDefault = () => (
  <DistributionBar
    label="Ownership distribution"
    segments={segments}
    legend="inline"
  />
);
```


Import from `@commenda/pathfinder/distribution-bar` and load the shared stylesheet once.

## API reference [#api-reference]

| Prop | Type | Requirement | Behavior |
| --- | --- | --- | --- |
| `label` | `string` | required | Accessible figure caption |
| `segments` | `readonly DistributionSegment[]` | required | `{ id, label, value, color }`; IDs must be unique |
| `total` | `number` | optional | Sum when omitted; explicit totals support remaining allocation |
| `size` | `"sm" \| "md"` | optional | 6px / 8px; defaults to md |
| `legend` | `"inline" \| "list" \| "none"` | optional | Inline by default; none retains an accessible breakdown |
| `formatValue` | `((value: number) => string)` | optional | Numeric formatting for values |
| `highlightConfig` | `{ activeId: string \| null; onActiveChange: (id: string \| null) => void; }` | optional | Optional controlled highlighting for a linked table |
| `className` | `string` | optional | Root styling |

### highlightConfig fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `activeId` | `string \| null` | Yes |  |
| `onActiveChange` | `(id: string \| null) => void` | Yes |  |

`color` accepts `1` through `6`, `other`, and semantic `success / warning / error / info / neutral`. Assign it by identity before sorting so the same holder keeps the same color. Categorical colors come from Figma's data palette; red belongs to status breakdowns.

## List legend [#list-legend]


```tsx
import {
  DistributionBar,
  type DistributionSegment,
} from '@commenda/pathfinder/distribution-bar';

const segments: readonly DistributionSegment[] = [
  { id: 'holding', label: 'Commenda Holding LLC', value: 32, color: '1' },
  { id: 'tushar', label: 'Tushar Shudeesh', value: 18.5, color: '2' },
  { id: 'horizon', label: 'Horizon Ventures Pte. Ltd.', value: 15, color: '3' },
  { id: 'priya', label: 'Priya Sharma', value: 14, color: '4' },
  { id: 'daniel', label: 'Daniel Kim', value: 9.5, color: '5' },
  { id: 'elena', label: 'Elena Petrova', value: 6, color: '6' },
  {
    id: 'other-a',
    label: 'Aleksandra Wiśniewska-Kowalczyk',
    value: 3,
    color: '1',
  },
  { id: 'other-b', label: 'Jo', value: 2, color: '2' },
];

export const DistributionBarLegend = () => (
  <DistributionBar
    label="Ownership distribution"
    segments={segments}
    legend="list"
    formatValue={(value) => `${String(value)} shares`}
  />
);
```


The largest parts appear first. Above six items, the largest five remain individual and the rest form Other. Every source member remains in the accessible breakdown and Other tooltip. Hovering a segment or focusing a legend entry highlights its group. A linked table can supply a source member ID to highlight Other when that member is grouped. The generated Other ID starts at `__other__`, adding leading underscores if needed to avoid collisions.

## Remaining allocation [#remaining-allocation]


```tsx
import {
  DistributionBar,
  type DistributionSegment,
} from '@commenda/pathfinder/distribution-bar';

const segments: readonly DistributionSegment[] = [
  { id: 'holding', label: 'Commenda Holding LLC', value: 32, color: '1' },
  { id: 'tushar', label: 'Tushar Shudeesh', value: 18.5, color: '2' },
  { id: 'horizon', label: 'Horizon Ventures Pte. Ltd.', value: 15, color: '3' },
  { id: 'priya', label: 'Priya Sharma', value: 14, color: '4' },
  { id: 'daniel', label: 'Daniel Kim', value: 9.5, color: '5' },
  { id: 'elena', label: 'Elena Petrova', value: 6, color: '6' },
  {
    id: 'other-a',
    label: 'Aleksandra Wiśniewska-Kowalczyk',
    value: 3,
    color: '1',
  },
  { id: 'other-b', label: 'Jo', value: 2, color: '2' },
];

export const DistributionBarRemainder = () => (
  <DistributionBar
    label="Capacity"
    total={100}
    size="sm"
    segments={[{ id: 'used', label: 'Used', value: 38, color: '1' }]}
  />
);
```


The unused total remains as track. A visual 4px minimum helps tiny positive parts remain visible; numeric shares are authoritative. Zero-valued entries remain in the legend but have no painted segment.

## Over-allocation [#over-allocation]


```tsx
import {
  DistributionBar,
  type DistributionSegment,
} from '@commenda/pathfinder/distribution-bar';

const segments: readonly DistributionSegment[] = [
  { id: 'holding', label: 'Commenda Holding LLC', value: 32, color: '1' },
  { id: 'tushar', label: 'Tushar Shudeesh', value: 18.5, color: '2' },
  { id: 'horizon', label: 'Horizon Ventures Pte. Ltd.', value: 15, color: '3' },
  { id: 'priya', label: 'Priya Sharma', value: 14, color: '4' },
  { id: 'daniel', label: 'Daniel Kim', value: 9.5, color: '5' },
  { id: 'elena', label: 'Elena Petrova', value: 6, color: '6' },
  {
    id: 'other-a',
    label: 'Aleksandra Wiśniewska-Kowalczyk',
    value: 3,
    color: '1',
  },
  { id: 'other-b', label: 'Jo', value: 2, color: '2' },
];

export const DistributionBarOverflow = () => (
  <DistributionBar
    label="Ownership allocation"
    total={80}
    segments={segments}
    legend="list"
  />
);
```


When the sum exceeds the total, the bar scales to the sum and a persistent Alert explains the original percentage. Negative, non-finite, duplicate-ID, and invalid-total inputs produce an error rather than misleading geometry. Empty/zero allocations show an empty track. This is a figure with a data breakdown, not an ARIA progressbar.

Read the [record component rules](/docs/components/distribution-bar#design-rules).

## Design rules [#design-rules]

Figma guidance and reviewed implementation decisions for this component. Rule IDs remain stable for source comments and AI references.

### Source rules [#source-rules]

| Rule             | Contract and provenance                                                                                             |
| ---------------- | ------------------------------------------------------------------------------------------------------------------- |
| DISTRIBUTION-001 | Figma 876:59943 / 883:100: 6/8px track, 2px gaps, identity-stable data colors.                                      |
| DISTRIBUTION-002 | Six visible groups maximum, five plus Other when necessary; source members remain available.                        |
| DISTRIBUTION-003 | Unallocated remainder stays track. Over-allocation scales geometry and explains the original percentage.            |
| DISTRIBUTION-004 | Visual minimum 4px is not numeric precision. Keep exact shares and a textual breakdown, including with legend=none. |

### Recorded design decisions [#recorded-design-decisions]

The Figma distribution instance paints six categories plus Other, while its documentation says at most six parts. The approved implementation plan uses six total (five plus Other when grouping). Tiny segments use constrained minimum widths, so the legend and tooltip supply exact data. Supporting text uses soft-pearl 800 where lighter Figma text would miss contrast requirements.
