Skip to content

ENG-2678: Show warnings on disabled notices in experience config#7558

Merged
gilluminate merged 10 commits intomainfrom
gill/ENG-2678/disabled-notices-in-experience-config
Mar 5, 2026
Merged

ENG-2678: Show warnings on disabled notices in experience config#7558
gilluminate merged 10 commits intomainfrom
gill/ENG-2678/disabled-notices-in-experience-config

Conversation

@gilluminate
Copy link
Copy Markdown
Contributor

@gilluminate gilluminate commented Mar 3, 2026

Ticket ENG-2678

Description Of Changes

Adds warning indicators to privacy notices that are disabled within the experience config editor. When a notice is disabled (either at creation time or after being added to an experience), a warning icon with a tooltip appears on its row in the privacy notices list, informing the user that the notice will not display and should be enabled or removed.

Also filters disabled notices out of the experience preview so the preview accurately reflects what end users will see.

Code Changes

  • clients/admin-ui/src/features/common/ScrollableList.tsx - Adds optional getWarningTooltip prop to ScrollableList and renders a focusable warning icon with tooltip on rows where the callback returns a string
  • clients/admin-ui/src/features/privacy-experience/PrivacyExperienceForm.tsx - Wires getWarningTooltip into both the TCF and non-TCF privacy notice ScrollableList instances, returning the disabled notice tooltip message when notice.disabled is true
  • clients/admin-ui/src/features/privacy-experience/preview/helpers.ts - Filters out disabled notices from generateMockNotices so the preview only shows notices that will actually display
  • clients/admin-ui/cypress/support/ant-support.ts - Adds getAntTooltip Cypress command
  • clients/admin-ui/cypress/e2e/privacy-experience/experience-editor.cy.ts - Adds Cypress tests covering the warning icon, tooltip content, and preview filtering for disabled notices

Steps to Confirm

  1. Open an existing experience config that has one or more privacy notices attached
  2. Navigate to the Notices page and deactivate one of the notices used in that experience
  3. Return to the experience config — confirm a yellow warning icon now appears on the deactivated notice row
  4. Hover or focus the warning icon — confirm the tooltip reads "This notice is disabled and will not display. Enable it or remove it from this experience."
  5. Confirm the disabled notice does not appear in the experience preview
CleanShot 2026-03-03 at 17 25 16@2x

Pre-Merge Checklist

  • Issue requirements met
  • All CI pipelines succeeded
  • CHANGELOG.md updated
    • Add a db-migration This indicates that a change includes a database migration label to the entry if your change includes a DB migration
    • Add a high-risk This issue suggests changes that have a high-probability of breaking existing code label to the entry if your change includes a high-risk change (i.e. potential for performance impact or unexpected regression) that should be flagged
    • Updates unreleased work already in Changelog, no new entry necessary
  • UX feedback:
    • All UX related changes have been reviewed by a designer
    • No UX review needed
  • Followup issues:
    • Followup issues created
    • No followup issues
  • Database migrations:
    • No migrations
  • Documentation:
    • No documentation updates required

Summary by CodeRabbit

  • New Features

    • Per-item warning indicators with tooltips added to lists and the experience editor for disabled privacy notices.
  • Bug Fixes

    • Disabled privacy notices are excluded from experience previews.
  • Tests

    • Added tests for disabled-notice warnings and preview behavior.
    • Improved tooltip lookup in end-to-end tests.
  • Style

    • Adjusted preview styling to hide screen-reader-only preview elements.
  • Chores

    • Added changelog entry documenting the change.

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fides-plus-nightly Ready Ready Preview, Comment Mar 5, 2026 5:19pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
fides-privacy-center Ignored Ignored Mar 5, 2026 5:19pm

Request Review

gilluminate added a commit that referenced this pull request Mar 3, 2026
gilluminate added a commit that referenced this pull request Mar 3, 2026
@gilluminate gilluminate force-pushed the gill/ENG-2678/disabled-notices-in-experience-config branch from e89374d to 214d5c9 Compare March 3, 2026 23:50
@gilluminate gilluminate marked this pull request as ready for review March 4, 2026 15:56
@gilluminate gilluminate requested a review from a team as a code owner March 4, 2026 15:56
@gilluminate gilluminate requested review from speaker-ender and removed request for a team March 4, 2026 15:56
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cf05cece-283f-4bcd-bf4d-9aa1c9d6dde9

