Skip to content

CONSOLE-5361: Add toast overflow and notification drawer integration#16636

Open
galkremer1 wants to merge 1 commit into
openshift:mainfrom
galkremer1:CONSOLE-5361-add-toast-overvflow-drawer-integration
Open

CONSOLE-5361: Add toast overflow and notification drawer integration#16636
galkremer1 wants to merge 1 commit into
openshift:mainfrom
galkremer1:CONSOLE-5361-add-toast-overvflow-drawer-integration

Conversation

@galkremer1

@galkremer1 galkremer1 commented Jun 16, 2026

Copy link
Copy Markdown
Member

RFE-9430: Add toast overflow and notification drawer integration

Jira ticket: CONSOLE-5361

Analysis / Root cause:

Toast alerts were shown in an unbounded stack with no persistence beyond the on-screen toast. As plugin usage grew (e.g. long-running upload progress toasts), users could end up with many simultaneous alerts, no way to review missed notifications, and no integration with the existing notification drawer.

Related follow-ups tracked separately:

  • RFE-9432 - user preference for max visible toasts
  • RFE-9433 - minimize toast to drawer action

Solution description:

This PR integrates toast alerts with the notification drawer and caps the number of simultaneously visible toasts (default: 3).

Core behavior

  • ToastProvider maintains two states: visible on-screen toasts and notification history for the drawer.
  • When visible toasts exceed the cap, PatternFly AlertGroup shows a "View N more notification(s)" overflow link that clears the visible stack and opens the notification drawer.
  • Toast history in the drawer supports mark read/unread, clear, mark all read, and clear all (header kebab).
  • The masthead notification badge count includes unread toast notifications; badge variant reflects unread danger toasts (attention) or other unread toasts (unread).

Plugin API (ToastOptions)

Option Default Purpose
drawerGroup built-in default group Named section in the notification drawer
skipOverflow false Exclude toast from visible cap / overflow link
persistInDrawer true When false, toast is on-screen only (legacy behavior)

Constraints:

  • persistInDrawer: false implies skipOverflow: true (enforced by normalizeToastOptions) so ephemeral toasts cannot be hidden by overflow with no drawer entry.
  • The default drawer group uses an internal key (default) and is displayed as translated Other Alerts. Custom drawerGroup values are shown as-is; plugins are responsible for their own i18n.

Architecture

  • ConnectedToastProvider - wires Redux notification drawer state into ToastProvider.
  • NotificationHistoryContext / useNotificationHistory - exposes drawer history to masthead and notification drawer.
  • toastDisplayUtils - overflow cap and visibility logic.
  • toastNotificationUtils - drawer grouping helpers, default group title translation, and getNotificationsVariant.
  • ToastNotificationDrawerItems - drawer UI for toast history items (public package).
  • Bug fix: toast ID counter moved to useRef so opening the notification drawer does not reset IDs and overwrite unrelated drawer notifications.

SDK / docs

  • CHANGELOG-core.md, release-notes/4.23.md, docs/api.md, and core-api.ts JSDoc updated.

Usage examples

Default behavior - toast on screen, persisted in drawer under Other Alerts, subject to overflow cap:

import { useToast } from '@openshift-console/dynamic-plugin-sdk';

const { addToast } = useToast();

addToast({
  title: 'Success',
  variant: 'success',
  content: 'Operation completed successfully.',
});

Grouped in the notification drawer (custom section title shown as-is):

addToast({
  title: 'Upload complete',
  variant: 'success',
  content: 'disk.img uploaded successfully.',
  drawerGroup: 'Uploads',
});

Always visible on screen, still persisted in drawer (e.g. in-progress upload with Cancel action):

addToast({
  title: 'Uploading disk.img',
  variant: 'info',
  content: <UploadProgressContent />,
  dismissible: false,
  timeout: false,
  skipOverflow: true,
  drawerGroup: 'Uploads',
});

Legacy ephemeral toast - on screen only, not in drawer, never hidden by overflow:

addToast({
  title: 'Saved',
  variant: 'success',
  content: 'Settings updated.',
  persistInDrawer: false,
});

Terminal toast with cleanup when dismissed from drawer or close button:

addToast({
  title: 'Upload canceled',
  variant: 'warning',
  content: 'The upload was aborted.',
  dismissible: true,
  onClose: () => removeUpload(uploadKey),
});

Demo

These recordings use the KubeVirt plugin as a dynamic-plugin consumer of the Console toast APIs.

1. Default drawer integration

addToast({
  drawerGroup: 'Custom Drawer Group',
  persistInDrawer: true,
  skipOverflow: false,
});

