# ImpersonationBanner

> A sticky bar that says you are viewing as another user, or previewing, with an exit button. It is a status region, pinned so it cannot scroll away, and AdminArea uses it.

Source: https://docs.nasaqui.com/components/impersonation-banner

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/impersonation-banner.json
```

The bar that keeps an admin honest while they use the product as someone else, and that tells a person
previewing a role that nothing is saved. Show it on every screen for as long as the session lasts.

## When to use

- An admin or support agent acts as a customer (`mode="impersonate"`).
- A designer or owner previews the app as another role or plan (`mode="preview"`).

## When not to use

- A general notice: use `Alert`.
- Switching your own account: use `UserMenu`.

## Import

```tsx
import { ImpersonationBanner } from "@fadymondy/nasaq/web";
```

## Quick start

```tsx
{session.impersonating ? (
  <ImpersonationBanner as={{ name: "Omar Khalid", email: "omar@example.com" }} startedAt={session.startedAt} onExit={endImpersonation} />
) : null}
```

## Anatomy

```
ImpersonationBanner    data-slot="impersonation-banner", data-mode, role="status"
├─ icon                shield (impersonate) or eye (preview)
├─ message             "You are viewing the app as {name}" + email + hint + "Since 5 minutes ago"
└─ Button              exit, with a loading state
```

## API

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `as` | `{ name, email? }` | required | Whose view this is. |
| `mode` | `"impersonate" \| "preview"` | `"impersonate"` | Warning colour with "actions count as this user", or info colour with "nothing is saved". |
| `startedAt` | `string \| number \| Date` | none | Shows "Since 5 minutes ago". |
| `onExit` | `() => void \| Promise<void>` | required | Ends the session. A rejection keeps the bar and shows a failure. |
| `sticky` | `boolean` | `true` | Pin to the top of the scroll container. |
| `hint` | `ReactNode` | by mode | Replaces the second sentence. |
| `labels` | `ImpersonationBannerLabels` | en / ar | Every string; `impersonating` and `previewing` are functions of the name. |

## Examples

- **Preview**: `mode="preview" as={{ name: "Viewer role" }}`.
- **Inside AdminArea**: pass `impersonating` and `onStopImpersonating`; the frame renders this component.

## Accessibility

A `role="status"` region announces when it appears. The exit button is a real button with a loading state; a
failed exit is announced with `role="alert"`. The tone is never the only cue: each mode has its own icon and text.

## RTL & i18n

Built-in English and Arabic. The email stays left-to-right inside an Arabic sentence; the time uses `DateTime`.

## Styling & tokens

`bg-nq-warning-soft` / `text-nq-warning-text` for impersonation, `bg-nq-info-soft` / `text-nq-info-text` for preview.

## Do / Don't

- Do render it above every screen while the session lasts.
- Do not let the exit button be hidden behind a menu.

## Related

- [AdminArea](https://docs.nasaqui.com/components/admin-area)
- [AdminUsers](https://docs.nasaqui.com/components/admin-users)

## Lab

https://docs.nasaqui.com/?path=/docs/components-admin-impersonation-banner--docs

## Code

### React

```tsx
{session.impersonating ? (
  <ImpersonationBanner as={{ name: "Omar Khalid", email: "omar@example.com" }} startedAt={session.startedAt} onExit={endImpersonation} />
) : null}
```

### shadcn

```tsx
{session.impersonating ? (
  <ImpersonationBanner as={{ name: "Omar Khalid", email: "omar@example.com" }} startedAt={session.startedAt} onExit={endImpersonation} />
) : null}
```

### Vue

```vue
<script setup lang="ts">
import { NqImpersonationBanner } from "@fadymondy/nasaq/vue";

const exit = () => new Promise<void>((resolve) => setTimeout(resolve, 600));
</script>

<template>
  <NqImpersonationBanner :as="{ name: 'Sara Ali', email: 'sara@example.com' }" :started-at="Date.now() - 5 * 60_000" :sticky="false" :on-exit="exit" />
</template>
```

### Blade

```blade
<x-nq::impersonation-banner :as="['name' => 'Sara Ali', 'email' => 'sara@example.com']" :sticky="false" />
```

### HTML + Alpine

```html
<div role="status" data-slot="impersonation-banner" data-mode="impersonate" x-data="nqImpersonationBanner(null)"
    class="flex shrink-0 flex-wrap items-center gap-x-3 gap-y-1 px-4 py-2 text-body-sm bg-nq-warning-soft text-nq-warning-text">
    <svg aria-hidden="true" class="size-4 shrink-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/>
  <path d="M6.376 18.91a6 6 0 0 1 11.249.003"/>
  <circle cx="12" cy="11" r="4"/>
</svg>    <span class="min-w-0 flex-1">
        <span class="font-medium">You are viewing the app as Sara Ali.</span>
        <bdi dir="ltr" class="opacity-80">sara@example.com</bdi>        <span class="opacity-80">Actions you take count as this user.</span>
                <span role="alert" x-show="failed" x-cloak style="display: none" class="ms-2 font-medium">Could not exit. Try again.</span>
    </span>
    <button data-slot="button"
     type="button"                         x-bind="exitButton" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg data-slot="spinner" aria-hidden="true" style="display: none;" x-show="busy" x-cloak="1" class="size-4 animate-spin motion-reduce:animate-none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21 12a9 9 0 1 1-6.219-8.56"/>
</svg>        <span x-show="!busy">Exit impersonation</span>
        <span x-show="busy" x-cloak style="display: none">Exiting…</span></button>
</div>
```
