registry/macos/blocks/reminders-01/reminders-01.tsx
"use client"
import * as React from "react"
import { PlusIcon } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/macos/ui/button"
import { Checkbox } from "@/registry/macos/ui/checkbox"
import { Input } from "@/registry/macos/ui/input"
import { SearchField } from "@/registry/macos/ui/search-field"
import {
Window,
WindowContent,
WindowControls,
WindowMain,
WindowTitle,
WindowTitlebar,
} from "@/registry/macos/ui/window"
type Reminder = { id: number; title: string; done: boolean }
const initialReminders: Reminder[] = [
{ id: 1, title: "Ship the free blocks", done: false },
{ id: 2, title: "Reply to Maya", done: false },
{ id: 3, title: "Renew the domain", done: true },
{ id: 4, title: "Book a dentist appointment", done: false },
{ id: 5, title: "Export the October invoices", done: false },
]
// A short reminder list: search, check off, and add a new one.
export function Reminders01({
className,
...props
}: React.ComponentProps<typeof Window>) {
const [reminders, setReminders] = React.useState(initialReminders)
const [query, setQuery] = React.useState("")
const [draft, setDraft] = React.useState("")
const nextId = React.useRef(initialReminders.length + 1)
const needle = query.trim().toLowerCase()
const visible = reminders.filter((item) => item.title.toLowerCase().includes(needle))
function toggle(id: number, done: boolean) {
setReminders((current) =>
current.map((item) => (item.id === id ? { ...item, done } : item))
)
}
return (
<Window className={cn("h-[480px] w-[340px]", className)} {...props}>
<WindowMain>
<WindowTitlebar>
<WindowControls />
<WindowTitle>Reminders</WindowTitle>
</WindowTitlebar>
<WindowContent className="flex flex-col overflow-hidden">
<div className="px-3 pt-3 pb-2">
<SearchField
value={query}
onChange={(event) => setQuery(event.target.value)}
placeholder="Search"
aria-label="Search reminders"
className="w-full"
/>
</div>
<div className="min-h-0 flex-1 overflow-auto px-1.5 pb-1">
{visible.length === 0 ? (
<p className="px-3 py-8 text-center text-mac-body text-mac-label-secondary">
{reminders.length === 0 ? "No reminders yet" : "No matching reminders"}
</p>
) : (
<ul>
{visible.map((item) => (
<li key={item.id}>
<label className="flex cursor-default items-center gap-2.5 rounded-[6px] px-2.5 py-[7px] hover:bg-mac-fill-quaternary">
<Checkbox
checked={item.done}
onCheckedChange={(checked) => toggle(item.id, checked === true)}
aria-label={item.title}
/>
<span
className={cn(
"min-w-0 truncate text-mac-body",
item.done && "text-mac-label-tertiary line-through"
)}
>
{item.title}
</span>
</label>
</li>
))}
</ul>
)}
</div>
<form
className="flex items-center gap-2 border-t border-mac-separator px-3 py-2.5"
onSubmit={(event) => {
event.preventDefault()
const title = draft.trim()
if (!title) return
const id = nextId.current++
setReminders((current) => [...current, { id, title, done: false }])
setDraft("")
setQuery("")
}}
>
<Input
value={draft}
onChange={(event) => setDraft(event.target.value)}
placeholder="New Reminder"
aria-label="New reminder"
/>
<Button
type="submit"
size="icon"
variant="secondary"
disabled={!draft.trim()}
aria-label="Add reminder"
>
<PlusIcon />
</Button>
</form>
</WindowContent>
</WindowMain>
</Window>
)
}