KQ-917 · APPEAL/CARD
Appeal Card
A removed message asking for another look. The review's stages stamp in turn — the disc lands from 1.5 on recoil, the tick draws its pathLength on flick, and the rail down to the next stage fills on glide — and the decision slides in from 8px on snap inside a ResizeObserver-measured height that opens in flow rather than floating. Approval restores with a wash that sweeps the quote once on a slow tween while the strike lifts; a refusal gets no wash and no bounce. A real textarea sends the appeal, and a polite region speaks one frozen sentence per change, never before the host has answered.
Appeal in Coldbrook
RemovedRui Santos · removed under Room rule 3
Whoever packed this Waylight Pay box clearly could not care less about it.
- Step 1 of 3, appeal sent, waiting.
- Step 2 of 3, read by a moderator, waiting.
- Step 3 of 3, second moderator agrees, waiting.
Rui · step 0 of 3 · not sent
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/appeal-card
Props
- author
- string
- default —
- Whose message is under appeal.
- messageText
- string
- default —
- The removed line, quoted on the card.
- room
- string
- default "Coldbrook"
- The room the message was removed from.
- reason
- string
- default "Room rule 3"
- The house rule the removal cited.
- steps
- AppealStep[]
- default —
- The review's stages: value, label and an optional note.
- step / defaultStep
- number
- default 0
- Controlled or initial count of stamped stages.
- onStepChange
- (step: number) => void
- default —
- Fires when sending the appeal stamps the first stage.
- note / defaultNote
- string
- default ""
- Controlled or initial appeal note.
- onNoteChange
- (note: string) => void
- default —
- Fires from every keystroke in the textarea.
- onSubmit
- (note: string) => void
- default —
- Fires from Send appeal with the trimmed note.
- maxLength
- number
- default 180
- Cap on the note; the remainder reads beside the control.
- decision
- "pending" | "restored" | "upheld"
- default "pending"
- The outcome. Only the host sets it.
- decisionNote
- string
- default —
- One line under the decision.
- onDecisionShown
- (decision: "restored" | "upheld") => void
- default —
- Fires once when a decision first lands, after the state settles.
- disabled
- boolean
- default false
- Holds the textarea and the control.
- className
- string
- default —
- Extra classes on the card.
| Prop | Type | Default | Description |
|---|---|---|---|
| author | string | — | Whose message is under appeal. |
| messageText | string | — | The removed line, quoted on the card. |
| room | string | "Coldbrook" | The room the message was removed from. |
| reason | string | "Room rule 3" | The house rule the removal cited. |
| steps | AppealStep[] | — | The review's stages: value, label and an optional note. |
| step / defaultStep | number | 0 | Controlled or initial count of stamped stages. |
| onStepChange | (step: number) => void | — | Fires when sending the appeal stamps the first stage. |
| note / defaultNote | string | "" | Controlled or initial appeal note. |
| onNoteChange | (note: string) => void | — | Fires from every keystroke in the textarea. |
| onSubmit | (note: string) => void | — | Fires from Send appeal with the trimmed note. |
| maxLength | number | 180 | Cap on the note; the remainder reads beside the control. |
| decision | "pending" | "restored" | "upheld" | "pending" | The outcome. Only the host sets it. |
| decisionNote | string | — | One line under the decision. |
| onDecisionShown | (decision: "restored" | "upheld") => void | — | Fires once when a decision first lands, after the state settles. |
| disabled | boolean | false | Holds the textarea and the control. |
| className | string | — | Extra classes on the card. |