📥 Commits

Reviewing files that changed from the base of the PR and between bf77ad5 and 5b672ba.

📒 Files selected for processing (1)
  • clients/admin-ui/src/features/common/ScrollableList.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • clients/admin-ui/src/features/common/ScrollableList.tsx

📝 Walkthrough

Walkthrough

Adds warning icons and tooltips for disabled privacy notices in the Experience editor, surfaces per-item warning tooltips via ScrollableList, excludes disabled notices from preview generation, adds a Cypress tooltip helper, and includes tests covering disabled-notice scenarios.

Changes

Cohort / File(s) Summary
Changelog
changelog/7558-disabled-notice-warnings-in-experience-config.yaml
New changelog entry documenting warning indicators for disabled privacy notices (PR #7558).
Cypress Tests
clients/admin-ui/cypress/e2e/privacy-experience/experience-editor.cy.ts
Added "disabled notices" test suite with scenarios asserting warning icon presence, tooltip text, and that disabled notices are excluded from preview.
Cypress Test Selectors
clients/admin-ui/cypress/e2e/action-center/aggregate-results.cy.ts, clients/admin-ui/cypress/e2e/action-center/assets-results.cy.ts
Replaced raw selector cy.get(".ant-tooltip-inner") with helper cy.getAntTooltip() for tooltip assertions.
Cypress Support
clients/admin-ui/cypress/support/ant-support.ts
Added getAntTooltip() Cypress command and extended Cypress.Chainable type.
ScrollableList Component
clients/admin-ui/src/features/common/ScrollableList.tsx
Added `getWarningTooltip?: (item: T) => string
Privacy Experience Form
clients/admin-ui/src/features/privacy-experience/PrivacyExperienceForm.tsx
Added DISABLED_NOTICE_TOOLTIP and passed getWarningTooltip callbacks to ScrollableList usages to surface disabled-notice tooltips.
Preview Helpers
clients/admin-ui/src/features/privacy-experience/preview/helpers.ts
generateMockNotices now filters out disabled notices so previews exclude them.
Preview Styling
clients/admin-ui/src/features/privacy-experience/preview/Preview.tsx
Added CSS to hide #preview-container .fides-sr-only via display: none !important;.
Misc UI & Lint
clients/admin-ui/src/pages/poc/prompt-explorer.tsx
Suppressed ESLint for two console.error calls and simplified Card hover styling to use hoverable.

Sequence Diagram(s)

sequenceDiagram
  participant Editor as Experience Editor (UI)
  participant API as Notices API
  participant List as ScrollableList
  participant Tooltip as AntD Tooltip
  participant Preview as Preview Generator

  Editor->>API: fetch privacy notices
  API-->>Editor: notices (some disabled)
  Editor->>List: render items with getWarningTooltip(item)
  alt item.disabled == true
    List->>Tooltip: render warning icon + tooltip (DISABLED_NOTICE_TOOLTIP)
    Tooltip-->>Editor: tooltip shown on hover/focus
  end
  Editor->>Preview: request preview
  Preview->>API: generateMockNotices (filters out disabled)
  API-->>Preview: enabled notices only
  Preview-->>Editor: render preview (disabled notices excluded)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • speaker-ender
  • kruulik

Poem

🐰 A hop, a nibble, a soft warning glow,

Disabled notices now show why they go.
Tooltips murmur secrets on gentle hover,
Tests nod yes and previews quietly cover.
A tiny rabbit cheers — code ready to show!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'ENG-2678: Show warnings on disabled notices in experience config' clearly summarizes the main change—adding warning indicators to disabled privacy notices in the experience editor.
Description check ✅ Passed The PR description follows the template structure with all required sections: ticket reference, description of changes, code changes, steps to confirm, and pre-merge checklist. All critical items are addressed.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch gill/ENG-2678/disabled-notices-in-experience-config

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

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 4, 2026

Greptile Summary

This PR adds warning indicators to disabled privacy notices in the experience config editor and filters them out of the experience preview, so the preview accurately reflects what end users will see. The implementation is clean and well-scoped: a new optional getWarningTooltip prop is added to the generic ScrollableList component, wired into both the TCF and non-TCF notice lists in PrivacyExperienceForm, and the generateMockNotices helper is updated with a one-line filter.

Key changes:

  • ScrollableList.tsx — new getWarningTooltip prop renders a focusable Ant Design Tooltip with a warning icon; accessibility handled via tabIndex={0} and trigger={["hover", "focus"]}
  • PrivacyExperienceForm.tsxgetWarningTooltip wired for both TCF and non-TCF ScrollableList instances; minor: new callback lambdas use single-character parameter n instead of a full name
  • preview/helpers.ts!notice.disabled filter added to generateMockNotices; clean and correct
  • Preview.tsx — adds .fides-sr-only { display: none !important; } inside the preview block to suppress screen-reader-only markup from the visual preview
  • ant-support.ts — new getAntTooltip Cypress command using cy.findByRole("tooltip") replaces raw .ant-tooltip-inner CSS selectors across three test files; an improvement in robustness
  • Test coverage in experience-editor.cy.ts covers the warning icon, tooltip text, and preview filtering for disabled notices; the two nested describe blocks share nearly identical beforeEach setups with minor redundancy between them

Confidence Score: 4/5

  • Safe to merge with minor style fixes; no logic bugs or regressions identified
  • The feature is well-contained with clear test coverage. The only issues found are minor style violations (single-character variable names and a double-invocation pattern that matches the pre-existing getTooltip convention). No correctness bugs, security concerns, or breaking changes were found.
  • clients/admin-ui/src/features/privacy-experience/PrivacyExperienceForm.tsx — single-character variable names in the new getWarningTooltip callbacks

Important Files Changed

Filename Overview
clients/admin-ui/src/features/common/ScrollableList.tsx Adds optional getWarningTooltip prop; renders a focusable warning icon with Ant Design Tooltip on rows that return a string. The double-invocation pattern (calling the callback twice per truthy result) is a minor inefficiency consistent with the pre-existing getTooltip pattern.
clients/admin-ui/src/features/privacy-experience/PrivacyExperienceForm.tsx Wires getWarningTooltip into both the TCF and non-TCF ScrollableList instances; uses single-character variable n in the new callbacks, violating the full-name convention.
clients/admin-ui/src/features/privacy-experience/preview/helpers.ts Filters out disabled notices from generateMockNotices with a clean one-line addition to the existing filter chain; no issues found.
clients/admin-ui/src/features/privacy-experience/preview/Preview.tsx Adds .fides-sr-only { display: none !important; } CSS rule inside the preview-available block to suppress screen-reader-only markup from appearing in the visual preview; reasonable and low-risk.
clients/admin-ui/cypress/e2e/privacy-experience/experience-editor.cy.ts Adds new disabled notices describe block with coverage for warning icon, tooltip text, and preview filtering. The two nested describe blocks share almost identical beforeEach setups and the "shows a warning icon" test is nearly duplicated between them; minor consolidation opportunity.
clients/admin-ui/cypress/support/ant-support.ts Adds getAntTooltip command using cy.findByRole("tooltip") — a clean, semantically correct approach; existing tests updated to use the new command instead of the raw CSS selector.

Last reviewed commit: 663653f

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
clients/admin-ui/src/features/common/ScrollableList.tsx (1)

338-342: Avoid recomputing getWarningTooltip(item) multiple times per row.

This callback is evaluated repeatedly in render. Compute once per item and pass through.

♻️ Suggested refactor
         {values.map((item) => {
           const itemId = getItemId(item);
+          const warningTooltip = getWarningTooltip?.(item);
           return (
             <ScrollableListItem
@@
-              warningTooltip={
-                getWarningTooltip && getWarningTooltip(item)
-                  ? getWarningTooltip(item)
-                  : undefined
-              }
+              warningTooltip={warningTooltip}
             />
           );
         })}
@@
         {values.map((item) => {
           const itemId = getItemId(item);
+          const warningTooltip = getWarningTooltip?.(item);
           return (
             <ScrollableListItem
@@
-              warningTooltip={
-                getWarningTooltip && getWarningTooltip(item)
-                  ? getWarningTooltip(item)
-                  : undefined
-              }
+              warningTooltip={warningTooltip}
               maxH={maxHeight}
               rowTestId={`${baseTestId}-row-${itemId}`}
             />

Also applies to: 363-367

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/admin-ui/src/features/common/ScrollableList.tsx` around lines 338 -
342, Compute the result of getWarningTooltip(item) once per render for each row
and reuse it instead of calling getWarningTooltip(item) multiple times; e.g.,
inside the row rendering logic (where warningTooltip prop is set in
ScrollableList/its row renderer) assign const warning = getWarningTooltip ?
getWarningTooltip(item) : undefined (or null) and pass warning to warningTooltip
and any other places that currently call getWarningTooltip(item) (also update
the other occurrence around the block that corresponds to lines 363-367 to use
the same local const).
clients/admin-ui/cypress/e2e/privacy-experience/experience-editor.cy.ts (1)

469-472: Add a positive preview assertion alongside the negative check.

The current check can pass when preview content is missing for unrelated reasons. Add one known-positive assertion (e.g., modal title) before asserting disabled notice absence.

Suggested fix
         // The preview container should not contain the disabled notice's name
-        cy.get(`#${PREVIEW_CONTAINER_ID}`).should(
-          "not.contain",
-          "Example Notice",
-        );
+        cy.get(`#${PREVIEW_CONTAINER_ID}`)
+          .should("contain", "Manage your consent preferences")
+          .and("not.contain", "Example Notice");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/admin-ui/cypress/e2e/privacy-experience/experience-editor.cy.ts`
around lines 469 - 472, Add a positive assertion that the preview actually
rendered before the negative check: first assert that the preview container
identified by PREVIEW_CONTAINER_ID contains a known-positive element (for
example the modal title text used elsewhere in this spec) via
cy.get(`#${PREVIEW_CONTAINER_ID}`).should('contain', 'Expected Modal Title') (or
the actual modal title string the test uses), then keep the existing negative
assertion that it does not contain "Example Notice" so the test fails only when
the notice is present rather than when the preview is absent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@clients/admin-ui/cypress/e2e/privacy-experience/experience-editor.cy.ts`:
- Around line 416-417: Tests currently only wait for the `@getExperienceDetail`
intercept but the assertions for the warning icon and preview filtering depend
on the `@getExperienceNoticesDisabled` payload; add explicit waits for the
`@getExperienceNoticesDisabled` alias immediately after the existing
cy.wait("@getExperienceDetail") calls wherever the `@getExperienceNoticesDisabled`
intercept is set (specifically in the places that assert the warning icon and
preview filtering) so the code calls cy.wait("@getExperienceNoticesDisabled")
before those assertions.

In `@clients/admin-ui/src/features/common/ScrollableList.tsx`:
- Around line 85-97: The warning tooltip currently uses a non-interactive span
with tabIndex={0}; replace that span with a semantic button element (e.g., a
plain <button> with type="button") that acts as the Tooltip trigger, give it an
appropriate aria-label (e.g., "Warning" or a prop-driven label) and move/remove
the eslint-disable comment; keep the Tooltip wrapping and the
Icons.WarningAltFilled usage so visual/placement behavior stays the same, and
ensure any styling/classes previously on the span are applied to the button to
preserve layout.

In `@clients/admin-ui/src/features/privacy-experience/preview/Preview.tsx`:
- Around line 351-353: The global CSS rule overriding .fides-sr-only should be
scoped to the preview component only: update the style block in Preview.tsx (the
CSS that currently contains ".fides-sr-only { display: none !important; }") so
the selector targets the preview root (e.g., prepend the preview component's
wrapper class/ID such as ".privacy-preview" or the component root element) like
".privacy-preview .fides-sr-only" to avoid hiding assistive text outside the
preview panel; ensure the wrapper class you pick is the element returned by the
Preview component so the rule only applies while the preview is mounted.

---

Nitpick comments:
In `@clients/admin-ui/cypress/e2e/privacy-experience/experience-editor.cy.ts`:
- Around line 469-472: Add a positive assertion that the preview actually
rendered before the negative check: first assert that the preview container
identified by PREVIEW_CONTAINER_ID contains a known-positive element (for
example the modal title text used elsewhere in this spec) via
cy.get(`#${PREVIEW_CONTAINER_ID}`).should('contain', 'Expected Modal Title') (or
the actual modal title string the test uses), then keep the existing negative
assertion that it does not contain "Example Notice" so the test fails only when
the notice is present rather than when the preview is absent.

In `@clients/admin-ui/src/features/common/ScrollableList.tsx`:
- Around line 338-342: Compute the result of getWarningTooltip(item) once per
render for each row and reuse it instead of calling getWarningTooltip(item)
multiple times; e.g., inside the row rendering logic (where warningTooltip prop
is set in ScrollableList/its row renderer) assign const warning =
getWarningTooltip ? getWarningTooltip(item) : undefined (or null) and pass
warning to warningTooltip and any other places that currently call
getWarningTooltip(item) (also update the other occurrence around the block that
corresponds to lines 363-367 to use the same local const).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 18fff2dc-3cf2-4cc2-a471-3604e813bdcc

📥 Commits

Reviewing files that changed from the base of the PR and between 789ec53 and 663653f.

📒 Files selected for processing (10)
  • changelog/7558-disabled-notice-warnings-in-experience-config.yaml
  • clients/admin-ui/cypress/e2e/action-center/aggregate-results.cy.ts
  • clients/admin-ui/cypress/e2e/action-center/assets-results.cy.ts
  • clients/admin-ui/cypress/e2e/privacy-experience/experience-editor.cy.ts
  • clients/admin-ui/cypress/support/ant-support.ts
  • clients/admin-ui/src/features/common/ScrollableList.tsx
  • clients/admin-ui/src/features/privacy-experience/PrivacyExperienceForm.tsx
  • clients/admin-ui/src/features/privacy-experience/preview/Preview.tsx
  • clients/admin-ui/src/features/privacy-experience/preview/helpers.ts
  • clients/admin-ui/src/pages/poc/prompt-explorer.tsx

@gilluminate
Copy link
Copy Markdown
Contributor Author

Re: nitpick on positive preview assertion — good catch. Added a positive assertion that the preview contains "Manage your consent preferences" before asserting the disabled notice is absent. This ensures we're checking rendered content, not an empty container.

gilluminate and others added 8 commits March 4, 2026 13:57
Update ScrollableList.tsx
- Add aria-label to warning tooltip span for screen reader support
- Extract getTooltip/getWarningTooltip into local vars to avoid double invocation
- Rename single-char lambda param (n) to (item) in getWarningTooltip callbacks
- Add positive assertion before negative check in disabled notice preview test
- Scope .fides-sr-only CSS rule to #preview-container

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@speaker-ender speaker-ender left a comment

Choose a reason for hiding this comment

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

Approving as is.
Minor nits/comments but otherwise looks good and functions as intended.

})
.filter((notice): notice is PrivacyNoticeResponse => notice !== undefined);
.filter(
(notice): notice is PrivacyNoticeResponse =>
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.

Suggested change
(notice): notice is PrivacyNoticeResponse =>
(notice) =>

Type coercion doesn't seem necessary here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The type predicate notice is PrivacyNoticeResponse is needed here to narrow away undefined from the .map() chain above. Without it, TypeScript would keep the return type as (PrivacyNoticeResponse | undefined)[]. Happy to change if you see it differently though!


setLlmResponse(result.response_text);
} catch (error) {
// eslint-disable-next-line no-console
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.

If this is correct, should we update our eslint rules to allow console.error?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this is just in the POC so generally not acceptable but giving a pass here

- Rename tooltip to infoTooltip on ScrollableListItem for clarity
- Remove redundant || undefined from optional chaining calls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gilluminate gilluminate enabled auto-merge March 5, 2026 17:14
@gilluminate gilluminate added this pull request to the merge queue Mar 5, 2026
Merged via the queue into main with commit e7fa470 Mar 5, 2026
42 of 47 checks passed
@gilluminate gilluminate deleted the gill/ENG-2678/disabled-notices-in-experience-config branch March 5, 2026 18:11
mfbrown pushed a commit that referenced this pull request Mar 12, 2026
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants