# PasskeyList

> Manage the passkeys on an account with a list with device hint, created and last-used dates, add through an async callback, rename in place, remove with confirmation, an unsupported-browser notice and an empty state.

Source: https://docs.nasaqui.com/components/passkey-list

## Install

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

The list of passkeys on an account, with add, rename and remove. It only draws the list: your `onAdd`
runs the WebAuthn ceremony (`navigator.credentials.create`) and saves the credential.

## When to use

- The security page of an account, next to two-factor and the password.

## When not to use

- Signing in with a passkey: that is a button on your sign-in form, not a list.
- Two-factor with an authenticator app: use [`TwoFactorSetup`](https://docs.nasaqui.com/components/two-factor-setup).

## Import

```tsx
import { PasskeyList, isPasskeySupported } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"
```

## Quick start

```tsx
import { PasskeyList, type Passkey } from "@fadymondy/nasaq/web";

declare const passkeys: Passkey[];
declare const api: { register(): Promise<void>; rename(id: string, name: string): Promise<void>; remove(id: string): Promise<void> };

export function Passkeys() {
  return <PasskeyList passkeys={passkeys} onAdd={api.register} onRename={api.rename} onRemove={api.remove} />;
}
```

## Anatomy

```
PasskeyList                        data-slot="passkey-list"
├─ Card header                     title, description, Add button (when the list is not empty)
├─ Alert                           unsupported browser, or an error from add/remove
└─ ul  aria-label
   └─ li                           data-slot="passkey-row"
      ├─ kind icon                 device, synced or security key
      ├─ name (or an inline form)  Enter saves, Escape cancels
      ├─ authenticator hint · Added <date> · Last used <relative>
      └─ Rename, Remove            Remove opens a ConfirmButton
```

The empty list renders an `EmptyState` with the add button.

## API

**PasskeyList**: every `div` prop except `children`, plus:

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `passkeys` | `readonly Passkey[]` | required | The passkeys to show. |
| `onAdd` | `() => Promise<void>` | required | Run the ceremony and save. Throw on failure; a `NotAllowedError` shows the "cancelled" message. |
| `onRename` | `(id, name) => Promise<void \| { error? }>` | | Shows the pencil. `{ error }` keeps the field open. |
| `onRemove` | `(id) => Promise<void \| { error? }>` | | Shows the remove button with a confirm dialog. |
| `supported` | `boolean` | `isPasskeySupported()` after mount | Force the browser check. |
| `labels` | `Partial<PasskeyLabels>` | | Override any string. |

**Passkey**: `{ id, name, kind?: "device" \| "synced" \| "security-key", authenticator?, createdAt, lastUsedAt? }`. Dates are `Date`, number or ISO string.

**isPasskeySupported(): boolean**: true when `window.PublicKeyCredential` exists. False on the server.

## Examples

**Show the add button only when supported**

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

export const canUsePasskeys = () => isPasskeySupported();
```

## Accessibility

- The list is a labelled `ul`. The icon buttons name the passkey: "Rename: MacBook Pro", "Remove: MacBook Pro".
- The rename input has an accessible name, Enter saves and Escape cancels. Save and Cancel are buttons with labels.
- Removal uses `AlertDialog`: focus starts on Cancel.
- Errors from rename are `role="alert"`; add and remove errors use `Alert`.
- Dates are `<time>` elements, and the relative "last used" has its absolute date in a `title`.

## RTL & i18n

- English and Arabic strings follow the Nasaq locale. Dates and relative times use the locale with Latin digits.
- The row mirrors: icon at the inline start, actions at the inline end.

## Styling & tokens

- `Card`, `Button`, `Alert` and `--nq-*` tokens. Target `[data-slot="passkey-row"]`.

## Do / Don't

- Do let people name a passkey: "iPhone" beats "Passkey 3".
- Do require a fresh sign-in on the server before removing one.
- Don't remove the last sign-in method: check on the server (see [`ConnectedAccounts`](https://docs.nasaqui.com/components/connected-accounts)).

## Related

- [`AlertDialog`](https://docs.nasaqui.com/components/alert-dialog)
- [`States`](https://docs.nasaqui.com/components/states)
- [`TwoFactorSetup`](https://docs.nasaqui.com/components/two-factor-setup)

## Lab

https://docs.nasaqui.com/?path=/docs/components-security-passkey-list--docs

## Code

### React

```tsx
import { PasskeyList, type Passkey } from "@fadymondy/nasaq/web";

declare const passkeys: Passkey[];
declare const api: { register(): Promise<void>; rename(id: string, name: string): Promise<void>; remove(id: string): Promise<void> };

export function Passkeys() {
  return <PasskeyList passkeys={passkeys} onAdd={api.register} onRename={api.rename} onRemove={api.remove} />;
}
```

### shadcn

```tsx
import { PasskeyList, type Passkey } from "@/components/ui/passkey-list";

declare const passkeys: Passkey[];
declare const api: { register(): Promise<void>; rename(id: string, name: string): Promise<void>; remove(id: string): Promise<void> };

export function Passkeys() {
  return <PasskeyList passkeys={passkeys} onAdd={api.register} onRename={api.rename} onRemove={api.remove} />;
}
```

### Vue

```vue
<script setup lang="ts">
import { NqPasskeyList, type Passkey } from "@fadymondy/nasaq/vue";
import { ref } from "vue";

const wait = () => new Promise<void>((resolve) => setTimeout(resolve, 600));

const passkeys = ref<Passkey[]>([
  { id: "1", name: "MacBook Pro", kind: "device", authenticator: "Touch ID", createdAt: "2026-03-02T09:00:00Z", lastUsedAt: "2026-09-28T08:30:00Z" },
  { id: "2", name: "iCloud Keychain", kind: "synced", authenticator: "iCloud Keychain", createdAt: "2026-05-14T12:00:00Z", lastUsedAt: null },
  { id: "3", name: "YubiKey 5C", kind: "security-key", createdAt: "2026-07-21T15:30:00Z", lastUsedAt: "2026-08-02T10:00:00Z" },
]);

const api = {
  async register() {
    await wait();
    passkeys.value = [...passkeys.value, { id: String(Date.now()), name: "New passkey", kind: "device", createdAt: new Date(), lastUsedAt: null }];
  },
  async rename(id: string, name: string) {
    await wait();
    passkeys.value = passkeys.value.map((p) => (p.id === id ? { ...p, name } : p));
  },
  async remove(id: string) {
    await wait();
    passkeys.value = passkeys.value.filter((p) => p.id !== id);
  },
};
</script>

<template>
  <NqPasskeyList :passkeys="passkeys" :on-add="api.register" :on-rename="api.rename" :on-remove="api.remove" :supported="true" />
</template>
```

### Blade

```blade
<div x-data
    x-on:nq-passkey-add="$event.detail.wait(new Promise((resolve) => setTimeout(resolve, 600)))"
    x-on:nq-passkey-rename="$event.detail.wait(new Promise((resolve) => setTimeout(resolve, 600)))"
    x-on:nq-passkey-remove="$event.detail.wait(new Promise((resolve) => setTimeout(resolve, 600)))">
    <x-nq::passkey-list
        :supported="true"
        :passkeys="[
            ['id' => '1', 'name' => 'MacBook Pro', 'kind' => 'device', 'authenticator' => 'Touch ID', 'created_at' => '2026-03-02T09:00:00Z', 'last_used_at' => '2026-09-28T08:30:00Z'],
            ['id' => '2', 'name' => 'iCloud Keychain', 'kind' => 'synced', 'authenticator' => 'iCloud Keychain', 'created_at' => '2026-05-14T12:00:00Z', 'last_used_at' => null],
            ['id' => '3', 'name' => 'YubiKey 5C', 'kind' => 'security-key', 'created_at' => '2026-07-21T15:30:00Z', 'last_used_at' => '2026-08-02T10:00:00Z'],
        ]" />
