# Webform `<transition>` element

How the `<transition>` element works in SaleSys webforms.

## Core idea

A `<transition>` element plays an animation (an "övergång") whenever the value you feed it via the **`lock`** attribute changes. The lock value is what the element watches — change it, and the transition fires.

```html
<transition lock="{{custom.listCount}}">
```

> "You can specify `lock` too. There's a transition whenever the value of `lock` changes."

## Driving it from state

The lock value typically comes from form state. For example, if `listCount` is the number of items in a list:

```js
window.form.setState({ listCount: list.length })
```

…then the transition re-animates each time the count changes.

You don't need a separate counter in state — you can pass `.length` (or any expression) straight into `lock`:

```html
<transition lock="{{custom.list.length}}">
```

(assuming you previously did `window.form.setState({ list: [...] })`)

## `lock` vs `boolLock`

Both attributes trigger a transition on change, but they differ in how empty/falsy values are treated:

| Attribute  | Behavior |
|------------|----------|
| `lock`     | Transitions on **any** value change. |
| `boolLock` | Interprets an empty string as `false`, so there is **no** transition between `""`, `null`, `undefined`, `0`, or `false` — they are all treated as the same "empty" state. |

> "The difference between `lock` and `boolLock` is that `boolLock` interprets an empty string as false, so there's no transition between `""`, `null`, `undefined`, `0` or `false`."

**When to use which:**
- Use **`boolLock`** when you only care about "has a value / doesn't have a value" and don't want re-triggers as the empty value churns between the various falsy forms.
- Use **`lock`** when every distinct value change should re-animate.

## Related notes

- **`TransitionedContainer`** is used in the ribbon UI and elsewhere in s2-frontend.
- A small visual "gupp" (bump) during a transition was traced to `display: inline-flex` on an `h1` — the element gains a few extra pixels of height when one of the transition children is `position: absolute`. Fix: switch `inline-flex` → `flex`. (Source: `#salesys-tech-log`, 2024-12-12.)
- UI is noticeably smoother if you guard `onAnimationEnd` / `onTransitionEnd` handlers with `event.currentTarget === event.target`, since `event.target` can be a child element. (Source: `#salesys-tech-log`, 2023-12-28.)
