Access request

Pro

Ask for a role you don't have on an environment. Says who decides, when the app knows. Once sent it shows as pending, with withdraw. A role at or below the one you hold there is locked, with the reason.

Markdown

Preview

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/access-request

Brings in: button, environment-band, locale, locked, team, terms, utils · npm: lucide-react@^1.67.0

Usage

TSX · The example above
"use client"

import * as React from "react"
import { AccessRequest, type SentAccessRequest } from "@/components/access-request"
import type { Environment, Role } from "@/lib/team"

const environments: Environment[] = [
  { id: "env-prod", name: "Acme API", production: true, hue: 3, connection: "connected" },
  { id: "env-staging", name: "Acme API", detail: "Staging", production: false, hue: 2, connection: "connected" },
]

const roles: Role[] = [
  { id: "contributor", label: "Contributor", rank: 1 },
  { id: "approver", label: "Approver", rank: 2 },
  { id: "admin", label: "Admin", rank: 3 },
]

const deciders = { "env-prod": ["Priya", "Dana"], "env-staging": ["Priya"] }

export default function Example() {
  const [sent, setSent] = React.useState<SentAccessRequest | null>(null)
  return (
    <AccessRequest
      className="w-full max-w-md"
      environments={environments}
      roles={roles}
      requestable={["approver", "admin"]}
      current={{ "env-staging": "contributor" }}
      deciders={deciders}
      note="Raising a role always needs approval."
      sent={sent}
      onSend={(environmentId, role) => setSent({ environment: environmentId, role, at: new Date().toISOString(), deciders: deciders[environmentId as keyof typeof deciders] })}
      onWithdraw={() => setSent(null)}
    />
  )
}

<AccessRequest>

PropTypeDefaultDescription
environmentsrequiredEnvironment[]—The environments a role can be asked for on.
rolesrequiredRole[]—Every role, so the one you hold can be named.
requestablerequiredstring[]—Role ids that can be asked for.
currentrequiredRecord<string, string | undefined>—The viewer's role id per environment id.
decidersrequiredRecord<string, string[]>—Who decides, per environment id.
notestring | undefined—The app's rule, e.g. "Raising a role always needs approval."
sentSentAccessRequest | null | undefined—The request already sent; set, the form gives way to a pending note. null/undefined means none sent.
onSendrequired(environmentId: string, roleId: string, reason: string) => void—Called on send with the environment id, role id and the reason given.
onWithdraw(() => void) | undefined—Shows Withdraw on a pending request; called when it's clicked.
classNamestring | undefined—Extra classes for the outer element.

Strings

The fixed words, in English by default. Change any of them under accessRequest in <LocaleProvider strings={{ … }}>; the table is exported as accessRequestStrings.

KeyEnglish
sentLabelAccess request
formLabelAsk for access
headingAsk for more access
withAa {role}
withAnan {role}
chooseEnvironmentChoose the {environment}.
chooseAccessChoose the access you need.
alreadyThereYou’re already {role} there.
sayWhySay why you need it; the deciders see this.
askedForYou asked to be {role} on {place}.
waitingForWaiting for {deciders}.
withdrawWithdraw
productionProduction
youAreYou’re {role} on this {environment}.
noRoleYou have no role on this {environment}.
roleRole
whyWhy
decidedByDecided by {deciders}.
sendSend request

Types

SentAccessRequest
{ /** The environment's id, as onSend gave it; shown by its name. (A name that matches no id is shown as it is.) */ environment: string /** The role's id, shown by its label. */ role: string at: string deciders: string[] }