</div>
```

### HTML + Alpine

```html
<div x-data
    x-on:nq-passkey-add="$event.detail.wait(new Promise((resolve) => setTimeout(resolve, 600)))"
    x-on:nq-passkey-rename="$event.detail.wait(new Promise((resolve) => setTimeout(resolve, 600)))"
    x-on:nq-passkey-remove="$event.detail.wait(new Promise((resolve) => setTimeout(resolve, 600)))">
    <div data-slot="passkey-list" x-data="nqPasskeyList(JSON.parse('{\u0022supported\u0022:true,\u0022names\u0022:{\u00221\u0022:\u0022MacBook Pro\u0022,\u00222\u0022:\u0022iCloud Keychain\u0022,\u00223\u0022:\u0022YubiKey 5C\u0022},\u0022messages\u0022:{\u0022addFailed\u0022:\u0022Could not add the passkey. Try again.\u0022,\u0022addCancelled\u0022:\u0022Adding the passkey was cancelled.\u0022,\u0022renameFailed\u0022:\u0022Could not rename the passkey. Try again.\u0022,\u0022removeFailed\u0022:\u0022Could not remove the passkey. Try again.\u0022}}'))"
    class="flex flex-col gap-4 rounded-card border border-border bg-card py-4 text-card-foreground w-full max-w-2xl">
    <div data-slot="card-header" class="grid auto-rows-min items-start gap-1 px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto]"><h2 data-slot="card-title" class="text-label text-foreground">Passkeys</h2>
        <div data-slot="card-description" class="text-body-sm text-muted-foreground">Sign in with your fingerprint, face or screen lock instead of a password.</div>
                    <div data-slot="card-action" x-show="count &gt; 0" class="col-start-2 row-span-2 row-start-1 self-start justify-self-end"><button data-slot="button"
     type="button"                         x-on:click="add()" x-bind:disabled="adding || ! supported" x-bind:data-disabled="(adding || ! supported) ? &#039;&#039; : null" x-bind:aria-busy="adding ? &#039;true&#039; : null" 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="adding" 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>                    <svg aria-hidden="true" x-show="! adding" 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="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>Add a passkey</button></div></div>
    <div data-slot="card-content" class="px-4 flex flex-col gap-3"><div data-slot="alert" data-tone="warning" role="alert"
        x-show="supported === false" style="display: none" class="relative grid grid-cols-[auto_1fr_auto] items-start gap-x-3 rounded-card border p-3 text-start border-nq-warning/30 bg-nq-warning-soft">
    <svg aria-hidden="true" data-slot="alert-icon" class="mt-0.5 size-4 text-nq-warning-text" 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">
  <circle cx="12" cy="12" r="10"/>
  <line x1="12" x2="12" y1="8" y2="12"/>
  <line x1="12" x2="12.01" y1="16" y2="16"/>
