KQ-2106 · ENV/RIBBON
Env Ribbon
An app shell whose top edge always says which environment it is pointed at: a ribbon in the environment's colour, and a change sweeps the new colour across it from the switcher outward on springs.glide, both edges reaching the frame's ends together with a glint riding each, while the console's data cross-fades and its rows rise 4px in cascade. Entering a protected environment grows a hatched edge on every destructive button on springs.snap, each timed to the moment the sweep reaches it, and switching into production or running a destructive action there asks for the environment's name to be typed first. Alt+E opens the switcher, a listbox with arrow keys, type-ahead and Escape; below a 22rem container the ribbon thickens into a labelled bar.
Waylight Deploy console
production · eu-west-1 · v2.14.3 · last: nothing run
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/env-ribbon
Props
- ribbonWidth
- number
- default 4
- Ribbon thickness along the frame's top edge, in px. The narrow labelled bar grows with it.
- hatch
- "stripe" | "cross" | "ticks" | "off"
- default "stripe"
- The edge destructive buttons grow in a protected environment.
- accent
- "cobalt" | "plum" | "mint" | "ink" | string
- default "cobalt"
- Interface accent: the mark, the primary action and the switcher's selection. A name or any CSS colour.
- environments
- EnvRibbonEnvironment[]
- default defaultEnvRibbonEnvironments
- The environments in switcher order: { id, name, colour?, protected?, region?, host? }. Colours default to green, amber and red pigments.
- environment / defaultEnvironment
- string
- default — / "staging"
- The current environment id, controlled or initial.
- onEnvironmentChange
- (id: string, environment: EnvRibbonEnvironment) => void
- default —
- Fires from the choice, after any confirmation, that changed the environment.
- snapshots
- Record<string, EnvRibbonSnapshot>
- default defaultEnvRibbonSnapshots
- What each environment runs, by id: version, commit, deployedAt, deployedBy, metrics and services.
- actions
- EnvRibbonAction[]
- default defaultEnvRibbonActions
- The action bar: { id, label, kind?, icon?, short?, consequence?, done? }. Destructive actions grow the hatched edge and ask first in a protected environment.
- onAction
- (actionId: string, envId: string) => void
- default —
- An action ran straight away: anything outside a protected environment, and non-destructive actions inside one.
- onConfirmProtected
- (request: { kind: "switch" | "action"; envId: string; actionId?: string }) => void
- default —
- A protected switch or destructive action was confirmed.
- confirmByTyping
- boolean
- default true
- Ask for the environment's name to be typed before a protected step. Off: one confirm press.
- now
- number
- default defaultEnvRibbonNow
- The moment relative times count from, in ms, so server and browser agree.
- product
- string
- default "Waylight"
- Product name beside the mark.
- title
- string
- default "Deploy console"
- The console's title under the product.
- shortcut
- boolean
- default true
- Alt+E opens the switcher while focus is in the frame, or while it is hovered with nothing focused.
- status
- "ready" | "loading" | "error"
- default "ready"
- Whether the current environment's data has arrived: a skeleton while loading, a message with Try again on error.
- onRetry
- () => void
- default —
- Try again after an error.
- disabled
- boolean
- default false
- Read only: nothing can be switched or run.
- label
- string
- default —
- The frame's accessible name. Defaults to the product and title.
- className
- string
- default —
- Classes for the outer container.
| Prop | Type | Default | Description |
|---|---|---|---|
| ribbonWidth | number | 4 | Ribbon thickness along the frame's top edge, in px. The narrow labelled bar grows with it. |
| hatch | "stripe" | "cross" | "ticks" | "off" | "stripe" | The edge destructive buttons grow in a protected environment. |
| accent | "cobalt" | "plum" | "mint" | "ink" | string | "cobalt" | Interface accent: the mark, the primary action and the switcher's selection. A name or any CSS colour. |
| environments | EnvRibbonEnvironment[] | defaultEnvRibbonEnvironments | The environments in switcher order: { id, name, colour?, protected?, region?, host? }. Colours default to green, amber and red pigments. |
| environment / defaultEnvironment | string | — / "staging" | The current environment id, controlled or initial. |
| onEnvironmentChange | (id: string, environment: EnvRibbonEnvironment) => void | — | Fires from the choice, after any confirmation, that changed the environment. |
| snapshots | Record<string, EnvRibbonSnapshot> | defaultEnvRibbonSnapshots | What each environment runs, by id: version, commit, deployedAt, deployedBy, metrics and services. |
| actions | EnvRibbonAction[] | defaultEnvRibbonActions | The action bar: { id, label, kind?, icon?, short?, consequence?, done? }. Destructive actions grow the hatched edge and ask first in a protected environment. |
| onAction | (actionId: string, envId: string) => void | — | An action ran straight away: anything outside a protected environment, and non-destructive actions inside one. |
| onConfirmProtected | (request: { kind: "switch" | "action"; envId: string; actionId?: string }) => void | — | A protected switch or destructive action was confirmed. |
| confirmByTyping | boolean | true | Ask for the environment's name to be typed before a protected step. Off: one confirm press. |
| now | number | defaultEnvRibbonNow | The moment relative times count from, in ms, so server and browser agree. |
| product | string | "Waylight" | Product name beside the mark. |
| title | string | "Deploy console" | The console's title under the product. |
| shortcut | boolean | true | Alt+E opens the switcher while focus is in the frame, or while it is hovered with nothing focused. |
| status | "ready" | "loading" | "error" | "ready" | Whether the current environment's data has arrived: a skeleton while loading, a message with Try again on error. |
| onRetry | () => void | — | Try again after an error. |
| disabled | boolean | false | Read only: nothing can be switched or run. |
| label | string | — | The frame's accessible name. Defaults to the product and title. |
| className | string | — | Classes for the outer container. |