feat(app-shell): the console mounts the notification surfaces (#3014 follow-up) - #3075
Merged
Merged
Conversation
…follow-up) #3071 gave each spec `NotificationTypeSchema` member its own presentation, but no host mounted `NotificationProvider` — the capability existed and the console could not reach it. `ConsoleShell` now mounts the provider plus the surfaces with a single global home; `ConsoleLayout` mounts the one that belongs in the content area: toast -> sonner, via the new `presentNotificationToast` (ConsoleShell) snackbar -> <NotificationSnackbar /> (ConsoleShell) alert -> <NotificationAlerts /> (ConsoleShell) banner -> <NotificationBanners />, beside the draft / unpublished bars (ConsoleLayout) inline -> the raising surface's own <NotificationInline />; deliberately NOT mounted globally, since rendering in place at the raiser is the whole difference between it and a banner `presentNotificationToast` is the single place a notification becomes a sonner call: severity -> variant, `duration: 0` -> `Infinity` (the contract's "persistent", which passed through raw would make the toast vanish on the next tick), first action -> sonner's one action slot, an absent duration left to the ConsoleToaster default. Its severity table is `Record<NotificationSeverityLevel, …>`, so a new spec severity fails type-check instead of silently rendering neutral. The banners go through `ConsoleNotificationBanners`, gated on `useHasNotificationProvider()`: `ConsoleShell` is deliberately composable pieces a host assembles itself, so `ConsoleLayout` can render without the provider above it — and `useNotifications()` throws there, white-screening the app instead of simply showing no banners. Both pieces are exported for hand-assembled shells. Verified in the running console (login route): a toast, a snackbar with an Undo action, and a blocking alert dialog on screen at once, visibly distinct; raising an `inline` with no outlet logs the dev warning naming the component to mount, once per notify(). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #3071 (which closed #3014). That PR gave each spec
NotificationTypeSchemamember its own presentation, but no host mountedNotificationProvider— the capability existed and the console could not reach it. This wires it in.What the console mounts now
displayTypetoastpresentNotificationToastConsoleShellsnackbar<NotificationSnackbar />ConsoleShellalert<NotificationAlerts />ConsoleShellbanner<NotificationBanners />ConsoleLayout, beside the draft / unpublished barsinline<NotificationInline scope="…" />inlineis left out on purpose: rendering in place at the raiser is the whole difference between it and a banner, so a global inline outlet would collapse the two again.ConsoleShell's header documents the split so the next person doesn't "fix" it.Two pieces worth reviewing
presentNotificationToast— the single place a notification becomes a sonner call, so the mapping is one testable function instead of a lambda in the shell:Record<NotificationSeverityLevel, …>so a new spec severity fails type-check rather than silently rendering neutral;duration: 0→Infinity. The contract's "persistent" passed through raw would make the toast vanish on the next tick;undefinedsoConsoleToaster's 4s default applies, rather than reinventing a number here;actions[0]→ sonner's one action slot (a notification needing more belongs on a banner or an alert).ConsoleNotificationBanners—NotificationBannersgated onuseHasNotificationProvider().ConsoleShellis deliberately a set of composable pieces a host assembles in its ownApp.tsx, soConsoleLayoutcan legitimately render without the provider above it — anduseNotifications()throws there, which would white-screen the whole app instead of simply showing no banners.Both are exported for hand-assembled shells. The provider's
defaultDurationmatchesConsoleToaster's 4s, so a snackbar and a toast raised together disappear together.Verification
In the running console (
apps/consoledev server, login route — which renders insideConsoleShell): a toast, a snackbar with an Undo action, and a blocking alert dialog on screen at once, visibly distinct — the exact collapse #3014 was about, gone. Raising aninlinewith no outlet logs the dev warning naming the component to mount, and exactly once pernotify()(measured, not assumed). No console errors on boot with the new root provider.The
bannerplacement is covered by tests rather than a screenshot: it lives inConsoleLayout, which is behind auth, and standing up a backend for one strip was disproportionate —ConsoleShell.notifications.test.tsxrendersConsoleNotificationBannersinside the realConsoleShelland asserts it lands ondata-notification-surface="banner"while sonner is never called.Suites:
packages/app-shell: 2047 tests, 247 files, all green (includes the 15 new ones — 7 shell integration + 8 toast-mapping).tsc --noEmitclean on@object-ui/app-shell; eslint 0 errors on every touched file.Docs: the notifications guide gains an "In the console" section, plus the
@object-ui/app-shellREADME.Refs #3014, #2942.
🤖 Generated with Claude Code