# Modes and triggers

Inline, popover, slide-in, modal and page modes, your own button, and timed, scroll and exit triggers.

One form can run in several places at once, each shown a different way. How it shows is the `mode` attribute on `<onestar-feedback>`, and an overlay can open from your own button, from the floating tab OneStar draws, from code or from a trigger such as a timer.

## Modes

| Mode | What it does |
|---|---|
| `inline` | The default. The form sits where the element is, up to 520px wide. It draws when it comes near the screen. |
| `page` | Like inline, wider (up to 640px) and centred, with more room around it. For a page of its own, such as `/feedback`. |
| `popover` | A panel that opens from a floating **Feedback** tab in the bottom right corner, or from your own button. |
| `slide-in` | A panel in the bottom right corner, opened by a trigger, your button or code. |
| `modal` | A dialog over a dimmed page, opened by a trigger, your button or code. |
| `thread` | No form: only this person's conversations about the form, for a page of your own. See [Replies](#replies). |

```html
<onestar-feedback form="f_hemsz66yupbd76d2" mode="popover"></onestar-feedback>
```

A popover, slide-in or modal takes no room on the page until it opens. Its widget code loads when it first opens, or a moment sooner when the pointer moves over its button or the button gets focus.

## Attributes that open an overlay

| Attribute | Modes | Meaning |
|---|---|---|
| `trigger-for` | `popover`, `slide-in`, `modal` | The `id` of your own button. A click opens the form, a second click closes it. A popover with this attribute draws no floating tab. |
| `label` | `popover` | The floating tab's text when there is no `trigger-for` button. Default `Feedback`. |
| `trigger` | `popover`, `slide-in`, `modal` | Opens the form by itself: `delay:5000`, `scroll:50` or `exit`. |

### Your own button

```html
<button id="feedback-button" type="button">Send feedback</button>
<onestar-feedback form="f_hemsz66yupbd76d2" mode="popover" trigger-for="feedback-button"></onestar-feedback>
```

The button must be on the page when the element starts, which is when the loader runs or when you add the element, whichever comes later. OneStar adds `aria-haspopup="dialog"` to it and keeps `aria-expanded` in step with the panel. A popover opens below your button when there is room and above it when there is not.

### Triggers

| Trigger | Opens the form |
|---|---|
| `delay:5000` | After that many milliseconds on the page. |
| `scroll:50` | Once the bottom of the window reaches that percent of the page's height. |
| `exit` | When the pointer leaves the window through the top, as it does on the way to the tabs or the address bar. Pointer only, so it never fires on a touch screen. |

Combine them with commas: `trigger="delay:20000, exit"`. Together they open the form at most once per page view, whichever comes first. When the form allows one answer per person (the default) and this browser already finished it, triggers do nothing.

```html
<onestar-feedback form="f_hemsz66yupbd76d2" mode="slide-in" trigger="scroll:60, exit"></onestar-feedback>
```

A slide-in or modal with no `trigger` and no `trigger-for` opens only from code.

### From code

`onestar.open()` opens the first overlay on the page, and `onestar.open("f_hemsz66yupbd76d2")` the one for that form. When the page has no element for that form, `open` adds a modal for it. `onestar.close()` closes every open overlay. See the [JavaScript API](https://onestar.sh/docs/feedback/javascript-api.md).

## Closing

Every overlay has a Close button. Escape closes it while focus is inside it. A click outside the panel closes a popover or slide-in, and a click on the dimmed page closes a modal. Each opening and closing fires `onestar:open` and `onestar:close` ([Events and errors](https://onestar.sh/docs/feedback/events.md)).

## Focus and keyboard

- Opened by a person (your button, the tab or `onestar.open()`), the panel takes focus and moves it to the form's first control. Closing returns focus to where it was, usually the button.
- Opened by a timer or scroll depth, the panel leaves focus on the page, so a person who is typing is never interrupted.
- A modal or slide-in keeps Tab inside it while open. A popover does not.
- Each panel is a dialog labelled "Feedback". A modal is marked as modal, so screen readers keep to it.

Inside the form, one question shows at a time:

- Ratings, NPS and single choice questions are a group of buttons. Arrow keys (and Home and End) move between the options and select one without sending it. A click, a tap, Enter or Space answers the question and moves on.
- Several choices, written answers and sliders take a **Next** button (**Send** on the last question).
- In a ranking, the arrow keys move between items, Alt with an arrow key moves the focused item, and each item has up and down buttons.
- **Back** returns to the previous question until its answer has been saved. Optional questions answered with one tap also get **Skip**.
- Every question is a fieldset whose legend is the question, errors are tied to the question they belong to, and the thank you and other changes are announced.

The first answer is saved the moment it is given, so a one tap reaction counts even if the person closes the panel straight after. Animations run only when the person's system does not ask for reduced motion.

## Replies

When you reply to an answer in OneStar, the person who wrote it sees the reply in the widget, with nothing to change on your side:

- When the form loads in a browser that answered it before (or for a signed in user), a line above the form says "The makers replied", or "The form's owner replied" when you have not shown that you make the product, with a **Read** button.
- **Read** opens the conversation: their answer, the messages, and a box to answer back in, up to 2,000 characters. **Back to the form** returns to the questions.
- A popover's floating tab shows a dot while a reply is unread. Your own `trigger-for` button gets `data-onestar-unread="<n>"` instead, for you to style. The element fires `onestar:replied`.
- Reading a reply marks it seen, and OneStar shows you "Seen in the widget".

For a browser that answered before, the unread check is the only request the loader makes before the form opens.

### mode="thread"

`mode="thread"` shows only the person's conversations about one form, with no questions to answer. Use it on a page of your own, such as an account area. With no replies yet it says so.

### The inbox element

`<onestar-inbox>` lists the person's conversations on every form you run, under the heading "Your feedback and our replies":

```html
<onestar-inbox form="f_hemsz66yupbd76d2" user-token="<signed token>"></onestar-inbox>
```

The `form` attribute says whose forms to list (yours). The `user-token` attribute, or `onestar.identify(token)`, says who the person is; see [Signed in users](https://onestar.sh/docs/feedback/identify-users.md). Without a token it lists what this browser answered. It loads the same loader, so add the script as for the form.

To draw conversations in your own UI instead, use `onestar.threads()` and `onestar.reply()` from the [JavaScript API](https://onestar.sh/docs/feedback/javascript-api.md).