</svg>    <div data-slot="alert-body" class="flex min-w-0 flex-col gap-0.5">
                    <div data-slot="alert-title" class="text-label text-foreground">Passkeys are not available in this browser</div>
                            <div data-slot="alert-description" class="text-body-sm text-muted-foreground">Use a recent version of Chrome, Safari, Edge or Firefox, on a device with a screen lock, to add a passkey.</div>
            </div>
    </div>
        <div data-slot="alert" data-tone="danger" role="alert"
        x-show="error" style="display: none" class="relative grid grid-cols-[auto_1fr_auto] items-start gap-x-3 rounded-card border p-3 text-start border-nq-danger/30 bg-nq-danger-soft">
    <svg aria-hidden="true" data-slot="alert-icon" class="mt-0.5 size-4 text-nq-danger-text" 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">
  <circle cx="12" cy="12" r="10"/>
  <path d="m15 9-6 6"/>
  <path d="m9 9 6 6"/>
</svg>    <div data-slot="alert-body" class="flex min-w-0 flex-col gap-0.5">
                            <div data-slot="alert-description" class="text-body-sm text-foreground"><span x-text="error"></span></div>
            </div>
    </div>
        <ul aria-label="Your passkeys" class="overflow-hidden rounded-card border border-border" x-show="count > 0" >
                                            <li data-slot="passkey-row" x-show="! gone['1']" class="flex flex-wrap items-center gap-x-3 gap-y-2 border-t border-border px-4 py-3 first:border-t-0">
                    <span class="inline-flex size-9 shrink-0 items-center justify-center rounded-control border border-border bg-secondary text-muted-foreground [&_svg]:size-4">
                        <svg aria-hidden="true" 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">
  <rect width="14" height="20" x="5" y="2" rx="2" ry="2"/>
  <path d="M12 18h.01"/>
