Conversation
|
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (37)
WalkthroughConfiguration adds Tailwind/Prettier plugins and centralizes Tailwind safelist/blocklist. Grid utilities are refactored to class-based helpers; WidgetArea updated accordingly. Navigation gains active-state logic and onItemClick support; MobileMenu becomes controlled. OTP and verification UIs are reworked. Tables/layout receive scroll/spacing tweaks. Store persists theme; theme hook honors persisted selection. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant MobileMenu
participant Sheet
participant MainNavigation
Note over MobileMenu,Sheet: Sheet is controlled (open, onOpenChange)
User->>MobileMenu: Tap menu button
MobileMenu->>Sheet: open = true
Sheet->>MainNavigation: Render with onItemClick
User->>MainNavigation: Select nav item
MainNavigation-->>MobileMenu: onItemClick()
MobileMenu->>Sheet: setOpen(false)
Sheet-->>User: Closes
sequenceDiagram
autonumber
actor User
participant AccountVerify
participant EmailHook as useEmailVerification
participant SDK
participant Status as VerificationStatus
User->>AccountVerify: Open verify link (?token,&email)
AccountVerify->>EmailHook: init (user, params)
EmailHook->>SDK: requestEmailVerification(email fallback)
AccountVerify->>SDK: verifyEmail(token)
alt 200 OK
AccountVerify->>Status: isVerified=true
else 409 Conflict
AccountVerify->>Status: alreadyVerified=true
else error
AccountVerify->>Status: isError=true
end
User->>Status: Resend / Redirect
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Poem
✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 27
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
libs/portal-plugin-dashboard/src/ui/widgets/account/2fa.tsx (2)
70-83: Keep 44px touch target on md+ and prevent accidental form submitsh-9 (36px) on md+ may undercut recommended 44px targets; also add type="button" to avoid unintended form submissions inside forms.
- <Button - className="w-full h-11 whitespace-normal md:h-9 md:whitespace-nowrap" + <Button + type="button" + className="w-full h-11 whitespace-normal md:h-11 md:whitespace-nowrap" onClick={(e) => {
80-81: Fix wording: “Authorization” → “Authentication”User-facing label inconsistency.
- {identity?.otp && "Disable Two-Factor Authorization"} + {identity?.otp && "Disable Two-Factor Authentication"}libs/portal-plugin-dashboard/src/ui/widgets/account/delete.tsx (1)
24-29: Match accessible height on md+ and set explicit button typeKeep ≥44px height on md+ and guard against form-submit defaults.
- <Button - className="w-full h-11 whitespace-normal md:h-9 md:whitespace-nowrap" + <Button + type="button" + className="w-full h-11 whitespace-normal md:h-11 md:whitespace-nowrap" onClick={handleDeleteClick} variant="destructive">libs/portal-plugin-core/src/features/navigation.ts (1)
166-185: Child processing is only one level deep; recursively flatten to support nested menus.Current logic maps only direct children and ignores grandchildren. Use a recursive helper to emit a fully flattened list with correct parentId chain.
Apply:
- private processRouteForNavigation(route: RouteDefinition, pluginId: NamespacedId): NavigationItem[] { - const item = this.createNavigationItem(route, pluginId); - if (!item) { - return []; - } - - const childItems = - route.children - ?.filter((child) => this.shouldIncludeRouteInNavigation(child)) - .map((child) => { - const childItem = this.createNavigationItem(child, pluginId); - if (childItem) { - childItem.parentId = item.id; // Set parentId for navigation hierarchy - } - return childItem; - }) - .filter((item): item is NavigationItem => item !== null) ?? []; - - return [item, ...childItems]; - } + private processRouteForNavigation( + route: RouteDefinition, + pluginId: NamespacedId, + parentId?: NamespacedId + ): NavigationItem[] { + const item = this.createNavigationItem(route, pluginId); + if (!item) return []; + if (parentId) item.parentId = parentId; + + const results: NavigationItem[] = [item]; + for (const child of route.children ?? []) { + if (!this.shouldIncludeRouteInNavigation(child)) continue; + results.push( + ...this.processRouteForNavigation(child, pluginId, item.id), + ); + } + return results; + }libs/portal-framework-ui/src/components/MainNavigation.tsx (1)
141-161: InvokeonItemClickwhen header link is clicked (mobile close).Header link stops propagation but doesn’t call
onItemClick, so mobile Sheet may remain open.- {headerHref && item.linkable !== false ? ( + {headerHref && item.linkable !== false ? ( <Link aria-label={label} - onClick={(e) => e.stopPropagation()} + onClick={(e) => { + e.stopPropagation(); + onItemClick?.(); + }}
🧹 Nitpick comments (26)
libs/portal-plugin-dashboard/src/ui/components/EmailVerificationBanner.tsx (1)
42-49: A11y: hide spinner from SR and announce loading.
Make the icon non-announcable and expose a polite status for "Sending…".Apply this diff within the loading branch:
- {isLoading ? ( - <> - <Loader2 className="mr-2 h-4 w-4 animate-spin" /> - Sending... - </> - ) : ( + {isLoading ? ( + <span role="status" aria-live="polite" className="inline-flex items-center"> + <Loader2 className="mr-2 h-4 w-4 animate-spin" aria-hidden="true" focusable="false" /> + Sending… + </span> + ) : ( "Resend Verification Email" )}Optional: add aria-busy to the button for completeness:
<Button ... aria-busy={isLoading} />libs/portal-framework-ui/src/store/uiStore.ts (1)
19-20: Namespace the storage key to avoid collisions across packages/apps.“ui-store” is generic; collisions are likely in a monorepo. Prefer a scoped key.
Example:
- name: "ui-store", + name: "lumeweb.portal.ui",libs/portal-framework-ui/src/hooks/useTheme.tsx (2)
87-101: Prevent FOUC: apply theme in an isomorphic layout effect.Using
useEffectapplies after paint, causing a flash. Switch to an isomorphic layout effect to apply before paint on the client.Apply this diff:
import React, { useEffect } from "react"; +// Apply theme before paint on client; falls back to useEffect on server +const useIsomorphicLayoutEffect = + typeof window !== "undefined" ? React.useLayoutEffect : React.useEffect; @@ - useEffect(() => { + useIsomorphicLayoutEffect(() => { if (!themes) { return; }Also applies to: 1-1
4-4: Unify import path to avoid duplicate module instances.Mixing alias and relative paths for the same module can bloat bundles or break singletons.
Apply this diff:
-import { getThemeById } from "@/utils/theme"; +import { getThemeById, applyThemeStyles } from "@/utils/theme"; @@ -import { applyThemeStyles } from "../utils/theme";Also applies to: 9-9
libs/portal-plugin-dashboard/src/ui/widgets/account/password.tsx (1)
27-27: Avoid overflow on md+ by truncating instead of forcing nowrap.Long i18n strings may overflow when nowrap at md+. Prefer md:truncate to get ellipsis.
- className="w-full h-11 whitespace-normal md:h-9 md:whitespace-nowrap" + className="w-full h-11 whitespace-normal md:h-9 md:truncate".prettierrc.json (1)
7-9: Enable sorting inside cn()/clsx() calls and stabilize plugin resolution in a monorepo.Helps the plugin catch Tailwind classes within your cn helper and avoids plugin lookup pitfalls across packages.
"singleQuote": false, "trailingComma": "all", - "plugins": ["prettier-plugin-tailwindcss"] + "plugins": ["prettier-plugin-tailwindcss"], + "pluginSearchDirs": false, + "tailwindFunctions": ["cn", "clsx", "cva"]libs/portal-framework-core/package.json (1)
33-34: Reassess core → ui-core dependency (layering and transitive peers)Making “core” depend on a UI package can force React/DOM peers onto “core” consumers and complicate server/bundler setups. If “core” only needs classlist/config, consider:
- Extracting shared constants to a small “portal-framework-shared” (no React).
- Or depend on ui-core as a peer and import only side-effect-free subpaths.
Please confirm where @lumeweb/portal-framework-ui-core is imported inside “core”. If it’s only config/classlist, we can safely move to a shared or peer dependency.
libs/portal-framework-ui/src/components/form/SchemaForm.tsx (2)
63-70: Propagate notifications with stronger typing; consider RHF success parity.
- Type
config.errorNotification/config.successNotificationto the refine notification payload (e.g.,{ message: string; description?: string; type?: "success"|"error"|"info" } | false) instead ofanyfor safety and DX.- Currently only error notifications are surfaced for the non-"refine" adapter. If intentional parity is desired, also surface
successNotificationfor non-"refine" flows after successful submit.I can add types in
types.tsand wire a non-refine success notification hook-up if you confirm the desired UX.
118-137: Harden non-refine error notifications.
errorcan beunknown. Guard conversion to a notification payload to avoid runtime surprises and make failures deterministic.Apply:
- onError: async (error) => { + onError: async (error: unknown) => { if (adapterName !== "refine" && cConfig.errorNotification) { - const notification = - typeof cConfig.errorNotification === "function" - ? cConfig.errorNotification(error) - : cConfig.errorNotification; + const notification = + typeof cConfig.errorNotification === "function" + ? cConfig.errorNotification(error) + : cConfig.errorNotification; openNotification?.(notification); } },libs/portal-framework-auth/src/ui/components/login/OtpForm.tsx (1)
28-31: Guard navigation when redirect target is absent.
go({ to: parsed.params?.to, ... })withtoundefined may mis-route depending on refine version. Prefer an explicit fallback.Apply:
- if (!isAuthLoading && authData?.authenticated) { - go({ to: parsed.params?.to, type: "push" }); - } + if (!isAuthLoading && authData?.authenticated) { + const to = parsed.params?.to ?? "/"; + go({ to, type: "push" }); + }libs/portal-plugin-core/src/features/navigation.ts (1)
163-163: Clarify inclusion rule for index routes; consider honoring explicitshow === true.If consumers set
navigation.show = false, it still passes this filter and relies on render-time checks. If you want to prune earlier, consider integratinghidden === truehere as well.Apply:
- return !!route.navigation && (!route.index || route.navigation.forceShowInNavigation); + return ( + !!route.navigation && + (!route.index || route.navigation.forceShowInNavigation) && + route.navigation.hidden !== true + );shared/assets/tailwind.css (1)
68-76: Validate HSL variable compatibility and consider cross-browser fallbacks
- hsl(var(--background)) etc. require the referenced custom props to be HSL triplets; if your tokens emit hex or rgb, this will resolve invalidly. Please confirm the theme variables resolve to HSL components.
- Consider adding Firefox fallbacks (scrollbar-color, scrollbar-width) at base scope to keep styling consistent outside WebKit.
Example fallback (outside this block):
* { scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); scrollbar-width: thin; }libs/portal-framework-auth/src/ui/forms/otp.tsx (2)
30-34: Copy consistency: “authenticator code” vs field label “Confirmation Code”Either align the header to “Confirmation code” or the field label to “Authenticator code” to avoid mixed terminology.
- <h3 className="font-bold">Enter your authenticator code</h3> + <h3 className="font-bold">Enter your confirmation code</h3>
21-27: Enhance OTP input UX and validity hintsIf supported by your FormField component, add numeric-friendly attributes and length guards to reduce input errors.
Additional change (outside the selected range’s diff, adjust to your form API):
{ label: "Confirmation Code", name: "otp", placeholder: "Enter 6-digit code", required: true, type: FormFieldType.TEXT, inputProps: { inputMode: "numeric", autoComplete: "one-time-code", maxLength: 6, pattern: "\\d{6}" }, }libs/portal-framework-core/src/types/navigation.ts (2)
40-41: ID typing consistency with NamespacedIdRoute IDs are often namespaced; consider typing NavigationItem.id as NamespacedId for symmetry, or document when a plain string is expected.
66-68: show() signature may be too constrainedA zero-arg show(): boolean limits dynamic checks. Consider allowing a context param (e.g., user/route/permissions) for future-proofing.
libs/portal-framework-core/src/util/grid.ts (2)
241-246: Comment and breakpoint mismatchThe implementation uses a “tablet” breakpoint but the comment mentions “sm”.
-// Always default to 1 column on mobile, expand on sm and up +// Always default to 1 column on mobile, expand on tablet and up
150-155: Gap map looks good; ensure parity with classlist safelistYour GRID_GAP_CLASSES includes values (e.g., 14, 28, 36, 44, …) not present in classlist’s gaps array. Add these to the safelist patterns or rely solely on gap-.* pattern.
libs/portal-framework-ui-core/config/tailwind.config.ts (2)
6-6: Unify safelist naming and (optionally) wire blocklistFor consistency with other packages using
tailwindSafelist, consider importing that named export here as well. IftailwindBlocklistexists in classlist, wiringblocklistreduces CSS size.-import tailwindClassList from "./classlist"; +import tailwindClassList, { tailwindSafelist, tailwindBlocklist } from "./classlist"; @@ - safelist: tailwindClassList, + safelist: tailwindSafelist ?? tailwindClassList, + // Optional: + // blocklist: tailwindBlocklist,Also applies to: 19-19
4-5: Scrollbar plugin config: consider variant/optionsIf you need rounded scrollbars or to limit plugin impact, pass options (e.g.,
{ nocompatible: true }) and enable variants.-import tailwindcss_scrollbar from "tailwind-scrollbar"; +import tailwindcss_scrollbar from "tailwind-scrollbar"; @@ - plugins: [tailwindcss_animate, tailwindcss_scrollbar], + plugins: [tailwindcss_animate, tailwindcss_scrollbar({ nocompatible: true })], + // variants: { scrollbar: ["rounded"] },Also applies to: 17-18
libs/portal-framework-ui/src/components/data-table/DataTable.tsx (1)
36-41: Actions column width: avoidsize: 0and prefer explicit min width
size: 0may collapse the column depending on TanStack sizing; better omit it or set a sensible pixel size.- Use
min-w-12 w-12instead ofmax-w-24 w-12to enforce a floor.- meta: { - cellClassName: "max-w-24 w-12", - headerClassName: "max-w-24 w-12", - }, - size: 0, + meta: { + cellClassName: "w-12 min-w-12", + headerClassName: "w-12 min-w-12", + }, + // omit size to allow CSS width to control, or set an explicit px value: + // size: 48,Please confirm
BaseTableconsumesmeta.cellClassName/headerClassName; otherwise these classes won’t apply.libs/portal-plugin-dashboard/src/ui/forms/createApiKey.tsx (1)
11-13: Copy nit: add a period- description: - "Give your API key a descriptive name to help you identify its purpose", + description: + "Give your API key a descriptive name to help you identify its purpose.",libs/portal-framework-ui/src/components/layout/MobileMenu.tsx (1)
16-20: Controlled Sheet + close-on-click: LGTM; also close on route change.Current behavior is solid. Optionally auto-close when navigation occurs via other mechanisms (e.g., browser back).
Add:
+import { useLocation } from "react-router-dom"; ... export function MobileMenu() { const [open, setOpen] = React.useState(false); + const { pathname } = useLocation(); + React.useEffect(() => setOpen(false), [pathname]);Also applies to: 36-39
libs/portal-framework-ui/src/components/layout/DesktopSidebar.tsx (1)
23-23: Removing overflow-y-auto can cause footer overlap on short viewports.With
justify-between, large menus can push the bottom slogans off-screen. Either keep container scroll or ensure the nav area owns scrolling.Option A (restore container scroll):
- <div className="relative h-full flex flex-col px-3 py-4 justify-between"> + <div className="relative h-full flex flex-col px-3 py-4 overflow-y-auto justify-between">Option B (preferable: make inner nav region scrollable; ensure min-h-0 so ScrollArea can shrink):
- <div className="relative h-full flex flex-col px-3 py-4 justify-between"> + <div className="relative h-full flex flex-col px-3 py-4 justify-between min-h-0">Test with many nav items to confirm the slogans remain visible and the nav area scrolls.
libs/portal-framework-ui/src/components/MainNavigation.tsx (2)
189-199: Use stable keys for submenu items.Index keys can cause incorrect re-renders on reorder. Prefer
href.- {submenus.map(({ active, href, icon: Icon, label }, index) => ( + {submenus.map(({ active, href, icon: Icon, label }) => ( <Button asChild className="w-full justify-start h-10 mb-1" - key={index} + key={href}
27-39: Normalize paths to avoid trailing-slash edge cases.
startsWith(\${itemPath}/`)fails ifitemPathends with/`. Normalize both sides.-const isRouteActive = (item: NavigationItemType, currentPathname: string): boolean => { - const itemPath = item.path; +const isRouteActive = (item: NavigationItemType, currentPathname: string): boolean => { + const itemPath = item.path; if (!itemPath) return false; - if (itemPath === currentPathname) return true; - if (itemPath !== "/" && currentPathname.startsWith(`${itemPath}/`)) return true; + const norm = (p: string) => (p !== "/" ? p.replace(/\/+$/, "") : "/"); + const a = norm(itemPath); + const b = norm(currentPathname); + if (a === b) return true; + if (a !== "/" && b.startsWith(`${a}/`)) return true; return false; };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (37)
.prettierrc.json(1 hunks)apps/portal-app-shell/tailwind.config.ts(1 hunks)libs/portal-framework-auth/src/ui/components/login/OtpForm.tsx(4 hunks)libs/portal-framework-auth/src/ui/forms/otp.tsx(1 hunks)libs/portal-framework-core/package.json(1 hunks)libs/portal-framework-core/src/components/WidgetArea.tsx(2 hunks)libs/portal-framework-core/src/types/navigation.ts(1 hunks)libs/portal-framework-core/src/util/grid.ts(2 hunks)libs/portal-framework-ui-core/config/classlist.ts(1 hunks)libs/portal-framework-ui-core/config/tailwind.config.ts(3 hunks)libs/portal-framework-ui-core/package.json(2 hunks)libs/portal-framework-ui-core/src/components/ui/table.tsx(7 hunks)libs/portal-framework-ui/src/components/MainNavigation.tsx(8 hunks)libs/portal-framework-ui/src/components/data-table/BaseTableContent.tsx(2 hunks)libs/portal-framework-ui/src/components/data-table/DataTable.tsx(1 hunks)libs/portal-framework-ui/src/components/data-table/DefaultPagination.tsx(1 hunks)libs/portal-framework-ui/src/components/form/SchemaForm.tsx(1 hunks)libs/portal-framework-ui/src/components/layout/DesktopSidebar.tsx(1 hunks)libs/portal-framework-ui/src/components/layout/GeneralLayout.tsx(1 hunks)libs/portal-framework-ui/src/components/layout/MobileMenu.tsx(2 hunks)libs/portal-framework-ui/src/components/layout/SidebarToggle.tsx(1 hunks)libs/portal-framework-ui/src/hooks/useTheme.tsx(2 hunks)libs/portal-framework-ui/src/store/uiStore.ts(2 hunks)libs/portal-plugin-core/src/features/navigation.ts(2 hunks)libs/portal-plugin-dashboard/src/routes.tsx(5 hunks)libs/portal-plugin-dashboard/src/ui/components/EmailVerificationBanner.tsx(2 hunks)libs/portal-plugin-dashboard/src/ui/forms/createApiKey.tsx(3 hunks)libs/portal-plugin-dashboard/src/ui/forms/editProfile.tsx(1 hunks)libs/portal-plugin-dashboard/src/ui/hooks/useEmailVerification.ts(3 hunks)libs/portal-plugin-dashboard/src/ui/routes/account.api-keys.tsx(3 hunks)libs/portal-plugin-dashboard/src/ui/routes/account.verify.tsx(3 hunks)libs/portal-plugin-dashboard/src/ui/widgets/account/2fa.tsx(1 hunks)libs/portal-plugin-dashboard/src/ui/widgets/account/delete.tsx(1 hunks)libs/portal-plugin-dashboard/src/ui/widgets/account/password.tsx(1 hunks)libs/portal-plugin-dashboard/tailwind.config.ts(1 hunks)package.json(1 hunks)shared/assets/tailwind.css(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (18)
libs/portal-framework-auth/src/ui/components/login/OtpForm.tsx (2)
libs/portal-framework-auth/src/ui/components/common/AuthPage.tsx (1)
AuthPage(18-59)libs/portal-framework-auth/src/ui/components/common/AuthPageTitle.tsx (1)
AuthPageTitle(9-15)
libs/portal-framework-ui/src/components/layout/DesktopSidebar.tsx (1)
libs/portal-framework-ui/src/components/layout/SidebarToggle.tsx (1)
SidebarToggle(10-27)
libs/portal-plugin-dashboard/src/ui/routes/account.verify.tsx (2)
libs/portal-sdk/src/account/generated/accountAPI.schemas.ts (1)
Error(74-78)libs/portal-plugin-dashboard/src/ui/hooks/useEmailVerification.ts (1)
useEmailVerification(8-64)
libs/portal-plugin-dashboard/src/ui/routes/account.api-keys.tsx (1)
libs/portal-framework-ui/src/components/layout/PageHeader.tsx (1)
PageHeader(9-19)
libs/portal-framework-ui-core/config/classlist.ts (1)
go/portal-plugin-abuse-report/build/static/js/view-BD93An_3.js (1)
gaps(23925-23925)
apps/portal-app-shell/tailwind.config.ts (1)
libs/portal-framework-ui-core/config/classlist.ts (1)
tailwindSafelist(86-86)
libs/portal-framework-ui/src/components/data-table/BaseTableContent.tsx (1)
libs/portal-framework-ui-core/src/components/ui/table.tsx (5)
TableHeader(124-124)TableRow(125-125)TableHead(123-123)TableBody(119-119)TableCell(121-121)
libs/portal-plugin-core/src/features/navigation.ts (1)
libs/portal-framework-core/src/types/navigation.ts (1)
RouteDefinition(76-104)
libs/portal-framework-ui/src/hooks/useTheme.tsx (2)
libs/portal-framework-ui/src/hooks/usePluginMeta.ts (1)
usePluginMeta(6-12)libs/portal-shared/src/hooks/useTheme.tsx (1)
Theme(39-45)
libs/portal-framework-core/src/components/WidgetArea.tsx (1)
libs/portal-framework-core/src/util/grid.ts (8)
getGridAutoRows(122-134)getResponsiveGridTemplateColumnsClass(241-246)getGridStyles(162-201)getResponsiveGridColumnSpanClass(224-239)getGridRowSpanClass(157-160)getMinHeightClass(216-218)getMaxWidthClass(212-214)getMaxHeightClass(208-210)
libs/portal-plugin-dashboard/tailwind.config.ts (1)
libs/portal-framework-ui-core/config/classlist.ts (2)
tailwindSafelist(86-86)tailwindBlocklist(87-87)
libs/portal-plugin-dashboard/src/routes.tsx (1)
libs/portal-framework-core/src/types/navigation.ts (1)
RouteDefinition(76-104)
libs/portal-framework-ui/src/components/layout/MobileMenu.tsx (1)
libs/portal-framework-ui/src/components/MainNavigation.tsx (1)
MainNavigation(313-377)
libs/portal-framework-ui/src/components/layout/GeneralLayout.tsx (2)
libs/portal-framework-ui/src/components/layout/UserNav.tsx (1)
UserNav(26-94)libs/portal-framework-ui/src/components/layout/MobileMenu.tsx (1)
MobileMenu(15-43)
libs/portal-framework-ui/src/components/MainNavigation.tsx (1)
libs/portal-framework-core/src/types/navigation.ts (1)
NavigationItemIconProps(71-74)
libs/portal-plugin-dashboard/src/ui/hooks/useEmailVerification.ts (1)
go/portal-plugin-dashboard/build/static/js/useEmailVerification-Cq2zbvCo.js (1)
verifyAgain(19-51)
libs/portal-framework-core/src/types/navigation.ts (1)
libs/portal-framework-core/src/types/plugin.ts (1)
NamespacedId(18-18)
libs/portal-framework-core/src/util/grid.ts (2)
go/portal-plugin-abuse-report/build/static/js/view-BD93An_3.js (1)
rowHeight(11760-11764)libs/portal-framework-core/src/types/widget.ts (1)
DEFAULT_WIDGET_AREA_DEFINITION(22-28)
🔇 Additional comments (19)
libs/portal-plugin-dashboard/src/ui/components/EmailVerificationBanner.tsx (1)
9-9: LGTM: importing Loader2 for spinner is appropriate.
No issues spotted with the new import.libs/portal-framework-ui/src/store/uiStore.ts (1)
25-26: Hook wrapper looks good.Selector-based access via useStore(uiStore, selector) is correct and keeps the store private.
libs/portal-framework-ui/src/hooks/useTheme.tsx (1)
62-65: useTheme fallback looks solid.Returning
undefinedwhen no themes exist and then falling back to default/first theme is consistent with the HOC behavior.Also applies to: 77-77
package.json (1)
62-62: Manual verification required: The debug check did not confirm thatprettier-plugin-tailwindcsswas loaded under your pnpm workspaces setup. Please run the verification command in your CI environment (or adjust the grep pattern) and confirm the plugin is discovered and applied.libs/portal-plugin-dashboard/src/ui/forms/editProfile.tsx (1)
13-17: LGTM: responsive grid spans align with form gridFields span full width on small and split on md+, matching formClassName. Ensure these classes are included in the Tailwind safelist (looks covered by the new classlist module).
Also applies to: 19-23
libs/portal-plugin-dashboard/src/ui/hooks/useEmailVerification.ts (1)
61-61: No change needed: using React Query v4,isLoadingis correct. Project’s package.json specifies@tanstack/react-queryv4.36.1, and in v4useMutationexposesisLoadingrather thanisPending.libs/portal-framework-auth/src/ui/components/login/OtpForm.tsx (1)
38-47: LGTM: AuthPage wrapper improves UX and discoverability of reset flow.The composition is clean and preserves existing form behavior.
libs/portal-framework-core/src/components/WidgetArea.tsx (1)
24-28: Guard against missing widget area dataIf
framework.getWidgetArea(id)can return undefined,area.grid.*will throw. Add an early return or a reasonable fallback.Would you like me to add a null-guard and default layout grid (e.g., 1 column, auto rows)?
libs/portal-framework-ui-core/config/tailwind.config.ts (1)
107-109: Confirm breakpoint semantics
tablet: "1000px"sits betweenmd (768px)andlg (1024px). Verify component logic doesn’t assumesm < tablet < md < lg. If it does, rename to avoid confusion or adjust conditional utilities.libs/portal-plugin-dashboard/src/ui/forms/createApiKey.tsx (1)
21-25: Nice: success notification wiredGood addition; aligns with SchemaForm notification forwarding.
apps/portal-app-shell/tailwind.config.ts (1)
2-2: LGTM: central safelist sourceUsing the shared
tailwindSafelistkeeps configs consistent across packages.Also applies to: 7-7
libs/portal-plugin-dashboard/tailwind.config.ts (1)
3-3: Import looks good and centralizes classlists.Tying this config to the shared safelist/blocklist source is the right call for consistency.
libs/portal-framework-ui/src/components/layout/GeneralLayout.tsx (2)
21-23: Header/spacing reordering: LGTM.No functional change; spacing reads cleaner with margins on content container.
Also applies to: 28-28
19-19: Verified responsive offset mapping.MainWithResponsiveOffsetcorrectly applieslg:ml-40when collapsed andlg:ml-72when expanded with the sametransition-[margin-left] duration-300 ease-in-outbehavior.libs/portal-plugin-dashboard/src/routes.tsx (3)
55-58: Non-linkable parent: ensure menu renders without an anchor.
navigation.linkable: falseimplies the parent should toggle only. VerifyCollapseMenuButton/NavItemhonor this so it doesn’t create a clickable link.If not already handled, propagate
linkableinto the rendering logic to switch between link and button semantics (role, aria-expanded).
62-65: Normalize top-level route path conventions
Routes currently mix absolute (/dashboard,/account) and relative (login,register,otp,account/verify, etc.) paths. Pick one convention and apply it consistently:
- For absolute paths, prefix all
pathvalues with/.- For relative segments (React Router’s default for top-level routes), drop leading slashes on
/dashboardand/account.Apply the same rule to
account/verify,login,register,reset-password,otp, etc.
26-31: Incorrect — index route already omitspath.The route (libs/portal-plugin-dashboard/src/routes.tsx, id: "account_index") has
index: trueand nopathproperty; the suggested removal is unnecessary.Likely an incorrect or invalid review comment.
libs/portal-framework-ui/src/components/data-table/BaseTableContent.tsx (1)
73-76: Ensure emptyState renders valid table markup.
emptyStateis inserted directly under<TableBody>. If callers pass a non-<TableRow>, the table DOM becomes invalid.Consider enforcing a default empty row or documenting the contract. Example:
- : table.getRowModel().rows.length > 0 + : table.getRowModel().rows.length > 0 ? table.getRowModel().rows.map((row) => { ... - }) - : emptyState} + }) + : (emptyState ?? ( + <TableRow> + <TableCell colSpan={table.getAllColumns().length} className="text-center"> + No data + </TableCell> + </TableRow> + ))}Also applies to: 108-110
libs/portal-plugin-dashboard/src/ui/routes/account.api-keys.tsx (1)
45-46: Fix typo in actionButtonsLayout value- actionButtonsLayout: "horizonal", + actionButtonsLayout: "horizontal",
libs/portal-plugin-dashboard/src/ui/hooks/useEmailVerification.ts
Outdated
Show resolved
Hide resolved
…-ui-core, portal-plugin-core, portal-plugin-dashboard): modularize UI components and enhance navigation/item rendering logic - **Tailwind CSS Integration:** - Add `prettier-plugin-tailwindcss` for consistent class ordering in `.prettierrc.json` - Introduce `tailwind-scrollbar` plugin for custom scrollbar styling - Define scrollbar CSS variables in `shared/assets/tailwind.css` - Create `tailwindSafelist` and `tailwindBlocklist` in `libs/portal-framework-ui-core/config/classlist.ts` to optimize Tailwind's build output - Update `tailwind.config.ts` in both `portal-framework-ui-core` and `portal-plugin-dashboard` to utilize the new safelist/blocklist and add a `tablet` screen size - **Widget Area Refactor:** - Replace inline style generation with Tailwind CSS utility classes in `WidgetArea.tsx` - Add helper functions in `grid.ts` to generate Tailwind classes for grid layouts, column/row spans, and min/max dimensions - Use `cn` utility for dynamic class composition in widget rendering - **Navigation System Improvements:** - Add `linkable` and `forceShowInNavigation` properties to `NavigationItem` type - Refactor `MainNavigation.tsx` to support non-linkable parent items and index routes visibility - Implement `isRouteActive` and `isChildRouteActive` helper functions for precise active state determination - Create reusable `NavItemContent`, `LinkableNavItem`, and `NonLinkableNavItem` components - Update `CollapseMenuButton` to handle icons for submenus and reset open state for mobile - **Authentication UI Refactor:** - Wrap `OtpForm.tsx` content with new `AuthPage` component for consistent layout - Simplify OTP form header content and remove footer link in `otp.tsx` - **Email Verification Enhancements:** - Create dedicated components (`VerificationStatus`, `VerificationLoading`, etc.) for different verification states in `account.verify.tsx` - Add `MissingParametersError` component for handling incomplete verification links - Improve error handling to distinguish between general errors and "already verified" (409 Conflict) responses - **UI Component Adjustments:** - Add scrollbar styling class to `BaseTableContent.tsx` for horizontal overflow - Set explicit width/height classes for DataTable action columns in `DataTable.tsx` - Update `DefaultPagination.tsx` to handle zero page count gracefully - Add loader icon to resend button in `EmailVerificationBanner.tsx` - Adjust button sizing and whitespace handling in account widgets (`2fa.tsx`, `delete.tsx`, `password.tsx`) - Add success/error notification support to `SchemaForm.tsx` - Modify sidebar/desktop layout dimensions and spacing in `DesktopSidebar.tsx` and `GeneralLayout.tsx` - Fix mobile menu closing behavior in `MobileMenu.tsx` - Adjust sidebar toggle positioning in `SidebarToggle.tsx` - **Theme Management Refactor:** - Implement `persist` middleware in `uiStore.ts` to save selected theme - Update `useTheme` and `withTheme` hooks to prioritize persisted theme state - **Miscellaneous:** - Add `portal-framework-ui-core` as a dependency to `portal-framework-core` - Update route definitions in `portal-plugin-dashboard` to include icons and navigation properties
aded4a7 to
32726c8
Compare
Tailwind CSS Integration:
prettier-plugin-tailwindcssfor consistent class ordering in.prettierrc.jsontailwind-scrollbarplugin for custom scrollbar stylingshared/assets/tailwind.csstailwindSafelistandtailwindBlocklistinlibs/portal-framework-ui-core/config/classlist.tsto optimize Tailwind's build outputtailwind.config.tsin bothportal-framework-ui-coreandportal-plugin-dashboardto utilize the new safelist/blocklist and add atabletscreen sizeWidget Area Refactor:
WidgetArea.tsxgrid.tsto generate Tailwind classes for grid layouts, column/row spans, and min/max dimensionscnutility for dynamic class composition in widget renderingNavigation System Improvements:
linkableandforceShowInNavigationproperties toNavigationItemtypeMainNavigation.tsxto support non-linkable parent items and index routes visibilityisRouteActiveandisChildRouteActivehelper functions for precise active state determinationNavItemContent,LinkableNavItem, andNonLinkableNavItemcomponentsCollapseMenuButtonto handle icons for submenus and reset open state for mobileAuthentication UI Refactor:
OtpForm.tsxcontent with newAuthPagecomponent for consistent layoutotp.tsxEmail Verification Enhancements:
VerificationStatus,VerificationLoading, etc.) for different verification states inaccount.verify.tsxMissingParametersErrorcomponent for handling incomplete verification linksUI Component Adjustments:
BaseTableContent.tsxfor horizontal overflowDataTable.tsxDefaultPagination.tsxto handle zero page count gracefullyEmailVerificationBanner.tsx2fa.tsx,delete.tsx,password.tsx)SchemaForm.tsxDesktopSidebar.tsxandGeneralLayout.tsxMobileMenu.tsxSidebarToggle.tsxTheme Management Refactor:
persistmiddleware inuiStore.tsto save selected themeuseThemeandwithThemehooks to prioritize persisted theme stateMiscellaneous:
portal-framework-ui-coreas a dependency toportal-framework-coreportal-plugin-dashboardto include icons and navigation propertiesSummary by CodeRabbit
New Features
Improvements
UI/Style
Bug Fixes