Moderation Queue
Reported content with its report reasons and a decision. Sensitive items are blurred until revealed, because a moderator should choose when to look at the worst thing in the queue.
src/components/ui/moderation-queue.tsxAbout
From the component's own source, where it was written.
A review queue for reported content.
Reported content is blurred until revealed. Moderators do not consent to seeing every image that gets flagged, and a queue that renders graphic material on load is a duty-of-care failure — the reveal is per item and deliberate.
Decisions are reported, never applied locally. Two moderators working the same queue must not both act on one item because each interface hid it optimistically; the server decides who won.
The report count and reason distribution are shown together — ten reports for spam is a different problem from ten reports across five unrelated reasons, which usually means brigading.
Install
npx astralyx-ui add moderation-queue
Usage
import { ModerationQueue } from '@/components/ui/moderation-queue'
<ModerationQueue items={items} onDecide={decide} onBulkDecide={decideMany} />Composer
Change the props and the source below follows.
- user_88213
user_8821314
reported
Check out this totally legitimate investment opportunity, DM me for the linkspam · 11scam · 3 - grimwald
grimwald1
reported
Honestly the update broke everything and support has been useless for a week.harassment · 1 - anon_4412
anon_44126
reported
[graphic image description withheld]graphic · 5self-harm · 1 - kestrel
kestrel2Approved
reported
Reposting because the first one got buried — free giveaway, 100 winners!spam · 2
<ModerationQueue items={items} onDecide={decide} onBulkDecide={decideMany} />Examples
A queue with bulk actions
<ModerationQueue items={items} now={now} onApprove={approve} onReject={reject} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
ModerationQueue
Extends Omit<ComponentProps<'div'>, 'onSelect'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| items | ModerationItem[] | required | { id, author, content, sensitive?, reportedAt, reportCount?, reasons?, status? }. |
| onDecide | (id: string, decision: 'approve' | 'remove') => void | — | 'approve' | 'remove' for one item. |
| onBulkDecide | (ids: string[], decision: 'approve' | 'remove') => void | — | Enables selection. Omit it and each item is decided on its own, which is right for a small, high-stakes queue. |
| now | Date | — | — |
| locale | string | 'en-GB' | — |
| emptyLabel | ReactNode | 'Queue is clear' | — |
| selectAllLabel | string | 'Select all pending' | — |
| clearSelectionLabel | string | 'Clear selection' | — |
| selectItemLabel | (id: string) => string | DEFAULT_SELECT_ITEM_LABEL | — |
| selectedLabel | (count: number) => ReactNode | DEFAULT_SELECTED_LABEL | — |
| pendingLabel | (count: number) => ReactNode | DEFAULT_PENDING_LABEL | — |
| approveLabel | ReactNode | 'Approve' | — |
| removeLabel | ReactNode | 'Remove' | — |
| approvedLabel | ReactNode | 'Approved' | — |
| removedLabel | ReactNode | 'Removed' | — |
| reportedLabel | ReactNode | 'reported' | Precedes the report time. |
| revealLabel | ReactNode | 'Reveal reported content' | Button that unblurs a sensitive item. |
Types
ModerationItem
A review queue for reported content.
| Field | Type | Description |
|---|---|---|
| id | string | — |
| author | ReactNode | — |
| authorAvatar? | ReactNode | — |
| content | ReactNode | — |
| sensitive? | boolean | Blurs the content behind a reveal. The reason and report count stay visible, which is often enough to decide without looking. |
| reportedAt | Date | — |
| reportCount? | number | — |
| reasons? | Record<string, number> | Reason to count. Fourteen spam reports and one harassment report are a different case from the reverse. |
| status? | 'pending' | 'approved' | 'removed' | — |