</svg>                    </span>
                    <div class="flex min-w-0 flex-1 basis-48 flex-col gap-0.5">
                        <form class="flex items-center gap-1.5" x-show="editing === '1'" style="display: none"
                            x-on:submit.prevent="save('1')" x-on:keydown.escape.stop="cancelEdit('1')">
                            <input data-slot="input" type="text"
                    x-model="draft" aria-label="Passkey name" maxlength="64" x-bind:aria-invalid="renameError[&#039;1&#039;] ? &#039;true&#039; : null" x-bind:disabled="renaming === &#039;1&#039;" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control-sm">
                            <button data-slot="button"
     type="submit"                         aria-label="Save name" x-bind:disabled="! draft.trim() || renaming === &#039;1&#039;" x-bind:data-disabled="(! draft.trim() || renaming === &#039;1&#039;) ? &#039;&#039; : null" x-bind:aria-busy="renaming === &#039;1&#039; ? &#039;true&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] size-control-sm p-0">
        <svg data-slot="spinner" aria-hidden="true" style="display: none;" x-show="renaming === &#039;1&#039;" 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>                                <svg aria-hidden="true" x-show="renaming !== '1'" 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 6 9 17l-5-5"/>
</svg></button>
                            <button data-slot="button"
     type="button"                         aria-label="Cancel" x-on:click="cancelEdit(&#039;1&#039;)" x-bind:disabled="renaming === &#039;1&#039;" x-bind:data-disabled="renaming === &#039;1&#039; ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" 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="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></button>
                        </form>
                        <p class="truncate text-label text-foreground" x-show="editing !== '1'" x-bind:title="names['1']" x-text="names['1']">MacBook Pro</p>
                        <p role="alert" class="text-caption text-nq-danger-text" x-show="renameError['1']" x-text="renameError['1']" style="display: none"></p>
                        <p class="flex flex-wrap gap-x-2 text-caption text-muted-foreground">
                            <span>Touch ID</span>
                            <span>Added <time data-slot="date-time" datetime="2026-03-02T09:00:00+00:00" dir="auto"     class="tabular-nums [unicode-bidi:isolate]">Mar 2, 2026</time>
</span>
                                                            <span>Last used <time data-slot="date-time" datetime="2026-09-28T08:30:00+00:00" dir="auto"  title="Sep 28, 2026"     class="tabular-nums [unicode-bidi:isolate]">1 day ago</time>
