or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

container.mdindex.mdnotification-center.mdtoast-api.mdtransitions.mdutilities.md

notification-center.mddocs/

0

# Notification Center

1

2

The Notification Center addon provides persistent notification management through a React hook-based API. Unlike regular toasts that automatically disappear, the notification center maintains a persistent list of notifications that users can manage manually.

3

4

## Package Information

5

6

The notification center is distributed as a separate addon:

7

8

- **Import Path**: `react-toastify/addons/use-notification-center`

9

- **Dependencies**: Requires `react-toastify` as a peer dependency

10

11

## Core Imports

12

13

```typescript

14

import { useNotificationCenter } from 'react-toastify/addons/use-notification-center';

15

```

16

17

## Capabilities

18

19

### useNotificationCenter Hook

20

21

Main hook for managing persistent notifications with full CRUD operations and state management.

22

23

```typescript { .api }

24

/**

25

* React hook for managing a persistent notification center

26

* @param params - Optional configuration parameters

27

* @returns Notification center API with methods and state

28

*/

29

function useNotificationCenter<T = {}>(

30

params?: UseNotificationCenterParams<T>

31

): UseNotificationCenter<T>;

32

33

interface UseNotificationCenterParams<T = {}> {

34

/** Initial notifications to populate the center (for rehydration) */

35

data?: NotificationCenterItem<T>[];

36

/** Filter function to determine which notifications to include */

37

filter?: FilterFn<T>;

38

/** Sort function to order notifications */

39

sort?: SortFn<T>;

40

}

41

42

type FilterFn<T = {}> = (item: NotificationCenterItem<T>) => boolean;

43

type SortFn<T = {}> = (a: NotificationCenterItem<T>, b: NotificationCenterItem<T>) => number;

44

45

interface UseNotificationCenter<T = {}> {

46

/** Array of all notifications in the center */

47

notifications: NotificationCenterItem<T>[];

48

/** Remove all notifications from the center */

49

clear(): void;

50

/** Mark all notifications as read or unread */

51

markAllAsRead(read?: boolean): void;

52

/** Mark specific notifications as read or unread */

53

markAsRead(id: Id | Id[], read?: boolean): void;

54

/** Remove specific notifications from the center */

55

remove(id: Id | Id[]): void;

56

/** Add a new notification to the center */

57

add(item: NotificationCenterItem<T>): void;

58

/** Update an existing notification */

59

update(id: Id, item: Partial<NotificationCenterItem<T>>): void;

60

/** Find notification(s) by ID */

61

find(id: Id): NotificationCenterItem<T> | undefined;

62

/** Sort notifications using a custom comparator */

63

sort(compareFn: SortFn<T>): void;

64

/** Number of unread notifications */

65

unreadCount: number;

66

}

67

```

68

69

**Basic Usage:**

70

71

```typescript

72

import React from 'react';

73

import { useNotificationCenter } from 'react-toastify/addons/use-notification-center';

74

75

function NotificationCenter() {

76

const {

77

notifications,

78

clear,

79

markAllAsRead,

80

markAsRead,

81

remove,

82

unreadCount

83

} = useNotificationCenter();

84

85

return (

86

<div className="notification-center">

87

<div className="header">

88

<h3>Notifications ({unreadCount} unread)</h3>

89

<button onClick={() => markAllAsRead()}>Mark All Read</button>

90

<button onClick={clear}>Clear All</button>

91

</div>

92

93

<div className="notifications">

94

{notifications.map(notification => (

95

<div

96

key={notification.id}

97

className={`notification ${notification.read ? 'read' : 'unread'}`}

98

>

99

<div className="content">{notification.content}</div>

100

<div className="actions">

101

<button onClick={() => markAsRead(notification.id)}>

102

{notification.read ? 'Mark Unread' : 'Mark Read'}

103

</button>

104

<button onClick={() => remove(notification.id)}>Remove</button>

105

</div>

106

</div>

107

))}

108

</div>

109

</div>

110

);

111

}

112

```

113

114

### Adding Notifications

115

116

Add notifications to the center programmatically or from toast events.

117

118

```typescript { .api }

119

/**

120

* Add a new notification to the center

121

* @param item - The notification item to add

122

*/

123

add(item: NotificationCenterItem<T>): void;

124

```

125

126

**Manual Addition:**

127

128

```typescript

129

function MyComponent() {

130

const { add } = useNotificationCenter();

131

132

const addNotification = () => {

133

add({

134

id: Date.now().toString(),

135

content: "New notification message",

136

theme: "light",

137

type: "info",

138

read: false,

139

createdAt: Date.now(),

140

data: { source: 'manual' }

141

});

142

};

143

144

return <button onClick={addNotification}>Add Notification</button>;

145

}

146

```

147

148

**From Toast Events:**

149

150