What to look for:

  • Toasts appear on screen and in the notification drawer.
  • Custom drawerGroup creates a dedicated drawer section titled Custom Drawer Group (shown as-is; Console does not translate custom group names).
  • After more than 3 toasts, Console shows the overflow link; older capped toasts move off-screen but remain in the drawer.
  • The masthead notification badge reflects unread drawer history.
Screen.Recording.2026-06-16.at.9.05.17.PM.mov

2. Ephemeral / on-screen only

addToast({
  persistInDrawer: false,
  skipOverflow: false, // skipOverflow has no effect here as persistInDrawer is set to false
});

What to look for:

  • Toast is on-screen only - it does not appear in the notification drawer.
  • Console forces skipOverflow: true when persistInDrawer is false, so the toast is never hidden by the overflow cap (there is no drawer entry to recover it from).
  • Matches pre–CONSOLE-5361 behavior for short-lived messages.
Screen.Recording.2026-06-16.at.9.08.57.PM.mov

3. Always-visible + drawer-persisted (upload progress)

addToast({
  persistInDrawer: true,
  skipOverflow: true,
});

What to look for:

  • The upload toast stays on screen with a live progress bar, even when other toasts exceed the default cap of 3 (skipOverflow: true).
  • The same notification is persisted in the notification drawer with read/unread state and clear/mark-read actions (persistInDrawer: true).
  • Intended for long-running operations (e.g. CDI upload progress) where the user must keep seeing progress while other alerts may be capped.
Screen.Recording.2026-06-16.at.9.11.02.PM.mov

Test setup:

  1. Build and run Console from this branch (yarn dev in frontend/).
  2. Hard refresh the browser after core changes.
  3. Optional: load a dynamic plugin that uses useToast (e.g. KubeVirt) to exercise plugin toasts with drawerGroup, skipOverflow, and persistInDrawer.

Test cases:

  • Trigger more than 3 default toasts → only 3 visible; overflow link shows correct count.
  • Click overflow link → visible toasts cleared; notification drawer opens; all toasts appear in drawer history.
  • Mark toast read/unread from drawer kebab → unread count and masthead badge update.
  • Clear single toast from drawer → removed from drawer and visible stack; onClose invoked when clearing from drawer.
  • Clear all from drawer header kebab → all toast history cleared; onClose invoked for each.
  • Add toast with drawerGroup: 'Uploads' → appears under custom drawer section (not under Other Alerts).
  • Add toast with persistInDrawer: false → shown on screen only; not in drawer; always visible regardless of cap.
  • Add toast with skipOverflow: true → always visible on screen; still in drawer unless persistInDrawer: false.
  • Unread danger toast → masthead badge uses attention variant.
  • Unread non-danger toast → masthead badge uses unread variant.
  • Open drawer via overflow, then add/replace toasts → toast IDs remain unique (no notification overwrite).
  • Dismiss toast via close button → removed from screen and drawer; onClose invoked.

Browser conformance:

  • Chrome
  • Firefox
  • Safari (or Epiphany on Linux)

Additional info:

  • Unit tests: 26 tests in packages/console-shared/src/components/toast/ (ToastProvider, toastDisplayUtils, toastNotificationUtils, useToast).
  • English i18n strings added via en/public.json; other locales include manual Clear all entry - remaining strings via Memsource.
  • Overflow click clears the visible toast stack without invoking toast onClose callbacks; consumers with long-lived toasts should use skipOverflow / persistInDrawer appropriately or handle lifecycle via onClose.

Reviewers and assignees

Summary by CodeRabbit

  • New Features
    • Toast notifications now appear in the notification drawer with read/unread tracking and management actions.
    • Added a visible toast cap (default 3) with an overflow “View more notification(s)” link.
    • Added ToastOptions support for drawerGroup, skipOverflow, and persistInDrawer, plus per-notification drawer actions (mark read/unread, clear).
    • Notification drawer and masthead badge now include toast unread counts alongside existing alerts.
  • Documentation
    • Updated API docs and release notes, including i18n labels for drawer actions and overflow text.
  • Tests
    • Expanded coverage for overflow capping, grouping, drawer/history behavior, and skipOverflow/persistInDrawer combinations.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jun 16, 2026
@openshift-ci-robot

openshift-ci-robot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

@galkremer1: This pull request references CONSOLE-5361 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

RFE-9430: Add toast overflow and notification drawer integration

Jira ticket: CONSOLE-5361

Analysis / Root cause:

Toast alerts were shown in an unbounded stack with no persistence beyond the on-screen toast. As plugin usage grew (e.g. long-running upload progress toasts), users could end up with many simultaneous alerts, no way to review missed notifications, and no integration with the existing notification drawer.

