Feature Flag Rollout

Reads back exactly who gets a feature flag and asks again before production skips ramp steps, so a flag isn't released to everyone early.

StopsFeature flag released to everyone early

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/feature-flag-rollout.json

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

Usage

feature-flag-rollout-usage.tsx
import { FeatureFlagRollout, type RolloutValue } from "@/components/ui/feature-flag-rollout"

return <FeatureFlagRollout environments={environments} segments={segments} defaultValue={saved} defaultDraft={draft} />

What it catches

  • Production rollouts that skip ramp steps
  • Production ahead of staging
  • Who actually gets the flag, counted in users
  • How many users lose the feature on a pullback

Props

FeatureFlagRollout props
PropTypeDefault
environments* (required)

Environments in promotion order, e.g. dev → staging → production.

RolloutEnvironment[]—
segments

Segments that can be switched on per environment (staff, beta testers…).

RolloutSegment[][]
value

Saved rollout (controlled).

RolloutValue—
defaultValue

Saved rollout when uncontrolled.

RolloutValue{}
defaultDraft

Unsaved edit to start from, e.g. a change restored from a link. Defaults to the saved rollout.

RolloutValue—
onValueChange

Called with the new rollout when the user saves. May return a promise.

(value: RolloutValue) => void | Promise<void>—
steps

Ramp steps for production. Raising past the next step asks for confirmation.

number[][5, 10, 25, 50, 100]
messages

Warning text per issue. `{env}`, `{from}`, `{to}`, `{fix}`, `{prev}` and `{lost}` are filled in.

Partial<Record<RolloutIssue["kind"], string>>—
fixLabels

One-tap fix labels. `{fix}` and `{prev}` are filled in.

Partial<Record<"jump" | "ahead", string>>—
armedText

Shown once the save button is armed.

string"Click again to save anyway."
saveLabel

Save button text.

string"Save rollout"
savedLabel

Shown after saving.

string"Saved"
savingLabel

Save label while onValueChange is pending.

string"Saving…"
productionLabel

Badge on production environments.

string"prod"
confirmLabel

Save label when there are warnings. `{count}` is filled in.

string"Save with {count} warnings"
discardLabel

Text for discarding changes.

string"Discard"
reachText

Readback templates. `{who}`, `{count}` and `{total}` are filled in.

string"{who} ≈ {count} of {total} users"
nobodyText

Readback when nobody gets the flag.

string"Nobody gets this flag."
everyoneText

Readback when everyone gets the flag.

string"Everyone ({total} users)"
restText

Joins segments and the percentage in the readback, e.g. "{segments} + {percent}% of everyone else".

string"{percent}% of everyone else"

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

Accessibility

  • Each environment is a fieldset with a legend; the slider has a <label> and an aria-valuetext readback
  • Segments are a labelled group of aria-pressed toggles
  • Warnings are aria-live="polite"; save status uses role="status"

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: Enforce rollout rules and approvals in the flag service, and keep an audit log of changes.

  • User counts come from the segment sizes you pass
  • Saving runs your callback; the flag service decides real exposure

What it stops

Feature flag released to everyone early

Also known as

feature flag · rollout · percentage rollout · canary · launchdarkly · kill switch · ramp · segments

Field type

Dependencies

Pairs well with