Feature Requests
Run a feature request board with voting, submissions, and a drop-in UI.
Mite gives you a feature request board your users can read, vote on, and submit
to. Mount FeatureRequestsSheet for a complete UI, or use the
hook and build your own.
Votes and submissions are tied to the SDK's identified or anonymous end user — you do not need to pass identifiers yourself.
Drop-in UI
FeatureRequestsSheet wraps any element and turns it into a trigger. Tapping it
opens a sheet listing the board, with vote buttons and a compose form.
import { FeatureRequestsSheet } from '@usemite/sdk'
<FeatureRequestsSheet onSubmitted={id => console.log('Created', id)}>
<Text>Request a feature</Text>
</FeatureRequestsSheet>| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Element used as the trigger |
title | string | 'Feature requests' | Sheet heading |
accentColor | string | #0a7ea4 | Color for vote buttons and the submit action |
onSubmitted | (featureRequestId: string) => void | — | Called after a successful submission |
The board is fetched lazily — nothing is requested until the sheet is opened. Voting is optimistic: the count moves immediately and reverts if the request fails.
Using the hook
import { useFeatureRequests } from '@usemite/sdk'
const {
featureRequests,
votedFeatureRequestIds,
loading,
error,
refetch,
submitFeatureRequest,
submitting,
submitError,
toggleVote,
votingFeatureRequestIds,
} = useFeatureRequests({ enabled: true })enabled defaults to false. Nothing is fetched until you pass
enabled: true — useful for deferring the request until a sheet or screen
opens, but surprising if you expect a fetch on mount.
Options
| Option | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Fetch the board and vote state on mount |
voterEmail | string | — | Deprecated. Look up votes by email instead of by end user |
Return value
| Field | Type | Description |
|---|---|---|
featureRequests | FeatureRequest[] | The board |
votedFeatureRequestIds | string[] | IDs the current user has voted for |
loading | boolean | Whether the board is being fetched |
error | Error | null | Fetch error |
refetch | () => Promise<void> | Refetch the board and vote state |
submitFeatureRequest | (input: SubmitFeatureRequestInput) => Promise<CreateFeatureRequestResponse> | Create a request, then refetch |
submitting | boolean | Whether a submission is in flight |
submitError | Error | null | Submission error |
toggleVote | (featureRequestId: string) => Promise<VoteFeatureRequestResponse> | Toggle a vote, optimistically |
votingFeatureRequestIds | string[] | IDs with a vote request in flight — use to disable buttons |
refetch never rejects. submitFeatureRequest and toggleVote do reject, in
addition to setting their error state, so you can react inline.
Submitting
await submitFeatureRequest({
title: 'Offline mode',
description: 'Let users browse cached content without a connection',
author_name: 'Taylor',
author_email: 'taylor@example.com',
})Or directly on the instance with mite.features.request():
await mite.features.request({
title: 'Offline mode',
description: 'Let users browse cached content without a connection',
author: { email: 'taylor@example.com', name: 'Taylor' },
})The author's email is required: author.email on features.request, or
author_email on the hook. The team needs it to follow up and to notify the
author of status changes. The name is optional. Requests without one show as
anonymous.
The hook's submitFeatureRequest still takes the flat author_name and
author_email fields. features.request takes them nested under author.
Emails are lowercased and trimmed before sending. title is trimmed;
description defaults to an empty string.
Voting
toggleVote flips the current user's vote:
const { voted, voteCount } = await toggleVote('fr_123')Or directly:
await mite.features.vote('fr_123')The vote is attributed to the current anonymous or identified user automatically. Fetch the current user's votes with:
const votedIds = await mite.features.myVotes()voter_email on the 1.0 voteFeatureRequest, and voterEmail on the hook
and the 1.0 getFeatureRequestVotes(), are deprecated. They exist only to keep older
email-based votes working. New code should omit them and let the SDK use the
end user identity. They are ignored entirely in
anonymous-only mode.
Fetching the board directly
const requests = await mite.features.list()Moving from 1.0
The 1.0 methods still work. They are deprecated and are removed in 2.0.
| 1.0 | Now |
|---|---|
createFeatureRequest({ title, author_email, author_name }) | features.request({ title, author: { email, name } }) |
voteFeatureRequest({ feature_request_id }) | features.vote(id) |
getFeatureRequests() | features.list() |
getFeatureRequestVotes() | features.myVotes() |
The FeatureRequest object
interface FeatureRequest {
id: string
title: string
description: string
authorName: string
voteCount: number
status: FeatureRequestStatus
createdAt: number
}Note the casing: responses use camelCase (authorName, voteCount). The hook
input and the 1.0 payloads use snake_case (author_name, author_email).
Status values
| Status | Description |
|---|---|
OPEN | Accepting votes and feedback |
IN_PROGRESS | Currently being worked on |
COMPLETED | Feature has been shipped |
CLOSED | No longer planned |
FeatureRequestsSheet renders these as "Open", "In progress", "Completed", and
"Closed".