# ShareButton

> A share button and dialog with copy link, email invites with a role, link access of restricted or anyone with the link, link expiry, the people who already have access and the native Web Share sheet where the browser offers it.

Source: https://docs.nasaqui.com/components/share-action

## Install

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

The "Share" action of a document, project or board. One dialog holds everything: invite people by email with a
role, see and change who already has access, choose whether the link is restricted or open to anyone, set an
expiry, copy the link, and hand it to the phone's native share sheet when there is one.

## When to use

- Giving people access to a resource with roles.
- Producing a link with an access level and an expiry.
- Sharing a URL from a mobile browser through the system sheet.

## When not to use

- Only copying a value: use [`CopyButton`](https://docs.nasaqui.com/components/copy-button).
- Taking data out as a file: use [`ExportButton`](https://docs.nasaqui.com/components/export-action).
- Managing a whole team: build a members page; this dialog is per resource.

## Import

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

## Quick start

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

export function Header() {
  return (
    <ShareButton
      url="https://app.example.com/docs/q3-plan"
      title="Q3 plan"
      onInvite={async (emails, role) => {
        await api.invite(emails, role);
      }}
    />
  );
}

declare const api: { invite(emails: string[], role: string): Promise<void> };
```

## Anatomy

```
ShareButton                    data-slot="share-button"
└─ ShareDialog                 data-slot="share-dialog"
   ├─ Invite people            TagInput of emails + role Select + Send
   ├─ People with access       avatar, name, email, role Select, remove
   ├─ Link access              Restricted / Anyone with the link, link role, expiry
   └─ Link                     CopyField, "Share via…" (Web Share), Email
```

## API

**ShareButton** (`ShareActionProps`)

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `url` | `string` | | The link. |
| `title` / `text` | `string` | | For the native share sheet and the email. |
| `roles` | `{ value, label }[]` | view, comment, edit | Roles to choose from. |
| `defaultRole` | `string` | first role | The role new invitees start with. |
| `people` | `SharePerson[]` | `[]` | Who has access. `owner: true` locks a row. |
| `onInvite` | `(emails, role) => void \| Promise` | | Enables the invite section. Reject to show an error. |
| `onRoleChange` / `onRemove` | `(person, role)` / `(person)` | | Change or remove a person. |
| `linkAccess` | `boolean` | `true` | Show the link access section. |
| `access` / `defaultAccess` | `"restricted" \| "anyone"` | `"restricted"` | Link access level. |
| `linkRole` / `defaultLinkRole` | `string` | first role | Role given through the link. |
| `expiry` / `defaultExpiry` | `"never" \| "1d" \| "7d" \| "30d"` | `"never"` | Link expiry. |
| `onLinkChange` | `(settings) => void` | | `{ access, role, expiry, expiresAt }` after any change. |
| `onCopy` / `onShared` | | | After copying, or after the native sheet finished. |
| `mailto` | `boolean` | `true` | Show the Email button. |
| `children` / `variant` / `size` / `disabled` / `className` | | `Share`, `secondary`, `sm` | The trigger. |
| `labels` | `Partial<ShareActionLabels>` | | Override any string. |

**ShareDialog** takes the same props plus `open` and `onOpenChange`.

**Helpers** (pure): `expiryToDate`, `isEmail`, `parseEmails`, `withExpiry`, `mailtoLink`.

## Examples

**Persist link settings**

```tsx
<ShareButton
  url={url}
  defaultAccess="anyone"
  defaultExpiry="7d"
  onLinkChange={({ access, role, expiresAt }) => api.saveLink({ access, role, expiresAt })}
/>
```

**Existing collaborators**

```tsx
<ShareButton
  url={url}
  people={[
    { id: "1", name: "Sara Ali", email: "sara@example.com", role: "owner", owner: true },
    { id: "2", name: "Omar Nasser", email: "omar@example.com", role: "editor" },
  ]}
  onRoleChange={(person, role) => api.setRole(person.id, role)}
  onRemove={(person) => api.remove(person.id)}
/>
```

## Accessibility

- The dialog traps focus and closes with Escape. Every control has a name: the role selects say whose role they set.
- Invite results and errors are announced (`role="status"` / `role="alert"`); a bad email explains itself in the tag field.
- Copying announces "Copied" through the copy button.
- "Share via…" only renders where `navigator.share` exists, after mount, so server and client markup match.

## RTL & i18n

- English and Arabic strings ship; roles are yours to translate (the defaults are translated).
- Emails and the link are always left-to-right (`<bdi dir="ltr">`, an LTR field), also in Arabic.
- Layout uses logical spacing; nothing needs mirroring.

## Styling & tokens

- Composed from `Dialog`, `Select`, `TagInput`, `CopyField`, `Avatar`, `Alert` and `Button`. Use their tokens; extend with `className`.
- No third-party brand buttons are drawn. Sharing goes through the system sheet and `mailto:`.

## Do / Don't

- Do check permissions on the server; the dialog only collects intent.
- Do reject from `onInvite` with a readable message.
- Don't treat the `?expires=` query as security; enforce expiry on the server.
- Don't rely on Web Share on desktop; the copy field is the fallback.

## Related

- [`ExportButton`](https://docs.nasaqui.com/components/export-action)
- [`CopyButton`](https://docs.nasaqui.com/components/copy-button)
- [`TagInput`](https://docs.nasaqui.com/components/tag-input)

## Lab

https://docs.nasaqui.com/?path=/docs/components-actions-share-button--docs

## Code

### React

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

export function Header() {
  return (
    <ShareButton
      url="https://app.example.com/docs/q3-plan"
      title="Q3 plan"
      onInvite={async (emails, role) => {
        await api.invite(emails, role);
      }}
    />
  );
}

declare const api: { invite(emails: string[], role: string): Promise<void> };
```

### shadcn

```tsx
import { ShareButton } from "@/components/ui/share-action";

export function Header() {
  return (
    <ShareButton
      url="https://app.example.com/docs/q3-plan"
      title="Q3 plan"
      onInvite={async (emails, role) => {
        await api.invite(emails, role);
      }}
    />
  );
}

declare const api: { invite(emails: string[], role: string): Promise<void> };
```

### Vue

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

const onInvite = async (emails: string[], role: string) => {
  console.log("invite", emails, role);
};
</script>

<template>
  <NqShareButton url="https://app.example.com/docs/q3-plan" title="Q3 plan" :on-invite="onInvite" />
</template>
```

### Blade

```blade
<x-nq::share-action
    url="https://app.example.com/docs/q3-plan"
    title="Q3 plan"
    :people="[
        ['id' => '1', 'name' => 'Sara Ali', 'email' => 'sara@example.com', 'role' => 'editor', 'owner' => true],
        ['id' => '2', 'name' => 'Omar Nasser', 'email' => 'omar@example.com', 'role' => 'viewer'],
    ]" />
```

### HTML + Alpine

```html
<div data-slot="share-action"
    x-data="nqShareAction('https:\/\/app.example.com\/docs\/q3-plan', JSON.parse('[{\u0022id\u0022:\u00221\u0022,\u0022name\u0022:\u0022Sara Ali\u0022,\u0022email\u0022:\u0022sara@example.com\u0022,\u0022role\u0022:\u0022editor\u0022,\u0022owner\u0022:true},{\u0022id\u0022:\u00222\u0022,\u0022name\u0022:\u0022Omar Nasser\u0022,\u0022email\u0022:\u0022omar@example.com\u0022,\u0022role\u0022:\u0022viewer\u0022}]'), JSON.parse('{\u0022title\u0022:\u0022Q3 plan\u0022,\u0022roles\u0022:[{\u0022value\u0022:\u0022viewer\u0022,\u0022label\u0022:\u0022Can view\u0022},{\u0022value\u0022:\u0022commenter\u0022,\u0022label\u0022:\u0022Can comment\u0022},{\u0022value\u0022:\u0022editor\u0022,\u0022label\u0022:\u0022Can edit\u0022}]}'))"
    class="contents">
    <button data-slot="share-button"
     type="button"                         x-on:click="dlg = true" 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 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="18" cy="5" r="3"/>
  <circle cx="6" cy="12" r="3"/>
  <circle cx="18" cy="19" r="3"/>
  <line x1="8.59" x2="15.42" y1="13.51" y2="17.49"/>
  <line x1="15.41" x2="8.59" y1="6.51" y2="10.49"/>
</svg>        Share</button>
    <div data-slot="dialog" x-data="nqDialog(false)" x-modelable="open" x-id="['nq-dialog']" x-model="dlg" class="contents">
    <template x-teleport="body">
            <div data-slot="dialog-portal">
                <div data-slot="dialog-backdrop" x-nq-presence="open" x-on:click="close()" 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="share-dialog" 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-lg grid-cols-[minmax(0,1fr)] 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="dialog-header" class="flex flex-col gap-1.5 pe-8 text-start"><h2 data-slot="dialog-title" :id="$id('nq-dialog', 'title')" class="text-h3 text-foreground">Share: Q3 plan</h2>
                        <p data-slot="dialog-description" :id="$id('nq-dialog', 'description')" class="text-body-sm text-muted-foreground">Invite people or send a link.</p></div>
                    <div class="flex flex-col gap-5">
                                                    <section class="flex flex-col gap-2" data-slot="share-invite">
                                <h3 class="text-label text-foreground">Invite people</h3>
                                <div class="flex flex-col gap-2 sm:flex-row sm:items-start">
                                    <div data-slot="tag-input" x-data="nqTagInput([], Object.assign(JSON.parse('{\u0022separators\u0022:[\u0022,\u0022,\u0022;\u0022,\u0022 \u0022]}'), { validate: (tag, tags) => (validate(tag, tags)) }))" x-modelable="tags" x-bind="root"
         x-model="emails" class="relative w-full min-w-0 flex-1">
    <div data-slot="tag-input-box" x-bind="box"
        class="flex w-full min-w-0 flex-wrap items-center gap-1.5 rounded-control border border-input bg-card px-2 py-1 text-body text-foreground min-h-[max(var(--nq-control),var(--nq-touch-min,0px))] transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger">
        <template x-for="(tag, i) in tags" :key="tag">
            <span data-slot="tag-input-tag" data-variant="neutral" class="inline-flex w-fit shrink-0 items-center justify-center whitespace-nowrap rounded-control border border-transparent bg-muted px-2 py-0.5 font-medium text-foreground h-6 gap-0.5 ps-2 pe-0.5 text-body-sm">
                <bdi x-text="tag"></bdi>
                <button type="button"  :aria-label="'Remove' + ' ' + tag" @click.stop="removeAt(i)"
                    class="inline-flex size-5 items-center justify-center rounded-[3px] text-muted-foreground outline-none hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus">
                    <span aria-hidden="true" class="flex [&_svg]:size-3"><svg 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></span>
                </button>
            </span>
        </template>
        <input data-slot="tag-input-field" x-ref="field" x-bind="field" autocomplete="off"             :placeholder="tags.length ? undefined : 'Add email addresses'"
                        type="email" dir="ltr" aria-label="Invite people" class="h-7 min-w-24 flex-1 border-0 bg-transparent px-1 text-body outline-none placeholder:text-muted-foreground pointer-coarse:text-[16px]">
    </div>
        <p x-show="error" x-cloak style="display: none" role="alert" data-slot="tag-input-error" x-text="error" class="mt-1.5 text-caption text-nq-danger-text"></p>
    <span role="status" aria-live="polite" class="sr-only" x-text="message"></span>
    </div>
                                    <div data-slot="select" x-data="nqSelect('viewer', false)" x-modelable="value" x-id="['nq-select']" x-model="inviteRole" class="contents">
    <button data-slot="select-trigger" x-ref="trigger" x-bind="trigger"
        aria-label="Role" class="flex h-control items-center justify-between gap-2 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] cursor-default select-none outline-none transition-colors duration-150 ease-nq focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-popup-open:border-nq-focus data-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] w-auto min-w-32">
    <span data-slot="select-value" x-text="label() ?? ''" :data-placeholder="empty() ? '' : undefined"
    class="min-w-0 flex-1 truncate text-start data-placeholder:text-muted-foreground"></span>
    <span class="flex shrink-0 text-muted-foreground [&_svg]:size-4"><svg 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="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg></span>
</button>
                                        <template x-teleport="body">
    <div data-slot="select-content" x-ref="popup" x-bind="popup" x-nq-presence="open" x-anchor.bottom-start.offset.4="$refs.trigger"
        class="z-50 min-w-[var(--anchor-width)] max-h-[var(--available-height)] overflow-y-auto rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0">
        <div data-slot="select-item" x-bind="item('viewer', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('viewer')" x-cloak class="contents"><svg class="size-4" 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></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">Can view</span>
</div>
                                                                                            <div data-slot="select-item" x-bind="item('commenter', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('commenter')" x-cloak class="contents"><svg class="size-4" 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></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">Can comment</span>
</div>
                                                                                            <div data-slot="select-item" x-bind="item('editor', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('editor')" x-cloak class="contents"><svg class="size-4" 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></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">Can edit</span>
</div>
    </div>
</template>
    </div>
                                    <button data-slot="share-send"
     type="button"                         x-bind:disabled="emails.length &amp;&amp; ! pending ? null : true" x-on:click="sendInvite()" 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 px-[var(--nq-control-pad)]">
        <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="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/>
  <circle cx="9" cy="7" r="4"/>
  <line x1="19" x2="19" y1="8" y2="14"/>
  <line x1="22" x2="16" y1="11" y2="11"/>
</svg>                                        Send invite</button>
                                </div>
                                <p class="text-caption text-muted-foreground">Press Enter or comma after each address.</p>
                                <div x-show="message" style="display: none">
                                    <div data-slot="alert" data-tone="info" role="status"
        x-bind:tone="message ? message.tone : &#039;success&#039;" class="relative grid grid-cols-[auto_1fr_auto] items-start gap-x-3 rounded-card border p-3 text-start border-nq-info/30 bg-nq-info-soft">
    <svg aria-hidden="true" data-slot="alert-icon" class="mt-0.5 size-4 text-nq-info-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"/>
  <circle cx="12" cy="12" r="1"/>
</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="message ? message.text : ''"></span></div>
            </div>
    </div>
                                </div>
                            </section>
                        <section x-show="people.length"  class="flex flex-col gap-2" data-slot="share-people">
                            <h3 class="text-label text-foreground">People with access</h3>
                            <ul class="flex max-h-48 flex-col divide-y divide-border overflow-y-auto rounded-control border border-border">
                                <template x-for="p in people" :key="p.id">
                                    <li class="flex items-center gap-3 px-3 py-2" data-slot="share-person">
                                        <span aria-hidden="true" class="inline-flex size-6 shrink-0 items-center justify-center overflow-hidden rounded-full bg-muted text-[10px] font-medium text-muted-foreground" x-text="p.name.trim().charAt(0).toUpperCase()"></span>
                                        <span class="flex min-w-0 flex-1 flex-col">
                                            <span class="truncate text-body-sm text-foreground" x-text="p.name"></span>
                                            <bdi dir="ltr" class="truncate text-start text-caption text-muted-foreground" x-show="p.email" x-text="p.email"></bdi>
                                        </span>
                                        <span class="text-body-sm text-muted-foreground" x-show="p.owner" style="display: none">Owner</span>
                                        <select class="h-8 min-w-28 rounded-control border border-input bg-card px-2 text-body-sm text-foreground outline-none focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus" x-show="! p.owner" x-model="p.role" x-bind:aria-label="roleFor(p.name)" x-on:change="fire('rolechange', { person: p, role: p.role })">
                                                                                            <option value="viewer">Can view</option>
                                                                                            <option value="commenter">Can comment</option>
                                                                                            <option value="editor">Can edit</option>
                                                                                    </select>
                                        <button data-slot="button"
     type="button"                         x-show="! p.owner" x-bind:aria-label="removeFor(p.name)" x-on:click="removePerson(p)" 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>
                                    </li>
                                </template>
                            </ul>
                        </section>
                                                    <section class="flex flex-col gap-3" data-slot="share-access">
                                <h3 class="text-label text-foreground">Link access</h3>
                                <div class="flex flex-col gap-2 sm:flex-row sm:items-center">
                                    <span class="flex min-w-0 flex-1 items-start gap-2.5">
                                        <span class="mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground">
                                            <svg aria-hidden="true" x-show="access === 'anyone'" style="display: none" class="size-4" 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="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/>
  <path d="M2 12h20"/>
</svg>                                            <svg aria-hidden="true" x-show="access !== 'anyone'" class="size-4" 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="18" height="11" x="3" y="11" rx="2" ry="2"/>
  <path d="M7 11V7a5 5 0 0 1 10 0v4"/>
</svg>                                        </span>
                                        <span class="flex min-w-0 flex-col">
                                            <div data-slot="select" x-data="nqSelect('restricted', false)" x-modelable="value" x-id="['nq-select']" x-model="access" class="contents">
    <button data-slot="select-trigger" x-ref="trigger" x-bind="trigger"
        aria-label="Link access" class="flex min-w-0 items-center justify-between gap-2 rounded-control border px-3 text-foreground min-h-[var(--nq-touch-min,0px)] cursor-default select-none outline-none transition-colors duration-150 ease-nq focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-popup-open:border-nq-focus data-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-8 w-auto border-transparent bg-transparent ps-1 text-label">
    <span data-slot="select-value" x-text="label() ?? ''" :data-placeholder="empty() ? '' : undefined"
    class="min-w-0 flex-1 truncate text-start data-placeholder:text-muted-foreground"></span>
    <span class="flex shrink-0 text-muted-foreground [&_svg]:size-4"><svg 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="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg></span>
</button>
                                                <template x-teleport="body">
    <div data-slot="select-content" x-ref="popup" x-bind="popup" x-nq-presence="open" x-anchor.bottom-start.offset.4="$refs.trigger"
        class="z-50 min-w-[var(--anchor-width)] max-h-[var(--available-height)] overflow-y-auto rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0">
        <div data-slot="select-item" x-bind="item('restricted', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('restricted')" x-cloak class="contents"><svg class="size-4" 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></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">Restricted</span>
</div>
                                                    <div data-slot="select-item" x-bind="item('anyone', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('anyone')" x-cloak class="contents"><svg class="size-4" 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></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">Anyone with the link</span>
</div>
    </div>
</template>
    </div>
                                            <span class="ps-1 text-caption text-muted-foreground" x-show="access !== 'anyone'">Only people you invite can open the link.</span>
                                            <span class="ps-1 text-caption text-muted-foreground" x-show="access === 'anyone'" style="display: none">Anyone who has the link can open it.</span>
                                        </span>
                                    </span>
                                    <div x-show="access === 'anyone'" style="display: none">
                                        <div data-slot="select" x-data="nqSelect('viewer', false)" x-modelable="value" x-id="['nq-select']" x-model="linkRole" class="contents">
    <button data-slot="select-trigger" x-ref="trigger" x-bind="trigger"
        aria-label="Link permission" class="flex h-control items-center justify-between gap-2 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] cursor-default select-none outline-none transition-colors duration-150 ease-nq focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-popup-open:border-nq-focus data-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] w-auto min-w-32">
    <span data-slot="select-value" x-text="label() ?? ''" :data-placeholder="empty() ? '' : undefined"
    class="min-w-0 flex-1 truncate text-start data-placeholder:text-muted-foreground"></span>
    <span class="flex shrink-0 text-muted-foreground [&_svg]:size-4"><svg 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="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg></span>
</button>
                                            <template x-teleport="body">
    <div data-slot="select-content" x-ref="popup" x-bind="popup" x-nq-presence="open" x-anchor.bottom-start.offset.4="$refs.trigger"
        class="z-50 min-w-[var(--anchor-width)] max-h-[var(--available-height)] overflow-y-auto rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0">
        <div data-slot="select-item" x-bind="item('viewer', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('viewer')" x-cloak class="contents"><svg class="size-4" 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></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">Can view</span>
</div>
                                                                                                    <div data-slot="select-item" x-bind="item('commenter', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('commenter')" x-cloak class="contents"><svg class="size-4" 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></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">Can comment</span>
</div>
                                                                                                    <div data-slot="select-item" x-bind="item('editor', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('editor')" x-cloak class="contents"><svg class="size-4" 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></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">Can edit</span>
</div>
    </div>
</template>
    </div>
                                    </div>
                                </div>
                                <div class="flex items-center gap-2.5">
                                    <span class="flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground">
                                        <svg aria-hidden="true" class="size-4" 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="M12 6v6l4 2"/>
</svg>                                    </span>
                                    <span class="flex-1 text-body-sm text-foreground">Link expires</span>
                                    <div data-slot="select" x-data="nqSelect('never', false)" x-modelable="value" x-id="['nq-select']" x-model="expiry" class="contents">
    <button data-slot="select-trigger" x-ref="trigger" x-bind="trigger"
        aria-label="Link expires" class="flex h-control items-center justify-between gap-2 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] cursor-default select-none outline-none transition-colors duration-150 ease-nq focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-popup-open:border-nq-focus data-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] w-auto min-w-32">
    <span data-slot="select-value" x-text="label() ?? ''" :data-placeholder="empty() ? '' : undefined"
    class="min-w-0 flex-1 truncate text-start data-placeholder:text-muted-foreground"></span>
    <span class="flex shrink-0 text-muted-foreground [&_svg]:size-4"><svg 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="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg></span>
</button>
                                        <template x-teleport="body">
    <div data-slot="select-content" x-ref="popup" x-bind="popup" x-nq-presence="open" x-anchor.bottom-start.offset.4="$refs.trigger"
        class="z-50 min-w-[var(--anchor-width)] max-h-[var(--available-height)] overflow-y-auto rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0">
        <div data-slot="select-item" x-bind="item('never', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('never')" x-cloak class="contents"><svg class="size-4" 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></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">Never</span>
</div>
                                                                                            <div data-slot="select-item" x-bind="item('1d', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('1d')" x-cloak class="contents"><svg class="size-4" 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></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">In 1 day</span>
</div>
                                                                                            <div data-slot="select-item" x-bind="item('7d', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('7d')" x-cloak class="contents"><svg class="size-4" 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></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">In 7 days</span>
</div>
                                                                                            <div data-slot="select-item" x-bind="item('30d', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('30d')" x-cloak class="contents"><svg class="size-4" 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></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">In 30 days</span>
</div>
    </div>
</template>
    </div>
                                </div>
                            </section>
                        <section class="flex flex-col gap-2" data-slot="share-link">
                            <h3 class="text-label text-foreground">Link</h3>
                            <div role="group" data-slot="input-group"
    class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><input data-slot="input-group-input"  dir="ltr"     readonly="readonly" aria-label="Link" x-bind:value="shareLink()" x-on:focus="$el.select()" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px] text-start" />
                                <div data-slot="input-group-addon" data-align="end"
    class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&_svg]:size-4 order-last ps-1 pe-3"><button data-slot="share-copy"
     type="button"                         x-on:click="copyLink()" 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-sm px-2.5">
        <svg aria-hidden="true" x-show="! copied" 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="14" x="8" y="8" rx="2" ry="2"/>
  <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>
</svg>                                        <svg aria-hidden="true" x-show="copied" style="display: 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="M20 6 9 17l-5-5"/>
</svg>                                        <span x-text="copied ? 'Copied' : 'Copy link'">Copy link</span></button></div></div>
                            <p class="text-caption text-muted-foreground" x-show="access === 'anyone'" style="display: none">Anyone with the link: <span x-text="roleLabel(linkRole)"></span></p>
                            <div class="flex flex-wrap gap-2">
                                <button data-slot="button"
     type="button"                         x-show="canShare" style="display: none" x-on:click="nativeShare()" 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 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="18" cy="5" r="3"/>
  <circle cx="6" cy="12" r="3"/>
  <circle cx="18" cy="19" r="3"/>
  <line x1="8.59" x2="15.42" y1="13.51" y2="17.49"/>
  <line x1="15.41" x2="8.59" y1="6.51" y2="10.49"/>
</svg>                                    Share via…</button>
                                                                    <a data-slot="share-mailto"
     href="#"                         x-bind:href="mailHref()" 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 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="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"/>
  <rect x="2" y="4" width="20" height="16" rx="2"/>
</svg>                                        Email</a>
                                                            </div>
                        </section>
                    </div>
                    <div data-slot="dialog-footer" class="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"><button data-slot="button"
     type="button"                         x-on:click="dlg = false" 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 px-[var(--nq-control-pad)]">
        Done</button></div>
                    <button type="button" data-slot="dialog-close" x-on:click="close()" aria-label="Close"
                        class="absolute end-3 top-3 inline-flex size-8 items-center justify-center rounded-control text-muted-foreground transition-colors duration-150 hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus [&_svg]:size-4"><svg 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>
                </div>
            </div>
        </template>
</div>
</div>
```