```typescript

151

import { toast } from 'react-toastify';

152

import { useNotificationCenter } from 'react-toastify/addons/use-notification-center';

153

154

function MyComponent() {

155

const { add } = useNotificationCenter();

156

157

const showToastAndAddToCenter = () => {

158

const toastId = toast.success("Operation completed", {

159

onClose: () => {

160

// Add to notification center when toast closes

161

add({

162

id: toastId.toString(),

163

content: "Operation completed successfully",

164

type: "success",

165

read: false,

166

createdAt: Date.now()

167

});

168

}

169

});

170

};

171

172

return <button onClick={showToastAndAddToCenter}>Show Toast</button>;

173

}

174

```

175

176

### Managing Read State

177

178

Control the read/unread state of notifications individually or in bulk.

179

180

```typescript { .api }

181

/**

182

* Mark all notifications as read or unread

183

* @param read - True to mark as read, false for unread (default: true)

184

*/

185

markAllAsRead(read?: boolean): void;

186

187

/**

188

* Mark specific notifications as read or unread

189

* @param id - Single ID or array of IDs to mark

190

* @param read - True to mark as read, false for unread (default: true)

191

*/

192

markAsRead(id: Id | Id[], read?: boolean): void;

193

```

194

195

**Usage Examples:**

196

197

```typescript

198

const { markAllAsRead, markAsRead, notifications } = useNotificationCenter();

199

200

// Mark all as read

201

markAllAsRead();

202

203

// Mark all as unread

204

markAllAsRead(false);

205

206

// Mark specific notification as read

207

markAsRead('notification-1');

208

209

// Mark multiple notifications as read

210

markAsRead(['notification-1', 'notification-2']);

211

212

// Mark as unread

213

markAsRead('notification-1', false);

214

215

// Toggle read state

216

const toggleRead = (id: string) => {

217

const notification = notifications.find(n => n.id === id);

218

if (notification) {

219

markAsRead(id, !notification.read);

220

}

221

};

222

```

223

224

### Removing Notifications

225

226

Remove individual notifications or clear the entire center.

227

228

```typescript { .api }

229

/**

230

* Remove specific notifications from the center

231

* @param id - Single ID or array of IDs to remove

232

*/

233

remove(id: Id | Id[]): void;

234

235

/**

236

* Remove all notifications from the center

237

*/

238

clear(): void;

239

```

240

241

**Usage Examples:**

242

243

```typescript

244

const { remove, clear } = useNotificationCenter();

245

246

// Remove single notification

247

remove('notification-1');

248

249

// Remove multiple notifications

250

remove(['notification-1', 'notification-2']);

251

252

// Clear all notifications

253

clear();

254

255

// Remove all read notifications

256

const removeAllRead = () => {

257

const readIds = notifications

258

.filter(n => n.read)

259

.map(n => n.id);

260

remove(readIds);

261

};

262

```

263

264

### Updating Notifications

265

266

Modify existing notifications in the center.

267

268

```typescript { .api }

269

/**

270

* Update an existing notification

271

* @param id - The ID of the notification to update

272

* @param item - Partial notification item with fields to update

273

*/

274

update(id: Id, item: Partial<NotificationCenterItem<T>>): void;

275

```

276

277

**Usage Examples:**

278

279

```typescript

280

const { update } = useNotificationCenter();

281

282

// Update notification content

283

update('notification-1', {

284

content: "Updated message content",

285

read: true

286

});

287

288

// Update notification data

289

update('notification-1', {

290

data: { ...existingData, priority: 'high' }

291

});

292

293

// Update notification theme

294

update('notification-1', {

295

theme: 'dark',

296

type: 'warning'

297

});

298

```

299

300

### Finding and Sorting

301

302

Search for specific notifications and customize the display order.

303

304

```typescript { .api }

305

/**

306

* Find a notification by ID

307

* @param id - The ID to search for

308

* @returns The notification item or undefined if not found

309

*/

310

find(id: Id): NotificationCenterItem<T> | undefined;

311

312

/**

313

* Sort notifications using a custom comparator function

314

* @param compareFn - Function to determine sort order

315

*/

316

sort(compareFn: SortFn<T>): void;

317

318

type SortFn<T> = (a: NotificationCenterItem<T>, b: NotificationCenterItem<T>) => number;

319

```

320

321

**Usage Examples:**

322

323

```typescript

324

const { find, sort, notifications } = useNotificationCenter();

325

326

// Find specific notification

327

const notification = find('notification-1');

328

if (notification) {

329

console.log('Found:', notification.content);

330

}

331

332

// Sort by creation time (newest first)

333

sort((a, b) => b.createdAt - a.createdAt);

334

335

// Sort by read status (unread first)

336

sort((a, b) => {

337

if (a.read === b.read) return 0;

338

return a.read ? 1 : -1;

339

});

340

341

// Sort by type priority

342

const typePriority = { error: 0, warning: 1, info: 2, success: 3 };

343

sort((a, b) => typePriority[a.type] - typePriority[b.type]);

344

```

345

346

### Configuration Options

347

348

Initialize the notification center with custom settings and data.

349

350