</span>
                                                    </p>
                    </div>
                    <div class="flex items-center gap-1" x-show="editing !== '1'">
                                                    <button data-slot="button"
     type="button"                         x-on:click="startEdit(&#039;1&#039;, $el)" x-bind:aria-label="&#039;Rename: &#039; + names[&#039;1&#039;]" x-bind:disabled="adding" x-bind:data-disabled="adding ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" 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.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg></button>
                                                                            <div data-slot="alert-dialog" x-data="nqAlertDialog(false)" x-modelable="open" x-id="['nq-alert-dialog']" class="contents">
    <button data-slot="alert-dialog-trigger"
     type="button"                         aria-haspopup="dialog" x-on:click="show()" :aria-expanded="open" x-bind:aria-label="&#039;Remove: &#039; + names[&#039;1&#039;]" x-bind:disabled="adding" x-bind:data-disabled="adding ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" 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="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg></button>
                                <template x-teleport="body">
    <div data-slot="alert-dialog-portal">
        <div data-slot="alert-dialog-backdrop" x-nq-presence="open" class="fixed inset-0 z-50 bg-nq-fg/15 dark:bg-nq-bg/60 transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0"></div>
        <div data-slot="alert-dialog-content" x-bind="popup" x-nq-presence="open" x-trap.noscroll="open"
            class="fixed inset-0 z-50 m-auto grid h-fit w-[calc(100%-2rem)] max-w-md gap-4 rounded-floating border border-border bg-popover p-6 text-popover-foreground outline-none max-h-[calc(100dvh-2rem)] overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0">
            <div data-slot="alert-dialog-header" class="flex flex-col gap-1.5 text-start"><h2 data-slot="alert-dialog-title" :id="$id('nq-alert-dialog', 'title')" x-text="&#039;Remove \u0022&#039; + names[&#039;1&#039;] + &#039;\u0022?&#039;" class="text-h3 text-foreground">Remove &quot;MacBook Pro&quot;?</h2>
                                        <p data-slot="alert-dialog-description" :id="$id('nq-alert-dialog', 'description')" class="text-body-sm text-muted-foreground">You will no longer be able to sign in with this passkey. This cannot be undone.</p></div>
                                    <div data-slot="alert-dialog-footer" class="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"><button data-slot="alert-dialog-cancel"
     type="button"                         autofocus="autofocus" x-on:click="close()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        Cancel</button>
                                        <button data-slot="confirm-button-action"
     type="button"                         x-on:click.capture="close()" x-on:click="remove(&#039;1&#039;)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 bg-destructive text-destructive-foreground hover:bg-[color-mix(in_oklab,var(--nq-danger-solid)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)]">
        Remove passkey</button></div>
        </div>
    </div>
</template>
</div>
                                            </div>
                </li>
                                            <li data-slot="passkey-row" x-show="! gone['2']" class="flex flex-wrap items-center gap-x-3 gap-y-2 border-t border-border px-4 py-3 first:border-t-0">
                    <span class="inline-flex size-9 shrink-0 items-center justify-center rounded-control border border-border bg-secondary text-muted-foreground [&_svg]:size-4">
                        <svg aria-hidden="true" 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="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z"/>
</svg>                    </span>
                    <div class="flex min-w-0 flex-1 basis-48 flex-col gap-0.5">
                        <form class="flex items-center gap-1.5" x-show="editing === '2'" style="display: none"
                            x-on:submit.prevent="save('2')" x-on:keydown.escape.stop="cancelEdit('2')">
                            <input data-slot="input" type="text"
                    x-model="draft" aria-label="Passkey name" maxlength="64" x-bind:aria-invalid="renameError[&#039;2&#039;] ? &#039;true&#039; : null" x-bind:disabled="renaming === &#039;2&#039;" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control-sm">
                            <button data-slot="button"
     type="submit"                         aria-label="Save name" x-bind:disabled="! draft.trim() || renaming === &#039;2&#039;" x-bind:data-disabled="(! draft.trim() || renaming === &#039;2&#039;) ? &#039;&#039; : null" x-bind:aria-busy="renaming === &#039;2&#039; ? &#039;true&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] size-control-sm p-0">
        <svg data-slot="spinner" aria-hidden="true" style="display: none;" x-show="renaming === &#039;2&#039;" 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>                                <svg aria-hidden="true" x-show="renaming !== '2'" 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 6 9 17l-5-5"/>