Related follow-ups tracked separately:

  • RFE-9432 — user preference for max visible toasts
  • RFE-9433 — minimize toast to drawer action

Solution description:

This PR integrates toast alerts with the notification drawer and caps the number of simultaneously visible toasts (default: 3).

Core behavior

  • ToastProvider maintains two states: visible on-screen toasts and notification history for the drawer.
  • When visible toasts exceed the cap, PatternFly AlertGroup shows a "View N more notification(s)" overflow link that clears the visible stack and opens the notification drawer.
  • Toast history in the drawer supports mark read/unread, clear, mark all read, and clear all (header kebab).
  • The masthead notification badge count includes unread toast notifications; badge variant reflects unread danger toasts (attention) or other unread toasts (unread).

Plugin API (ToastOptions)

Option Default Purpose
drawerGroup built-in default group Named section in the notification drawer
skipOverflow false Exclude toast from visible cap / overflow link
persistInDrawer true When false, toast is on-screen only (legacy behavior)

Constraints:

  • persistInDrawer: false implies skipOverflow: true (enforced by normalizeToastOptions) so ephemeral toasts cannot be hidden by overflow with no drawer entry.
  • The default drawer group uses an internal key (default) and is displayed as translated Other Alerts. Custom drawerGroup values are shown as-is; plugins are responsible for their own i18n.

Architecture

  • ConnectedToastProvider — wires Redux notification drawer state into ToastProvider.
  • NotificationHistoryContext / useNotificationHistory — exposes drawer history to masthead and notification drawer.
  • toastDisplayUtils — overflow cap and visibility logic.
  • toastNotificationUtils — drawer grouping helpers, default group title translation, and getNotificationsVariant.
  • ToastNotificationDrawerItems — drawer UI for toast history items (public package).
  • Bug fix: toast ID counter moved to useRef so opening the notification drawer does not reset IDs and overwrite unrelated drawer notifications.

SDK / docs

  • CHANGELOG-core.md, release-notes/4.23.md, docs/api.md, and core-api.ts JSDoc updated.

Usage examples

Default behavior — toast on screen, persisted in drawer under Other Alerts, subject to overflow cap:

import { useToast } from '@openshift-console/dynamic-plugin-sdk';

const { addToast } = useToast();

addToast({
 title: 'Success',
 variant: 'success',
 content: 'Operation completed successfully.',
});

Grouped in the notification drawer (custom section title shown as-is):

addToast({
 title: 'Upload complete',
 variant: 'success',
 content: 'disk.img uploaded successfully.',
 drawerGroup: 'Uploads',
});

Always visible on screen, still persisted in drawer (e.g. in-progress upload with Cancel action):

addToast({
 title: 'Uploading disk.img',
 variant: 'info',
 content: <UploadProgressContent />,
 dismissible: false,
 timeout: false,
 skipOverflow: true,
 drawerGroup: 'Uploads',
});

Legacy ephemeral toast — on screen only, not in drawer, never hidden by overflow:

addToast({
 title: 'Saved',
 variant: 'success',
 content: 'Settings updated.',
 persistInDrawer: false,
});

Terminal toast with cleanup when dismissed from drawer or close button:

addToast({
 title: 'Upload canceled',
 variant: 'warning',
 content: 'The upload was aborted.',
 dismissible: true,
 onClose: () => removeUpload(uploadKey),
});

Screenshots / screen recording:

  • Before: unbounded toast stack with no overflow link
  • After: max 3 visible toasts + "View N more notification(s)" link
  • Notification drawer with toast history (read/unread, clear, grouped sections)
  • Masthead badge reflecting toast unread count and danger variant

Test setup:

  1. Build and run Console from this branch (yarn dev in frontend/).
  2. Hard refresh the browser after core changes.
  3. Optional: load a dynamic plugin that uses useToast (e.g. KubeVirt) to exercise plugin toasts with drawerGroup, skipOverflow, and persistInDrawer.

Test cases:

  • Trigger more than 3 default toasts → only 3 visible; overflow link shows correct count.
  • Click overflow link → visible toasts cleared; notification drawer opens; all toasts appear in drawer history.
  • Mark toast read/unread from drawer kebab → unread count and masthead badge update.
  • Clear single toast from drawer → removed from drawer and visible stack; onClose invoked when clearing from drawer.
  • Clear all from drawer header kebab → all toast history cleared; onClose invoked for each.
  • Add toast with drawerGroup: 'Uploads' → appears under custom drawer section (not under Other Alerts).
  • Add toast with persistInDrawer: false → shown on screen only; not in drawer; always visible regardless of cap.
  • Add toast with skipOverflow: true → always visible on screen; still in drawer unless persistInDrawer: false.
  • Unread danger toast → masthead badge uses attention variant.
  • Unread non-danger toast → masthead badge uses unread variant.
  • Open drawer via overflow, then add/replace toasts → toast IDs remain unique (no notification overwrite).
  • Dismiss toast via close button → removed from screen and drawer; onClose invoked.
  • Run unit tests: yarn test packages/console-shared/src/components/toast

