A year of days, as a grid you can read at a glance.
Import it from rei-kit:
import { ActivityGrid } from 'rei-kit'
Open ActivityGrid in the live documentation, where every prop below is a control you can change, in four materials and ten palettes.
<script setup lang="ts">
import { ActivityGrid, lastNDays, useToast } from 'rei-kit'
const toast = useToast()
const days = lastNDays(365)
/** Four steps, so a busy day reads differently from a quiet one. */
const LEVELS = ['bg-muted', 'bg-primary/25', 'bg-primary/50', 'bg-primary/75', 'bg-primary']
const count = (key: string) => (key.charCodeAt(9) + key.charCodeAt(8)) % 5
const levelFor = (key: string) => LEVELS[count(key)]!
const dayLabel = (key: string) => `${key}: ${count(key)} entries`
const isSelectable = (key: string) => count(key) > 0
</script>
<template>
<ActivityGrid
:days="days"
label="Your year"
:level-for="levelFor"
:day-label="dayLabel"
:is-selectable="isSelectable"
@select="toast.info($event)"
/>
</template>
| Prop | Type | Required or default | What it is for |
|---|---|---|---|
days | readonly string[] | yes | The days to draw, as `YYYY-MM-DD`, oldest first. |
label | string | yes | Names the grid, e.g. "Your year". Already translated. |
levelFor | (key: string) => string | yes | A class for one day's square, e.g. `bg-positive/40`. |
dayLabel | (key: string) => string | yes | What a reader hears on a day: the date, and what happened. Translated. |
isSelectable | ((key: string) => boolean) | undefined | Which days lead somewhere. Unset, the grid is a picture and nothing else. |
weekStartsOn | WeekStart | 1 | `1` Monday, `0` Sunday. |
startAtEnd | boolean | true | Open on the most recent weeks — a year otherwise starts far off-screen. |
rei-kit is an accessible Vue 3 and Tailwind CSS 4 component library: 106 components, themed by role rather than by colour on three independent axes — ten WCAG-checked palettes, four materials and light or dark, each switched with one attribute. Typed, tested, SSR-safe, no runtime dependencies, MIT.