# Signals

Class props are signals. Read with label(), write with label(value), tween with yield* label(next, duration). Bind children with () => this.label().

A signal is a value that can change over time. Other values that read it update when it changes.

On a custom element, every public prop is a signal. Declare it with `@initial` and `@signal` on the class. Do not store animated state in a plain field or a hand-rolled `createSignal` on the class.

## Three calls

The action depends on how many arguments you pass.

Read:

```ts
const value = this.label();
```

Write immediately:

```ts
this.label('Hello');
```

Tween (inside a generator):

```ts
yield* this.label('Hello', 0.3);
```

Colors work the same after `@colorSignal`:

```ts
yield* this.textColor('#68ABDF', 0.4);
```

## Bind children to functions

Pass a function into JSX so the child keeps reading the signal:

```tsx
this.add(
  <Txt
    text={() => this.label()}
    fill={() => this.textColor()}
    fontSize={() => this.textSize()}
  />,
);
```

A one-shot `text` assignment that calls `label()` copies the string once. Later edits to `label` will not reach the `Txt`.

A signal can also compute from other signals:

```ts
const width = () => this.label().length * this.textSize() * 0.55 + this.textSize();
```

Use that pattern when a chip or keycap must size to its string. Do not let flex measure the `Txt`. See [Layout](/docs/custom-elements/layout).

## Class signals vs `createSignal`

`createSignal` from `@vidova/core` is for a local value inside a method. It is not a replacement for a class prop.

Forbidden for props and animated class state:

```ts
// Wrong. Not a class signal. Tweening it does not update the element.
const label = createSignal('Hello');
```

Required:

```tsx
@initial('Hello')
@signal()
public declare readonly label: SimpleSignal<string, this>;
```

Do not cast a closure to `SimpleSignal`. It is not reactive and never animates.

Node properties are already signals. `this.opacity()`, `this.scale()`, and `this.position()` tween the same way. Do not declare a class field with those names. The field overwrites the node property.

How to wire props onto a class: [Authoring](/docs/custom-elements/authoring). How to sequence tweens: [Animation](/docs/custom-elements/animation).
