Queue & Concurrency
Relevant source files
The following files were used as context for generating this wiki page:
The Queue & Concurrency system in @pcstyle/toast manages the lifecycle, visibility, and asynchronous state transitions of toast notifications. It ensures that the user interface remains uncluttered by enforcing a strict concurrency limit on visible elements and provides mechanisms for handling asynchronous operations through a promise-based queue management pattern.
This system is built around a centralized ToastStore that acts as the single source of truth, coordinating updates between the imperative API and the reactive React components. Sources: src/store.ts, src/index.ts
State Management & Concurrency Control
The core concurrency logic is implemented within the ToastStore class. The system maintains an internal array of active toasts and limits the display to the most recent items.
Visibility Limits
To prevent UI saturation, the system implements a hard limit on the number of concurrently visible notifications. When a new toast is added, the store prepends it to the stack and truncates the array to maintain only the 5 most recent notifications.
The diagram above illustrates the truncation logic used to manage visual concurrency. Sources: src/store.ts:41-43
The Observer Pattern
Concurrency between the logic layer and the UI layer is handled via a subscription model. The ToastProvider subscribes to the ToastStore on mount, ensuring that any state changes (additions, removals, or updates) are immediately reflected in the React state.
| Method | Description |
|---|---|
subscribe(observer) | Adds a callback to the observers list and returns an unsubscribe function. |
notify() | Iterates through all observers with a shallow copy of the current toast array. |
add(toast) | Injects a new toast into the queue with a randomized ID. |
Sources: src/store.ts:25-39, src/provider.tsx:16-18
Asynchronous Promise Management
The system provides a specialized toast.promise API to handle concurrent asynchronous operations. This allows the UI to represent the state of a background task (loading, success, or error) using a single notification entry that updates its properties dynamically.
Promise Lifecycle Flow
When a promise is registered, the system creates a "loading" toast that bypasses the standard auto-dismissal logic. Once the promise resolves or rejects, the store updates the existing notification by ID rather than creating a new one.
The sequence diagram demonstrates how the system maintains a stable reference to a notification throughout an asynchronous lifecycle. Sources: src/index.ts:44-67
Lifecycle and Expiry Logic
Notifications in the queue follow specific expiration rules based on their type. This ensures that transient messages do not linger indefinitely while critical status indicators remain visible.
- Standard Toasts: Automatically removed after a duration (default 4000ms).
- Loading Toasts: These do not trigger a
setTimeoutduring theadd()phase, requiring manual removal or anupdate()call to transition into a dismissible state. - Manual Dismissal: The
toast.dismiss(id)andtoastStore.remove(id)methods provide immediate cleanup of the queue.
| Property | Type | Default | Description |
|---|---|---|---|
duration | number | 4000 | Time in ms before the toast is removed from the queue. |
type | ToastType | "default" | Determines if the toast is persistent (loading) or transient. |
id | string | random | Unique identifier used for targeting updates and removals. |
Sources: src/store.ts:7-16, src/store.ts:45-48, src/index.ts:40-42
Infrastructure Configuration
The project utilizes a modern TypeScript/ESM stack to ensure type safety across the concurrent state transitions. Strict type checking is enforced via tsconfig.json and custom CI rules in cubic.yaml.
- Compiler Settings: Targeted at
ES2020withESNextmodules to support modern asynchronous patterns. Sources: tsconfig.json:3-6 - Strictness:
strict: trueand custom rules prohibitinganytypes ensure that the data flowing through the queue remains predictable. Sources: tsconfig.json:10, cubic.yaml:26-29 - Dependencies: Concurrency in the UI is augmented by
framer-motion(v10+), which handles the entry/exit animations of the notification queue components. Sources: package.json:22
Summary: The system manages notification concurrency by limiting the active queue to 5 items and utilizing an observer-based store that supports dynamic updates for asynchronous promise states.