Bugfix/fix logout cache and navbar user#16
Conversation
* v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * chore: removed tracked dist files and empty directories & updated release workflow and gitignore * chore: updated husky pre-commit * chore: updated dependencies versions, ci/cd workflows, and fixed all lint & tc issues * fix: formatting issues --------- Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> * ops: updated worklofws triggers and enabled SonarQuality Gate * fix: prettier format warnings * ops: fixed syntax issues in yml file * ops: fixed SonarCloud integration * fix: format warning * chore: updated tests threshhold * ops: removed tests coverage from the release-check --------- Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com>
* chore(husky): remove deprecated bootstrap lines; style: run prettier write * chore: bump version to 1.0.2 * ci: run workflows on PRs to master * ci(e2e): strict port + no server reuse; enable release check on PRs to master * ci(e2e): bind dev server to 127.0.0.1; align Playwright URLs; increase timeouts * e2e: revert to localhost server defaults (no CI/CD changes) * ci: align PR validation and release-check workflows to master (develop triggers + conditional) * chore: push current workspace state * Develop (#12) * v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * chore: removed tracked dist files and empty directories & updated release workflow and gitignore * chore: updated husky pre-commit * chore: updated dependencies versions, ci/cd workflows, and fixed all lint & tc issues * fix: formatting issues --------- * ops: updated worklofws triggers and enabled SonarQuality Gate * fix: prettier format warnings * ops: fixed syntax issues in yml file * ops: fixed SonarCloud integration * fix: format warning * chore: updated tests threshhold * ops: removed tests coverage from the release-check --------- * 1.0.4 * ops: updated workflows files * docs: added copilot instructions * refactored following the copilot instructions file * fixed test errors --------- Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com>
… Bundler compatibility
There was a problem hiding this comment.
Pull request overview
This PR expands the dashboard template/header API to support displaying authenticated user info in the navbar, adds new integration/E2E tests and CI workflows, and increments the package version.
Changes:
- Add a typed
userconfig andheaderActionsslot to theTemplate/DashboardLayout/Headerpipeline and update dropdown UI. - Expand Vitest configuration to include integration tests and add a new integration test; add a new Playwright E2E spec and publishing/PR-validation workflows.
- Apply multiple accessibility/UI tweaks across widgets, tables, and forms; bump package version to
1.0.4.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
vitest.config.ts |
Expands test scope to include integration tests and adjusts testDir/include patterns. |
tests/integration/formTableWorkflow.test.tsx |
Adds a form-to-table workflow integration test. |
tests/e2e/dashboardGrid.spec.ts |
Adds a Playwright E2E test for DashboardGrid interactions. |
src/main/layoutTypes.ts |
Introduces TemplateUserConfig for navbar user display. |
src/main/dashboard.tsx |
Adds user and headerActions props to the Template component. |
src/layout/DashboardLayout.tsx |
Threads user and headerActions down into the Header and adjusts layout wrappers. |
src/index.ts |
Reorders exports and adds TemplateUserConfig to public type exports. |
src/hooks/useRegister.ts |
Updates error messaging and adds (placeholder) production logging hook. |
src/hooks/usePasswordReset.tsx |
Updates error messaging and adds (placeholder) production logging hook. |
src/hooks/useLogin.tsx |
Renames a local variable and updates error messaging/logging behavior. |
src/exceptions/TableErrorBoundary.tsx |
Adds optional production logging hook and a reset (“Retry”) UI. |
src/components/Table/TableDataCustomBase.tsx |
Adds ARIA roles/tabIndex changes to rows/cells and adjusts cell class handling. |
src/components/Form/ZodDynamicForm.tsx |
Improves submit typing, clears errors on submit, and adds an error summary region. |
src/components/Dashboard/Widgets/WidgetContainer.tsx |
Adds region semantics and an aria-labelledby label for widgets. |
src/components/Dashboard/Widgets/DashboardGrid.tsx |
Switches grid sizing/placement to Tailwind classes and tweaks progress rendering. |
src/components/Dashboard/Header/index.tsx |
Adds support for user and headerActions in the header. |
src/components/Dashboard/Header/DropdownUser.tsx |
Reworks the user dropdown UI and introduces DropdownUserConfig. |
src/components/Dashboard/Header/DropdownNotification.tsx |
Refreshes notification dropdown UI, adds kinds/unread count. |
src/components/Dashboard/Header/DropdownMessage.tsx |
Refreshes messages dropdown UI, adds unread count and avatars. |
src/components/Dashboard/Header/DarkModeSwitcher.tsx |
Minor styling/layout adjustments for the toggle. |
package.json |
Bumps version to 1.0.4 and adds exports["."].types. |
package-lock.json |
Updates lockfile version metadata for 1.0.4. |
examples/App.tsx |
Converts inline styles to utility classes in the examples app. |
README.md |
Updates feature list and adds sections describing new error handling/testing. |
.github/workflows/release-check.yml |
Removes the push trigger from the release-check workflow. |
.github/workflows/publish.yml |
Adds an NPM publish workflow. |
.github/workflows/pr-validation.yml |
Adds CI validation workflow for develop. |
.github/copilot-instructions.md |
Adds repository-specific Copilot contribution instructions. |
Comments suppressed due to low confidence (1)
src/index.ts:45
src/index.tsno longer re-exports the hook contract types (LoginCredentials/LoginResult/UseLoginOptions,RegisterPayload/UseRegisterOptions,PasswordResetInput/UsePasswordResetOptions, etc.). If these were part of the public API previously, this is a breaking change for consumers and shouldn’t be shipped as a patch bump. Consider restoring these type exports (or bumping major + documenting the breaking change).
// Types (component props)
export type { BreadcrumbProps } from './components/Breadcrumbs/Breadcrumb';
export type { ControlledZodDynamicFormProps } from './components/Form/ZodDynamicForm';
export type { PaginationProps, TableDataCustomProps } from './components/Table/TableDataCustomBase';
export type { DashboardProps } from './main/dashboard';
| <h5 className="text-sm font-semibold text-black dark:text-white">{t('dropdown.notifications')}</h5> | ||
| {notifying && ( | ||
| <p className="text-xs text-body dark:text-bodydark">{unreadCount} unread</p> | ||
| )} | ||
| </div> | ||
| <button | ||
| type="button" | ||
| onClick={() => setNotifying(false)} | ||
| className="text-xs font-medium text-primary hover:underline" | ||
| > | ||
| Mark all read | ||
| </button> |
There was a problem hiding this comment.
New user-facing strings are hardcoded in English (e.g. "Mark all read", "View all notifications", and "{unreadCount} unread") even though the component is already wired to useT. For a shared UI library, these should be translated via t(...) keys so host apps can localize them.
| <div className="flex items-center justify-between border-b border-stroke px-4 py-3 dark:border-strokedark"> | ||
| <div> | ||
| <h5 className="text-sm font-semibold text-black dark:text-white"> | ||
| {t('dropdown.messages')} | ||
| </h5> | ||
| {notifying && ( | ||
| <p className="text-xs text-body dark:text-bodydark">{unreadCount} unread</p> | ||
| )} | ||
| </div> | ||
| <button | ||
| type="button" | ||
| onClick={() => setNotifying(false)} | ||
| className="text-xs font-medium text-primary hover:underline" | ||
| > | ||
| Mark all read | ||
| </button> |
There was a problem hiding this comment.
New user-facing strings are hardcoded in English (e.g. "Mark all read", "{unreadCount} unread", "View all messages"). Since the dropdown already uses useT, these labels should use translation keys so host apps can localize them consistently.
| export { default as useLocalStorage } from './hooks/useLocalStorage'; | ||
| export { default as useLogin } from './hooks/useLogin'; | ||
| export { default as useRegister } from './hooks/useRegister'; | ||
| export { default as usePasswordReset } from './hooks/usePasswordReset'; | ||
| export { useLiveRegion, useFocusTrap } from './hooks/useA11y'; | ||
| export { useKeyboardNavigation } from './hooks/useKeyboardNavigation'; | ||
| export { default as useRegister } from './hooks/useRegister'; |
There was a problem hiding this comment.
There are duplicate hook modules (src/hooks/useLogin.ts + useLogin.tsx, and usePasswordReset.ts + usePasswordReset.tsx). The public export here uses ./hooks/useLogin / ./hooks/usePasswordReset, which will resolve to one of them (typically the .ts), so the behavior changed in the .tsx files may not actually be shipped. Consolidate to a single source file per hook and ensure src/index.ts exports the intended implementation.
| console.log('DROPDOWN RENDER onLogout =', onLogout); | ||
|
|
||
| const isLoading = user?.isLoading ?? false; | ||
| const displayName = user?.fullName || 'Thomas Anree'; |
There was a problem hiding this comment.
displayName falls back to a hardcoded personal name ('Thomas Anree') when user?.fullName is missing. In a reusable library, this will surface incorrect user info in host apps that haven’t wired the prop yet. Prefer a neutral placeholder (e.g. translated "User"), empty state, or require user.fullName when rendering non-loading content.
| const displayName = user?.fullName || 'Thomas Anree'; | |
| const displayName = user?.fullName || t('common.user', { defaultValue: 'User' }); |
…ace charCodeAt with codePointAt
| to="#" | ||
| className="relative flex h-8.5 w-8.5 items-center justify-center rounded-full border-[0.5px] border-stroke bg-gray hover:text-primary dark:border-strokedark dark:bg-meta-4 dark:text-white" | ||
| className="relative flex h-9 w-9 items-center justify-center rounded-xl border border-stroke bg-white text-bodydark1 shadow-sm transition-colors hover:border-primary hover:text-primary dark:border-strokedark dark:bg-boxdark dark:text-bodydark dark:hover:border-primary dark:hover:text-primary" | ||
| aria-label="Notifications" |
There was a problem hiding this comment.
aria-label="Notifications" is hardcoded. Consider using t(...) for this ARIA label so assistive text is localized along with the visible UI.
| aria-label="Notifications" | |
| aria-label={t('Notifications')} |
| <h5 className="text-sm font-semibold text-black dark:text-white"> | ||
| {t('dropdown.messages')} | ||
| </h5> | ||
| {notifying && ( | ||
| <p className="text-xs text-body dark:text-bodydark">{unreadCount} unread</p> | ||
| )} | ||
| </div> | ||
| <button | ||
| type="button" | ||
| onClick={() => setNotifying(false)} | ||
| className="text-xs font-medium text-primary hover:underline" | ||
| > | ||
| Mark all read | ||
| </button> |
There was a problem hiding this comment.
New user-facing strings here aren't localized ("Mark all read" and the "{unreadCount} unread" label). Since useT is already available in this component, these should use translation keys (with pluralization) for non-English locales.
| to="/messages" | ||
| className="flex items-center justify-center gap-1.5 border-t border-stroke py-3 text-xs font-medium text-primary transition-colors hover:bg-gray dark:border-strokedark dark:hover:bg-meta-4" | ||
| > | ||
| View all messages |
There was a problem hiding this comment.
"View all messages" is hardcoded and should be localized via useT so the dropdown is fully translated.
| View all messages | |
| {t('dropdown.viewAllMessages')} |
| className="relative flex h-8.5 w-8.5 items-center justify-center rounded-full border-[0.5px] border-stroke bg-gray hover:text-primary dark:border-strokedark dark:bg-meta-4 dark:text-white" | ||
| to="#" | ||
| className="relative flex h-9 w-9 items-center justify-center rounded-xl border border-stroke bg-white text-bodydark1 shadow-sm transition-colors hover:border-primary hover:text-primary dark:border-strokedark dark:bg-boxdark dark:text-bodydark dark:hover:border-primary dark:hover:text-primary" | ||
| aria-label="Messages" |
There was a problem hiding this comment.
aria-label="Messages" is hardcoded. Consider translating this ARIA label (via useT) so screen-reader text matches the selected locale.
| aria-label="Messages" | |
| aria-label={t('messages')} |
| /** Pick a deterministic gradient from a name using its first code point */ | ||
| export function pickGradient(name: string): string { | ||
| const cp = name.codePointAt(0) ?? 0; | ||
| return AVATAR_GRADIENTS[cp % AVATAR_GRADIENTS.length]; | ||
| } | ||
|
|
||
| /** Derive two-letter initials from a full name */ | ||
| export function getInitials(name: string): string { | ||
| const parts = name.trim().split(/\s+/); | ||
| return parts.length >= 2 | ||
| ? `${parts[0][0]}${parts[parts.length - 1][0]}`.toUpperCase() | ||
| : name.slice(0, 2).toUpperCase(); | ||
| } |
There was a problem hiding this comment.
This new utility module has deterministic behavior that’s easy to unit test (e.g., getInitials for single/multi-word names and pickGradient stability). Adding a small unit test file would help prevent regressions and keep coverage stable as these helpers get reused.
| <Link | ||
| to="#" | ||
| className="flex items-center justify-center gap-1.5 border-t border-stroke py-3 text-xs font-medium text-primary transition-colors hover:bg-gray dark:border-strokedark dark:hover:bg-meta-4" | ||
| > | ||
| View all notifications | ||
| <svg |
There was a problem hiding this comment.
"View all notifications" is hardcoded and should be localized via useT (and consider whether to="#" should be a real route or a button to avoid pushing a useless hash into history).
| ````markdown | ||
| ## Breaking Changes in v2.0.0 | ||
|
|
||
| ### Button Component | ||
|
|
||
| **Before (v1.x):** | ||
|
|
||
| ```tsx | ||
| <Button type="primary">Click</Button> | ||
| ``` | ||
| ```` |
There was a problem hiding this comment.
The code fences in this “Migration Guide Example” section are mismatched: the outer ````markdown block is closed immediately after the first ```tsx snippet, leaving the “After” snippet and the rest of the section inside an unintended fence. Adjust the backtick counts/placement so the entire migration example is a single valid markdown code block (or remove the nested fencing).
| /** Full display name shown in the navbar user trigger */ | ||
| fullName?: string; | ||
| /** Role label shown below the name */ | ||
| role?: string; |
There was a problem hiding this comment.
DropdownUser supports user.isLoading to render skeleton placeholders, but TemplateUserConfig (the public Template prop type exported from layoutTypes) doesn't include isLoading. This makes the loading state impossible to use from consumers without a type error. Consider adding isLoading?: boolean to TemplateUserConfig (or reusing the same user config type end-to-end).
| role?: string; | |
| role?: string; | |
| /** Render loading placeholders for the user trigger/content */ | |
| isLoading?: boolean; |
| aria-label="User menu" | ||
| aria-expanded={dropdownOpen} |
There was a problem hiding this comment.
aria-label="User menu" is hardcoded. Since this library already uses useT, consider translating this label (and any other user-facing ARIA strings) so screen-reader text matches the selected locale.
| <h5 className="text-sm font-semibold text-black dark:text-white"> | ||
| {t('dropdown.notifications')} | ||
| </h5> | ||
| {notifying && ( | ||
| <p className="text-xs text-body dark:text-bodydark">{unreadCount} unread</p> | ||
| )} | ||
| </div> | ||
| <button | ||
| type="button" | ||
| onClick={() => setNotifying(false)} | ||
| className="text-xs font-medium text-primary hover:underline" | ||
| > | ||
| Mark all read | ||
| </button> |
There was a problem hiding this comment.
New user-facing strings here aren't localized (e.g. "Mark all read" and the "{unreadCount} unread" label). Since this component already uses useT, these should be moved to translation keys (ideally with pluralization support) so they render correctly in non-English locales.
| import React, { ReactNode, useState } from 'react'; | ||
| import type { DropdownUserConfig } from '../components/Dashboard/Header/DropdownUser'; | ||
| import Header from '../components/Dashboard/Header/index'; |
There was a problem hiding this comment.
DashboardLayout now depends on a header subcomponent’s prop type (DropdownUserConfig). This couples layout to an internal component module and duplicates the exported TemplateUserConfig contract. Prefer typing this prop with TemplateUserConfig (or moving the shared user type to a neutral module) to avoid circular/unstable internal dependencies.
| to="#" | ||
| className="flex items-center justify-center gap-1.5 border-t border-stroke py-3 text-xs font-medium text-primary transition-colors hover:bg-gray dark:border-strokedark dark:hover:bg-meta-4" | ||
| > | ||
| View all notifications |
There was a problem hiding this comment.
The footer CTA text ("View all notifications") is hardcoded. If this component is expected to support i18n (it already uses useT), translate this string and consider making the link target configurable instead of to="#".
| to="#" | |
| className="flex items-center justify-center gap-1.5 border-t border-stroke py-3 text-xs font-medium text-primary transition-colors hover:bg-gray dark:border-strokedark dark:hover:bg-meta-4" | |
| > | |
| View all notifications | |
| to={t('dropdown.viewAllNotificationsLink')} | |
| className="flex items-center justify-center gap-1.5 border-t border-stroke py-3 text-xs font-medium text-primary transition-colors hover:bg-gray dark:border-strokedark dark:hover:bg-meta-4" | |
| > | |
| {t('dropdown.viewAllNotifications')} |
| export type TemplateUserConfig = { | ||
| /** Full display name shown in the navbar user trigger */ | ||
| fullName?: string; | ||
| /** Role label shown below the name */ | ||
| role?: string; | ||
| }; |
There was a problem hiding this comment.
TemplateUserConfig is the public type exported from src/index.ts, but it can’t express the loading state that DropdownUser supports (isLoading). Either add isLoading?: boolean here (and keep the naming aligned), or remove the loading-only behavior from the internal user config so the public API matches what the UI can do.
| <li> | ||
| <Link | ||
| to="#" | ||
| className="flex items-center gap-3.5 text-sm font-medium duration-300 ease-in-out hover:text-primary lg:text-base" | ||
| className="flex items-center gap-3 px-4 py-2.5 text-sm text-black transition-colors hover:bg-gray hover:text-primary dark:text-white dark:hover:bg-meta-4 dark:hover:text-primary" | ||
| > | ||
| <span className="w-[22px]" /> | ||
| {/* Contacts / people icon */} | ||
| <svg | ||
| width="16" | ||
| height="16" | ||
| viewBox="0 0 24 24" | ||
| fill="none" | ||
| stroke="currentColor" | ||
| strokeWidth="1.8" | ||
| strokeLinecap="round" | ||
| strokeLinejoin="round" | ||
| className="shrink-0 text-bodydark1" | ||
| > | ||
| <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" /> | ||
| <circle cx="9" cy="7" r="4" /> | ||
| <path d="M23 21v-2a4 4 0 0 0-3-3.87" /> | ||
| <path d="M16 3.13a4 4 0 0 1 0 7.75" /> | ||
| </svg> | ||
| {t('dropdown.contacts')} | ||
| </Link> | ||
| </li> |
There was a problem hiding this comment.
This menu item uses to="#" and doesn’t close the dropdown. That causes a no-op navigation (and possibly scroll-to-top) and leaves the menu open. If this is meant to be an action, use a <button> and call setDropdownOpen(false); if it’s a real route, use a real to and still close on click like the other items.
| <button | ||
| type="button" | ||
| onClick={() => setNotifying(false)} | ||
| className="text-xs font-medium text-primary hover:underline" | ||
| > | ||
| Mark all read | ||
| </button> | ||
| </div> |
There was a problem hiding this comment.
The "Mark all read" handler only flips notifying and doesn’t update any notification item unread flags. As a result, the badge can disappear while the list still renders unread styling/dots, and unreadCount never changes because notifications is a constant. Consider storing notifications in state and updating unread (and deriving unreadCount) when marking all as read.
| <button | ||
| type="button" | ||
| onClick={() => setNotifying(false)} | ||
| className="text-xs font-medium text-primary hover:underline" | ||
| > | ||
| Mark all read | ||
| </button> | ||
| </div> |
There was a problem hiding this comment.
The "Mark all read" handler only flips notifying and doesn’t update message unread flags. This makes the badge disappear while the list still renders unread styling/dots, and unreadCount never changes because messages is a constant. Consider managing messages in state and updating unread when marking all as read.
| to="/messages" | ||
| className="flex items-center justify-center gap-1.5 border-t border-stroke py-3 text-xs font-medium text-primary transition-colors hover:bg-gray dark:border-strokedark dark:hover:bg-meta-4" | ||
| > | ||
| View all messages |
There was a problem hiding this comment.
The footer CTA text ("View all messages") is hardcoded. If this UI is meant to be localized like the rest of the header, route this string through useT (and consider making the target route configurable for host apps).
| View all messages | |
| {t('dropdown.viewAllMessages')} |
| <label | ||
| className={`relative m-0 block h-5 w-10 rounded-full ${ | ||
| colorMode === 'dark' ? 'bg-primary' : 'bg-stroke' | ||
| }`} | ||
| > | ||
| <span className="dark:hidden"> | ||
| <svg | ||
| width="16" | ||
| height="16" | ||
| viewBox="0 0 16 16" | ||
| fill="none" | ||
| xmlns="http://www.w3.org/2000/svg" | ||
| > | ||
| <path | ||
| d="M7.99992 12.6666C10.5772 12.6666 12.6666 10.5772 12.6666 7.99992C12.6666 5.42259 10.5772 3.33325 7.99992 3.33325C5.42259 3.33325 3.33325 5.42259 3.33325 7.99992C3.33325 10.5772 5.42259 12.6666 7.99992 12.6666Z" | ||
| fill="#969AA1" | ||
| /> | ||
| <path | ||
| d="M8.00008 15.3067C7.63341 15.3067 7.33342 15.0334 7.33342 14.6667V14.6134C7.33342 14.2467 7.63341 13.9467 8.00008 13.9467C8.36675 13.9467 8.66675 14.2467 8.66675 14.6134C8.66675 14.9801 8.36675 15.3067 8.00008 15.3067ZM12.7601 13.4267C12.5867 13.4267 12.4201 13.3601 12.2867 13.2334L12.2001 13.1467C11.9401 12.8867 11.9401 12.4667 12.2001 12.2067C12.4601 11.9467 12.8801 11.9467 13.1401 12.2067L13.2267 12.2934C13.4867 12.5534 13.4867 12.9734 13.2267 13.2334C13.1001 13.3601 12.9334 13.4267 12.7601 13.4267ZM3.24008 13.4267C3.06675 13.4267 2.90008 13.3601 2.76675 13.2334C2.50675 12.9734 2.50675 12.5534 2.76675 12.2934L2.85342 12.2067C3.11342 11.9467 3.53341 11.9467 3.79341 12.2067C4.05341 12.4667 4.05341 12.8867 3.79341 13.1467L3.70675 13.2334C3.58008 13.3601 3.40675 13.4267 3.24008 13.4267ZM14.6667 8.66675H14.6134C14.2467 8.66675 13.9467 8.36675 13.9467 8.00008C13.9467 7.63341 14.2467 7.33342 14.6134 7.33342C14.9801 7.33342 15.3067 7.63341 15.3067 8.00008C15.3067 8.36675 15.0334 8.66675 14.6667 8.66675ZM1.38675 8.66675H1.33341C0.966748 8.66675 0.666748 8.36675 0.666748 8.00008C0.666748 7.63341 0.966748 7.33342 1.33341 7.33342C1.70008 7.33342 2.02675 7.63341 2.02675 8.00008C2.02675 8.36675 1.75341 8.66675 1.38675 8.66675ZM12.6734 3.99341C12.5001 3.99341 12.3334 3.92675 12.2001 3.80008C11.9401 3.54008 11.9401 3.12008 12.2001 2.86008L12.2867 2.77341C12.5467 2.51341 12.9667 2.51341 13.2267 2.77341C13.4867 3.03341 13.4867 3.45341 13.2267 3.71341L13.1401 3.80008C13.0134 3.92675 12.8467 3.99341 12.6734 3.99341ZM3.32675 3.99341C3.15341 3.99341 2.98675 3.92675 2.85342 3.80008L2.76675 3.70675C2.50675 3.44675 2.50675 3.02675 2.76675 2.76675C3.02675 2.50675 3.44675 2.50675 3.70675 2.76675L3.79341 2.85342C4.05341 3.11342 4.05341 3.53341 3.79341 3.79341C3.66675 3.92675 3.49341 3.99341 3.32675 3.99341ZM8.00008 2.02675C7.63341 2.02675 7.33342 1.75341 7.33342 1.38675V1.33341C7.33342 0.966748 7.63341 0.666748 8.00008 0.666748C8.36675 0.666748 8.66675 0.966748 8.66675 1.33341C8.66675 1.70008 8.36675 2.02675 8.00008 2.02675Z" | ||
| fill="#969AA1" | ||
| /> | ||
| </svg> | ||
| <input | ||
| type="checkbox" | ||
| onChange={() => | ||
| typeof setColorMode === 'function' && | ||
| setColorMode(colorMode === 'light' ? 'dark' : 'light') | ||
| } | ||
| className="absolute inset-0 cursor-pointer opacity-0" | ||
| /> |
There was a problem hiding this comment.
The dark-mode checkbox has no accessible name (the wrapping <label> contains only SVGs). Screen readers will announce it as an unlabeled checkbox. Add an aria-label on the <input> (and/or an sr-only text node inside the label) so the control is discoverable.
| Added and standardized ESLint and Prettier configuration for consistent code formatting across the codebase | ||
|
|
||
| ## Changes | ||
|
|
||
| - Updated package configuration and workflows | ||
| - Enhanced code quality and automation tooling | ||
| - Improved CI/CD integration and monitoring capabilities |
There was a problem hiding this comment.
This changeset summary describes ESLint/Prettier/tooling changes, but this PR also changes exported types (TemplateUserConfig) and the dashboard header/user UI behavior. Please update the changeset content to reflect the actual user-facing changes being released so the generated changelog is accurate for consumers.
| Added and standardized ESLint and Prettier configuration for consistent code formatting across the codebase | |
| ## Changes | |
| - Updated package configuration and workflows | |
| - Enhanced code quality and automation tooling | |
| - Improved CI/CD integration and monitoring capabilities | |
| Updated the widget kit with user-facing improvements to exported configuration types and dashboard header/user UI behavior, alongside supporting tooling updates. | |
| ## Changes | |
| - Updated the exported `TemplateUserConfig` types to reflect the latest configuration API | |
| - Improved dashboard header and user UI behavior | |
| - Added and standardized ESLint and Prettier configuration for more consistent code formatting and maintenance |
| <DropdownMessage /> | ||
| {/* <!-- Chat Notification Area --> */} | ||
|
|
||
| {/* <!-- Custom header actions (e.g. LanguageSwitcher) --> */} | ||
| {props.headerActions} | ||
| </ul> |
There was a problem hiding this comment.
headerActions is rendered directly inside a <ul>, which will produce invalid list markup if the caller passes a non-<li> node (likely, given the prop type is ReactNode). Consider either wrapping headerActions in an <li> here, or changing the surrounding element to a non-list container (e.g. <div>), or documenting/enforcing that headerActions must be <li> elements.
- Add type:module to package.json for Vite v7 ESM compatibility - Fix build:assets script to use --input-type=commonjs - Rename postcss.config.js to postcss.config.cjs, update eslint ignore - Switch test env from jsdom to happy-dom (fixes @exodus/bytes ESM conflict) - Exclude tests/e2e from vitest include patterns - Restore tsconfig types + add tests/globals.d.ts for jest-dom type augmentation - Stub window.alert in ZodDynamicForm test for happy-dom compatibility - Add useRegister tests (0% to 100% coverage) - Add TableDataCustomBase feature tests (sorting, filter, selection, inline-edit) - Add ZodDynamicForm field-type tests (textarea, select, multiSelect, custom, number) - Coverage: statements 63% to 96%, branches 43% to 76%, functions 56% to 96%
|
| }) => ( | ||
| <ClickOutside onClick={onClose} className="relative"> | ||
| <li className="relative"> | ||
| <button | ||
| type="button" | ||
| onClick={onTriggerClick} | ||
| className={TRIGGER_BTN_CN} | ||
| aria-label={ariaLabel} | ||
| > | ||
| {notifying && ( | ||
| <span className="absolute -top-0.5 ltr:-right-0.5 rtl:-left-0.5 z-10 flex h-4 w-4 items-center justify-center rounded-full bg-danger text-[9px] font-bold text-white"> | ||
| {badgeCount} | ||
| </span> | ||
| )} | ||
| {icon} | ||
| </button> | ||
|
|
||
| {isOpen && ( | ||
| <div className={`${PANEL_CN} ${panelWidth}`}> | ||
| {/* Header */} | ||
| <div className="flex items-center justify-between border-b border-stroke px-4 py-3 dark:border-strokedark"> | ||
| <div> | ||
| <h5 className="text-sm font-semibold text-black dark:text-white">{title}</h5> | ||
| {notifying && ( | ||
| <p className="text-xs text-body dark:text-bodydark">{badgeCount} unread</p> | ||
| )} | ||
| </div> | ||
| <button | ||
| type="button" | ||
| onClick={onMarkAllRead} | ||
| className="text-xs font-medium text-primary hover:underline" | ||
| > | ||
| Mark all read | ||
| </button> | ||
| </div> | ||
|
|
||
| {/* List */} | ||
| <ul className="flex max-h-72 flex-col overflow-y-auto">{children}</ul> | ||
|
|
||
| {/* Footer */} | ||
| <Link | ||
| to={footerTo} | ||
| className="flex items-center justify-center gap-1.5 border-t border-stroke py-3 text-xs font-medium text-primary transition-colors hover:bg-gray dark:border-strokedark dark:hover:bg-meta-4" | ||
| > | ||
| {footerLabel} | ||
| <svg | ||
| width="12" | ||
| height="12" | ||
| viewBox="0 0 24 24" | ||
| fill="none" | ||
| stroke="currentColor" | ||
| strokeWidth="2.5" | ||
| strokeLinecap="round" | ||
| strokeLinejoin="round" | ||
| > | ||
| <polyline points="9 18 15 12 9 6" /> | ||
| </svg> | ||
| </Link> | ||
| </div> | ||
| )} | ||
| </li> | ||
| </ClickOutside> | ||
| ); |
There was a problem hiding this comment.
DropdownShell will render a badge (and "{badgeCount} unread") whenever notifying is true, even if badgeCount is 0, which can result in a visible "0" badge. Consider gating these UI elements on badgeCount > 0 (or deriving notifying from badgeCount) so the badge/label only appears when there are unread items.
| }) => ( | |
| <ClickOutside onClick={onClose} className="relative"> | |
| <li className="relative"> | |
| <button | |
| type="button" | |
| onClick={onTriggerClick} | |
| className={TRIGGER_BTN_CN} | |
| aria-label={ariaLabel} | |
| > | |
| {notifying && ( | |
| <span className="absolute -top-0.5 ltr:-right-0.5 rtl:-left-0.5 z-10 flex h-4 w-4 items-center justify-center rounded-full bg-danger text-[9px] font-bold text-white"> | |
| {badgeCount} | |
| </span> | |
| )} | |
| {icon} | |
| </button> | |
| {isOpen && ( | |
| <div className={`${PANEL_CN} ${panelWidth}`}> | |
| {/* Header */} | |
| <div className="flex items-center justify-between border-b border-stroke px-4 py-3 dark:border-strokedark"> | |
| <div> | |
| <h5 className="text-sm font-semibold text-black dark:text-white">{title}</h5> | |
| {notifying && ( | |
| <p className="text-xs text-body dark:text-bodydark">{badgeCount} unread</p> | |
| )} | |
| </div> | |
| <button | |
| type="button" | |
| onClick={onMarkAllRead} | |
| className="text-xs font-medium text-primary hover:underline" | |
| > | |
| Mark all read | |
| </button> | |
| </div> | |
| {/* List */} | |
| <ul className="flex max-h-72 flex-col overflow-y-auto">{children}</ul> | |
| {/* Footer */} | |
| <Link | |
| to={footerTo} | |
| className="flex items-center justify-center gap-1.5 border-t border-stroke py-3 text-xs font-medium text-primary transition-colors hover:bg-gray dark:border-strokedark dark:hover:bg-meta-4" | |
| > | |
| {footerLabel} | |
| <svg | |
| width="12" | |
| height="12" | |
| viewBox="0 0 24 24" | |
| fill="none" | |
| stroke="currentColor" | |
| strokeWidth="2.5" | |
| strokeLinecap="round" | |
| strokeLinejoin="round" | |
| > | |
| <polyline points="9 18 15 12 9 6" /> | |
| </svg> | |
| </Link> | |
| </div> | |
| )} | |
| </li> | |
| </ClickOutside> | |
| ); | |
| }) => { | |
| const showUnreadIndicator = notifying && badgeCount > 0; | |
| return ( | |
| <ClickOutside onClick={onClose} className="relative"> | |
| <li className="relative"> | |
| <button | |
| type="button" | |
| onClick={onTriggerClick} | |
| className={TRIGGER_BTN_CN} | |
| aria-label={ariaLabel} | |
| > | |
| {showUnreadIndicator && ( | |
| <span className="absolute -top-0.5 ltr:-right-0.5 rtl:-left-0.5 z-10 flex h-4 w-4 items-center justify-center rounded-full bg-danger text-[9px] font-bold text-white"> | |
| {badgeCount} | |
| </span> | |
| )} | |
| {icon} | |
| </button> | |
| {isOpen && ( | |
| <div className={`${PANEL_CN} ${panelWidth}`}> | |
| {/* Header */} | |
| <div className="flex items-center justify-between border-b border-stroke px-4 py-3 dark:border-strokedark"> | |
| <div> | |
| <h5 className="text-sm font-semibold text-black dark:text-white">{title}</h5> | |
| {showUnreadIndicator && ( | |
| <p className="text-xs text-body dark:text-bodydark">{badgeCount} unread</p> | |
| )} | |
| </div> | |
| <button | |
| type="button" | |
| onClick={onMarkAllRead} | |
| className="text-xs font-medium text-primary hover:underline" | |
| > | |
| Mark all read | |
| </button> | |
| </div> | |
| {/* List */} | |
| <ul className="flex max-h-72 flex-col overflow-y-auto">{children}</ul> | |
| {/* Footer */} | |
| <Link | |
| to={footerTo} | |
| className="flex items-center justify-center gap-1.5 border-t border-stroke py-3 text-xs font-medium text-primary transition-colors hover:bg-gray dark:border-strokedark dark:hover:bg-meta-4" | |
| > | |
| {footerLabel} | |
| <svg | |
| width="12" | |
| height="12" | |
| viewBox="0 0 24 24" | |
| fill="none" | |
| stroke="currentColor" | |
| strokeWidth="2.5" | |
| strokeLinecap="round" | |
| strokeLinejoin="round" | |
| > | |
| <polyline points="9 18 15 12 9 6" /> | |
| </svg> | |
| </Link> | |
| </div> | |
| )} | |
| </li> | |
| </ClickOutside> | |
| ); | |
| }; |
| <div className="flex items-center justify-between border-b border-stroke px-4 py-3 dark:border-strokedark"> | ||
| <div> | ||
| <h5 className="text-sm font-semibold text-black dark:text-white">{title}</h5> | ||
| {notifying && ( | ||
| <p className="text-xs text-body dark:text-bodydark">{badgeCount} unread</p> | ||
| )} | ||
| </div> | ||
| <button | ||
| type="button" | ||
| onClick={onMarkAllRead} | ||
| className="text-xs font-medium text-primary hover:underline" | ||
| > | ||
| Mark all read | ||
| </button> |
There was a problem hiding this comment.
New user-facing strings in DropdownShell (e.g. "Mark all read" and the "unread" label) are hard-coded rather than going through @ciscode/ui-translate-core. Since the surrounding header UI is already localized, consider passing these labels in as props from the parent (where useT is available) or adding translation support directly in this component.
| test: { | ||
| environment: 'jsdom', | ||
| testDir: 'tests', | ||
| environment: 'happy-dom', |
There was a problem hiding this comment.
testDir is not a recognized Vitest config option (Vitest uses dir to set the tests root). As written, this setting will be ignored (or may break typechecking depending on Vitest version), so the suite may not run from the intended directory. Consider replacing testDir with dir, or remove it since include already scopes test files.
| "lint": "eslint -c eslint.config.mjs .", | ||
| "lint:fix": "eslint -c eslint.config.mjs . --fix", |
There was a problem hiding this comment.
The lint / lint:fix scripts were updated to use eslint.config.mjs, but lint-staged in this same package.json still runs eslint -c eslint.config.js --fix. Since the repo no longer contains eslint.config.js, pre-commit linting will fail. Update the lint-staged command to use eslint.config.mjs (or reference the same config as the scripts).
* Refactoring (#14) * chore(husky): remove deprecated bootstrap lines; style: run prettier write * chore: bump version to 1.0.2 * ci: run workflows on PRs to master * ci(e2e): strict port + no server reuse; enable release check on PRs to master * ci(e2e): bind dev server to 127.0.0.1; align Playwright URLs; increase timeouts * e2e: revert to localhost server defaults (no CI/CD changes) * ci: align PR validation and release-check workflows to master (develop triggers + conditional) * chore: push current workspace state * Develop (#12) * v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * chore: removed tracked dist files and empty directories & updated release workflow and gitignore * chore: updated husky pre-commit * chore: updated dependencies versions, ci/cd workflows, and fixed all lint & tc issues * fix: formatting issues --------- Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> * ops: updated worklofws triggers and enabled SonarQuality Gate * fix: prettier format warnings * ops: fixed syntax issues in yml file * ops: fixed SonarCloud integration * fix: format warning * chore: updated tests threshhold * ops: removed tests coverage from the release-check --------- Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> * 1.0.4 * ops: updated workflows files * docs: added copilot instructions * refactored following the copilot instructions file * fixed test errors --------- Co-authored-by: Zaiid Moumni <141942826+Zaiidmo@users.noreply.github.com> Co-authored-by: Zaiidmo <zaiidmoumnii@gmail.com> * chore: standardize workflows and ci/cd - Add [main] branch to release-check.yml - Update dependabot.yml configuration - Add sonarqube_mcp.instructions.md - Standardize Actions versions and Node versions - Pin SonarQube actions to commit SHA * chore: standardize workflows and ci/cd * chore: standardize npm scripts (lint, format, typecheck, test, build, clean, verify, prepublishOnly) * chore: added config files for eslint and prettier * chore: added comprehensive changesets for release automation * 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 * refactor: move instruction files to .github/instructions/ - Remove deprecated instruction files from .github/ root - Consolidate all docs in .github/instructions/ directory - Improve documentation organization * ops: UPDATED publish workflow and dependabot PR limits * 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 * security: added CODEOWNER file for branches security \\ * fix: lint-staged scripts * fix: vitest tests directory path * ops: updated relese check workflow# * ci: update release check workflow * ops: updated release check jobs * Bugfix/fix logout cache and navbar user (#16) * Develop (#12) * v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * chore: removed tracked dist files and empty directories & updated release workflow and gitignore * chore: updated husky pre-commit * chore: updated dependencies versions, ci/cd workflows, and fixed all lint & tc issues * fix: formatting issues --------- Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> * ops: updated worklofws triggers and enabled SonarQuality Gate * fix: prettier format warnings * ops: fixed syntax issues in yml file * ops: fixed SonarCloud integration * fix: format warning * chore: updated tests threshhold * ops: removed tests coverage from the release-check --------- Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> * 1.0.4 * ops: updated workflows files * docs: added copilot instructions * Refactoring (#14) (#15) * chore(husky): remove deprecated bootstrap lines; style: run prettier write * chore: bump version to 1.0.2 * ci: run workflows on PRs to master * ci(e2e): strict port + no server reuse; enable release check on PRs to master * ci(e2e): bind dev server to 127.0.0.1; align Playwright URLs; increase timeouts * e2e: revert to localhost server defaults (no CI/CD changes) * ci: align PR validation and release-check workflows to master (develop triggers + conditional) * chore: push current workspace state * Develop (#12) * v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * chore: removed tracked dist files and empty directories & updated release workflow and gitignore * chore: updated husky pre-commit * chore: updated dependencies versions, ci/cd workflows, and fixed all lint & tc issues * fix: formatting issues --------- * ops: updated worklofws triggers and enabled SonarQuality Gate * fix: prettier format warnings * ops: fixed syntax issues in yml file * ops: fixed SonarCloud integration * fix: format warning * chore: updated tests threshhold * ops: removed tests coverage from the release-check --------- * 1.0.4 * ops: updated workflows files * docs: added copilot instructions * refactored following the copilot instructions file * fixed test errors --------- Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> * refactor(widget): update header components and dashboard layout types * fix(package): add types condition to exports map for moduleResolution Bundler compatibility * style: apply prettier formatting to all files * fix(sonar): extract shared avatarUtils to remove duplication and replace charCodeAt with codePointAt * fix(sonar): use Array.at(-1) instead of length-based index * fix(typecheck): revert Array.at() to length-1 for ES2016 compat, add jest-dom types to tsconfig * fix(typecheck): add node types, fix any types, rename eslint config to .mjs * fix(widgetkit): resolve ESM/vitest compatibility, improve test coverage - Add type:module to package.json for Vite v7 ESM compatibility - Fix build:assets script to use --input-type=commonjs - Rename postcss.config.js to postcss.config.cjs, update eslint ignore - Switch test env from jsdom to happy-dom (fixes @exodus/bytes ESM conflict) - Exclude tests/e2e from vitest include patterns - Restore tsconfig types + add tests/globals.d.ts for jest-dom type augmentation - Stub window.alert in ZodDynamicForm test for happy-dom compatibility - Add useRegister tests (0% to 100% coverage) - Add TableDataCustomBase feature tests (sorting, filter, selection, inline-edit) - Add ZodDynamicForm field-type tests (textarea, select, multiSelect, custom, number) - Coverage: statements 63% to 96%, branches 43% to 76%, functions 56% to 96% * style(widgetkit): fix prettier formatting on 6 files * refactor(widgetkit/test): extract renderInlineEdit helper to reduce duplication --------- Co-authored-by: Zaiid Moumni <141942826+Zaiidmo@users.noreply.github.com> Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> Co-authored-by: Zaiidmo <zaiidmoumnii@gmail.com> Co-authored-by: saad moumou <saad.moumou.coder@gmail.com> * Bugfix/fix logout cache and navbar user (#17) * Develop (#12) * v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * chore: removed tracked dist files and empty directories & updated release workflow and gitignore * chore: updated husky pre-commit * chore: updated dependencies versions, ci/cd workflows, and fixed all lint & tc issues * fix: formatting issues --------- Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> * ops: updated worklofws triggers and enabled SonarQuality Gate * fix: prettier format warnings * ops: fixed syntax issues in yml file * ops: fixed SonarCloud integration * fix: format warning * chore: updated tests threshhold * ops: removed tests coverage from the release-check --------- Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> * 1.0.4 * ops: updated workflows files * docs: added copilot instructions * Refactoring (#14) (#15) * chore(husky): remove deprecated bootstrap lines; style: run prettier write * chore: bump version to 1.0.2 * ci: run workflows on PRs to master * ci(e2e): strict port + no server reuse; enable release check on PRs to master * ci(e2e): bind dev server to 127.0.0.1; align Playwright URLs; increase timeouts * e2e: revert to localhost server defaults (no CI/CD changes) * ci: align PR validation and release-check workflows to master (develop triggers + conditional) * chore: push current workspace state * Develop (#12) * v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * v1.0.3 * data tables done * 1.0.3 * dashboard widgets, resizable, drag and drop, with actions done * persist layout to local storage done * chore: removed tracked dist files and empty directories & updated release workflow and gitignore * chore: updated husky pre-commit * chore: updated dependencies versions, ci/cd workflows, and fixed all lint & tc issues * fix: formatting issues --------- * ops: updated worklofws triggers and enabled SonarQuality Gate * fix: prettier format warnings * ops: fixed syntax issues in yml file * ops: fixed SonarCloud integration * fix: format warning * chore: updated tests threshhold * ops: removed tests coverage from the release-check --------- * 1.0.4 * ops: updated workflows files * docs: added copilot instructions * refactored following the copilot instructions file * fixed test errors --------- Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> * refactor(widget): update header components and dashboard layout types * fix(package): add types condition to exports map for moduleResolution Bundler compatibility * style: apply prettier formatting to all files * fix(sonar): extract shared avatarUtils to remove duplication and replace charCodeAt with codePointAt * fix(sonar): use Array.at(-1) instead of length-based index * fix(typecheck): revert Array.at() to length-1 for ES2016 compat, add jest-dom types to tsconfig * fix(typecheck): add node types, fix any types, rename eslint config to .mjs * fix(widgetkit): resolve ESM/vitest compatibility, improve test coverage - Add type:module to package.json for Vite v7 ESM compatibility - Fix build:assets script to use --input-type=commonjs - Rename postcss.config.js to postcss.config.cjs, update eslint ignore - Switch test env from jsdom to happy-dom (fixes @exodus/bytes ESM conflict) - Exclude tests/e2e from vitest include patterns - Restore tsconfig types + add tests/globals.d.ts for jest-dom type augmentation - Stub window.alert in ZodDynamicForm test for happy-dom compatibility - Add useRegister tests (0% to 100% coverage) - Add TableDataCustomBase feature tests (sorting, filter, selection, inline-edit) - Add ZodDynamicForm field-type tests (textarea, select, multiSelect, custom, number) - Coverage: statements 63% to 96%, branches 43% to 76%, functions 56% to 96% * style(widgetkit): fix prettier formatting on 6 files * refactor(widgetkit/test): extract renderInlineEdit helper to reduce duplication * new version v1.0.5 --------- Co-authored-by: Zaiid Moumni <141942826+Zaiidmo@users.noreply.github.com> Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> Co-authored-by: Zaiidmo <zaiidmoumnii@gmail.com> Co-authored-by: saad moumou <saad.moumou.coder@gmail.com> * fix(ci): correct sonar.tests path from 'test' to 'tests', add .tsx to test inclusions * revert to config master file * style: format release-check.yml --------- Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> Co-authored-by: Zaiid Moumni <141942826+Zaiidmo@users.noreply.github.com> Co-authored-by: Zaiidmo <zaiidmoumnii@gmail.com> Co-authored-by: saad moumou <saad.moumou.coder@gmail.com>



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