> For the complete documentation index, see [llms.txt](https://docs.akinon.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.akinon.com/akinon-ui/ui-protocol/client-application/configuration/actions.md).

# Actions

This allows micro-frontends to trigger shell functionality such as showing toasts, opening modals, or calling custom business logic.

### <mark style="color:red;">Action Types</mark>

There are two types of actions:

1. **Default Actions** - Built-in UI actions (toast, modal, confirmation)
2. **Custom Actions** - Application-specific actions defined by the shell

### <mark style="color:red;">Using Default Actions</mark>

Default actions are available directly from `useAppClient`:

```tsx
import { useAppClient } from '@akinon/app-client';

const MyComponent = () => {
  const { 
    showToast, 
    showModalDialog, 
    showConfirmationDialog,
    showErrorMessage,
    showRichModal 
  } = useAppClient();

  // Use these functions to invoke default actions
};
```

#### showToast

Display a brief notification message:

```tsx
const NotificationExample = () => {
  const { showToast } = useAppClient();

  const handleSuccess = () => {
    showToast('Operation completed successfully!', 'success');
  };

  const handleError = () => {
    showToast('Something went wrong', 'error');
  };

  const handleWarning = () => {
    showToast('Please review your input', 'warning');
  };

  const handleLoading = () => {
    showToast('Processing...', 'loading');
  };

  const clearToasts = () => {
    showToast('', 'destroy');
  };

  return (
    <div>
      <button onClick={handleSuccess}>Success</button>
      <button onClick={handleError}>Error</button>
      <button onClick={handleWarning}>Warning</button>
      <button onClick={handleLoading}>Loading</button>
      <button onClick={clearToasts}>Clear All</button>
    </div>
  );
};
```

#### showConfirmationDialog

Display a confirmation dialog with callbacks:

```tsx
const DeleteButton = ({ itemId }: { itemId: string }) => {
  const { showConfirmationDialog, showToast } = useAppClient();

  const handleDelete = () => {
    showConfirmationDialog({
      title: 'Delete Item',
      content: 'Are you sure you want to delete this item? This action cannot be undone.',
      onConfirm: async () => {
        await deleteItem(itemId);
        showToast('Item deleted', 'success');
      },
      onCancel: () => {
        console.log('Deletion cancelled');
      }
    });
  };

  return <button onClick={handleDelete}>Delete</button>;
};
```

#### showModalDialog

Display an informational modal:

```tsx
const InfoButton = () => {
  const { showModalDialog } = useAppClient();

  const showInfo = () => {
    showModalDialog({
      title: 'About This Feature',
      content: 'This feature allows you to manage your orders efficiently.'
    });
  };

  return <button onClick={showInfo}>Info</button>;
};
```

#### showErrorMessage

Display an error message prominently:

```tsx
const ErrorHandler = () => {
  const { showErrorMessage } = useAppClient();

  const handleApiError = (error: Error) => {
    showErrorMessage('Request Failed', error.message);
  };

  return <ApiConsumer onError={handleApiError} />;
};
```

#### showRichModal

Open a rich modal with micro-frontend content:

```tsx
const ProductList = () => {
  const { showRichModal } = useAppClient();

  const openProductDetail = (productId: string) => {
    showRichModal(
      `/products/${productId}`,           // path
      { productId, mode: 'view' },        // context (accessible via modalContext)
      { maxWidth: 800, maxHeight: '90vh' }, // size
      '#333333'                            // closeIconColor
    );
  };

  return (
    <ul>
      {products.map(product => (
        <li key={product.id}>
          {product.name}
          <button onClick={() => openProductDetail(product.id)}>
            View Details
          </button>
        </li>
      ))}
    </ul>
  );
};
```

### <mark style="color:red;">Using Custom Actions</mark>

Custom actions are invoked via `invokeAction`:

```tsx
import { useAppClient } from '@akinon/app-client';

const CustomActionExample = () => {
  const { invokeAction, showToast, showErrorMessage } = useAppClient();

  const handleLogout = async () => {
    try {
      await invokeAction('performLogout');
      showToast('Logged out successfully', 'success');
    } catch (error) {
      showErrorMessage('Logout Failed', error.message);
    }
  };

  const fetchUserData = async (userId: number) => {
    try {
      const userData = await invokeAction('fetchUserData', userId);
      console.log('User data:', userData);
      return userData;
    } catch (error) {
      showErrorMessage('Fetch Failed', error.message);
    }
  };

  const refreshPermissions = async () => {
    const result = await invokeAction('refreshPermissions');
    if (result.success) {
      showToast('Permissions updated', 'success');
    }
  };

  return (
    <div>
      <button onClick={handleLogout}>Logout</button>
      <button onClick={() => fetchUserData(123)}>Fetch User</button>
      <button onClick={refreshPermissions}>Refresh Permissions</button>
    </div>
  );
};
```

### <mark style="color:red;">URL Search Params</mark>

Manage URL search parameters via shell actions:

```tsx
const FilterComponent = () => {
  const { setSearchParams, removeSearchParams, data } = useAppClient();

  const applyFilters = (filters: Record<string, string>) => {
    setSearchParams({
      ...filters,
      page: 1
    });
  };

  const clearFilters = () => {
    removeSearchParams(['category', 'status', 'page']);
  };

  return (
    <div>
      <p>Current: {JSON.stringify(data?.searchParams)}</p>
      <button onClick={() => applyFilters({ category: 'electronics' })}>
        Electronics
      </button>
      <button onClick={clearFilters}>Clear</button>
    </div>
  );
};
```

### <mark style="color:red;">Accessing Modal Context</mark>

When opened via `showRichModal`, access the context:

```tsx
// Parent component calls:
// showRichModal('/product-detail', { productId: '123', mode: 'edit' })

// In the modal content:
const ProductDetailModal = () => {
  const { modalContext } = useAppClient();
  
  const context = modalContext as { productId: string; mode: string };

  return (
    <div>
      <h1>Product Detail</h1>
      <p>ID: {context?.productId}</p>
      <p>Mode: {context?.mode}</p>
    </div>
  );
};
```

### <mark style="color:red;">Best Practices</mark>

#### 1. Error Handling

Always wrap action invocations in try-catch:

```tsx
const handleAction = async () => {
  try {
    const result = await invokeAction('riskyAction');
    showToast('Success!', 'success');
  } catch (error) {
    showErrorMessage('Action Failed', error.message);
  }
};
```

#### 2. Loading States

Show loading indicators during async actions:

```tsx
const AsyncActionButton = () => {
  const { invokeAction, showToast } = useAppClient();
  const [isLoading, setIsLoading] = useState(false);

  const handleClick = async () => {
    setIsLoading(true);
    try {
      await invokeAction('longRunningAction');
      showToast('Done!', 'success');
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <button onClick={handleClick} disabled={isLoading}>
      {isLoading ? 'Processing...' : 'Run Action'}
    </button>
  );
};
```

#### 3. Type Safety

Type your action results:

```tsx
interface UserData {
  id: number;
  name: string;
  email: string;
}

const fetchUser = async (userId: number): Promise<UserData> => {
  const result = await invokeAction<UserData>('fetchUserData', userId);
  return result;
};
```

### <mark style="color:red;">Next Steps</mark>

* Navigation - Client-side navigation
* Hooks - Complete useAppClient reference


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.akinon.com/akinon-ui/ui-protocol/client-application/configuration/actions.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
