# Health 1

> A weekly habit and streak tracking widget displaying current and longest streaks with a status grid.

A shadcn/ui block from the [@pacekit](https://ui.pacekit.dev/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/pacekit/app-health-1).

- Page, with a live preview: https://shadcn.exchange/r/pacekit/app-health-1
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/pacekit/app-health-1-light-eeaa6cdb87c93c99.png
- Registry item: https://ui.pacekit.dev/r/app-health-1.json
- Listed: 2026-10-21, source last changed 2026-10-21

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/pacekit/app-health-1.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `card`, `button`, `dropdown-menu`

## Files

### `components/blocks/app/health/health-1.tsx`

```tsx
import { Check, Flame, MoreHorizontal, X } from "lucide-react";

import { Button } from "@/components/ui/button";
import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import {
    DropdownMenu,
    DropdownMenuContent,
    DropdownMenuItem,
    DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";

interface DayStreak {
    id: string;
    label: string;
    status: "active" | "completed" | "uncompleted";
}

const streakDays: DayStreak[] = [
    { id: "1", label: "01", status: "active" },
    { id: "2", label: "02", status: "active" },
    { id: "3", label: "03", status: "active" },
    { id: "4", label: "04", status: "active" },
    { id: "5", label: "05", status: "active" },
    { id: "6", label: "06", status: "completed" },
    { id: "7", label: "07", status: "completed" },
    { id: "8", label: "08", status: "uncompleted" },
    { id: "9", label: "09", status: "uncompleted" },
    { id: "10", label: "10", status: "uncompleted" },
];

const getStatusIcon = (status: DayStreak["status"]) => {
    switch (status) {
        case "active":
            return <Flame className="size-3.5" />;
        case "completed":
            return <Check className="size-3.5" />;
        case "uncompleted":
            return <X className="size-3.5" />;
    }
};

export const Health1 = () => {
    return (
        <Card className="gap-4">
            <CardHeader>
                <CardTitle>Weekly Streak</CardTitle>
                <CardDescription>Learning Habit Tracker</CardDescription>
                <CardAction>
                    <DropdownMenu>
                        <DropdownMenuTrigger
                            render={
                                <Button variant="ghost" size="icon-xs">
                                    <MoreHorizontal className="size-4" />
                                </Button>
                            }
                        />
                        <DropdownMenuContent align="end">
                            <DropdownMenuItem>
                                <span>Reset Streak</span>
                            </DropdownMenuItem>
                            <DropdownMenuItem>
                                <span>Share Progress</span>
                            </DropdownMenuItem>
                        </DropdownMenuContent>
                    </DropdownMenu>
                </CardAction>
            </CardHeader>
            <CardContent>
                <p className="text-2xl font-semibold">7 Days</p>
                <div className="flex items-center justify-between">
                    <span className="text-muted-foreground text-sm">Longest Streak</span>
                    <span className="text-sm font-medium">10 days</span>
                </div>
                <div className="mt-3 grid grid-cols-5 gap-2">
                    {streakDays.map((day) => (
                        <div
                            key={day.id}
                            className={`flex flex-col items-center justify-center gap-1 rounded-md border px-2 py-3 ${
                                day.status === "active" ? "bg-muted" : day.status === "completed" ? "" : "border-dashed"
                            }`}>
                            <span className="text-sm font-medium">{day.label}</span>
                            <div
                                className={`flex size-5 items-center justify-center rounded-md ${
                                    day.status === "active"
                                        ? "border"
                                        : day.status === "completed"
                                          ? "bg-background text-muted-foreground"
                                          : "text-muted-foreground"
                                }`}>
                                {getStatusIcon(day.status)}
                            </div>
                        </div>
                    ))}
                </div>
            </CardContent>
        </Card>
    );
};
```
