Bar Picker

A short run of values as columns of lights, one column picked.

Dark previewReplay previewOpen in new tab

Deploys

This week · 59

Thursday

17

29% of the week

Use it for a handful of values where one is in focus: a week with one day picked, six sprints with the latest picked. Each value is a column of lights, lit from the bottom up to the value. Pressing a column picks it, and you show that column's figure beside the row.

It behaves as a row of radio buttons, so exactly one column is always picked.

A column of eight lights shows a value to the nearest eighth. For values someone has to read precisely, for more than about twelve of them, or for more than one series, use a chart with an axis.

Installation

Copy the folder into components/ui, where you can edit it. It needs the cn helper and the theme's info, success and warning colours.

text
components/ui/bar-picker/
├── BarPicker.vue
└── index.ts

Usage

vue
<script setup lang="ts">
import { ref } from "vue";
import { BarPicker, type BarPickerBar } from "@/components/ui/bar-picker";

const week: BarPickerBar[] = [
  { label: "Mon", name: "Monday", value: 9 },
  { label: "Tue", name: "Tuesday", value: 14 },
  { label: "Wed", name: "Wednesday", value: 11 },
];
const day = ref(0);
</script>

<template>
  <BarPicker v-model="day" :data="week" />
</template>

A fixed scale and a colour

max sets what a fully lit column stands for, here 100 percent, so the columns are lit against the whole scale and not against the tallest of them. default-value picks a column to begin with and lets the component hold the choice.

Dark previewReplay previewOpen in new tab

API Reference

BarPicker

PropTypeDefaultDescription
dataBarPickerBar[]—The columns, left to right: { label, value, name? }.
maxnumber—The value a fully lit column stands for. Defaults to the largest in data.
modelValuenumber—The index of the picked column, when the caller holds it with v-model.
defaultValuenumber0The index picked to begin with, when the caller does not hold it.
segmentsnumber8How many lights a column is made of.
color"primary" | "info" | "success" | "warning" | "destructive""primary"Which of the theme's roles the lights are drawn in.
formatValue(value: number) => string(value) => String(value)Writes a value for a screen reader: "17 deploys".
labelstring"Values"What a screen reader calls the row.
EventDescription
update:modelValueThe index of a column when it is picked.

It also takes the attributes of the element it renders, and a class.

Notes

Scale

A column lights the share of its segments that its value is of max, rounded to the nearest segment. Leave max out to scale to the largest value in data, or set it when the values share a known ceiling.

Any value above zero lights at least one segment. A value of zero lights none, and a value above max lights them all.

Segments

A column has 8 segments unless segments says otherwise. More segments show a value more finely and need more height to stay readable. The stack is 7rem tall.

Picking

The whole column is the target, so an empty column can still be picked. The picked column is half as wide again as the others, lit at full strength, and its highest light glows. The others are lit at about a quarter of the same colour.

Labels

label is drawn under the column and should be a few characters. name is the long form a screen reader is given with the value: "Thursday: 17 deploys". Use format-value to say the unit.

Keyboard

The row is one Tab stop. Left and right move the pick and wrap at the ends, and Home and End go to the first and last column.

Motion

The columns light from the bottom when the row first appears, in CSS, so the values show even before the page hydrates, and the picked column widens as the pick moves. With reduced motion on, both happen at once.

Accessibility

Keyboard shortcuts and ARIA behavior.

Shortcut Description
TabMove focus to the picked column. The row is one Tab stop.
← + →Pick the previous or next column, wrapping at the ends.
HomePick the first column.
EndPick the last column.
  • The row is a radiogroup and each column a radio, named "Thursday: 17 deploys" from name and format-value.