Lewis/policies#83
Conversation
… and editor components - Reorganize policies directory structure with new (overview) and editor routes - Move policy-related hooks, actions, and types into more specific directories - Implement new PolicyEditor and RichTextEditor components with enhanced functionality - Add SaveStatus component for tracking editor save state - Create default and extended editor extensions - Improve type safety and code organization for policy management - Update Biome configuration to disable import sorting
…rm sections - Add new landing page components: WhyUs, OurSolution, HowItWorks, and CTA - Implement responsive design with Tailwind CSS and Shadcn UI - Update layout and styling for improved visual hierarchy - Add new marketing assets and images for platform features - Set default theme to dark mode - Enhance waitlist form with improved UX and styling - Optimize header and navigation components
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
1 Skipped Deployment
|
WalkthroughThis pull request encompasses a broad refactor across the project. It removes unused React hooks and outdated components, updates module import paths, and introduces new components—especially for policy management and rich text editing. Several UI components and layouts have been improved, while global styles, configuration settings, and a database seed script have been updated. The overall changes streamline the codebase, reorganize file structures, and refresh styling and functionality for both web and app contexts. Changes
Sequence Diagram(s)sequenceDiagram
participant U as User
participant P as PolicyEditor Page
participant A as Auth Service
participant D as PolicyDetails Component
U->>P: Navigate to Policy Editor
P->>P: Await params (locale, policyId) & set locale
P->>A: Call auth() for session
A-->>P: Return session with organizationId
alt Organization exists
P->>D: Render PolicyDetails with policyId
else Organization missing
P->>U: Redirect to "/"
end
Poem
✨ Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 5
🔭 Outside diff range comments (1)
apps/web/src/app/(home)/layout.tsx (1)
1-1: 🛠️ Refactor suggestionRemove unused import.
The
SiteFootercomponent is imported but not used in this file. According to the AI summary, it was removed from the layout, but the import statement wasn't cleaned up.-import { SiteFooter } from "../components/site-footer";
🧹 Nitpick comments (22)
packages/ui/src/editor.css (1)
69-74: Notice the removal of vertical padding from.ProseMirror.The removal of the
py-6utility class (previously providing vertical padding) reduces vertical spacing within the editor component. Please verify that this change is intentional and aligns with the new design expectations for the RichTextEditor. Confirm that overall readability and content spacing aren’t adversely affected across different screen sizes.packages/ui/src/components/badge.tsx (1)
18-19: Fix redundant border class in the marketing variant.There appears to be a duplicate
borderclass in the styling:border border. One of these should be removed to avoid redundancy.- "flex items-center opacity-80 px-3 font-mono gap-2 whitespace-nowrap border border bg-primary/10 text-primary hover:bg-primary/5 before:content-[''] before:absolute before:left-0 before:top-0 before:bottom-0 before:w-0.5 before:bg-primary", + "flex items-center opacity-80 px-3 font-mono gap-2 whitespace-nowrap border bg-primary/10 text-primary hover:bg-primary/5 before:content-[''] before:absolute before:left-0 before:top-0 before:bottom-0 before:w-0.5 before:bg-primary",Otherwise, the new
marketingvariant is well-structured and provides a consistent visual style that aligns with the existing variant patterns. The use of pseudo-elements for the left accent bar is an elegant approach.apps/app/src/components/editor/headers/status.tsx (3)
7-17: Consider using the imported Badge component instead of custom styling.The component imports
Badgefrom "@bubba/ui/badge" but doesn't use it. For consistency with your UI library, consider replacing the custom div with the Badge component.export function SaveStatus({ saveStatus }: SaveStatusProps) { return ( <div className="mx-auto w-full"> <div className="flex justify-end"> - <div className="flex items-center gap-1 bg-accent/60 px-2 py-1 rounded-md"> - <span className="text-muted-foreground text-xs">{saveStatus}</span> - </div> + <Badge variant="secondary" className="text-muted-foreground text-xs"> + {saveStatus} + </Badge> </div> </div> ); }
7-17: Add ARIA attributes for better accessibility.For users with screen readers, status changes should be announced. Consider adding appropriate ARIA attributes.
export function SaveStatus({ saveStatus }: SaveStatusProps) { return ( <div className="mx-auto w-full"> <div className="flex justify-end"> <div className="flex items-center gap-1 bg-accent/60 px-2 py-1 rounded-md" + role="status" + aria-live="polite" > <span className="text-muted-foreground text-xs">{saveStatus}</span> </div> </div> </div> ); }
9-15: Consider adding visual indicators beyond just text.For better usability, consider adding status-specific icons or colors to help users quickly identify the current state.
You could add different colors or icons for each status to make the state more immediately apparent:
<div className="flex justify-end"> <div className={`flex items-center gap-1 px-2 py-1 rounded-md ${ - "bg-accent/60" + saveStatus === "Saved" ? "bg-green-100" : + saveStatus === "Saving" ? "bg-blue-100" : "bg-amber-100" }`}> + {saveStatus === "Saved" && <CheckIcon className="h-3 w-3" />} + {saveStatus === "Saving" && <SpinnerIcon className="h-3 w-3 animate-spin" />} + {saveStatus === "Unsaved" && <AlertIcon className="h-3 w-3" />} <span className="text-muted-foreground text-xs">{saveStatus}</span> </div> </div>Note: You would need to import the appropriate icons.
apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/editor/components/PolicyHeader.tsx (1)
1-17: Well-structured status indicator componentThis is a clean implementation of a save status indicator component with proper typing and focused responsibility.
Consider enhancing the visual differentiation between statuses by using different colors or icons for each state. For example:
- <div className="flex items-center gap-1 bg-accent/60 px-2 py-1 rounded-md"> - <span className="text-muted-foreground text-xs">{saveStatus}</span> + <div className={cn("flex items-center gap-1 px-2 py-1 rounded-md", { + "bg-green-100 dark:bg-green-900/20": saveStatus === "Saved", + "bg-yellow-100 dark:bg-yellow-900/20": saveStatus === "Saving", + "bg-red-100 dark:bg-red-900/20": saveStatus === "Unsaved", + })}> + <span className={cn("text-xs", { + "text-green-700 dark:text-green-300": saveStatus === "Saved", + "text-yellow-700 dark:text-yellow-300": saveStatus === "Saving", + "text-red-700 dark:text-red-300": saveStatus === "Unsaved", + })}>{saveStatus}</span>This would require importing the
cnutility which appears to be used elsewhere in the project.packages/db/prisma/seed.js (1)
299-325: Improved bidirectional relationship for evidence and control requirements.The update enhances the seed function by establishing a proper two-way relationship between evidence records and control requirements. Previously, evidence creation didn't update the control requirement with the evidence ID.
This bidirectional linking creates better data consistency and simplifies future queries, making it easier to navigate between related entities.
apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/editor/components/PolicyDetails.tsx (1)
55-70: Comprehensive error handling in save functionality.The save implementation properly:
- Updates status during the saving process
- Handles errors gracefully
- Provides feedback through state updates
Consider adding a toast notification or more visible feedback for users when an error occurs during saving, beyond just changing the status.
packages/ui/src/globals.css (4)
7-7: Slightly reduced brightness.Changing the background from 100% to 98% brightness is generally fine, but please confirm that the new shade meets your intended visual design and user accessibility requirements.
52-52: Check card background in dark mode.Confirm that reduced brightness (228 10% 10%) does not degrade text or component visibility on cards.
58-58: Revised secondary color.Observe that the secondary color changed to 225 10% 20%. If used for text or backgrounds, validate its readability.
64-64: Destructive color altered.Updating destructive to 0 60% 50% might feel less urgent than before. Ensure it remains attention-grabbing enough for destructive actions.
apps/app/src/components/editor/rich-text-editor.tsx (1)
46-83: Save state and debouncing logic.Using a debounced callback to delay save calls is a solid approach. However, if multiple quick edits happen, saves might overlap. Consider a cancellation or concurrency management approach if needed.
apps/app/src/components/editor/policy-editor.tsx (1)
20-20: Consider removing unused local state.
editorContentis stored but never read. If not needed for additional logic, removing it can simplify the code.- const [editorContent, setEditorContent] = useState<JSONContent | null>(null); ... - const handleUpdate = (updatedContent: JSONContent) => { - setEditorContent(updatedContent); - }; + // Remove this state if not needed, or use it if you plan to utilize the stored content later.apps/web/src/app/components/cta.tsx (1)
5-45: LGTM! Well-structured CTA component with good visual hierarchy.The implementation effectively separates decorative background elements from interactive content and uses proper z-indexing. The responsive design approach and use of Balancer for text wrapping are good practices.
Consider adding an aria-label or role="region" with an aria-labelledby attribute to the outer div for better accessibility:
- <div className="relative overflow-hidden bg-background py-24"> + <div className="relative overflow-hidden bg-background py-24" aria-label="Call to action section">apps/web/src/app/components/compliance-section.tsx (1)
39-39: Consider conditional priority for images.Setting priority={true} marks all instances of this component as high priority for loading, which might not be optimal if there are multiple instances on a page. Consider making this a prop or setting it only for the first or most important instance.
- priority={true} + priority={index === 0}Or add it as a prop:
interface ComplianceSectionProps { title: string; description: string; image: string; alt: string; index?: number; totalItems?: number; + priority?: boolean; } // Then in the component: - priority={true} + priority={priority}apps/web/src/app/components/how-it-works.tsx (2)
26-37: Consider refactoring image rendering for consistency and maintainabilityThe component has inconsistent image dimensions across different positions:
- Top image: height=400 (line 31)
- Bottom image: height=200 (line 54)
- Mobile image: height hardcoded to 200px via className (line 72)
This could lead to visual inconsistencies or layout shifts.
// Create a reusable image component to ensure consistency +function StepImage({ src, alt, priority, position }) { + const isDesktop = position !== "mobile"; + return ( + <Image + src={src} + alt={alt} + width={400} + height={position === "top" ? 400 : 200} + quality={100} + priority={priority} + loading={isDesktop ? undefined : "lazy"} + className={cn( + "object-contain", + !isDesktop && "w-full h-[200px]" + )} + /> + ); +}Also applies to: 49-60, 63-75
140-176: Reduce code duplication in responsive layout handlingThe component duplicates the
WorkflowStepcomponent for mobile and desktop views. Consider refactoring to use CSS for responsive behavior instead of duplicating component instances.<div className="flex flex-col justify-between md:h-full"> <div className="border-b"> {steps[1] && ( - <WorkflowStep - {...steps[1]} - imagePosition="top" - className="md:block hidden" - /> - )} - - {steps[1] && ( - <WorkflowStep - {...steps[1]} - className="md:hidden block" - imagePosition="bottom" - /> + <WorkflowStep + {...steps[1]} + imagePosition={{mobile: "bottom", desktop: "top"}} + className="block" /> )} </div> {/* Step 3 - bottom middle */} <div className="border-b md:border-none"> {steps[2] && ( - <WorkflowStep - {...steps[2]} - imagePosition="top" - className="md:block hidden" - /> - )} - {steps[2] && ( - <WorkflowStep - {...steps[2]} - className="md:hidden block" - imagePosition="bottom" + <WorkflowStep + {...steps[2]} + imagePosition={{mobile: "bottom", desktop: "top"}} + className="block" /> )} </div> </div>This would require updating the
WorkflowStepcomponent to handle the responsive behavior internally:interface WorkflowStepProps { // ... - imagePosition?: "top" | "bottom"; + imagePosition?: "top" | "bottom" | {mobile: "top" | "bottom", desktop: "top" | "bottom"}; // ... }apps/web/src/app/components/our-solution.tsx (4)
25-29: Enhance accessibility with aria-label for icon buttonsThe icon-only elements should have accessible labels for screen readers.
<div className={cn( "p-1 rounded-full mt-0.5", isPositive ? "bg-primary/10 text-primary border border-primary" : "bg-destructive/10 text-destructive", )} + aria-label={isPositive ? "Positive point" : "Negative point"} + role="img" > {isPositive ? <Check size={12} /> : <X size={12} />} </div>
27-28: Make text styling more consistentThe text color for negative items is set to
text-muted-foreground, but positive items don't have a specific text color class, which could lead to inconsistency.-<p className={cn("text-md", isPositive ? "" : "text-muted-foreground")}> +<p className={cn("text-md", isPositive ? "text-foreground" : "text-muted-foreground")}> {text} </p>
76-76: Review padding for mobile responsivenessThe component uses a fixed horizontal padding of
px-16, which might be too large for small mobile screens.-<div className={cn("container mx-auto px-16 py-24", className)}> +<div className={cn("container mx-auto px-4 md:px-16 py-12 md:py-24", className)}>
94-124: Make column headings customizable and add empty state handlingThe column headings "The Problem" and "Our Solution" are hardcoded. Consider making them customizable via props and add handling for empty arrays.
interface OurSolutionProps { title?: string; subtitle?: string; + problemsTitle?: string; + solutionsTitle?: string; problems?: Array<{ id: string; text: string }>; solutions?: Array<{ id: string; text: string }>; className?: string; } export default function OurSolution({ title = "Every framework you need to win deals", subtitle = "Most compliance solutions are closed, costly, and complex. We're building an open-source platform to make SOC 2, ISO 27001, and GDPR accessible and affordable.", + problemsTitle = "The Problem", + solutionsTitle = "Our Solution", problems = [ /* ... */ ], solutions = [ /* ... */ ], className, }: OurSolutionProps) { // ... <div className="grid md:grid-cols-2 gap-8 md:gap-12 mt-8"> <div className="rounded-lg space-y-4"> <h3 className="text-2xl font-medium border-b border-border pb-4"> - The Problem + {problemsTitle} </h3> <div> - {problems.map((problem) => ( + {problems.length > 0 ? problems.map((problem) => ( <ProblemSolutionItem key={problem.id} text={problem.text} isPositive={false} /> - ))} + )) : ( + <p className="text-muted-foreground py-4">No problems defined.</p> + )} </div> </div> <div className="rounded-lg space-y-4"> <h3 className="text-2xl font-medium border-b border-border pb-4"> - Our Solution + {solutionsTitle} </h3> <div> - {solutions.map((solution) => ( + {solutions.length > 0 ? solutions.map((solution) => ( <ProblemSolutionItem key={solution.id} text={solution.text} isPositive={true} /> - ))} + )) : ( + <p className="text-muted-foreground py-4">No solutions defined.</p> + )} </div> </div> </div>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (10)
apps/web/public/assets/compliance-made-easy.pngis excluded by!**/*.pngapps/web/public/assets/cta-bg.pngis excluded by!**/*.pngapps/web/public/assets/enterprise-platform.pngis excluded by!**/*.pngapps/web/public/assets/evidence.pngis excluded by!**/*.pngapps/web/public/assets/export-audit.pngis excluded by!**/*.pngapps/web/public/assets/one-platform.pngis excluded by!**/*.pngapps/web/public/assets/overview.pngis excluded by!**/*.pngapps/web/public/assets/security-and-compliance.pngis excluded by!**/*.pngapps/web/public/assets/tech-stack.pngis excluded by!**/*.pngapps/web/public/assets/upload-evidence.pngis excluded by!**/*.png
📒 Files selected for processing (32)
apps/app/src/app/[locale]/(app)/(dashboard)/policies/(overview)/hooks/usePolicies.ts(0 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/policies/(overview)/hooks/usePolicy.ts(1 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/components/PolicyDetails.tsx(0 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/components/PolicyHeader.tsx(0 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/editor/actions/update-policy.ts(0 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/editor/components/PolicyDetails.tsx(1 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/editor/components/PolicyHeader.tsx(1 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/editor/page.tsx(1 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/layout.tsx(1 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/page.tsx(2 hunks)apps/app/src/components/editor/extensions.ts(1 hunks)apps/app/src/components/editor/headers/status.tsx(1 hunks)apps/app/src/components/editor/policy-editor.tsx(1 hunks)apps/app/src/components/editor/rich-text-editor.tsx(1 hunks)apps/web/src/app/(home)/layout.tsx(1 hunks)apps/web/src/app/(home)/page.tsx(1 hunks)apps/web/src/app/components/compliance-section.tsx(1 hunks)apps/web/src/app/components/cta.tsx(1 hunks)apps/web/src/app/components/how-it-works.tsx(1 hunks)apps/web/src/app/components/logo-header.tsx(1 hunks)apps/web/src/app/components/main-nav.tsx(1 hunks)apps/web/src/app/components/our-solution.tsx(1 hunks)apps/web/src/app/components/site-header.tsx(1 hunks)apps/web/src/app/components/waitlist-form.tsx(2 hunks)apps/web/src/app/components/why-us.tsx(1 hunks)apps/web/src/app/layout.tsx(1 hunks)biome.json(2 hunks)packages/db/prisma/seed.js(2 hunks)packages/ui/src/components/badge.tsx(2 hunks)packages/ui/src/components/button.tsx(2 hunks)packages/ui/src/editor.css(1 hunks)packages/ui/src/globals.css(3 hunks)
💤 Files with no reviewable changes (4)
- apps/app/src/app/[locale]/(app)/(dashboard)/policies/(overview)/hooks/usePolicies.ts
- apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/components/PolicyHeader.tsx
- apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/components/PolicyDetails.tsx
- apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/editor/actions/update-policy.ts
🔇 Additional comments (60)
apps/web/src/app/components/site-header.tsx (2)
5-5: CSS class simplification appears intentional.The header element's CSS classes have been simplified by removing
border-grid,z-50, andborder-bclasses. This styling change aligns with the broader refactoring mentioned in the PR summary. The component appears more streamlined while maintaining its core positioning properties.
1-13: ModeSwitcher component has been removed.The
ModeSwitcherimport and its associated JSX elements have been completely removed from this component. This appears to be an intentional simplification of the UI as part of the broader refactoring effort described in the PR summary.Is this change intentional? Please confirm that the mode-switching functionality is either no longer needed or has been implemented elsewhere in the application.
packages/ui/src/components/button.tsx (2)
13-13: Reduced width of left border decoration in default button variant.The pseudo-element width has been decreased from
before:w-2tobefore:w-1, making the left border decoration thinner. This is a visual styling change that creates a more subtle accent on the left side of default buttons.
23-23: Reduced width of left border decoration in action button variant.Similar to the default variant change, the pseudo-element width has been decreased from
before:w-2tobefore:w-1for the action variant. This change ensures consistent styling between button variants and creates a more refined look for the action buttons.packages/ui/src/components/badge.tsx (1)
6-6: Good addition of therelativepositioning.Adding the
relativeclass to the base styles is a good decision as it provides positioning context for any absolute positioned elements within the badge, particularly for the pseudo-elements used in the newmarketingvariant.apps/app/src/components/editor/headers/status.tsx (1)
1-5: Good interface definition with proper typing.The interface with string literal types for
saveStatusprovides clear type safety and documents the expected values.apps/app/src/components/editor/extensions.ts (4)
1-23: Good organization of imports for Tiptap extensions.The imports are well-structured and provide a comprehensive set of rich text editing capabilities.
24-57: Well-documented default extensions with thoughtful configuration.The
defaultExtensionsarray provides essential text formatting features with appropriate configurations. The JSDoc comment clearly explains its purpose.
73-83: Appropriate simplified extension set for basic editors.The
starterExtensionsarray provides a good minimal set using StarterKit with additional Underline and Link extensions.
85-90: Clear utility function for customizing extensions.The
createExtensionsfunction provides a clean way to extend the default set with custom extensions.apps/web/src/app/layout.tsx (1)
38-38: Verify intention behind theme changeThe defaultTheme has been changed from "system" to "dark" and the enableSystem prop has been removed. This means the application will no longer respect the user's system theme preference and will always default to dark mode.
Was this change intentional? Consider that respecting system theme preferences is a common accessibility practice.
biome.json (2)
4-4: Import organization disabledThe
organizeImportssetting has been changed fromenabled: truetoenabled: false. This means Biome will no longer automatically organize import statements in the codebase.This could lead to inconsistent import organization across files. Was this change intentional, perhaps due to conflicts with other tools or specific import ordering requirements?
7-10: Formatting improvement for ignore arrayThe ignore array has been reformatted for better readability while maintaining the same content.
apps/app/src/app/[locale]/(app)/(dashboard)/policies/(overview)/hooks/usePolicy.ts (1)
4-6: Path updates for project reorganizationThe import paths have been updated to reflect the reorganization of policy-related functionality into an
editorsubdirectory, maintaining a clearer separation of concerns in the codebase.apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/page.tsx (1)
7-7: Function renamed from PolicyDetailsPage to PolicyDetails.The function has been renamed while maintaining the same parameter structure.
apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/layout.tsx (2)
9-50: Well-structured layout component with proper navigation.This layout component effectively:
- Handles authentication and redirects
- Fetches policy data
- Provides navigation between policy overview and editor
- Properly renders children components
52-67: Effective caching implementation for policy data.The
getPolicyfunction is properly cached usingunstable_cache, which improves performance by reducing redundant database queries.Just note that
unstable_cacheis marked as unstable API in Next.js, so be prepared for potential changes in future Next.js versions.apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/editor/components/PolicyDetails.tsx (2)
16-81: Well-implemented PolicyDetails component with appropriate loading and error states.The component effectively:
- Manages loading states with skeleton UI
- Handles policy content formatting
- Implements proper save mechanics with status tracking
- Redirects when policy isn't found
49-53: Robust content formatting with type checking.The content formatting logic handles various potential data structures safely, ensuring the editor receives properly formatted content regardless of how it's stored.
packages/ui/src/globals.css (8)
50-50: Adjusting dark background hue.Ensure this new hue (228 10.2% 9.61%) remains consistent with your dark theme contrast goals.
54-54: Popover dark styling.Again, verify that the updated popover background (228 10% 10%) provides sufficient contrast and maintains a coherent dark mode appearance.
60-62: Muted and accent choices.Lines 60-62 introduce 225 10% 20% for muted and accent, plus a new muted-foreground of 210 1.1% 64.7%. Double-check the palette for clarity and avoid confusion between muted and accent usage.
66-68: Revised border, input, and ring values.Shifting border and input to 225-based hues and ring to 151 100% 43% influences focus/hover states. Confirm that each color remains functional in your UI flows.
116-123: New.grid-patternutility class.The CSS grid pattern is a neat visual effect. Looks good. Confirm no performance or layout conflicts arise where the pattern is used.
125-138: New.grid-fade-maskutility class.Excellent approach for creating a gradual mask effect. Check cross-browser compatibility for both
mask-imageand-webkit-mask-image.
140-149: New.dotted-borderutility class.A straightforward dotted border using repeating linear gradients. It’s concise and reusable—no issues noted.
151-160: New.shaped-gradientutility class.A well-defined radial gradient for decorative backgrounds. This should be very flexible for accenting headers or sections.
apps/app/src/components/editor/rich-text-editor.tsx (7)
1-23: Imports and initial setup.Bringing in TipTap, React hooks, icons, and a custom “use client” directive is fine. Watch for bundle size; ensure these imports remain necessary. Otherwise, this part looks good.
25-34: RichTextEditorProps interface.Clear definitions of optional props, including readOnly, placeholder, and saveDebounceMs, provide good flexibility. Nice job.
36-45: Editor component signature and defaults.Establishing default values (readOnly, placeholder, etc.) is clean. No concerns here.
85-109: Editor configuration andonUpdatecallback.The default extensions and onUpdate logic look correct. Good job setting up focus states and maintaining a “Saved” vs. “Unsaved” status. No major issues found.
111-125: Initializing editor content.Nice use of try/catch for error handling. The fallback to a safe “empty doc” scenario ensures no runtime meltdown if content is invalid. This code is correct and robust.
127-129: Loading state.Displaying a placeholder during editor init is user-friendly. Nothing to add here.
131-221: Bubble menu and final render.Offering bold/italic/underline, list toggles, etc., in a bubble menu is intuitive. The
SaveStatuscomponent to show saving state is helpful as well. Overall, a polished, well-structured implementation.apps/app/src/app/[locale]/(app)/(dashboard)/policies/[policyId]/editor/page.tsx (3)
1-6: Import statements and dependencies.Retrieving
auth, i18n, and hooking inPolicyDetailsis straightforward. No issues here.
8-24:PolicyEditorfunction logic.Awaiting params, checking session, and redirecting if the org ID is missing is neat. This ensures secure access. Looks good.
26-39:generateMetadatafunction.Properly setting locale and returning a translated title. Straightforward and essential for SEO. Good implementation.
apps/app/src/components/editor/policy-editor.tsx (7)
5-5: Import appears valid and aligns with the new editor usage.
No issues with importing theRichTextEditorcomponent as intended.
11-11: OptionalonSavetype is clear.
Defining it as an optional Promise-based callback is a good design choice for asynchronous saves.
18-18: DestructuringonSaveis consistent with the prop definition.
Ensures a clear handoff for the save logic. No concerns here.
24-27: Fallback content initialization is sensible.
Providing a default paragraph ensures the editor always has a valid starting point.
30-32:handleUpdatecallback updates local state.
The callback pattern is appropriate. But be mindful thateditorContentis currently not consumed elsewhere.
34-44: ValidatecontentToSave.contentbefore casting.
Casting toJSONContent[]is convenient but may cause runtime issues if the structure is invalid. Consider an additional check to ensurecontentToSave.contentis an array.
46-52: RichTextEditor integration looks correct.
Passing initial content, update, and save handlers, plus thereadOnlyflag, is straightforward and consistent with typical usage.apps/web/src/app/(home)/layout.tsx (1)
12-12: LGTM!Adding the
w-fullclass to ensure the main content takes the full width of its container is a good improvement.apps/web/src/app/components/main-nav.tsx (2)
8-8: LGTM!The change from right margin to top margin improves the vertical spacing of the navigation component.
10-10: Verify logo appearance with width-only constraint.The LogoHeader component now has only a width constraint (
w-48) without a height constraint. Verify that the logo maintains its proper aspect ratio and appearance without an explicit height.apps/web/src/app/components/waitlist-form.tsx (4)
66-66: UI consistency improvement with added height.Adding the
h-12class ensures the input field has a consistent height with the button, creating a more polished appearance.
70-70: Enhanced form validation with required attribute.Adding the
requiredattribute improves user experience by ensuring email submission before form processing, reducing unnecessary server requests.
82-82: Button height standardization.The explicit
h-12class ensures consistent height between the button and input field, creating a visually balanced form row.
87-87: Improved loading state text.Changed from "Joining..." to "Please wait..." which is a more universally appropriate message while the form submission is processing.
apps/web/src/app/components/logo-header.tsx (2)
5-8: Logo dimensions and fill properties updated.The SVG dimensions have been reduced from 334×70 to 220×40, making it more compact. The fill has been changed from "none" to "currentColor" which allows the logo to inherit colors from parent elements, improving theme compatibility.
12-19: Simplified SVG structure with direct path definitions.The previous complex SVG structure with clip paths has been replaced with two direct path elements. This simplification makes the SVG more maintainable and potentially improves rendering performance.
apps/web/src/app/components/why-us.tsx (3)
6-28: Well-structured data array for dynamic content rendering.The sections array is well-organized, containing all necessary information for each marketing section including titles, descriptions, and image paths, making the component maintainable and easy to extend.
48-57: Effective use of dynamic rendering for marketing sections.The component efficiently maps through the sections array to render multiple ComplianceSection components, passing the appropriate props including an index for tracking. This pattern promotes DRY code principles and simplifies future content updates.
59-105: Responsive grid layout for feature highlights.The two-column grid layout with appropriate spacing and borders creates a clean visual separation between features. The consistent structure for each feature (image followed by title and description) enhances readability and user experience.
apps/web/src/app/(home)/page.tsx (3)
3-6: New component imports enhance page structure.The addition of specialized component imports (WhyUs, OurSolution, HowItWorks, CTA) indicates a more modular approach to page composition, improving code organization and maintenance.
11-20: Improved headline and messaging for better marketing clarity.The headline change to "Open Source Compliance Automation Platform" and the updated description provide a clearer value proposition. The increased font size (md:text-6xl) and adjusted spacing improve visual hierarchy.
25-39: Enhanced page structure with logical content sections.The restructured layout with distinct sections (WaitlistForm, WhyUs, OurSolution, HowItWorks, CTA) creates a natural user flow through the marketing content. The gradient background between sections adds visual interest and helps separate content areas.
apps/web/src/app/components/how-it-works.tsx (1)
132-184: Add error handling for missing stepsThe component doesn't handle the case where
stepsarray has fewer than 4 items. Consider adding a check to avoid rendering errors.<div className="grid grid-cols-1 md:grid-cols-3 border"> + {steps.length < 4 && <div className="text-muted-foreground p-4">Not enough steps provided. Expected at least 4 steps.</div>} + {steps.length >= 4 && ( + <> <div className="flex md:h-full md:border-r border-b md:border-b-0"> {steps[0] && ( <WorkflowStep {...steps[0]} imagePosition="bottom" /> )} </div> {/* Rest of the grid layout */} + </> + )} </div>
| /** | ||
| * Extended extensions that include table support | ||
| */ | ||
| export const extendedExtensions = [ | ||
| ...defaultExtensions, | ||
| Table.configure({ | ||
| resizable: true, | ||
| allowTableNodeSelection: true, | ||
| }), | ||
| TableRow, | ||
| TableHeader, | ||
| TableCell, | ||
| ]; |
There was a problem hiding this comment.
Remove duplicate table extensions in extendedExtensions.
Table-related extensions (Table, TableRow, TableHeader, TableCell) are already included in defaultExtensions (lines 50-56), making their inclusion here redundant and potentially problematic.
export const extendedExtensions = [
...defaultExtensions,
- Table.configure({
- resizable: true,
- allowTableNodeSelection: true,
- }),
- TableRow,
- TableHeader,
- TableCell,
];📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /** | |
| * Extended extensions that include table support | |
| */ | |
| export const extendedExtensions = [ | |
| ...defaultExtensions, | |
| Table.configure({ | |
| resizable: true, | |
| allowTableNodeSelection: true, | |
| }), | |
| TableRow, | |
| TableHeader, | |
| TableCell, | |
| ]; | |
| /** | |
| * Extended extensions that include table support | |
| */ | |
| export const extendedExtensions = [ | |
| ...defaultExtensions, | |
| ]; |
| } | ||
|
|
||
| return <PolicyDetails policyId={policyId} />; | ||
| return <>Hi</>; |
There was a problem hiding this comment.
Empty placeholder needs implementation.
The page is returning just "Hi" instead of rendering meaningful content. This appears to be an incomplete implementation.
This page should likely render appropriate policy content or components. Consider implementing the actual policy details view or adding a proper redirect if this page is being replaced by another route.
| src={image} | ||
| alt={title} | ||
| width={600} |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Use the provided alt prop instead of title for image accessibility.
The alt attribute for the Image component is using the title prop instead of the alt prop that's specifically provided in the props interface. This doesn't follow accessibility best practices.
<Image
src={image}
- alt={title}
+ alt={alt}
width={600}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| src={image} | |
| alt={title} | |
| width={600} | |
| src={image} | |
| alt={alt} | |
| width={600} |
| alt={title} | ||
| width={600} | ||
| height={600} | ||
| sizes="(max-height: 150px) 150px, 600px, (max-width: 400px) 400px, 600px" |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Fix the sizes attribute syntax.
The sizes attribute has syntax issues. It's trying to mix max-height and max-width conditions, which isn't the correct format for the sizes attribute.
- sizes="(max-height: 150px) 150px, 600px, (max-width: 400px) 400px, 600px"
+ sizes="(max-width: 400px) 400px, 600px"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| sizes="(max-height: 150px) 150px, 600px, (max-width: 400px) 400px, 600px" | |
| sizes="(max-width: 400px) 400px, 600px" |
| steps = [ | ||
| { | ||
| stepNumber: 1, | ||
| title: "Connect your tech stack", | ||
| description: | ||
| "Easily integrate with your existing tools like AWS, GCP, Azure, GitHub, Slack and more.", | ||
| image: "/assets/tech-stack.png", | ||
| }, | ||
| { | ||
| stepNumber: 2, | ||
| title: "Get an instant overview", | ||
| description: | ||
| "Get real-time insights into security gaps, misconfigurations, and compliance deviations.", | ||
| image: "/assets/overview.png", | ||
| }, | ||
| { | ||
| stepNumber: 3, | ||
| title: "Immediate action", | ||
| description: | ||
| "Receive immediate actions your company can take to help get you compliant.", | ||
| image: "/assets/upload-evidence.png", | ||
| }, | ||
| { | ||
| stepNumber: 4, | ||
| title: "Effortless audit preparation", | ||
| description: | ||
| "Generate comprehensive reports and evidence logs for auditors with one click.", | ||
| image: "/assets/export-audit.png", | ||
| }, |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Verify asset paths exist
The component references several asset paths like "/assets/tech-stack.png". Make sure these files exist in your public directory to avoid 404 errors.
🏁 Script executed:
#!/bin/bash
# Check if the image files referenced in the component exist
echo "Checking for image files in public directory..."
for img in "tech-stack.png" "overview.png" "upload-evidence.png" "export-audit.png"; do
if [ -f "public/assets/$img" ]; then
echo "✅ Found: public/assets/$img"
else
echo "❌ Missing: public/assets/$img"
fi
doneLength of output: 987
Asset Paths Issue: Update Required to Prevent 404 Errors
The asset files referenced in the component ("/assets/tech-stack.png", "/assets/overview.png", "/assets/upload-evidence.png", and "/assets/export-audit.png") were not found in the public/assets directory. Please address this by either adding the missing image files or updating the paths accordingly.
- Missing files:
public/assets/tech-stack.pngpublic/assets/overview.pngpublic/assets/upload-evidence.pngpublic/assets/export-audit.png
Summary by CodeRabbit
New Features
Refactor
Style
Chores