<!-- Protocore Design System — RoleChip -->
# RoleChip

- **Category:** Data Display (`data-display`)
- **Slug:** `data-display/role-chip`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { RoleChip } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/data-display/role-chip

> A static operator-role label — neutral ghost-outlined mono, never borrowing a status hue.

## When to use it

Use **RoleChip** wherever you show *who someone is* in the access model — `owner`, `admin`, `operator`, `viewer`, `service-account`. It deliberately looks like a quiet metadata **Tag** (mono, muted, as-typed) rather than a status **Badge**, because a role is a durable identity attribute, not a changing state.

Don't reach for a Badge here: giving `admin` a `success` tint or `viewer` a `neutral` tint implies a value judgement the role doesn't carry. If you genuinely need to flag a *state* of the membership (e.g. "invite pending"), that's a separate Badge next to the RoleChip, not a recolouring of it.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `children` | `ReactNode` | no | — | The role label, when composed as a child instead of via `role`. |
| `className` | `string` | no | — | — |
| `role` | `string` | no | — | The role string, rendered as-typed. Alternative to `children`. |
| `style` | `CSSProperties` | no | — | — |

## Examples

### Basics

Pass the role via the `role` prop or as children. It renders as-typed in neutral mono with a faint ghost outline — a role is *identity*, so it never takes a status colour.

```tsx
import { RoleChip, Stack } from "@protocore/pds";

// A role is identity, not status — so RoleChip is always neutral mono, never a
// status hue. Pass the role via `role` or as children.
export default function RoleChipBasics() {
  return (
    <Stack direction="row" gap={2} align="center" wrap>
      <RoleChip role="owner" />
      <RoleChip role="admin" />
      <RoleChip role="operator" />
      <RoleChip role="viewer" />
      <RoleChip>service-account</RoleChip>
    </Stack>
  );
}
```

### In a member list

RoleChip is designed to sit at the trailing edge of a person or service-account row, labelling access without competing with the name or handle.

```tsx
import { RoleChip, Avatar, Stack, Text } from "@protocore/pds";

const members = [
  { name: "Ana Petrescu", handle: "ana@protocore.io", role: "owner" },
  { name: "Deploy Bot", handle: "svc/deployer", role: "service-account" },
  { name: "Radu Ilie", handle: "radu@protocore.io", role: "operator" },
];

// RoleChip sits naturally at the end of a member row, labelling identity
// without competing with the person's name.
export default function RoleChipMemberList() {
  return (
    <Stack direction="column" gap={4}>
      {members.map((m) => (
        <Stack key={m.handle} direction="row" gap={2} align="center">
          <Avatar name={m.name} size="sm" />
          <Stack direction="column" gap={1}>
            <Text size="sm" weight={500}>
              {m.name}
            </Text>
            <Text size="sm" color="muted" mono>
              {m.handle}
            </Text>
          </Stack>
          <span style={{ marginLeft: "auto" }}>
            <RoleChip role={m.role} />
          </span>
        </Stack>
      ))}
    </Stack>
  );
}
```

## Usage

**Do**

- Use it for role/identity labels in member lists, audit rows, and access panels.
- Keep role strings lowercase and as-typed to match the values in your IAM system.
- Pair it with an Avatar and handle so the row reads person → identity → role.
- If a membership has a transient state, add a separate Badge rather than tinting the RoleChip.

**Don't**

- Don't give roles status colours — `admin` is not "danger", `viewer` is not "neutral-good".
- Don't make a RoleChip interactive; to *change* a role, use a Select or a menu.
- Don't overload it with permission scopes — those belong in a DefinitionList or a detail panel.
- Don't invent per-role colours; the neutral treatment is the point.

## Accessibility

**Notes**

- RoleChip is a non-interactive `<span>` — screen readers announce the role text inline with the surrounding row.
- Because the label is text (not colour), the role is fully conveyed to monochrome and colour-blind readers by default.
- When a role needs a fuller description for assistive tech, add an `aria-label` or an adjacent visually-hidden expansion (e.g. "operator — can deploy and roll back").

## Related

`tag`, `badge`, `env-badge`, `status-dot`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