Browser conformance:

  • Chrome
  • Firefox
  • Safari (or Epiphany on Linux)

Additional info:

  • Unit tests: 26 tests in packages/console-shared/src/components/toast/ (ToastProvider, toastDisplayUtils, toastNotificationUtils, useToast).
  • English i18n strings added via en/public.json; other locales include manual Clear all entry — remaining strings via Memsource.
  • Overflow click clears the visible toast stack without invoking toast onClose callbacks; consumers with long-lived toasts should use skipOverflow / persistInDrawer appropriately or handle lifecycle via onClose.

Reviewers and assignees

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 16, 2026
@openshift-ci openshift-ci Bot requested review from cajieh and rhamilto June 16, 2026 20:56
@openshift-ci openshift-ci Bot added the component/core Related to console core functionality label Jun 16, 2026
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Extends ToastOptions with drawerGroup, skipOverflow, and persistInDrawer fields, adds a NotificationHistoryContext and utility modules for overflow capping and notification grouping, rewrites ToastProvider to maintain a capped notification history, introduces ConnectedToastProvider to bridge Redux drawer state, and integrates toast history into the notification drawer and masthead badge.

Changes

Toast Notification History & Drawer Integration

Layer / File(s) Summary
SDK Type Contract & Documentation
frontend/packages/console-dynamic-plugin-sdk/src/extensions/console-types.ts, frontend/packages/console-dynamic-plugin-sdk/src/api/core-api.ts, frontend/packages/console-dynamic-plugin-sdk/docs/api.md, frontend/packages/console-dynamic-plugin-sdk/CHANGELOG-core.md, frontend/packages/console-dynamic-plugin-sdk/release-notes/4.23.md
ToastOptions gains optional drawerGroup, skipOverflow, and persistInDrawer fields with inline documentation; useToast examples and SDK docs/changelog are updated to document the new fields, defaults, and interaction semantics.
Shared Toast Types, Context & Hook
frontend/packages/console-shared/src/components/toast/types.ts, frontend/packages/console-shared/src/components/toast/NotificationHistoryContext.tsx, frontend/packages/console-shared/src/components/toast/useNotificationHistory.ts
Defines ToastNotification, NotificationHistoryContextValues, and default constants; exports NotificationHistoryContext and the useNotificationHistory hook for accessing notification history from components.
Toast Display & Notification Grouping Utilities
frontend/packages/console-shared/src/components/toast/toastDisplayUtils.ts, frontend/packages/console-shared/src/components/toast/toastNotificationUtils.ts, frontend/packages/console-shared/src/components/toast/__tests__/toastDisplayUtils.spec.ts, frontend/packages/console-shared/src/components/toast/__tests__/toastNotificationUtils.spec.ts
Adds normalizeToastOptions, getVisibleToasts, getOverflowCount for overflow capping, and grouping/badge helpers (groupToastNotifications, getNotificationsVariant, etc.), with full unit test coverage validating overflow capping, ephemeral/skipOverflow semantics, and edge cases.
Enhanced ToastProvider: Notification History & Overflow
frontend/packages/console-shared/src/components/toast/ToastProvider.tsx, frontend/packages/console-shared/src/components/toast/__tests__/ToastProvider.spec.tsx
Rewrites ToastProvider to maintain a history list, normalize and ID-stamp toasts, compute unread/danger/overflow state, expose it via NotificationHistoryContext, and render overflow messaging. Props extended with isNotificationDrawerExpanded, maxDisplayed, and onNotificationDrawerOpen callback. Tests cover overflow capping, ephemeral/skipOverflow semantics, drawer suppression, history clearing, and ID continuity.
Toast Notification Drawer Item Component
frontend/public/components/ToastNotificationDrawerItems.tsx
Renders ToastNotification entries as NotificationDrawerListItem elements with per-item ellipsis dropdowns for mark-read/unread and clear, variant mapping, ISO timestamps, and translated labels.
Redux Connection & App Root Wiring
frontend/public/components/toast/ConnectedToastProvider.tsx, frontend/public/components/app.tsx
Adds ConnectedToastProvider selecting UI.notifications.isExpanded and dispatching notificationDrawerToggleExpanded; app.tsx replaces ToastProvider with it at the render root to inject Redux drawer state.
NotificationDrawer Integration
frontend/public/components/notification-drawer.tsx
Integrates toast history via useNotificationHistory, renders ToastNotificationDrawerItems in "Other Alerts" and custom groups, and adds header "Mark all read"/"Clear all" actions with unread count display.
Masthead Badge Integration
frontend/public/components/masthead/masthead-toolbar.tsx
Combines alert count with toast unread count and derives badge variant via getNotificationsVariant to unify notification state display across alert and toast sources.
Internationalization: UI Strings & Translations
frontend/public/locales/en/public.json, frontend/public/locales/es/public.json, frontend/public/locales/fr/public.json, frontend/public/locales/ja/public.json, frontend/public/locales/ko/public.json, frontend/public/locales/zh/public.json
Adds/reorganizes English keys for drawer action labels, per-notification actions, pluralized overflow link text, and parameterized notification-group label. Adds "Clear all" translations across five non-English locales.