</svg></button>
                            <button data-slot="button"
     type="button"                         aria-label="Cancel" x-on:click="cancelEdit(&#039;2&#039;)" x-bind:disabled="renaming === &#039;2&#039;" x-bind:data-disabled="renaming === &#039;2&#039; ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" 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="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></button>
                        </form>
                        <p class="truncate text-label text-foreground" x-show="editing !== '2'" x-bind:title="names['2']" x-text="names['2']">iCloud Keychain</p>
                        <p role="alert" class="text-caption text-nq-danger-text" x-show="renameError['2']" x-text="renameError['2']" style="display: none"></p>
                        <p class="flex flex-wrap gap-x-2 text-caption text-muted-foreground">
                            <span>iCloud Keychain</span>
                            <span>Added <time data-slot="date-time" datetime="2026-05-14T12:00:00+00:00" dir="auto"     class="tabular-nums [unicode-bidi:isolate]">May 14, 2026</time>
</span>
                                                            <span>Never used</span>
                                                    </p>
                    </div>
                    <div class="flex items-center gap-1" x-show="editing !== '2'">
                                                    <button data-slot="button"
     type="button"                         x-on:click="startEdit(&#039;2&#039;, $el)" x-bind:aria-label="&#039;Rename: &#039; + names[&#039;2&#039;]" x-bind:disabled="adding" x-bind:data-disabled="adding ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" 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.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg></button>
                                                                            <div data-slot="alert-dialog" x-data="nqAlertDialog(false)" x-modelable="open" x-id="['nq-alert-dialog']" class="contents">
    <button data-slot="alert-dialog-trigger"
     type="button"                         aria-haspopup="dialog" x-on:click="show()" :aria-expanded="open" x-bind:aria-label="&#039;Remove: &#039; + names[&#039;2&#039;]" x-bind:disabled="adding" x-bind:data-disabled="adding ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" 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="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg></button>
                                <template x-teleport="body">
    <div data-slot="alert-dialog-portal">
        <div data-slot="alert-dialog-backdrop" x-nq-presence="open" class="fixed inset-0 z-50 bg-nq-fg/15 dark:bg-nq-bg/60 transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0"></div>
        <div data-slot="alert-dialog-content" x-bind="popup" x-nq-presence="open" x-trap.noscroll="open"
            class="fixed inset-0 z-50 m-auto grid h-fit w-[calc(100%-2rem)] max-w-md gap-4 rounded-floating border border-border bg-popover p-6 text-popover-foreground outline-none max-h-[calc(100dvh-2rem)] overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0">
            <div data-slot="alert-dialog-header" class="flex flex-col gap-1.5 text-start"><h2 data-slot="alert-dialog-title" :id="$id('nq-alert-dialog', 'title')" x-text="&#039;Remove \u0022&#039; + names[&#039;2&#039;] + &#039;\u0022?&#039;" class="text-h3 text-foreground">Remove &quot;iCloud Keychain&quot;?</h2>
                                        <p data-slot="alert-dialog-description" :id="$id('nq-alert-dialog', 'description')" class="text-body-sm text-muted-foreground">You will no longer be able to sign in with this passkey. This cannot be undone.</p></div>
                                    <div data-slot="alert-dialog-footer" class="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"><button data-slot="alert-dialog-cancel"
     type="button"                         autofocus="autofocus" x-on:click="close()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        Cancel</button>
                                        <button data-slot="confirm-button-action"
     type="button"                         x-on:click.capture="close()" x-on:click="remove(&#039;2&#039;)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 bg-destructive text-destructive-foreground hover:bg-[color-mix(in_oklab,var(--nq-danger-solid)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)]">
        Remove passkey</button></div>
        </div>
    </div>
