Skip to content

Ranked list ​

A top-N list: a leading tile, a label, a value and a proportional bar.

Open in demo
Open in demo

Usage ​

items is RankedItem[]. value is a string you have already formatted, and percent is the bar fill from 0 to 100. Whether that is a share of the total or of the largest row is your decision, and the component clamps it either way so a raw ratio cannot overflow the track.

It is deliberately not a chart. Nothing here imports ECharts, so it can go on any page without pulling the charting bundle along.

With no icon, the tile shows the label's initials. They are segmented by grapheme, so a name that starts with an emoji or a combining mark is not cut in half, and they are uppercased in the active language.

Examples ​

Icons and accents ​

icon takes a Lucide icon and accent is one of primary, sky, emerald, amber, violet or rose, the same six the stat cards use.

Loading and empty ​

loading renders five skeleton lines. An empty list shows "Nothing to show yet" rather than collapsing to nothing.

API ​

Source: src/shared/components/common/charts/RankedList.vue

Props ​

PropTypeDefaultDescription
itemsRankedItem[]requiredThe rows, in the order you want them.
loadingbooleanfalseRenders five skeleton lines.

RankedItem ​

KeyTypeDescription
idstringThe list key.
labelstringThe first line, and the source of the initials.
sublabelstringThe second line: an owner, a category.
valuestringThe right-aligned figure, already formatted.
percentnumberThe bar fill, 0 to 100. Clamped.
iconLucideIconReplaces the initials.
accent'primary' | 'sky' | 'emerald' | 'amber' | 'violet' | 'rose'The tile color. Defaults to primary.

Emits ​

None.

Slots ​

None.

Accessibility ​

  • The rows are a real list, so a screen reader announces how many there are.
  • The bar is role="presentation". The number it stands for is already printed beside it, and announcing the bar too would only be noise.
  • The tile is aria-hidden, because initials and an icon add nothing to the label next to them.
  • Labels and sublabels truncate rather than wrap, so a long name cannot push the value out of the row.