Make room for a walk
7–13 September 2026
Evening walk
Mark a day complete, or clear a completed day.
- Mon 7
- Tue 8
- Wed 9
- Thu 10
- Fri 11
- Sat 12
- Sun 13
This example keeps changes only while the page is open.
Shows dated complete, missed, skipped, and unrecorded states, with controlled completion actions and a responsive week view.
Evening walk
7–13 September 2026
Evening walk
Mark a day complete, or clear a completed day.
This example keeps changes only while the page is open.
Three ways in. They share one source, so the pixels match whichever you pick.
npm install @noorddev/vlak-react
// once, next to your app's root
import "@noorddev/vlak-react/css";
import { HabitTracker } from "@noorddev/vlak-react";Precompiled React and one stylesheet. No compiler to configure. Per-component imports work too: @noorddev/vlak-react/components/habit-tracker.
npx @noorddev/vlak-cli add habit-tracker
The StyleX leaf lands in components/vlak/, for your own compiler to own. See StyleX.
npx shadcn add https://vlak.dev/r/habit-tracker.json
The same registry item, installed by shadcn's CLI.
<link rel="stylesheet" href="node_modules/@noorddev/vlak/css/vlak.css" />
No React. Link vlak.css and use the markup and classes below.
import { useState } from "react";
import { HabitTracker } from "@noorddev/vlak-react";
import type { HabitDay } from "@noorddev/vlak-react";
function WalkingRecord() {
const [days, setDays] = useState<HabitDay[]>([
{ date: "2026-09-07", label: "Mon 7 Sep", status: "complete" },
{ date: "2026-09-08", label: "Tue 8 Sep", status: "unrecorded" },
]);
return <HabitTracker label="Evening walk" days={days} onDayChange={(date, status) => setDays((records) => records.map((day) => day.date === date ? { ...day, status } : day))} />;
}Dated completion records with caller-owned state and no inferred streak.
| Prop | Type | Default | Description |
|---|---|---|---|
labelrequired | ReactNode | ||
description | ReactNode | ||
daysrequired | HabitDay[] | A supplied week or another dated range, rendered in the given order. | |
onDayChange | (date: string, status: HabitStatus) => void | A completion action requests complete, or unrecorded when clearing completion. | |
disabled | boolean | false | |
readOnly | boolean | false |
Also accepts HTMLAttributes<HTMLDivElement>.
| Keys | Does |
|---|---|
| Tab | Moves through enabled completion controls when onDayChange is supplied. |
| Enter, Space | Requests completion, or clears an existing completion to unrecorded. |
<div class="rs-habit-tracker" role="group" aria-labelledby="habit-label"><p class="rs-habit-tracker-label" id="habit-label">Evening walk</p><ul class="rs-habit-tracker-days"><li class="rs-habit-tracker-day"><span class="rs-habit-tracker-date">Mon 7 Sep</span><div class="rs-habit-tracker-control rs-habit-tracker-complete rs-habit-tracker-static"><span class="rs-habit-tracker-mark" aria-hidden="true">✓</span><span>Complete</span></div></li><li class="rs-habit-tracker-day"><span class="rs-habit-tracker-date">Tue 8 Sep</span><div class="rs-habit-tracker-control rs-habit-tracker-static"><span class="rs-habit-tracker-mark" aria-hidden="true">·</span><span>Unrecorded</span></div></li></ul></div>