Components/AllocationBar

AllocationBar

A pill split by share, with legend chips — selecting a segment changes what you are inspecting.

VerifiedSince 0.3.9

AllocationBar

Basic Usage

AllocationBar

Inventory allocation

Segmented bar, legend and detail panel, with the selection held by the host.

Loading demo...

Selecting Is Inspecting

The bar is not a read-only chart: clicking a segment — or its legend chip — changes which one you are inspecting, without the bar itself moving. That is what separates it from a progress bar: it says what the whole is made of, not how far along it is.

The selection is fully controlled. With no modelValue the first segment reads as active, but a click still only emits — the host either binds v-model or handles change itself.

amount travels with the data but the bar never paints it: it belongs to the card's headline figure, laid out by the host (see the example).

API

Props

NameTypeDefaultDescription
segmentsAllocationSegment[]The segments, described below.
modelValuestringSelected segment key. Omit and the first one reads as active.
legendbooleantrueRenders the legend chips underneath.
detailbooleanfalseRenders the detail panel (active segment's label and description).
ariaLabelstring'Allocation segments'Accessible name for the segment group.
percentFormatter(percent: number) => stringOverrides the default ${percent}%.

AllocationSegment is { key, label, short?, percent, amount?, color?, description? }. short is the legend code (falling back to label), and percent runs 0–100.

Events

EventPayloadDescription
update:modelValue(key: string)A different segment was selected.
change(segment: AllocationSegment)The same move, carrying the whole segment.

Interaction Contract

  • The segments and the legend are two sets of buttons over one value; both carry aria-pressed, the segments add aria-label="{label}: {percent}", and the container is a role="group".
  • Clicking the active segment again emits nothing — there is no "deselect" here.
  • A segment without color falls back through an accent-then-receding-greys ladder, which is how upstream expresses "colour the headline share, leave the rest grey".
  • Segment width is exactly percent%; if the shares overrun 100% slightly, flex shrinks them proportionally rather than clipping the last one.
  • The selected sheen is class-driven, not animation-driven: with motion reduced the transition is dropped and the sheen still appears immediately, with no blank gap.
  • The easing is cubic-bezier(0.16, 1, 0.3, 1) (upstream's --ease-link), heavier than this family's usual --tx-ease-out-strong. That difference is deliberate.

Best Practices

  • Keep it to three to five segments and fold the tail into an "other". Anything under ~2% is neither clickable nor readable.
  • Colour the headline share and let the rest take the default greys — colouring everything erases the point of the bar.
  • Colour is never the only carrier: the legend always shows the code and the percentage, and the detail panel names the segment in full.
  • Render the headline figure ($51,785) yourself, reading it off segments by modelValue, so the card's height does not change with the selection.

Source

  • Component source: packages/tuffex/packages/components/src/allocation-bar/src/TxAllocationBar.vue.
  • Types: packages/tuffex/packages/components/src/allocation-bar/src/types.ts.
  • Tested coverage: packages/tuffex/packages/components/src/allocation-bar/__tests__/allocation-bar.test.ts (13 cases) covers widths and accessible names, the colour-ladder fallback, controlled selection, silence on a repeat click, legend/segment parity, the formatter, the detail panel switch, and the reduced-motion contract against compiled CSS.
  • Adapted from Beautiful UI (https://www.beautifului.dev), © 2026 Shane Levine, MIT.
查看源码
packages/tuffex/packages/components/src/allocation-bar/index.ts