# Action

Die Action wird um einen Button gelegt, um beispielsweise visuelles Feedback bei asynchronen Aktionen zu ermöglichen oder ein Bestätigungsmodal auszulösen.

## Overview

# Playground

Lege `<Action />`, um einen [Button](/04-components/actions/button/overview), um
die States des Buttons zu steuern.

```tsx
import {
  Action,
  Button,
} from "@mittwald/flow-react-components";
import { sleep } from "@/content/04-components/actions/action/examples/lib";

<Action onAction={sleep}>
  <Button color="accent">Speichern</Button>
</Action>
```

---

# Pending

Wenn eine asynchrone Aktion länger als 1000 Millisekunden dauert, wird der
**Pending** State angezeigt.

```tsx
import {
  Action,
  Button,
} from "@mittwald/flow-react-components";
import { sleepLong } from "@/content/04-components/actions/action/examples/lib";

<Action onAction={sleepLong}>
  <Button color="accent">Speichern</Button>
</Action>
```

---

# Feedback

Wenn ein visuelles Feedback nach einer Userinteraktion angezeigt werden soll,
kann das Property `showFeedback` genutzt werden.

```tsx
import {
  Action,
  Button,
} from "@mittwald/flow-react-components";

<Action
  onAction={() => {
    // do nothing
  }}
  showFeedback
>
  <Button color="accent">Speichern</Button>
</Action>
```

---

# Bestätigungsmodal

Um User vor unbeabsichtigten Aktionen zu schützen, kann ein Bestätigungsmodal
angezeigt werden. Dafür muss innerhalb der Action ein
[Modal](/04-components/overlays/modal/overview) mit dem Attribut
`slot="actionConfirm"` platziert werden.

```tsx
import {
  Action,
  ActionGroup,
  Button,
  Content,
  Heading,
  Modal,
} from "@mittwald/flow-react-components";
import { sleepLong } from "@/content/04-components/actions/action/examples/lib";

<Action onAction={sleepLong}>
  <Modal slot="actionConfirm">
    <Heading>Projekt löschen</Heading>
    <Content>
      Wenn das Projekt &quot;Test&quot; einmal gelöscht ist,
      kann es nicht wiederhergestellt werden.
    </Content>
    <ActionGroup>
      <Button color="danger">Löschen</Button>
      <Button color="secondary" variant="soft">
        Abbrechen
      </Button>
    </ActionGroup>
  </Modal>
  <Button color="danger">Projekt löschen</Button>
</Action>
```

---

# Verschachtelte Actions

Wenn mehrere Aktionen auf eine Userinteraktion folgen, können Actions auch
ineinander verschachtelt werden.

```tsx
import {
  Action,
  Button,
} from "@mittwald/flow-react-components";

<Action onAction={() => console.log("close modal")}>
  <Action onAction={() => console.log("save")}>
    <Button color="accent">Speichern</Button>
  </Action>
</Action>
```

---

# In MenuItems

Actions können auch um `MenuItems` gelegt werden, um deren State zu steuern.

```tsx
import {
  Action,
  Button,
  ContextMenuTrigger,
  ContextMenu,
  MenuItem,
} from "@mittwald/flow-react-components";
import { sleepLong } from "@/content/04-components/actions/action/examples/lib";

<ContextMenuTrigger>
  <Button>Trigger</Button>
  <ContextMenu>
    <Action onAction={sleepLong}>
      <MenuItem>Herunterladen</MenuItem>
    </Action>
  </ContextMenu>
</ContextMenuTrigger>
```


## Develop

# Actions abbrechen

Wenn eine Action abgebrochen werden soll, ohne einen Fehler auszulösen, kann die
Funktion `abortAction` aus dem Action-Modul verwendet werden. Diese Funktion
wirft einen speziellen Fehler, der von der Action-Komponente erkannt wird.
Dadurch kann die Action sauber abgebrochen werden, ohne dass unerwünschte
Fehlermeldungen oder Seiteneffekte auftreten.

Alle nachfolgenden Funktionen in der Action-Execution-Logik, die nach dem Aufruf
von `abortAction` definiert sind, werden nicht mehr ausgeführt. Das bedeutet,
dass der gesamte Ablauf der Action sofort gestoppt wird, sobald `abortAction`
aufgerufen wird.

Umschließende Actions bei einer Verschachtelung von Actions werden ebenfalls
abgebrochen, wenn `abortAction` in einer inneren Action aufgerufen wird.

```tsx
import { sleep } from "@/content/04-components/actions/action/examples/lib";
import {
  abortAction,
  Action,
  Button,
} from "@mittwald/flow-react-components";

<Action
  onAction={() => {
    console.log("Outer action");
  }}
>
  <Action
    onAction={async () => {
      await sleep();
      console.log("Inner action");
      abortAction();
    }}
  >
    <Button>Start action</Button>
  </Action>
</Action>
```

# Properties

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `actionModel` | `ActionModel` | - | - |
| `closeOverlay` | `keyof FlowComponentPropsTypes \| OverlayController \| CloseOverlayOptions` | - | - |
| `openOverlay` | `keyof FlowComponentPropsTypes \| OverlayController` | - | - |
| `toggleOverlay` | `keyof FlowComponentPropsTypes \| OverlayController` | - | - |
| `closeModal` | `boolean \| CloseModalOptions` | - | - |
| `openModal` | `boolean` | - | - |
| `toggleModal` | `boolean` | - | - |
| `break` | `boolean` | - | - |
| `skip` | `number \| boolean` | - | - |
| `showFeedback` | `boolean` | - | - |
| `children` | `ReactNode` | - | - |
| `wrapWith` | `ReactElement<unknown, string \| JSXElementConstructor<any>>` | - | - |
| `ref` | `Ref<HTMLSpanElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see [React Docs](https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom) |
| `key` | `Key` | - | - |

### Events

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `onAction` | `ActionFn` | - | - |


## Guidelines

# Grundlagen

Die Action wird verwendet, um das asynchrone Verhalten von zum Beispiel
[Buttons](/04-components/actions/button/overview) zu steuern. Sie wird genutzt,
um den Usern visuelles Feedback bei Interaktionen zu geben, zum Beispiel durch
Ladezustände oder Bestätigungsmodals.

## Best practices

Achte bei der Verwendung einer Action darauf, dass ...

- der Pending State nur für Vorgänge verwendet wird, die in der Regel unter 5
  Sekunden dauern. Für längere Prozesse kann eine
  [Notification](/04-components/status/notification/overview) die bessere Wahl
  sein.
- Feedback States nur dann eingesetzt werden, wenn sie dem Nutzer einen Mehrwert
  in der Interaktion bieten.

## Verwendung

Verwende eine Action, um ...

- einen Button mit einem automatisierten Lade- und Erfolgs-Feedback bei
  asynchronen Prozessen zu versehen.
- Useraktionen mit Bestätigungsmodals zu sichern, bevor ein kritischer Vorgang
  gestartet wird.