Sequence Diagram(s)

sequenceDiagram
  participant Plugin as Plugin / App Code
  participant ConnectedToastProvider
  participant ToastProvider
  participant History as Notification History
  participant Drawer as NotificationDrawer
  participant Masthead as Masthead Badge

  Plugin->>ToastProvider: addToast({ content, drawerGroup, persistInDrawer })
  ToastProvider->>ToastProvider: normalizeToastOptions, assign id/timestamp
  alt persistInDrawer !== false
    ToastProvider->>History: push ToastNotification
  end
  alt isNotificationDrawerExpanded
    ToastProvider->>ToastProvider: skip visible rendering
  else
    ToastProvider->>ToastProvider: add to visible toasts
    ToastProvider->>ToastProvider: compute getVisibleToasts(maxDisplayed)
  end
  ToastProvider-->>Plugin: render AlertGroup ± overflow link

  Masthead->>History: useNotificationHistory
  Masthead->>Masthead: unreadCount, hasUnreadDangerNotifications
  Masthead->>Masthead: notificationCount = alertCount + toastUnreadCount
  Masthead->>Masthead: getNotificationsVariant → badge variant

  Drawer->>History: useNotificationHistory
  Drawer->>Drawer: groupToastNotifications
  Drawer->>Drawer: render ToastNotificationDrawerItems per group
  Drawer->>Drawer: header: unread count + "Mark all read"/"Clear all"

  Plugin->>ConnectedToastProvider: drawerToggle
  ConnectedToastProvider->>ConnectedToastProvider: notificationDrawerToggleExpanded
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

docs-approved, jira/valid-bug

Suggested reviewers

  • jhadvig
  • cajieh
  • jgbernalp
