---
title: "Notifications — Docs zenit Zig UI"
description: "Utilisez le Notifier pour des notifications dans la fenêtre qui ne bloquent jamais la tâche en cours — succès, erreur, progression, annulation et messages —…"
url: https://zenit.z.express/fr/docs/advanced/notifications
language: fr
alternate_en: https://zenit.z.express/docs/advanced/notifications.md
alternate_zh: https://zenit.z.express/zh/docs/advanced/notifications.md
alternate_es: https://zenit.z.express/es/docs/advanced/notifications.md
alternate_ja: https://zenit.z.express/ja/docs/advanced/notifications.md
alternate_ko: https://zenit.z.express/ko/docs/advanced/notifications.md
alternate_de: https://zenit.z.express/de/docs/advanced/notifications.md
project: zenit v0.1.0-alpha (Zig 0.15.2, macOS)
source: https://github.com/version-next/zenit
---

# Notifications

Utilisez le Notifier pour des notifications dans la fenêtre qui ne bloquent jamais la tâche en cours — succès, erreur, progression, annulation et messages —, avec l’empilement, le déploiement au survol et huit positions d’ancrage gérés pour vous.

## Qu’est-ce que le Notifier

`ui.widgets.Notifier` est un service au niveau de la fenêtre : initialisez-le une fois, puis appelez `show` depuis n’importe où. Les cartes vivent sur le niveau toast du portal de superposition de la fenêtre (z 2000 — au-dessus des dialogues, sous les tooltips) et ne participent jamais à la mise en page. Chaque carte possède un nœud fixe : en retirer une ne reconstruit jamais les autres et ne rejoue pas leur entrée. Il remplace l’ancien ToastManager.

