KQ-1705 · UPGRADE/REQUEST
Upgrade Request
A member's upgrade request: the locked feature, the admins who can approve it as a radiogroup, and a card with the plan and a note. Send folds the card into an envelope that scales from the card's measured box on springs.glide while its flap closes on springs.snap, then flies to the chosen admin's avatar with x on glide and y on springs.drift so the path arcs, where the ring lands and a Pending chip arrives on springs.recoil. Approval unlocks the feature in place — the shackle swings open on snap and the veil lifts — and a decline shows the admin's note with a way to ask someone else; admins move with arrows, Home and End, and focus moves to Remind once the request lands.
asking priya · business · version history
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/upgrade-request
Props
- admins
- UpgradeRequestAdmin[]
- default defaultUpgradeRequestAdmins
- Who can approve: { id, name, role, presence?, tint? }.
- plan
- UpgradeRequestPlan
- default defaultUpgradeRequestPlan
- The plan asked for: { name, price, adds }.
- feature
- UpgradeRequestFeature
- default defaultUpgradeRequestFeature
- The feature the member reached for: { name, description }.
- reason
- string
- default a sentence about the Q3 roadmap
- The note's starting text.
- value / defaultValue
- string
- default — / the first admin online
- The chosen admin id, controlled or initial.
- onValueChange
- (id) => void
- default —
- Fires from the press or key that chose an admin.
- request / defaultRequest
- UpgradeRequestRecord | null
- default — / null
- The request: { adminId, note, at, status, reply?, remindedAt? }; set its status to answer it.
- onRequestChange
- (request | null) => void
- default —
- Fires when asking creates the request, a reminder updates it, or Ask someone else clears it.
- onRequest
- (details: { admin, note }) => void | Promise
- default —
- Send was pressed; a promise holds the button and a rejection keeps the form with its message.
- onRemind
- (request) => void
- default —
- Remind was pressed on a pending request.
- onOpenFeature
- () => void
- default —
- The unlocked feature's Open button was pressed.
- now
- number
- default defaultUpgradeRequestNow
- The moment times are written against, in ms.
- remindAfter
- number
- default 15
- Minutes before a second reminder can go.
- maxNote
- number
- default 280
- The note's length limit, in characters.
- status
- "ready" | "loading" | "error"
- default "ready"
- Whether the admins have arrived.
- onRetry
- () => void
- default —
- Try again was pressed after the admins failed to load.
- cardStyle
- "raised" | "outline" | "tinted"
- default "raised"
- The request card: a raised popover, a hairline outline, or a wash of the accent.
- envelopeStyle
- "classic" | "airmail" | "plain"
- default "classic"
- The envelope the card folds into: flap and seams, an airmail border, or a plain sleeve with a seal.
- accent
- "cobalt" | "mint" | "amber" | "ink" | string
- default "cobalt"
- The selection, Send and the envelope's seal: a named pigment or any CSS colour.
- formatTime
- (ms) => string
- default "14:32" (24-hour UTC)
- How a time is written.
- maxHeight
- number
- default 560
- The surface's height cap in px; it scrolls inside it.
- disabled
- boolean
- default false
- Nothing can be sent; the request can still be read.
- className
- string
- default —
- Classes for the surface.
| Prop | Type | Default | Description |
|---|---|---|---|
| admins | UpgradeRequestAdmin[] | defaultUpgradeRequestAdmins | Who can approve: { id, name, role, presence?, tint? }. |
| plan | UpgradeRequestPlan | defaultUpgradeRequestPlan | The plan asked for: { name, price, adds }. |
| feature | UpgradeRequestFeature | defaultUpgradeRequestFeature | The feature the member reached for: { name, description }. |
| reason | string | a sentence about the Q3 roadmap | The note's starting text. |
| value / defaultValue | string | — / the first admin online | The chosen admin id, controlled or initial. |
| onValueChange | (id) => void | — | Fires from the press or key that chose an admin. |
| request / defaultRequest | UpgradeRequestRecord | null | — / null | The request: { adminId, note, at, status, reply?, remindedAt? }; set its status to answer it. |
| onRequestChange | (request | null) => void | — | Fires when asking creates the request, a reminder updates it, or Ask someone else clears it. |
| onRequest | (details: { admin, note }) => void | Promise | — | Send was pressed; a promise holds the button and a rejection keeps the form with its message. |
| onRemind | (request) => void | — | Remind was pressed on a pending request. |
| onOpenFeature | () => void | — | The unlocked feature's Open button was pressed. |
| now | number | defaultUpgradeRequestNow | The moment times are written against, in ms. |
| remindAfter | number | 15 | Minutes before a second reminder can go. |
| maxNote | number | 280 | The note's length limit, in characters. |
| status | "ready" | "loading" | "error" | "ready" | Whether the admins have arrived. |
| onRetry | () => void | — | Try again was pressed after the admins failed to load. |
| cardStyle | "raised" | "outline" | "tinted" | "raised" | The request card: a raised popover, a hairline outline, or a wash of the accent. |
| envelopeStyle | "classic" | "airmail" | "plain" | "classic" | The envelope the card folds into: flap and seams, an airmail border, or a plain sleeve with a seal. |
| accent | "cobalt" | "mint" | "amber" | "ink" | string | "cobalt" | The selection, Send and the envelope's seal: a named pigment or any CSS colour. |
| formatTime | (ms) => string | "14:32" (24-hour UTC) | How a time is written. |
| maxHeight | number | 560 | The surface's height cap in px; it scrolls inside it. |
| disabled | boolean | false | Nothing can be sent; the request can still be read. |
| className | string | — | Classes for the surface. |