Skip to content

fix(audit-sprint-7b): consolidate 3 in-house toasts onto sonner - #176

Closed
ejay-dev wants to merge 1 commit into
fix/audit-sprint-4c-modal-primitivesfrom
fix/audit-sprint-7b-toast-consolidation
Closed

fix(audit-sprint-7b): consolidate 3 in-house toasts onto sonner#176
ejay-dev wants to merge 1 commit into
fix/audit-sprint-4c-modal-primitivesfrom
fix/audit-sprint-7b-toast-consolidation

Conversation

@ejay-dev

Copy link
Copy Markdown
Owner

Summary

Modal-audit agent found 4 hand-rolled toast implementations. This PR consolidates 3 onto the shared sonner Toaster from Sprint 4c. Net -325 LoC. The 4th has no consumers and is left in place.

Base branch: fix/audit-sprint-4c-modal-primitives (PR #167).

Migrated

File Before After Notes
notification-toast.tsx 128 LoC, hand-rolled portal + queue + ToastItem 71 LoC, returns null Realtime Supabase subscription preserved (the actual job). Click-to-route via sonner action prop.
ComplianceToastAlerts.tsx 237 LoC 95 LoC 30s polling preserved. Critical triggers → toast.error; others → toast.warning.
compliance-toast.tsx 237 LoC custom renderer 97 LoC sonner shim Public API preserveduseComplianceToast(), ComplianceToastProvider, ComplianceToastData unchanged. Callers (use-compliance-action.tsx) don't need to change.

Out of scope

What we lose

  • Hand-rolled animations + per-node color badges (off-brand cyan/teal/violet per the stored enterprise-aesthetic preference). Sonner default is neutral dark which matches the new primitive style.

What we keep

  • Realtime subscription + polling logic (the real work)
  • All call-site contracts
  • ComplianceToastData typed surface for graph events
  • Click-through routing for notification toasts

Validation

  • npm run type-check clean
  • npm run lint 0 errors, 18 warnings (baseline)
  • npx jest 5319/5334 pass (no test changes)

Test plan

  • Insert a critical-priority notification row → toast appears bottom-right with "View" action that routes
  • Trigger a control_failed automation → red toast with title + description
  • In a React component: useComplianceToast().showToast({ type:'success', title:'X', nodeType:'policy', nodeAction:'created' }) → green toast with "policy created" description

🤖 Generated with Claude Code

Modal-audit agent found 4 hand-rolled toast implementations across the
codebase. This PR migrates 3 of them to the shared sonner Toaster
(Sprint 4c). The 4th (motion/InteractionFeedback.ToastItem) has no
external consumers and is left in place for separate cleanup.

Each migration preserves the component's call-site contract — only the
internals change. Visual unification is the win: same neutral default
surface across notifications, automation alerts, and compliance graph
events. Off-brand cyan/teal/violet badges go away (matches stored
"enterprise aesthetic" preference).

Migrated
  - components/notifications/notification-toast.tsx (-60 LoC):
    Realtime Supabase subscription stays (the actual job of the
    component). Hand-rolled portal + queue + ToastItem render replaced
    with toast.error / toast.warning. Click-to-route preserved via
    sonner's action prop. Component now returns null; mount in
    app/app/layout.tsx unchanged.
  - components/automation/ComplianceToastAlerts.tsx (-140 LoC):
    30-second polling against getAutomationHistory() stays. ToastItem
    renderer + dismiss button + slide-in animation deleted. Critical
    triggers (control_failed, risk_score_change) → toast.error;
    others → toast.warning. Same returns-null pattern.
  - components/compliance-system/compliance-toast.tsx (-150 LoC):
    Trickier — this one has external consumers via the
    useComplianceToast() hook in use-compliance-action.tsx. Preserves
    the full public API (ComplianceToastData type, showToast,
    dismissToast). Provider becomes a passthrough; internally
    showToast maps to sonner's typed variants and builds a short
    description from message/nodeType/nodeAction/impactArea/impactDelta.
    No caller changes needed.

Out of scope
  - components/motion/InteractionFeedback.tsx ToastItem export
    (~30 lines of a 437-line utility module). Zero external consumers
    of ToastItem found via grep — left in place. Can be a one-line
    re-export removal later.

Built on top of fix/audit-sprint-4c-modal-primitives (PR #167) for the
shared Toaster.

Validation
  - tsc -p tsconfig.typecheck.json: clean
  - eslint: 0 errors, 18 warnings (baseline)
  - jest: 5319/5334 pass (no test changes)

Test plan
  - Send a critical notification → top-right red sonner toast with
    title + body + View action that routes to data.href
  - Trigger a control_failed automation → bottom-right red toast
  - Call useComplianceToast().showToast({ type:'success', title:'x',
    nodeType:'policy', nodeAction:'created' }) from a React component
    → green toast with description "policy created"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 23, 2026 16:14
@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2452a631-f078-461f-ac49-3d3dd2fc0072

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/audit-sprint-7b-toast-consolidation

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

@vercel

vercel Bot commented May 23, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
forma-os Error Error May 23, 2026 4:17pm

Request Review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR consolidates three in-house toast implementations onto the shared sonner Toaster that’s mounted at the app root, keeping the underlying notification/polling/subscription “work” while removing custom portal/queue/rendering code.

Changes:

  • NotificationToast now only subscribes to Supabase realtime inserts and emits sonner toasts (no local queue/UI).
  • ComplianceToastAlerts keeps 30s polling of automation history but emits sonner toasts (no portal/UI).
  • compliance-toast is refactored into a thin shim over sonner while preserving the hook/provider/data API shape.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
components/notifications/notification-toast.tsx Replaces hand-rolled notification toast rendering/queue with sonner toasts triggered from the realtime subscription.
components/compliance-system/compliance-toast.tsx Replaces custom compliance toast renderer/provider with a sonner-backed shim for useComplianceToast() / provider usage.
components/automation/ComplianceToastAlerts.tsx Replaces custom polling toast UI with sonner toasts while preserving the polling behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +67 to +75
async function checkForNewAlerts() {
if (cancelled) return;
try {
const history = await getAutomationHistory(5);
if (!Array.isArray(history) || history.length === 0) return;

const latest = history[0];
if (latest.id === lastSeenIdRef.current) return;
lastSeenIdRef.current = latest.id;
</div>
</ToastContext.Provider>
);
}
Comment on lines +88 to +92
variant(data.title, {
id: data.id,
description,
duration: data.duration,
});
}
if (data.impactArea && typeof data.impactDelta === "number") {
const sign = data.impactDelta > 0 ? "+" : "";
parts.push(`${data.impactArea}: ${sign}${data.impactDelta}`);

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2e29629649

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

</div>
</ToastContext.Provider>
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Restore removed ComplianceToast export from module

This refactor removed the ComplianceToast named export, but components/compliance-system/index.ts still re-exports it (export { ComplianceToast, ... } from './compliance-toast'). In ESM module linking, that mismatch can make any import from @/components/compliance-system fail with a missing-export error before runtime, which would break existing consumers even if they never import ComplianceToast directly.

Useful? React with 👍 / 👎.

Comment on lines +88 to +92
variant(data.title, {
id: data.id,
description,
duration: data.duration,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve legacy duration semantics in compliance toasts

Forwarding duration: data.duration directly to Sonner changes the previous API contract from this provider: omitted durations no longer default to 5000ms, and duration: 0 no longer gets the old sticky/manual-dismiss behavior. That is a behavioral regression for existing useComplianceToast/useComplianceAction callers that rely on those semantics for important notifications.

Useful? React with 👍 / 👎.

@ejay-dev
ejay-dev deleted the branch fix/audit-sprint-4c-modal-primitives May 23, 2026 16:55
@ejay-dev ejay-dev closed this May 23, 2026
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