[Video](https://zenit.z.express/media/stories/notification.mp4?v=5f8cadb85b)

Le vrai Storybook : succès, erreur, avertissement, progression, action, personne, annulation, discret et résumé l’un après l’autre, puis une rafale de quatre en pile, déployée au survol, avec la carte du milieu fermée.

L’API champ par champ (`Notification`, `NotifierOptions` et la signature de chaque méthode) se trouve sur la [page Notification](https://zenit.z.express/fr/components/notification) du site des composants.

## Créer un Notifier

Créez-le une fois dans votre fonction de montage racine et passez le pointeur à ce qui doit notifier (par exemple l’état de l’application conservé par `cx.bindState`). Le Notifier appartient au Scope que vous passez et disparaît avec lui.

`app.zig`

```zig
const notifier = try ui.widgets.Notifier.init(scope, cx, .{
    .position = .bottom_center,
    // Keep the stack clear of a 56px toolbar.
    .content_insets = .{ .top = 56 },
    .max_visible = 4,
});
```

| Champ de NotifierOptions | Rôle |
| --- | --- |
| `position` | L’une des huit positions, .bottom\_center par défaut ; modifiable à l’exécution avec setPosition |
| `max_visible` | Nombre de cartes affichées une fois déployé (2–6, 4 par défaut) |
| `expand_on_hover` | Si false, le survol met seulement les minuteurs en pause sans déployer |
| `content_insets` | Retraits depuis les bords de la fenêtre (barre de titre, barre d’outils, barre d’état) ; la marge d’ancrage de 22px part de là |
| `width` | Largeur des cartes, 392 par défaut |
| `strings` | Textes de l’UI ("now", "Undo", "Reply…", le badge replié…) pour la localisation |
| `listener` | Callback pour les actions de l’utilisateur et l’expiration ; aussi définissable avec setListener |

## Afficher une notification

`show` prend une valeur `ui.widgets.Notification` et renvoie son id. Le Notifier copie chaque chaîne, vos tampons sont donc réutilisables immédiatement. Au-delà de six cartes à l’écran, la plus ancienne part avec son animation de sortie normale.

`notify.zig`

```zig
// Success: auto-dismisses after 3.6 s.
_ = try notifier.show(.{
    .tone = .success,
    .title = "Saved to iCloud",
    .body = "3 files synced · 2.1 MB",
});

// Error with two actions: errors stay until the user acts.
const failed = try notifier.show(.{
    .tone = .@"error",
    .title = "Upload failed",
    .body = "network timeout · dist/app.zip",
    .actions = &.{
        .{ .label = "Retry", .primary = true, .tag = "retry" },
        .{ .label = "View log", .tag = "log" },
    },
});

// Undo: a 7 s countdown ring and a default "Undo" button.
_ = try notifier.show(.{
    .kind = .undo,
    .title = "Moved 4 items to the Trash",
    .body = "You can undo this for 7 seconds.",
});

// A person's message with an inline reply box.
_ = try notifier.show(.{
    .tone = .violet,
    .avatar = "L",
    .title = "Lin",
    .body = "I finished the table widths in section three.",
    .reply = true,
});
```

> NOTE
> 
> **Deux boutons au maximum.** Les boutons se placent sous un séparateur, à largeur égale, sur un fond neutre ; primary signifie seulement un fond et une graisse plus marqués — il ne prend jamais la couleur du ton.

## Types, tons et durées

L’apparence d’une carte dépend de deux axes : `kind` (mise en page) et `tone` (couleur sémantique). L’icône de tête découle des deux, ou se définit explicitement avec `lead` / `glyph`.

| kind | Mise en page |
| --- | --- |
| `.default` | Icône, titre et corps, avec boutons, zone de réponse ou avatar en option |
| `.progress` | Spinner, barre déterminée et un compteur n / N ; pas de barre de vie |
| `.undo` | Anneau de compte à rebours affichant les secondes restantes, plus un bouton "Undo" par défaut |

| tone | Usage | Durée par défaut |
| --- | --- | --- |
| `.success` | Une opération terminée | 3.6 s |
| `.@"error"` | Un échec qui demande une action | persistante |
| `.warning` | À remarquer, sans bloquer | 5.6 s |
| `.info` | Information générale (par défaut) | 4.2 s |
| `.violet` | Personnes, invitations et autres messages sociaux | 4.2 s ; persistante avec boutons |
| `.quiet` | Statut discret (un petit point au lieu d’une icône) | 2.8 s |

-   **Persistantes par défaut :** les cartes progress, celles avec une zone de réponse, le ton error et les cartes violet avec boutons ne se ferment jamais d’elles-mêmes.
    
-   **Surcharges explicites :** `sticky = true` la rend persistante ; `duration_ms` remplace la durée par défaut ; `life_bar` affiche ou masque la barre de vie.
    
-   **Undo** dure 7 secondes par défaut, l’anneau suivant le minuteur.
    

## Mises à jour sur place et progression

`update(id, …)` réécrit le type, le ton, le titre et le corps de la même carte et relance sa durée de vie — ni destruction, ni reconstruction, ni entrée rejouée. Faites avancer une carte de progression avec `setProgress`, qui ne touche que la couche de progression. Appeler `show` avec un `id` existant la transforme aussi sur place.

`upload.zig`

```zig
const id = try notifier.show(.{
    .kind = .progress,
    .title = "Uploading attachment",
    .body = "assets/hero-shot.png",
    .progress = .{ .value = 0, .label = "Uploading · about 5 s", .count = "0 / 5" },
});

// Each tick: only the progress layer is touched, the card isn't rebuilt.
notifier.setProgress(id, 0.6, "Uploading · about 2 s", "3 / 5");

// Done: the same card turns into a success card in place —
// no new entrance, and it now dismisses itself after 3.4 s.
try notifier.update(id, .{
    .tone = .success,
    .title = "Upload complete",
    .body = "assets/hero-shot.png",
    .duration_ms = 3400,
});
```

## Gérer les actions de l’utilisateur

Le Notifier rend compte via un unique `ui.widgets.NotificationListener`. Un `NotificationEvent` transporte l’`id` de la carte, le `kind` de l’événement, et le `tag` / `index` du bouton ou le `text` de la réponse.

| EventKind | Quand |
| --- | --- |
| `.action` | Un bouton a été cliqué (distinguez-les par tag) |
| `.undo` | Undo a été cliqué ; l’anneau est déjà devenu un ✓ |
| `.reply` | La zone de réponse a été envoyée (Entrée ou Send) ; text la contient |
| `.dismissed` | L’utilisateur l’a fermée (✕ ou d’un geste) |
| `.expired` | Elle a expiré |

`uploads.zig`

```zig
const Uploads = struct {
    fn onEvent(ctx: ?*anyopaque, n: *ui.widgets.Notifier, e: ui.widgets.NotificationEvent) void {
        const self: *Uploads = @ptrCast(@alignCast(ctx orelse return));
        switch (e.kind) {
            .action => if (std.mem.eql(u8, e.tag, "retry")) {
                // Turn the sticky error card into a progress card in place.
                n.update(e.id, .{
                    .kind = .progress,
                    .title = "Retrying upload",
                    .progress = .{ .value = 0, .label = "Uploading", .count = "0 / 5" },
                }) catch return;
                self.restart(e.id);
            } else n.dismiss(e.id),
            .reply => self.send(e.text),
            .undo => self.restoreTrash(),
            .dismissed, .expired => {},
        }
    }
    // …restart / send / restoreTrash
};

const uploads = try cx.bindState(Uploads, .{});
notifier.setListener(.{ .context = @ptrCast(uploads), .callback = Uploads.onEvent });
```

> TIP
> 
> **La réponse n’est pas partie ?** Appelez `notifier.replyFailed(id, title, body)` pour faire passer la même carte en état d’échec sur place, sans perdre ce que l’utilisateur a saisi.

## Empilement et survol

Plusieurs notifications se replient en pile : la plus récente est la plus proche de l’ancre, avec le z le plus élevé ; chaque couche derrière dépasse de 9px et rétrécit de 3.8 %, jusqu’à trois couches, avec un badge « N de plus · survoler pour déployer ». Quand le pointeur entre dans les limites de la pile (agrandies de 18px), elle se déploie avec des écarts de 9px et tous les minuteurs se mettent en pause ; en sortant, elle se replie et ils reprennent.

STACK

Les valeurs viennent de Spec dans notification/model.zig : débord de 9px, échelle de 3.8 % par couche, écart de 9px une fois déployé.

**Tout effacer**

À côté du badge se trouve un bouton « tout effacer » : le premier clic révèle son libellé, le second efface vraiment, et s’éloigner le replie. Dans le code, appelez dismissAll().

**Glisser pour fermer**

Une carte isolée peut être écartée d’un geste, ce qui signale dismissed.

**Redimensionnement de la fenêtre**

Au redimensionnement de la fenêtre, la pile suit son ancre de façon rigide, sans interpolation à la traîne.

## Positions

`setPosition` ne change que l’ancre, la direction de croissance et le décalage d’entrée — les cartes ne sont pas reconstruites, et une carte en train de sortir termine sa sortie dans la nouvelle direction.

POSITIONS

[Video](https://zenit.z.express/media/stories/notification-positions.mp4?v=2df7ff87b6)

Les quatre mêmes notifications ancrées tour à tour aux huit positions ; cadrage sur toute la fenêtre, car les positions de gauche longent le bord de la fenêtre.

## Le centre de notifications vous appartient

L’historique, le mode Ne pas déranger et un point d’entrée en forme de cloche — les fonctions d’un centre de notifications — relèvent de la logique de l’application et restent hors de zenit : enregistrez l’historique là où vous appelez show, décidez s’il faut afficher une carte, et suivez fermetures, expirations et actions de boutons via le Listener. La carte Résumé du Storybook illustre le principe : à la fin du mode Ne pas déranger, une seule carte quiet récapitule ce qui est arrivé.

> WARNING
> 
> **L’accessibilité n’est pas encore validée.** Comme pour le reste de zenit, la validation VoiceOver des cartes de notification n’est pas encore faite ; n’en faites pas le seul canal pour les informations critiques.