🚥 Pre-merge checks | ✅ 15
✅ Passed checks (15 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and specifically describes the main change: adding toast overflow handling and notification drawer integration as indicated by CONSOLE-5361.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed No Ginkgo tests found in the PR; only Jest tests in TypeScript/JavaScript. All 28 test names are static, deterministic, and contain no dynamic identifiers, timestamps, or generated values.
Test Structure And Quality ✅ Passed This PR contains no Ginkgo test code. All test files are Jest-based TypeScript/React tests (.spec.ts/.spec.tsx), not Go Ginkgo tests. The check is not applicable.
Microshift Test Compatibility ✅ Passed This PR contains no Ginkgo e2e tests—only frontend TypeScript/React components and Jest unit tests. The check is not applicable.
Single Node Openshift (Sno) Test Compatibility ✅ Passed PR contains no Ginkgo e2e tests; only Jest React/TypeScript unit tests. Custom check for SNO e2e test compatibility is not applicable.
Topology-Aware Scheduling Compatibility ✅ Passed This is a frontend console UI PR (React/TypeScript components and localization) that does not introduce deployment manifests, operator code, controllers, or Kubernetes scheduling constraints. The t...
Ote Binary Stdout Contract ✅ Passed OTE Binary Stdout Contract check is inapplicable: PR modifies only frontend TypeScript/React code (toast UI, notifications drawer), contains zero Go code, and no OTE binary/test runner artifacts.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed This PR contains only frontend UI changes (React/TypeScript) with Jest unit tests. No Ginkgo e2e tests are added; the check does not apply to this PR.
No-Weak-Crypto ✅ Passed PR contains no weak cryptography usage. All changes are UI/state management code for toast notifications with no cryptographic imports, algorithms, or secret comparisons.
Container-Privileges ✅ Passed No container or Kubernetes manifests present in PR. All changes are frontend TypeScript/React components, localization JSON, and documentation—no container privilege configurations to assess.
No-Sensitive-Data-In-Logs ✅ Passed No logging statements exposing sensitive data found in newly added toast/notification code. All new toast-related files (NotificationHistoryContext, toastDisplayUtils, toastNotificationUtils, types...
Description check ✅ Passed The pull request description is comprehensive and follows the required template structure with all essential sections completed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci openshift-ci Bot added component/sdk Related to console-plugin-sdk component/shared Related to console-shared kind/i18n Indicates issue or PR relates to internationalization or has content that needs to be translated plugin-api-changed Categorizes a PR as containing plugin API changes labels Jun 16, 2026
@galkremer1 galkremer1 force-pushed the CONSOLE-5361-add-toast-overvflow-drawer-integration branch from ffd43a2 to 8779e3c Compare June 16, 2026 21:05
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 16, 2026
@openshift-ci

openshift-ci Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: galkremer1
Once this PR has been reviewed and has the lgtm label, please ask for approval from jhadvig. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (1)
frontend/packages/console-shared/src/components/toast/NotificationHistoryContext.tsx (1)

4-6: Consider using a null default with a clear error check in the hook.

createContext({} as NotificationHistoryContextValues) allows the hook to silently return an empty object if called outside a provider, deferring failures to undefined callback access. While all current consumers are properly nested under ToastProvider (via ConnectedToastProvider in app.tsx), change the default to null and add a validation check in useNotificationHistory to fail fast with a helpful error message if the hook is ever called outside the provider context.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/packages/console-shared/src/components/toast/NotificationHistoryContext.tsx`
around lines 4 - 6, The default value for NotificationHistoryContext is
currently an empty object cast as the type, which silently returns an empty
object if the useNotificationHistory hook is called outside the provider
context, deferring failures until undefined callback access. Change the default
value in createContext from {} to null, then add a validation check at the
beginning of the useNotificationHistory hook that verifies the context value is
not null and throws a clear error message if the hook is called outside the
NotificationHistoryContext provider.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/packages/console-dynamic-plugin-sdk/release-notes/4.23.md`:
- Line 63: The markdown heading "#### Example: grouping toasts in the
notification drawer" skips a level after the "## Changes to shared modules and
API" header, violating the markdownlint heading-increment rule. Change the
four-hash heading (####) to a three-hash heading (###) to maintain proper
heading hierarchy, going from level 2 to level 3 instead of skipping to level 4.

In `@frontend/packages/console-shared/src/components/toast/toastDisplayUtils.ts`:
- Around line 23-26: The slice operation on getCappedToasts(toasts) in the
visibleCappedIds calculation does not clamp the maxDisplayed parameter before
use, causing negative values to produce unexpected slice behavior (JavaScript
slice returns all-but-last items for negative indices) which is inconsistent
with the overflow logic elsewhere that treats maxDisplayed <= 0 as 0. Clamp
maxDisplayed to a non-negative value using Math.max(0, maxDisplayed) before
passing it to the slice operation to ensure consistent behavior across all uses
of maxDisplayed in this function.

In `@frontend/packages/console-shared/src/components/toast/ToastProvider.tsx`:
- Around line 209-216: The AlertGroup component at line 209 is currently only
gated by the toasts.length condition, allowing toasts to remain visible even
when the notification drawer is expanded. Modify the condition that wraps the
AlertGroup rendering to additionally check whether the notification drawer is
open/expanded, and only render the AlertGroup when both conditions are met:
toasts exist AND the drawer is not expanded. This will hide the toasts when the
drawer is opened, maintaining the intended drawer-suppressed behavior.

In `@frontend/public/components/ToastNotificationDrawerItems.tsx`:
- Around line 1-2: Replace all usages of `React.Ref` with the directly imported
`Ref` type to comply with TypeScript's `allowUmdGlobalAccess=false`
configuration. In frontend/public/components/ToastNotificationDrawerItems.tsx
(lines 1-2), add `Ref` to the import statement from `react`, then at line 65
replace `React.Ref` with `Ref`. In
frontend/public/components/notification-drawer.tsx (line 543), replace the usage
of `React.Ref` with `Ref` which is already imported in that file's imports
section.

In `@frontend/public/locales/en/public.json`:
- Around line 1796-1797: The "View {{count}} more notification(s)_one" key uses
"notification(s)" which creates awkward user-visible copy for the singular form.
Replace "(s)" with nothing in the message for the _one form so it reads "View
{{count}} more notification" (singular only), while keeping the _other form as
"View {{count}} more notifications" (plural).

In `@frontend/public/locales/es/public.json`:
- Line 1130: The Spanish locale file is missing translations for several new
notification-drawer feature keys that were added to English. In the
es/public.json file, add Spanish translations for all the missing
notification-drawer keys including "Notification drawer actions", "Mark all
read", "Notification actions", "Mark as read", "Mark as unread", and any other
overflow or action-related text introduced by this feature. Ensure each new key
has a corresponding Spanish value entry matching the structure of the existing
"Clear all" entry. After adding all translations, run yarn i18n as per the
frontend i18n update guidelines and commit the updated locale file alongside the
code changes.

---

Nitpick comments:
In
`@frontend/packages/console-shared/src/components/toast/NotificationHistoryContext.tsx`:
- Around line 4-6: The default value for NotificationHistoryContext is currently
an empty object cast as the type, which silently returns an empty object if the
useNotificationHistory hook is called outside the provider context, deferring
failures until undefined callback access. Change the default value in
createContext from {} to null, then add a validation check at the beginning of
the useNotificationHistory hook that verifies the context value is not null and
throws a clear error message if the hook is called outside the
NotificationHistoryContext provider.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9749499f-1680-497d-b6a8-349c9cea4645

📥 Commits

Reviewing files that changed from the base of the PR and between 376c8a8 and ffd43a2.

📒 Files selected for processing (25)
  • frontend/packages/console-dynamic-plugin-sdk/CHANGELOG-core.md
  • frontend/packages/console-dynamic-plugin-sdk/docs/api.md
  • frontend/packages/console-dynamic-plugin-sdk/release-notes/4.23.md
  • frontend/packages/console-dynamic-plugin-sdk/src/api/core-api.ts
  • frontend/packages/console-dynamic-plugin-sdk/src/extensions/console-types.ts
  • frontend/packages/console-shared/src/components/toast/NotificationHistoryContext.tsx
  • frontend/packages/console-shared/src/components/toast/ToastProvider.tsx
  • frontend/packages/console-shared/src/components/toast/__tests__/ToastProvider.spec.tsx
  • frontend/packages/console-shared/src/components/toast/__tests__/toastDisplayUtils.spec.ts
  • frontend/packages/console-shared/src/components/toast/__tests__/toastNotificationUtils.spec.ts
  • frontend/packages/console-shared/src/components/toast/toastDisplayUtils.ts
  • frontend/packages/console-shared/src/components/toast/toastNotificationUtils.ts
  • frontend/packages/console-shared/src/components/toast/types.ts
  • frontend/packages/console-shared/src/components/toast/useNotificationHistory.ts
  • frontend/public/components/ToastNotificationDrawerItems.tsx
  • frontend/public/components/app.tsx
  • frontend/public/components/masthead/masthead-toolbar.tsx
  • frontend/public/components/notification-drawer.tsx
  • frontend/public/components/toast/ConnectedToastProvider.tsx
  • frontend/public/locales/en/public.json
  • frontend/public/locales/es/public.json
  • frontend/public/locales/fr/public.json
  • frontend/public/locales/ja/public.json
  • frontend/public/locales/ko/public.json
  • frontend/public/locales/zh/public.json

Comment thread frontend/packages/console-dynamic-plugin-sdk/release-notes/4.23.md Outdated
Comment thread frontend/packages/console-shared/src/components/toast/ToastProvider.tsx Outdated
Comment thread frontend/public/components/ToastNotificationDrawerItems.tsx Outdated
Comment thread frontend/public/locales/en/public.json Outdated
Comment thread frontend/public/locales/es/public.json

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
frontend/packages/console-shared/src/components/toast/toastDisplayUtils.ts (1)

23-26: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clamp maxDisplayed once and reuse it in both visibility and overflow calculations.

Line 25 uses raw maxDisplayed in slice, but Line 39 treats non-positive values as 0. With negative values, visibility and overflow diverge.

Proposed fix
 export const getVisibleToasts = (
   toasts: (ToastOptions & { id: string })[],
   maxDisplayed: number,
 ): (ToastOptions & { id: string })[] => {
+  const limit = Math.max(0, maxDisplayed);
   const visibleCappedIds = new Set(
     getCappedToasts(toasts)
-      .slice(0, maxDisplayed)
+      .slice(0, limit)
       .map((toast) => toast.id),
   );
@@
 export const getOverflowCount = (
   toasts: (ToastOptions & { id: string })[],
   maxDisplayed: number,
 ): number => {
+  const limit = Math.max(0, maxDisplayed);
   const cappedLength = getCappedToasts(toasts).length;
-  return maxDisplayed > 0 ? Math.max(0, cappedLength - maxDisplayed) : 0;
+  return Math.max(0, cappedLength - limit);
 };

Also applies to: 39-39

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/packages/console-shared/src/components/toast/toastDisplayUtils.ts`
around lines 23 - 26, The maxDisplayed parameter is used inconsistently across
visibility and overflow calculations: at line 25 in the slice() call within the
visibility calculation, it's used as-is, but at line 39 it's treated as having a
minimum value of 0. To fix this divergence, clamp maxDisplayed to a non-negative
value once at the beginning of the function (e.g., const clampedMaxDisplayed =
Math.max(0, maxDisplayed)), then replace the raw maxDisplayed reference in both
the slice() call around line 25 and the overflow calculation around line 39 with
the clamped variable to ensure consistent behavior regardless of the input
value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@frontend/packages/console-shared/src/components/toast/toastDisplayUtils.ts`:
- Around line 23-26: The maxDisplayed parameter is used inconsistently across
visibility and overflow calculations: at line 25 in the slice() call within the
visibility calculation, it's used as-is, but at line 39 it's treated as having a
minimum value of 0. To fix this divergence, clamp maxDisplayed to a non-negative
value once at the beginning of the function (e.g., const clampedMaxDisplayed =
Math.max(0, maxDisplayed)), then replace the raw maxDisplayed reference in both
the slice() call around line 25 and the overflow calculation around line 39 with
the clamped variable to ensure consistent behavior regardless of the input
value.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0d430aa7-2c0e-4f25-b084-47d5bd257de4

📥 Commits

Reviewing files that changed from the base of the PR and between ffd43a2 and 8779e3c.

📒 Files selected for processing (14)
  • frontend/packages/console-dynamic-plugin-sdk/CHANGELOG-core.md
  • frontend/packages/console-dynamic-plugin-sdk/docs/api.md
  • frontend/packages/console-dynamic-plugin-sdk/release-notes/4.23.md
  • frontend/packages/console-dynamic-plugin-sdk/src/api/core-api.ts
  • frontend/packages/console-dynamic-plugin-sdk/src/extensions/console-types.ts
  • frontend/packages/console-shared/src/components/toast/NotificationHistoryContext.tsx
  • frontend/packages/console-shared/src/components/toast/ToastProvider.tsx
  • frontend/packages/console-shared/src/components/toast/__tests__/ToastProvider.spec.tsx
  • frontend/packages/console-shared/src/components/toast/__tests__/toastDisplayUtils.spec.ts
  • frontend/packages/console-shared/src/components/toast/__tests__/toastNotificationUtils.spec.ts
  • frontend/packages/console-shared/src/components/toast/toastDisplayUtils.ts
  • frontend/packages/console-shared/src/components/toast/toastNotificationUtils.ts
  • frontend/packages/console-shared/src/components/toast/types.ts
  • frontend/packages/console-shared/src/components/toast/useNotificationHistory.ts
✅ Files skipped from review due to trivial changes (4)
  • frontend/packages/console-shared/src/components/toast/useNotificationHistory.ts
  • frontend/packages/console-dynamic-plugin-sdk/src/api/core-api.ts
  • frontend/packages/console-shared/src/components/toast/NotificationHistoryContext.tsx
  • frontend/packages/console-dynamic-plugin-sdk/docs/api.md
🚧 Files skipped from review as they are similar to previous changes (7)
  • frontend/packages/console-shared/src/components/toast/types.ts
  • frontend/packages/console-shared/src/components/toast/tests/toastNotificationUtils.spec.ts
  • frontend/packages/console-dynamic-plugin-sdk/src/extensions/console-types.ts
  • frontend/packages/console-shared/src/components/toast/tests/toastDisplayUtils.spec.ts
  • frontend/packages/console-shared/src/components/toast/toastNotificationUtils.ts
  • frontend/packages/console-shared/src/components/toast/ToastProvider.tsx
  • frontend/packages/console-shared/src/components/toast/tests/ToastProvider.spec.tsx

@galkremer1 galkremer1 force-pushed the CONSOLE-5361-add-toast-overvflow-drawer-integration branch from c17fe1a to 7b0573b Compare June 16, 2026 22:53
@galkremer1 galkremer1 force-pushed the CONSOLE-5361-add-toast-overvflow-drawer-integration branch from 7b0573b to dcf1921 Compare June 17, 2026 00:44
@openshift-ci

openshift-ci Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

@galkremer1: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-gcp-console dcf1921 link true /test e2e-gcp-console
ci/prow/frontend dcf1921 link true /test frontend

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 18, 2026
@openshift-ci

openshift-ci Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

PR needs rebase.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/core Related to console core functionality component/sdk Related to console-plugin-sdk component/shared Related to console-shared jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. kind/i18n Indicates issue or PR relates to internationalization or has content that needs to be translated needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. plugin-api-changed Categorizes a PR as containing plugin API changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants