# Website components

> The account button and the data-toolaby-* attributes that sign buyers in, show content by what they own, and sell your tools.

`toolaby-web.js` defines one element, `<toolaby-user>`, and reads a set of `data-toolaby-*` attributes on your page. Together they cover sign-in, content by sign-in state or by what the buyer owns, and selling, with no code of your own.

This page lists every attribute, part, custom property and event, then complete recipes. It assumes the script is on the page; see [Your website](https://toolaby.app/docs/own-site.md).

## `<toolaby-user>`

```html
<toolaby-user></toolaby-user>
```

| State                                  | It shows                                                                                                                          |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Before the first answer                | Nothing, in the space it will take, so the header does not move and a signed-in buyer never sees **Sign in** first.               |
| Signed out                             | A **Sign in** button. It opens the sign-in page, and the buyer returns to the page they were on, including its `#section`.        |
| Signed in                              | The buyer's picture, or their initial, with a menu: their name and email, **Manage account** (the account page) and **Sign out**. |
| The page cannot see the buyer (`link`) | An **Account** link to the account page.                                                                                          |

The menu opens on a click or <kbd>↓</kbd>. <kbd>↑</kbd> <kbd>↓</kbd> <kbd>Home</kbd> <kbd>End</kbd> move between its items, <kbd>Esc</kbd> closes it and returns focus to the button, and a click outside closes it.

### Attributes

| Attribute            |                                                                                                                                                                                            |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `sign-in-url`        | A sign-in page of your own, used instead of the hosted sign-in page. It receives `?next=` with the page to return to. See [What works in each way](https://toolaby.app/docs/own-site.md#what-works-in-each-way). |
| `account-url`        | An account page of your own, used for **Manage account** instead of the hosted account page.                                                                                               |
| `after-sign-out-url` | A page on your site to go to after **Sign out**. Without it, the page stays and the button shows **Sign in**.                                                                              |
| `sign-in-label`      | The signed-out button's text. Default: `Sign in`.                                                                                                                                          |
| `theme`              | `light` or `dark`. Without it, the button matches the background of the element it sits in.                                                                                                |
| `align`              | `end` (the default) opens the menu aligned to the button's right edge; `start`, to its left edge.                                                                                          |

### Styling

The button draws in its own shadow root: your CSS does not reach inside it, and its CSS does not reach your page. It uses your page's font. Style it with these custom properties, set on `toolaby-user` or any ancestor:

| Property              |                                                                                         |
| --------------------- | --------------------------------------------------------------------------------------- |
| `--toolaby-accent`    | The **Sign in** button's background. Default: near-black, or near-white on a dark page. |
| `--toolaby-accent-fg` | The **Sign in** button's text colour.                                                   |
| `--toolaby-radius`    | The corner radius of the button and the menu. Default: `10px`.                          |

For anything else, each part is exposed to `::part()`:

| Part     |                         |
| -------- | ----------------------- |
| `button` | The **Sign in** button. |
| `avatar` | The signed-in button.   |
| `menu`   | The menu.               |
| `item`   | Each item in the menu.  |

```css
toolaby-user { --toolaby-accent: #635bff; --toolaby-radius: 999px; }
toolaby-user::part(avatar) { width: 36px; height: 36px; }
```

### Events

| Event                | On                   |                                                                                                         |
| -------------------- | -------------------- | ------------------------------------------------------------------------------------------------------- |
| `toolaby:ready`      | `window`             | The first answer arrived. `event.detail` is `Toolaby.state`.                                            |
| `toolaby:change`     | `window`             | A later answer differs from the one before: the buyer signed in or out, or bought something.            |
| `toolaby:signed-out` | the element          | The buyer signed out from its menu.                                                                     |
| `toolaby:sent`       | the button, bubbling | A `data-toolaby-signin` button sent a sign-in link from your page. `event.detail.email` is the address. |
| `toolaby:error`      | the element          | An action failed. `event.detail.message` says why.                                                      |

## Content by state

```html
<div data-toolaby-signed-out hidden>
  <button data-toolaby-signin>Sign in</button>
</div>
<div data-toolaby-signed-in hidden>
  Welcome back, <span data-toolaby-name></span> (<span data-toolaby-email></span>)
</div>
<div data-toolaby-owns="word-count" hidden>Thanks for buying Word Count.</div>
```

Elements with these attributes are hidden until the first answer arrives, then shown or hidden by it. Give them the `hidden` attribute in your HTML as well, so nothing shows before the script runs.

`data-toolaby-owns` hides an element from a buyer who does not hold the tool. It does not keep the element's content from them: anyone can read your page's HTML. Keep content that must stay private on your server.

## Buttons

```html
<button data-toolaby-signin>Sign in</button>
<button data-toolaby-signout>Sign out</button>
<button data-toolaby-checkout="word-count">Buy</button>
<button data-toolaby-checkout="word-count" data-toolaby-plan="yearly">Subscribe yearly</button>
<button data-toolaby-trial="word-count">Try it free</button>
<button data-toolaby-portal>Manage billing</button>
```

* `data-toolaby-checkout` opens Stripe Checkout for the tool, on your Stripe account.
* `data-toolaby-trial` starts the tool's free trial for the signed-in buyer, then opens the after-purchase page, which signs the extension in to the buyer's account.
* `data-toolaby-portal` opens the Stripe customer portal for a signed-in buyer.

The trial needs no card. It lasts as long as the longest trial your plans offer, and unlocks what that plan does, with the Free plan's features. When several plans offer that longest trial, it unlocks what the one with the fewest features does. One buyer has one trial of a tool.

A subscription and a trial need a signed-in buyer; a lifetime licence does not. Clicked signed out, they open the sign-in page. When the buyer returns, the checkout or the trial continues without another click. It continues once: if the page still cannot see the session, it fires `toolaby:error` instead of sending the buyer round again.

## Attribute reference

| Attribute                 | On                |                                                                                                                                                                                                                                     |
| ------------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data-toolaby-signin`     | a button          | Opens the sign-in page and returns to this page. In a form with an email field, on your domain, sends a sign-in link to that address instead and fires `toolaby:sent`; through a proxy or in development it opens the sign-in page. |
| `data-toolaby-next`       | the same button   | Where the buyer lands after signing in, instead of this page.                                                                                                                                                                       |
| `data-toolaby-signout`    | a button          | Signs the buyer out.                                                                                                                                                                                                                |
| `data-toolaby-checkout`   | a button          | Opens Stripe Checkout for the tool with this id. A subscription signed out signs in first and continues.                                                                                                                            |
| `data-toolaby-plan`       | the same button   | The plan's id, as its card under **Pricing** shows it. Without it, the tool's default plan.                                                                                                                                         |
| `data-toolaby-email`      | the same button   | The buyer's address for checkout or a sign-in link, instead of reading it from the form.                                                                                                                                            |
| `data-toolaby-ext`        | the same button   | The id of the extension that sent the buyer, so the purchase unlocks it at once.                                                                                                                                                    |
| `data-toolaby-trial`      | a button          | Starts the free trial of the tool with this id, then opens the after-purchase page. Signed out, signs in first and continues.                                                                                                       |
| `data-toolaby-portal`     | a button          | Opens the Stripe customer portal. Its value, when present, is a subscription's id.                                                                                                                                                  |
| `data-toolaby-signed-in`  | any element       | Shown when a buyer is signed in.                                                                                                                                                                                                    |
| `data-toolaby-signed-out` | any element       | Shown when no buyer is signed in.                                                                                                                                                                                                   |
| `data-toolaby-owns`       | any element       | Shown when the signed-in buyer holds the tool with this id.                                                                                                                                                                         |
| `data-toolaby-email`      | any other element | Filled with the signed-in buyer's email; hidden when there is none.                                                                                                                                                                 |
| `data-toolaby-name`       | any element       | Filled with the account's name; hidden when there is none.                                                                                                                                                                          |
| `data-toolaby-ignore`     | any element       | None of these attributes acts inside it. Put it around anything a visitor wrote.                                                                                                                                                    |

A tool id in these attributes is either of the tool's ids: the short one, as in these examples, or the full one shown as **Tool id** on the tool's page.

A button that fails fires `toolaby:error` on itself, with `event.detail.message`.

### Content your visitors write

If your page shows HTML that visitors write, such as comments, posts or profiles, wrap it in an element with `data-toolaby-ignore`. Otherwise a visitor can write `<button data-toolaby-trial="word-count">`, and one click by a buyer starts that buyer's only trial. Inside the wrapper, the attributes on this page do nothing.

```html
<section data-toolaby-ignore>
  <!-- comments rendered from your database -->
</section>
```

## Recipes

### A header with the account button

```html
<header>
  <a href="/">Word Count</a>
  <nav><a href="/pricing">Pricing</a></nav>
  <toolaby-user after-sign-out-url="/"></toolaby-user>
</header>
<script src="https://accounts.example.com/client/toolaby-web.js" defer></script>
```

### A pricing section

```html
<section id="pricing">
  <h2>Word Count Pro</h2>
  <p>€3 a month, or €29 once.</p>
  <button data-toolaby-checkout="word-count" data-toolaby-plan="monthly">Subscribe</button>
  <button data-toolaby-checkout="word-count">Buy once</button>
  <button data-toolaby-trial="word-count">Try it free for 7 days</button>
  <p data-toolaby-owns="word-count" hidden>You have Pro. <button data-toolaby-portal>Manage billing</button></p>
</section>
```

Each plan's id is on its card under **Pricing**. The first plan made is `default`; later ones are `lifetime`, `monthly` or `yearly`, with a suffix when that one is taken. This section's lifetime plan was made first, so **Buy once** needs no `data-toolaby-plan`.

### A page the extension sends buyers to

An extension's **Buy** can open your page with `?ext=<extension id>`. Pass it on, and the purchase unlocks that extension while the buyer is still looking:

```html
<button id="buy" data-toolaby-checkout="word-count">Buy</button>
<script>
  const ext = new URLSearchParams(location.search).get('ext');
  if (ext) document.getElementById('buy').setAttribute('data-toolaby-ext', ext);
</script>
```

### A sign-in form of your own

On your domain, a form with an email field sends the link from your page:

```html
<form>
  <input type="email" name="email" required>
  <button data-toolaby-signin>Email me a sign-in link</button>
</form>
<p id="sent" hidden>Check your inbox.</p>
<script>
  window.addEventListener('toolaby:sent', () => { document.getElementById('sent').hidden = false; });
</script>
```

Through a proxy or in development the same button opens the hosted sign-in page.

## See also

* [Your website](https://toolaby.app/docs/own-site.md)
* [Website JavaScript](https://toolaby.app/docs/web-javascript.md)
* [Buyer pages](https://toolaby.app/docs/buyer-pages.md)