</template>
</div>
                                            </div>
                </li>
                                            <li data-slot="passkey-row" x-show="! gone['3']" class="flex flex-wrap items-center gap-x-3 gap-y-2 border-t border-border px-4 py-3 first:border-t-0">
                    <span class="inline-flex size-9 shrink-0 items-center justify-center rounded-control border border-border bg-secondary text-muted-foreground [&_svg]:size-4">
                        <svg aria-hidden="true" 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">
  <circle cx="10" cy="7" r="1"/>
  <circle cx="4" cy="20" r="1"/>
  <path d="M4.7 19.3 19 5"/>
  <path d="m21 3-3 1 2 2Z"/>
  <path d="M9.26 7.68 5 12l2 5"/>
  <path d="m10 14 5 2 3.5-3.5"/>
  <path d="m18 12 1-1 1 1-1 1Z"/>
</svg>                    </span>
                    <div class="flex min-w-0 flex-1 basis-48 flex-col gap-0.5">
                        <form class="flex items-center gap-1.5" x-show="editing === '3'" style="display: none"
                            x-on:submit.prevent="save('3')" x-on:keydown.escape.stop="cancelEdit('3')">
                            <input data-slot="input" type="text"
                    x-model="draft" aria-label="Passkey name" maxlength="64" x-bind:aria-invalid="renameError[&#039;3&#039;] ? &#039;true&#039; : null" x-bind:disabled="renaming === &#039;3&#039;" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control-sm">
                            <button data-slot="button"
     type="submit"                         aria-label="Save name" x-bind:disabled="! draft.trim() || renaming === &#039;3&#039;" x-bind:data-disabled="(! draft.trim() || renaming === &#039;3&#039;) ? &#039;&#039; : null" x-bind:aria-busy="renaming === &#039;3&#039; ? &#039;true&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] size-control-sm p-0">
        <svg data-slot="spinner" aria-hidden="true" style="display: none;" x-show="renaming === &#039;3&#039;" 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>                                <svg aria-hidden="true" x-show="renaming !== '3'" 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 6 9 17l-5-5"/>
</svg></button>
                            <button data-slot="button"
     type="button"                         aria-label="Cancel" x-on:click="cancelEdit(&#039;3&#039;)" x-bind:disabled="renaming === &#039;3&#039;" x-bind:data-disabled="renaming === &#039;3&#039; ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" 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="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></button>
                        </form>
                        <p class="truncate text-label text-foreground" x-show="editing !== '3'" x-bind:title="names['3']" x-text="names['3']">YubiKey 5C</p>
                        <p role="alert" class="text-caption text-nq-danger-text" x-show="renameError['3']" x-text="renameError['3']" style="display: none"></p>
                        <p class="flex flex-wrap gap-x-2 text-caption text-muted-foreground">
                            <span>Security key</span>
                            <span>Added <time data-slot="date-time" datetime="2026-07-21T15:30:00+00:00" dir="auto"     class="tabular-nums [unicode-bidi:isolate]">Jul 21, 2026</time>
</span>
                                                            <span>Last used <time data-slot="date-time" datetime="2026-08-02T10:00:00+00:00" dir="auto"  title="Aug 2, 2026"     class="tabular-nums [unicode-bidi:isolate]">1 month ago</time>
