Conversation
|
There was a problem hiding this comment.
Pull request overview
Introduces the first functional implementation of NotificationKit-UI as a reusable React component library, including notification state management, provider + hook APIs, UI components, styling build pipeline, and initial test coverage.
Changes:
- Added notification domain models and a
NotificationStore, plusNotificationProvider+useNotificationhook and supporting UI components. - Added Tailwind/PostCSS configuration and a CSS build step with a published
./style.cssexport; updated package exports to ESM.js. - Replaced template/placeholder utilities/components with real notification implementation; added tests and updated README + changeset.
Reviewed changes
Copilot reviewed 40 out of 42 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tailwind.config.mjs | Adds Tailwind config (RTL plugin, z-index extension). |
| tailwind.config.js | Adds Tailwind config duplicate in .js. |
| src/utils/noop.ts | Removes template noop utility. |
| src/utils/index.ts | Removes placeholder exports; leaves empty utils barrel. |
| src/store/notificationStore.ts | Adds notification store (add/update/dismiss/clear/restore + history + provider defaults). |
| src/store/index.ts | Adds store barrel export. |
| src/models/notification.ts | Adds notification types/config/state models. |
| src/models/index.ts | Adds models barrel export. |
| src/index.ts | Updates public exports to ESM .js paths; exports models/store. |
| src/hooks/useNotification.ts | Adds hook for accessing notification context. |
| src/hooks/useNoop.ts | Removes template noop hook. |
| src/hooks/useClearOnNavigate.ts | Adds route-change clearing helper hook. |
| src/hooks/useAccessibility.ts | Adds focus trap and live region hooks. |
| src/hooks/index.ts | Replaces placeholder hook exports with notification hooks. |
| src/context/NotificationContext.tsx | Adds notification context + value type. |
| src/components/index.ts | Replaces placeholder component exports with notification components. |
| src/components/index.css | Adds component CSS entry importing base styles + icon animations. |
| src/components/NotificationViewport.tsx | Adds portal-based viewport renderer. |
| src/components/NotificationProvider.tsx | Adds provider that wires store to React context + viewport. |
| src/components/NotificationProgress.tsx | Adds auto-dismiss progress bar component. |
| src/components/NotificationItem.tsx | Adds notification UI item rendering, timing/pause logic, and a11y behaviors. |
| src/components/NotificationIcons.css | Adds keyframes + animation classes for notifications. |
| src/components/NotificationIcon.tsx | Adds icon rendering (type icons / custom icon / no icon). |
| src/components/NotificationContainer.tsx | Adds position-based grouping and container rendering. |
| src/components/NotificationActionList.tsx | Adds rendering for per-notification action buttons. |
| src/components/NoopButton.tsx | Removes template button component. |
| src/assets/styles/style.css | Adds Tailwind directives and sr-only utility layer. |
| src/tests/notificationStore.test.ts | Adds store behavior tests. |
| src/tests/NotificationProvider.test.tsx | Adds provider + navigationKey behavior tests. |
| src/tests/NotificationItem.a11y.test.tsx | Adds basic a11y assertions for NotificationItem. |
| postcss.config.mjs | Adds PostCSS config (tailwindcss + autoprefixer). |
| postcss.config.js | Adds PostCSS config duplicate in .js. |
| package.json | Updates exports/module fields to ESM .js, adds CSS export and Tailwind build step + deps. |
| package-lock.json | Updates lockfile for new build/style dependencies. |
| README.md | Replaces template README with library docs and usage examples. |
| .github/workflows/release-check.yml | Minor workflow formatting adjustment. |
| .github/instructions/testing.instructions.md | Formatting updates in internal testing instructions. |
| .github/instructions/general.instructions.md | Formatting updates in internal general instructions. |
| .github/instructions/features.instructions.md | Formatting updates in internal feature instructions. |
| .github/instructions/copilot-instructions.md | Formatting updates in internal Copilot instructions. |
| .github/instructions/bugfix.instructions.md | Formatting updates in internal bugfix instructions. |
| .changeset/bright-owls-approve.md | Adds a changeset for the initial functional release. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export function useClearOnNavigate(clearAll: () => void, locationKey: string) { | ||
| useEffect(() => { | ||
| clearAll(); | ||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| }, [locationKey]); |
There was a problem hiding this comment.
This effect intentionally omits clearAll from the dependency array, which can lead to a stale callback if the caller ever passes a new clearAll reference. Prefer including clearAll in the dependency array (and requiring it to be stable via useCallback in the caller) so the hook behaves correctly without an eslint disable.
| return ( | ||
| <> | ||
| <button onClick={() => notify({ title: 'Test', message: 'Hello' })}>Show</button> | ||
| <button onClick={() => dismiss(state.notifications[0]?.id)}>Dismiss</button> |
There was a problem hiding this comment.
dismiss expects a string, but state.notifications[0]?.id is string | undefined. This will fail npm run typecheck (tests are under src/ so they’re included by tsconfig) and also calls dismiss(undefined) at runtime when there are no notifications. Guard the click handler (or disable the button) until an id exists.
| return ( | |
| <> | |
| <button onClick={() => notify({ title: 'Test', message: 'Hello' })}>Show</button> | |
| <button onClick={() => dismiss(state.notifications[0]?.id)}>Dismiss</button> | |
| const firstNotificationId = state.notifications[0]?.id; | |
| return ( | |
| <> | |
| <button onClick={() => notify({ title: 'Test', message: 'Hello' })}>Show</button> | |
| <button | |
| disabled={!firstNotificationId} | |
| onClick={() => { | |
| if (firstNotificationId) { | |
| dismiss(firstNotificationId); | |
| } | |
| }} | |
| > | |
| Dismiss | |
| </button> |
| onDismiss(item.id); | ||
| } |
There was a problem hiding this comment.
The notification container is focusable (tabIndex={0}) and clickable (onClick), but keyboard activation isn’t supported (the key handler only handles Escape). For accessibility, either handle Enter/Space to trigger the click action when item.onClick is present, or avoid making the non-interactive container focusable/clickable and move the action to an actual button/link element.
| onDismiss(item.id); | |
| } | |
| onDismiss(item.id); | |
| return; | |
| } | |
| // Enter/Space to activate notification click action when present | |
| if ((event.key === 'Enter' || event.key === ' ') && item.onClick) { | |
| event.preventDefault(); | |
| item.onClick(); | |
| } |
| defaultCloseButton: true, | ||
| defaultClearOnNavigate: false, | ||
| defaultAriaRole: 'status', | ||
| defaultIcon: null, | ||
| historyLimit: 20, |
There was a problem hiding this comment.
defaultIcon defaults to null, and toRecord() assigns icon via config.icon ?? provider.defaultIcon, which makes icon always null by default. With the current NotificationIcon logic, this suppresses icons and makes the built-in type icons unreachable unless consumers explicitly set defaultIcon to undefined. If the intent is “show built-in icons by default, allow opt-out”, default defaultIcon to undefined and reserve null for explicitly disabling icons.
| "build": "tsup", | ||
| "clean": "rimraf dist *.tsbuildinfo", | ||
| "build": "tsup && npm run build:css", | ||
| "build:css": "tailwindcss -i ./src/assets/styles/style.css -o ./dist/style.css --minify", |
There was a problem hiding this comment.
The CSS build is using src/assets/styles/style.css as the Tailwind input, but key component styles (e.g., NotificationIcons.css defining animate-notify-* keyframes) aren’t included in that file. As a result, dist/style.css will miss the animation/keyframe definitions used by NotificationItem. Consider inlining/importing NotificationIcons.css into the Tailwind input (or switch the input to a single entry CSS that includes all component layers) so the published ./style.css contains all required styles.
| "build:css": "tailwindcss -i ./src/assets/styles/style.css -o ./dist/style.css --minify", | |
| "build:css": "tailwindcss -i ./src/assets/styles/index.css -o ./dist/style.css --minify", |
| "exports": { | ||
| ".": { | ||
| "types": "./dist/index.d.ts", | ||
| "import": "./dist/index.mjs", | ||
| "import": "./dist/index.js", | ||
| "require": "./dist/index.cjs" | ||
| } | ||
| }, | ||
| "./style.css": "./dist/style.css" | ||
| }, |
There was a problem hiding this comment.
exports["./style.css"] encourages consumers to import '@ciscode/ui-notification-kit/style.css', but the package is still marked "sideEffects": false. Some bundlers use this to tree-shake side-effect imports and can drop CSS imports, resulting in missing styles at runtime. Consider setting sideEffects to include CSS (e.g., an array matching **/*.css) or otherwise marking the style entry as side-effectful.
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
| const { dismissedAt: _dismissedAt, ...rest } = historyItem; | ||
| this.add(rest); | ||
| this.state = { | ||
| ...this.state, |
There was a problem hiding this comment.
restore() calls this.add(rest) (which notifies subscribers), then mutates this.state.history to remove the restored item but never calls this.notify() afterward. Subscribers can miss the history removal and remain out of sync until a later store update. Add a final this.notify() (or update history before add) so the restore operation is fully observable.
* ops: updated workflows and unit tests coverage rules * chore: update test coverage rules * chore: setting up env * chore: fixed prettier format errors * ops: updated workflow trigger * 0.0.1 * chore: standardize workflows and ci/cd - Fix SONAR_PROJECT_KEY (critical bug fix) - Add dependabot.yml for dependency management - Add sonarqube_mcp.instructions.md - Standardize branch triggers and Actions versions - Pin SonarQube actions to commit SHA * chore: add copilot-instructions.md for standardization - Add comprehensive copilot-instructions.md guiding notification UI development - Align documentation with other frontend packages - Establish clear naming conventions and testing standards - Define module structure and development workflow * chore: standardize npm scripts (lint, format, typecheck, test, build, clean, verify, prepublishOnly) * chore: Standardize ESLint and Prettier configs with best practices * docs: add standardized instruction files structure - Add comprehensive instruction files in .github/instructions/ - Includes copilot, testing, bugfix, features, general guidelines - Standardize documentation across all repositories * ci: update publish workflow to require version tags - Change trigger from tag push to master branch push - Add tag validation using 'git describe --exact-match' - Prevent failed workflows on feature branch tag pushes - Maintain semantic versioning with mandatory tags * ops: UPDATED publish workflow and dependabot PR limits * Notification UI (#3) * Develop (#1) * ops: updated workflows and unit tests coverage rules * chore: update test coverage rules * chore: setting up env * chore: fixed prettier format errors * ops: updated workflow trigger * 0.0.1 * first version * fixed a style issue and added changeset --------- Co-authored-by: Zaiid Moumni <141942826+Zaiidmo@users.noreply.github.com> * ops (ci): standardize publish validation and dependabot across all packages - Replace git tag --list strategy with package.json-driven tag validation in all 16 publish workflows; use git rev-parse to verify the exact tag exists rather than guessing the latest repo-wide tag - Update error guidance to reflect feat/** → develop → master flow - Standardize dependabot to npm-only, grouped, monthly cadence across all 16 packages; remove github-actions ecosystem updates - Add missing dependabot.yml to AuthKit-UI, ChartKit-UI, HealthKit, HooksKit, paymentkit, StorageKit * fix: missing dependencies for test coverage * tests: added test files to pass thresholds * fix: release check Sonar test directory * fix: added `lcov`to reporter --------- Co-authored-by: Zaiidmo <zaiidmoumnii@gmail.com> Co-authored-by: Zaiid Moumni <141942826+Zaiidmo@users.noreply.github.com>
* ops: updated workflows and unit tests coverage rules * chore: update test coverage rules * chore: setting up env * chore: fixed prettier format errors * ops: updated workflow trigger * 0.0.1 * chore: standardize workflows and ci/cd - Fix SONAR_PROJECT_KEY (critical bug fix) - Add dependabot.yml for dependency management - Add sonarqube_mcp.instructions.md - Standardize branch triggers and Actions versions - Pin SonarQube actions to commit SHA * chore: add copilot-instructions.md for standardization - Add comprehensive copilot-instructions.md guiding notification UI development - Align documentation with other frontend packages - Establish clear naming conventions and testing standards - Define module structure and development workflow * chore: standardize npm scripts (lint, format, typecheck, test, build, clean, verify, prepublishOnly) * chore: Standardize ESLint and Prettier configs with best practices * docs: add standardized instruction files structure - Add comprehensive instruction files in .github/instructions/ - Includes copilot, testing, bugfix, features, general guidelines - Standardize documentation across all repositories * ci: update publish workflow to require version tags - Change trigger from tag push to master branch push - Add tag validation using 'git describe --exact-match' - Prevent failed workflows on feature branch tag pushes - Maintain semantic versioning with mandatory tags * ops: UPDATED publish workflow and dependabot PR limits * Notification UI (#3) * Develop (#1) * ops: updated workflows and unit tests coverage rules * chore: update test coverage rules * chore: setting up env * chore: fixed prettier format errors * ops: updated workflow trigger * 0.0.1 * first version * fixed a style issue and added changeset --------- Co-authored-by: Zaiid Moumni <141942826+Zaiidmo@users.noreply.github.com> * ops (ci): standardize publish validation and dependabot across all packages - Replace git tag --list strategy with package.json-driven tag validation in all 16 publish workflows; use git rev-parse to verify the exact tag exists rather than guessing the latest repo-wide tag - Update error guidance to reflect feat/** → develop → master flow - Standardize dependabot to npm-only, grouped, monthly cadence across all 16 packages; remove github-actions ecosystem updates - Add missing dependabot.yml to AuthKit-UI, ChartKit-UI, HealthKit, HooksKit, paymentkit, StorageKit * fix: missing dependencies for test coverage * tests: added test files to pass thresholds * fix: release check Sonar test directory * fix: added `lcov`to reporter * 0.0.2 * security: added CODEOWNER file for branches security \\ * Empty * empty * ops: updated relese check workflow --------- Co-authored-by: Zaiidmo <zaiidmoumnii@gmail.com> Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> Co-authored-by: Zaiid Moumni <141942826+Zaiidmo@users.noreply.github.com>



Summary
Why
Checklist
npm run lintpassesnpm run typecheckpassesnpm testpassesnpm run buildpassesnpx changeset) if this affects consumersNotes