Trash Countdown

Shows how long each trashed item has before it's deleted forever, and makes emptying the trash need the typed item count.

StopsTrash purged before anyone restored

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/trash-countdown.json

The files land in your project. They're yours to edit.

Usage

trash-countdown-usage.tsx
import { TrashCountdown, type TrashItem } from "@/components/ui/trash-countdown"

<TrashCountdown
  items={items}
  onRestore={(id) => setItems((list) => list?.filter((item) => item.id !== id))}
  onEmpty={() => new Promise<void>((resolve) => setTimeout(() => { setItems([]); resolve() }, 600))}
/>

What it catches

  • Items close to permanent deletion (within soonDays)
  • Time left per item, as text and a bar
  • Recently trashed items, called out before emptying
  • New items arriving during the empty confirmation, which resets it

Props

TrashCountdown props
PropTypeDefault
items* (required)

Trashed items with when they were trashed and where they restore to.

TrashItem[]—
retentionDays

Days an item stays in the trash before it's deleted forever.

number30
soonDays

Items with fewer days than this left are highlighted.

number3
recentFor

Items trashed more recently than this (ms) are called out before emptying.

numberDAY
onRestore* (required)

Put an item back. Return a promise to show progress; a rejection keeps the row.

(id: string) => void | Promise<void>—
onEmpty* (required)

Delete these items forever.

(ids: string[]) => void | Promise<void>—
title

Heading of the list.

string"Trash"
emptyLabel

Label of the empty-trash button.

string"Empty trash"
restoreLabel

Label of each restore button.

string"Restore"
nothingText

Shown when the trash is empty.

string"Trash is empty."

* required. Also accepts the native props of <section> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Section labelled by its title; empty toggle uses aria-expanded/aria-controls
  • Confirm area is inert until opened; focus moves to the count input; Escape cancels
  • Count input has a <label> and is described by the grew-meanwhile note
  • Countdown bars respect reduced motion

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

This is a UX guard rail. Enforce on the server: Run purges server-side on the stated schedule and authorize empty-trash requests; keep restore possible until the purge.

  • Purge timing comes from retentionDays you pass; the server's purge job decides
  • Typing the count proves attention, not authorization

What it stops

Trash purged before anyone restored

Also known as

trash · recycle bin · bin · restore · soft delete · empty trash · deleted items · 30 days

Dependencies

Pairs well with