</span>
                                                    </p>
                    </div>
                    <div class="flex items-center gap-1" x-show="editing !== '3'">
                                                    <button data-slot="button"
     type="button"                         x-on:click="startEdit(&#039;3&#039;, $el)" x-bind:aria-label="&#039;Rename: &#039; + names[&#039;3&#039;]" x-bind:disabled="adding" x-bind:data-disabled="adding ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" 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.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg></button>
                                                                            <div data-slot="alert-dialog" x-data="nqAlertDialog(false)" x-modelable="open" x-id="['nq-alert-dialog']" class="contents">
    <button data-slot="alert-dialog-trigger"
     type="button"                         aria-haspopup="dialog" x-on:click="show()" :aria-expanded="open" x-bind:aria-label="&#039;Remove: &#039; + names[&#039;3&#039;]" x-bind:disabled="adding" x-bind:data-disabled="adding ? &#039;&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" 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="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg></button>
                                <template x-teleport="body">
    <div data-slot="alert-dialog-portal">
        <div data-slot="alert-dialog-backdrop" x-nq-presence="open" class="fixed inset-0 z-50 bg-nq-fg/15 dark:bg-nq-bg/60 transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0"></div>
        <div data-slot="alert-dialog-content" x-bind="popup" x-nq-presence="open" x-trap.noscroll="open"
            class="fixed inset-0 z-50 m-auto grid h-fit w-[calc(100%-2rem)] max-w-md gap-4 rounded-floating border border-border bg-popover p-6 text-popover-foreground outline-none max-h-[calc(100dvh-2rem)] overflow-y-auto transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0">
            <div data-slot="alert-dialog-header" class="flex flex-col gap-1.5 text-start"><h2 data-slot="alert-dialog-title" :id="$id('nq-alert-dialog', 'title')" x-text="&#039;Remove \u0022&#039; + names[&#039;3&#039;] + &#039;\u0022?&#039;" class="text-h3 text-foreground">Remove &quot;YubiKey 5C&quot;?</h2>
                                        <p data-slot="alert-dialog-description" :id="$id('nq-alert-dialog', 'description')" class="text-body-sm text-muted-foreground">You will no longer be able to sign in with this passkey. This cannot be undone.</p></div>
                                    <div data-slot="alert-dialog-footer" class="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"><button data-slot="alert-dialog-cancel"
     type="button"                         autofocus="autofocus" x-on:click="close()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        Cancel</button>
                                        <button data-slot="confirm-button-action"
     type="button"                         x-on:click.capture="close()" x-on:click="remove(&#039;3&#039;)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 bg-destructive text-destructive-foreground hover:bg-[color-mix(in_oklab,var(--nq-danger-solid)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)]">
        Remove passkey</button></div>
        </div>
    </div>
</template>
</div>
                                            </div>
                </li>
                    </ul>
        <div data-slot="empty-state" style="display: none;" x-show="count === 0" class="flex flex-col items-center justify-center gap-3 border border-dashed border-border px-6 py-12 text-center rounded-card">
            <span data-slot="state-icon" class="inline-flex size-10 items-center justify-center rounded-control border border-border bg-card [&amp;_svg]:size-5 text-muted-foreground">
            <svg aria-hidden="true" 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="M12 10a2 2 0 0 0-2 2c0 1.02-.1 2.51-.26 4"/>
  <path d="M14 13.12c0 2.38 0 6.38-1 8.88"/>
  <path d="M17.29 21.02c.12-.6.43-2.3.5-3.02"/>
  <path d="M2 12a10 10 0 0 1 18-6"/>
  <path d="M2 16h.01"/>
  <path d="M21.8 16c.2-2 .131-5.354 0-6"/>
  <path d="M5 19.5C5.5 18 6 15 6 12a6 6 0 0 1 .34-2"/>
  <path d="M8.65 22c.21-.66.45-1.32.57-2"/>
  <path d="M9 6.8a6 6 0 0 1 9 5.2v2"/>
</svg>        </span>
        <div class="flex max-w-sm flex-col gap-1">
        <p class="text-label text-foreground">No passkeys yet</p>
                    <p class="text-body-sm text-muted-foreground">Add one to sign in faster and safer than with a password.</p>
            </div>
            <div class="mt-1 flex flex-wrap items-center justify-center gap-2"><button data-slot="button"
     type="button"                         x-on:click="add()" x-bind:disabled="adding || ! supported" x-bind:data-disabled="(adding || ! supported) ? &#039;&#039; : null" x-bind:aria-busy="adding ? &#039;true&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent 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 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] h-control-sm px-2.5">
        <svg data-slot="spinner" aria-hidden="true" style="display: none;" x-show="adding" 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>                    <svg aria-hidden="true" x-show="! adding" 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="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>Add a passkey</button></div>
    </div></div>
</div>
</div>
```