```typescript { .api }

351

interface UseNotificationCenterParams<T = {}> {

352

/** Initial notifications to populate the center */

353

data?: NotificationCenterItem<T>[];

354

/** Maximum number of notifications to keep (oldest removed first) */

355

limit?: number;

356

/** Filter function to determine which notifications to include */

357

filter?: FilterFn<T>;

358

/** Sort function to order notifications */

359

sort?: SortFn<T>;

360

}

361

362

type FilterFn<T> = (notification: NotificationCenterItem<T>) => boolean;

363

type SortFn<T> = (a: NotificationCenterItem<T>, b: NotificationCenterItem<T>) => number;

364

```

365

366

**Configuration Examples:**

367

368

```typescript

369

// Initialize with data and limit

370

const { notifications } = useNotificationCenter({

371

data: [

372

{

373

id: '1',

374

content: 'Welcome notification',

375

type: 'info',

376

read: false,

377

createdAt: Date.now()

378

}

379

],

380

limit: 50,

381

filter: (notification) => !notification.read, // Only show unread

382

sort: (a, b) => b.createdAt - a.createdAt // Newest first

383

});

384

385

// Filter for important notifications only

386

const { notifications: importantNotifications } = useNotificationCenter({

387

filter: (notification) =>

388

notification.data?.priority === 'high' || notification.type === 'error'

389

});

390

```

391

392

### Integration with Toast Events

393

394

Automatically populate the notification center from toast lifecycle events.

395

396

```typescript

397

import { toast } from 'react-toastify';

398

import { useNotificationCenter } from 'react-toastify/addons/use-notification-center';

399

400

function IntegratedNotifications() {

401

const { add, notifications } = useNotificationCenter();

402

403

// Subscribe to toast events

404

React.useEffect(() => {

405

const unsubscribe = toast.onChange((payload) => {

406

if (payload.status === 'added') {

407

// Add to notification center when toast appears

408

add({

409

id: payload.id.toString(),

410

content: payload.content,

411

type: payload.type || 'default',

412

theme: payload.theme || 'light',

413

read: false,

414

createdAt: Date.now(),

415

data: payload.data

416

});

417

}

418

});

419

420

return unsubscribe;

421

}, [add]);

422

423

const showToast = () => {

424

toast.success("This will appear in both toast and notification center");

425

};

426

427

return (

428

<div>

429

<button onClick={showToast}>Show Toast</button>

430

<div>Notification Center has {notifications.length} items</div>

431

</div>

432

);

433

}

434

```

435

436

## Notification Item Type

437

438

```typescript { .api }

439

interface NotificationCenterItem<T = {}> {

440

/** Unique identifier for the notification */

441

id: Id;

442

/** Content to display (string, React node, or render function) */

443

content: ToastContent<T>;

444

/** Timestamp when notification was created */

445

createdAt: number;

446

/** Whether the notification has been read */

447

read?: boolean;

448

/** Toast type for styling and icons */

449

type?: TypeOptions;

450

/** Theme for styling */

451

theme?: Theme;

452

/** Custom data associated with the notification */

453

data?: T;

454

/** Custom icon for the notification */

455

icon?: ToastIcon;

456

}

457

```

458

459

## Advanced Patterns

460

461

### Persistent Storage

462

463

Save notification center state to localStorage:

464

465

```typescript

466

function usePersistentNotificationCenter<T>() {

467

const STORAGE_KEY = 'notification-center';

468

469

// Load initial data from storage

470

const loadInitialData = (): NotificationCenterItem<T>[] => {

471

try {

472

const stored = localStorage.getItem(STORAGE_KEY);

473

return stored ? JSON.parse(stored) : [];

474

} catch {

475

return [];

476

}

477

};

478

479

const nc = useNotificationCenter<T>({

480

data: loadInitialData()

481

});

482

483

// Save to storage whenever notifications change

484

React.useEffect(() => {

485

localStorage.setItem(STORAGE_KEY, JSON.stringify(nc.notifications));

486

}, [nc.notifications]);

487

488

return nc;

489

}

490

```

491

492

### Notification Categories

493

494

Group notifications by category:

495

496

```typescript

497

interface CategorizedNotification {

498

category: 'system' | 'user' | 'marketing';

499

priority: 'low' | 'medium' | 'high';

500

}

501

502

function CategorizedNotificationCenter() {

503

const { notifications, add } = useNotificationCenter<CategorizedNotification>();

504

505

const notificationsByCategory = React.useMemo(() => {

506

return notifications.reduce((acc, notification) => {

507

const category = notification.data?.category || 'system';

508

if (!acc[category]) acc[category] = [];

509

acc[category].push(notification);

510

return acc;

511

}, {} as Record<string, NotificationCenterItem<CategorizedNotification>[]>);

512

}, [notifications]);

513

514

return (

515

<div>

516

{Object.entries(notificationsByCategory).map(([category, items]) => (

517

<div key={category}>

518

<h4>{category} ({items.length})</h4>

519

{items.map(item => (

520

<div key={item.id}>{item.content}</div>

521

))}

522

</div>

523

))}

524

</div>

525

);

526

}

527

```