Skip to content

Add documantation markdown cms #124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 39 commits into
base: master
Choose a base branch
from
Open

Add documantation markdown cms #124

wants to merge 39 commits into from

Conversation

vLuckyyy
Copy link
Member

@vLuckyyy vLuckyyy commented May 9, 2025

No description provided.

Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Copy link

vercel bot commented May 9, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
website ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 8, 2025 2:02pm

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (17)
app/prism-languages.ts (1)

1-29: PrismJS languages set up nicely. Loading the key languages and extending TypeScript is on point. Consider translating the Polish comment (Dodaj inne języki według potrzeb) to English for consistency.

components/docs/DocCopyEnhancer.tsx (3)

8-8: Remove or translate non-English comment

The comment "już jest" should be in English for consistency.

-      if (preEl.querySelector(".copy-btn")) return; // już jest
+      if (preEl.querySelector(".copy-btn")) return; // already exists

15-21: Simplify string escaping in setTimeout callback

The template string in setTimeout has unnecessary escaped quotes.

-          btn.innerHTML = `<svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" viewBox=\"0 0 24 24\"><path d=\"M16 8v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8m4-4h6a2 2 0 0 1 2 2v2H4V6a2 2 0 0 1 2-2z\"/></svg>Copy`;
+          btn.innerHTML = `<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M16 8v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8m4-4h6a2 2 0 0 1 2 2v2H4V6a2 2 0 0 1 2-2z"/></svg>Copy`;

4-27: Consider a more React-like approach for DOM manipulation

While the current implementation works, using direct DOM manipulation in React can sometimes lead to issues. Consider using React refs and a more declarative approach:

"use client";
import { useEffect, useRef } from "react";

export default function DocCopyEnhancer() {
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);
  
  useEffect(() => {
    const addCopyButtons = () => {
      document.querySelectorAll(".prose pre").forEach((pre) => {
        const preEl = pre as HTMLElement;
        if (preEl.querySelector(".copy-btn")) return; // already exists
        
        const btn = document.createElement("button");
        btn.className =
          "copy-btn absolute top-3 right-4 z-10 flex items-center gap-1 rounded-md bg-[#23272e] text-gray-300 border border-gray-700 px-3 py-1 text-xs font-medium opacity-70 hover:opacity-100 hover:bg-[#181c23] hover:text-white transition-all shadow";
        btn.innerHTML = `<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M16 8v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8m4-4h6a2 2 0 0 1 2 2v2H4V6a2 2 0 0 1 2-2z"/></svg>Copy`;
        btn.type = "button";
        
        btn.onclick = async () => {
          await navigator.clipboard.writeText(preEl.innerText);
          btn.innerHTML = `<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"/></svg>Copied!`;
          
          // Clear any existing timeout
          if (timeoutRef.current) {
            clearTimeout(timeoutRef.current);
          }
          
          timeoutRef.current = setTimeout(() => {
            btn.innerHTML = `<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M16 8v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8m4-4h6a2 2 0 0 1 2 2v2H4V6a2 2 0 0 1 2-2z"/></svg>Copy`;
            timeoutRef.current = null;
          }, 1200);
        };
        
        preEl.style.position = "relative";
        preEl.appendChild(btn);
      });
    };
    
    // Run once on mount
    addCopyButtons();
    
    // Clean up timeouts on unmount
    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }
    };
  }, []);
  
  return null;
}
components/docs/DocSearch.tsx (1)

13-88: Nice search implementation with good user experience

The search component works well with debouncing, loading indicators, and clear result presentation. Here are a few small suggestions:

  1. Consider showing a message when no results are found but the query is valid
  2. Add keyboard navigation support for the dropdown results
  {results.length > 0 && (
    <div className="absolute z-10 mt-2 w-full rounded-lg border border-gray-200 bg-white shadow-lg dark:border-gray-700 dark:bg-gray-800">
      {results.map((result) => (
        <button
          key={result.path}
          onClick={() => {
            router.push(result.path);
            setQuery("");
            setResults([]);
          }}
          className="w-full px-4 py-2 text-left hover:bg-gray-100 focus:outline-none dark:hover:bg-gray-700"
        >
          <div className="font-medium text-gray-900 dark:text-white">
            {result.title}
          </div>
          <div className="text-sm text-gray-500 dark:text-gray-400">
            {result.excerpt}
          </div>
        </button>
      ))}
    </div>
  )}
+  {query.length >= 2 && results.length === 0 && !isLoading && (
+    <div className="absolute z-10 mt-2 w-full rounded-lg border border-gray-200 bg-white p-4 text-center text-sm text-gray-500 shadow-lg dark:border-gray-700 dark:bg-gray-800 dark:text-gray-400">
+      No results found
+    </div>
+  )}
components/docs/DocSidebar.tsx (1)

34-34: Remove redundant folder icon

This line adds a folder icon even though it's already handled in the hasChildren branch above.

-            {hasChildren && <Folder className="mr-2 h-4 w-4" />}
content/docs/formatting.md (2)

8-8: Minor grammar fix needed

Missing "the" article before "formatting options".

-Below you can find all formatting options supported in our documentation system.
+Below you can find all the formatting options supported in our documentation system.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~8-~8: You might be missing the article “the” here.
Context: ...atting Examples Below you can find all formatting options supported in our documentation ...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


1-99: Great documentation examples!

The formatting examples cover most common markdown features and custom components. It's very helpful for users.

Consider adding an example of a table, which is often useful in documentation:

## Tables

| Header 1 | Header 2 |
|----------|----------|
| Cell 1   | Cell 2   |
| Cell 3   | Cell 4   |
🧰 Tools
🪛 LanguageTool

[uncategorized] ~8-~8: You might be missing the article “the” here.
Context: ...atting Examples Below you can find all formatting options supported in our documentation ...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

app/api/docs/search/route.ts (2)

12-56: Consider adding search result limits.

The search function works well for small to medium documentation sets, but could benefit from a result limit to prevent performance issues with large document collections.

async function searchInDirectory(
  dir: string,
  query: string,
+ maxResults: number = 20
): Promise<SearchResult[]> {
  const results: SearchResult[] = [];
  const entries = await fs.readdir(dir, { withFileTypes: true });

  for (const entry of entries) {
    const fullPath = path.join(dir, entry.name);

+   // Stop searching if we've reached the maximum results
+   if (results.length >= maxResults) break;

    if (entry.isDirectory()) {
      const subResults = await searchInDirectory(fullPath, query);
      results.push(...subResults);
+     // Trim results if we've exceeded the maximum
+     if (results.length > maxResults) {
+       results.length = maxResults;
+       break;
+     }
    } else if (entry.isFile() && entry.name.endsWith(".md")) {
      // Rest of the code remains the same

36-41: Simple excerpt generation.

The excerpt creation works well, but consider adding a check for empty content to avoid empty excerpts.

const excerpt = markdownContent
  .split("\n")
  .slice(0, 3)
  .join(" ")
- .substring(0, 150);
+ .substring(0, 150) || "No content available";
app/docs/layout.tsx (2)

9-13: Font configuration is simple.

The Poppins font is configured with a single weight, which is efficient but might be limiting. Consider adding more weights if headers or emphasized text will use this font.


20-52: Layout structure is clean and responsive.

The documentation layout has a good responsive design with sidebar and main content areas.

- <div id="docs-navigation-buttons" className="flex w-full max-w-4xl justify-between">
-   {/* Przyciski Next/Previous będą renderowane w page.tsx */}
- </div>
+ <div id="docs-navigation-buttons" className="flex w-full max-w-4xl justify-between">
+   {/* Next/Previous buttons will be rendered in page.tsx */}
+ </div>
components/docs/AnimatedHeading.tsx (1)

4-68: Good factory pattern for heading components.

The createAnimatedHeading factory function efficiently generates heading components with consistent behavior.

Consider adding a fallback for browsers without clipboard API and translating the hardcoded text:

if (navigator.clipboard) {
  navigator.clipboard.writeText(
    window.location.origin + window.location.pathname + `#${headingId}`
  );
+} else {
+  // Fallback for browsers without clipboard API
+  const textArea = document.createElement('textarea');
+  textArea.value = window.location.origin + window.location.pathname + `#${headingId}`;
+  document.body.appendChild(textArea);
+  textArea.select();
+  document.execCommand('copy');
+  document.body.removeChild(textArea);
}

// Later in the code:
{copied && (
  <span className="animate-fade-in ml-2 text-xs text-green-500">
-   Skopiowano!
+   Copied!
  </span>
)}

// And change the aria-label:
-aria-label="Kopiuj link do nagłówka"
+aria-label="Copy link to heading"
app/docs/[...slug]/page.tsx (1)

64-105: Document rendering with MDX and navigation.

The document rendering includes title, description, content with custom components, and navigation links.

Consider making the navigation links styling more consistent:

<a
  href={prev.path}
- className="rounded-lg border border-gray-200 bg-gray-100 px-4 py-2 no-underline transition-colors hover:bg-gray-200 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700"
+ className="rounded-lg border border-gray-200 bg-gray-100 px-4 py-2 no-underline transition-colors hover:bg-gray-200 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700"
>
  ← {prev.title}
</a>

// Later for next link:
<a
  href={next.path}
- className="rounded-lg bg-blue-600 px-4 py-2 text-white no-underline transition-colors hover:bg-blue-700"
+ className="rounded-lg border border-blue-600 bg-blue-600 px-4 py-2 text-white no-underline transition-colors hover:bg-blue-700"
>
components/docs/CodeTabs.tsx (3)

18-19: Consider avoiding 'any' type.

The type casting with as any makes your code less type-safe. Try using more specific types to improve type checking.

- const Icon = (SIIcons as any)[iconName];
+ const Icon = (SIIcons as Record<string, React.ComponentType<{ className: string, title: string, size: number }>>)[iconName];

11-25: Add error handling for label formatting.

The icon name formatting assumes valid inputs. Consider adding validation or error handling for edge cases.

function getLanguageIcon(label: string) {
+  if (!label) return <span className="mr-1">📄</span>;
  const iconName =
    "Si" +
    label
      .replace(/[^a-zA-Z0-9]/g, "")
      .toLowerCase()
      .replace(/^./, (c) => c.toUpperCase());
  const Icon = (SIIcons as any)[iconName];
  if (Icon) return <Icon className="mr-1" title={label} size={18} />;
  return (
    <span className="mr-1" title={label}>
      📄
    </span>
  );
}

29-68: Add aria labels for better accessibility.

The tabs would benefit from additional ARIA attributes to improve screen reader experience.

  return (
-    <div className="my-6 overflow-hidden rounded-xl bg-gray-800 shadow">
+    <div className="my-6 overflow-hidden rounded-xl bg-gray-800 shadow" role="region" aria-label="Code examples">
      <TabGroup>
        <TabList className="flex space-x-1 px-2 pb-0 pl-4 pt-2">
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a502807 and 3bbd65a.

⛔ Files ignored due to path filters (2)
  • bun.lock is excluded by !**/*.lock
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (27)
  • app/api/docs/search/route.ts (1 hunks)
  • app/docs/[...slug]/page.tsx (1 hunks)
  • app/docs/layout.tsx (1 hunks)
  • app/docs/page.tsx (1 hunks)
  • app/globals.css (2 hunks)
  • app/layout.tsx (1 hunks)
  • app/page.tsx (1 hunks)
  • app/prism-languages.ts (1 hunks)
  • app/prism-tomorrow.css (1 hunks)
  • app/projects/page.tsx (2 hunks)
  • app/team/page.tsx (2 hunks)
  • components/docs/Alert.tsx (1 hunks)
  • components/docs/AnimatedHeading.tsx (1 hunks)
  • components/docs/CodeTabs.tsx (1 hunks)
  • components/docs/DocCopyEnhancer.tsx (1 hunks)
  • components/docs/DocSearch.tsx (1 hunks)
  • components/docs/DocSidebar.tsx (1 hunks)
  • components/docs/sidebar-structure.ts (1 hunks)
  • components/footer/Footer.tsx (1 hunks)
  • components/header/Navbar.tsx (1 hunks)
  • components/team/Team.tsx (1 hunks)
  • content/docs/formatting.md (1 hunks)
  • content/docs/getting-started/installation.md (1 hunks)
  • content/docs/getting-started/introduction.md (1 hunks)
  • lib/mdx.ts (1 hunks)
  • package.json (1 hunks)
  • tailwind.config.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (7)
app/projects/page.tsx (1)
components/header/hero/Hero.tsx (1)
  • Hero (8-41)
app/team/page.tsx (1)
components/header/hero/Hero.tsx (1)
  • Hero (8-41)
app/page.tsx (1)
components/header/hero/Hero.tsx (1)
  • Hero (8-41)
app/docs/page.tsx (1)
components/SectionTitle.tsx (1)
  • SectionTitle (3-24)
lib/mdx.ts (1)
components/docs/AnimatedHeading.tsx (4)
  • H1 (70-70)
  • H2 (71-71)
  • H3 (72-72)
  • H4 (73-73)
components/docs/DocSidebar.tsx (1)
components/docs/sidebar-structure.ts (2)
  • DocItem (1-5)
  • docsStructure (7-28)
app/docs/[...slug]/page.tsx (2)
components/docs/sidebar-structure.ts (1)
  • docsStructure (7-28)
lib/mdx.ts (1)
  • components (9-17)
🪛 LanguageTool
content/docs/formatting.md

[uncategorized] ~8-~8: You might be missing the article “the” here.
Context: ...atting Examples Below you can find all formatting options supported in our documentation ...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

🔇 Additional comments (34)
tailwind.config.ts (1)

19-22: Nice addition of typography plugin! Including @tailwindcss/typography will give you great default prose styles for your markdown content.

components/footer/Footer.tsx (1)

34-35: Footer text split looks good. Breaking the line improves readability without changing meaning.

app/prism-tomorrow.css (1)

1-124: Prism Tomorrow theme is correctly applied. The CSS covers code and inline blocks with a consistent dark palette.

app/projects/page.tsx (2)

3-3: Importing the Hero component is correct. This aligns with the other pages in your app.


16-16: Hero component added to main content. This will give the docs and projects pages a consistent look.

app/page.tsx (1)

4-4: Hero component added to home page

This change adds the Hero component from the header/hero directory to the home page. This is part of moving the Hero from the global layout to individual pages, which is a good approach for more specific control.

Also applies to: 12-12

app/team/page.tsx (1)

3-3: Hero component added to team page

The addition of the Hero component to the team page matches the same pattern used on the home page, creating consistent UI across the site.

Also applies to: 13-13

app/layout.tsx (1)

11-11: Added Prism language support

The import of Prism language configuration supports syntax highlighting for the new documentation system, replacing the previous Hero component that's now in individual pages.

components/header/Navbar.tsx (1)

29-32: Updated Documentation link

Changed the documentation link from external URL to internal path /docs, correctly updating the isExternal flag to match. This connects to the new internal documentation system being added.

components/team/Team.tsx (1)

100-101: Looks good!

Simple class order change that doesn't affect the visual appearance.

app/globals.css (4)

1-1: Good addition for code highlighting

Adding the Prism theme will help with syntax highlighting in the documentation.


6-12: Nice font styling for code blocks

Consistent font family helps make code more readable.


14-19: Good font consistency

Applying the same fonts to all code elements keeps things looking uniform.


34-41: Clean heading links

Removing decoration from heading links gives a cleaner look in documentation.

app/docs/page.tsx (1)

4-52: Good documentation landing page!

Nice, clean documentation page with clear section links. The layout is responsive and has good dark mode support.

content/docs/getting-started/introduction.md (1)

1-51: Well-structured introduction

Clear, organized content with good use of headings, lists, and code examples. This provides a helpful starting point for users.

components/docs/Alert.tsx (1)

1-20: Clean alert component implementation!

This alert component is well-structured with four different types (info, warning, danger, tip) and consistent styling for both light and dark modes. The component is simple and focused, making it easy to use in documentation.

components/docs/sidebar-structure.ts (1)

1-28: Well-organized sidebar structure!

The TypeScript interface and structure definition provide a clean way to organize documentation navigation. The hierarchy makes sense with main sections and child pages.

package.json (1)

14-36: Appropriate dependencies for documentation system

All the added dependencies support the documentation features described in the PR. The markdown processing, syntax highlighting, and UI libraries are current and work well together.

content/docs/getting-started/installation.md (1)

1-84: Good installation guide with a few placeholders to update

The installation instructions are clear, but there are some placeholders that should be updated before release:

  1. The repository URL is generic (line 22)
  2. Some linked pages at the end may not exist yet (lines 81-83)
  3. The guide mentions next-contentlayer which isn't in the package.json we reviewed

Could you confirm if the linked pages exist and if next-contentlayer should be added to the dependencies?

lib/mdx.ts (1)

1-27: Well-structured MDX configuration

The component mappings and plugin setup look good. This provides a solid foundation for the documentation system.

You might want to consider adding some configuration for rehypePrism to specify which languages to support explicitly.

app/api/docs/search/route.ts (4)

1-5: Imports look good.

The necessary imports are included for handling API routes, file operations, path manipulation, and markdown parsing.


6-10: Clean interface definition.

The SearchResult interface clearly defines the structure of search results with title, path, and excerpt.


29-35: Path normalization looks complex but correct.

The path normalization logic correctly converts file system paths to URL paths for the documentation.


58-74: Good error handling in the API route.

The GET handler properly handles missing queries and search errors with appropriate responses.

app/docs/layout.tsx (2)

1-8: Imports are appropriate.

All necessary components for the documentation layout are properly imported.


15-18: Good metadata for SEO.

The page title and description are appropriately set for search engine optimization.

components/docs/AnimatedHeading.tsx (2)

1-3: Client-side component with proper imports.

The component is correctly marked as a client component with the necessary imports.


70-73: Clean exports of heading components.

The heading components are exported clearly using the factory function.

app/docs/[...slug]/page.tsx (4)

1-8: Appropriate imports for document rendering.

All necessary imports for file system operations, MDX rendering, and navigation are included.


9-28: Utility function for flattening docs structure.

The flattenDocs function works correctly to create a linear navigation structure from the nested sidebar.


36-51: Good document fetching function.

The getDocBySlug function properly handles file reading and parsing, with error handling.


53-63: Clean page component setup with navigation.

The DocPage component correctly handles missing documents and sets up previous/next navigation.

components/docs/CodeTabs.tsx (1)

77-79: LGTM. Simple and effective component.

The CodeTab component is clean and focused on its purpose of being a container for tab content.

Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
vLuckyyy added 2 commits May 9, 2025 23:41
Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
components/docs/sidebar-structure.ts (1)

7-15: Good structure for the docs sidebar

This creates a clear hierarchy for the documentation. As the docs grow, you'll be able to easily add more sections and pages here.

Consider adding a brief comment explaining the purpose of this file for other developers who might work with it later.

app/globals.css (2)

6-12: Nice font setup—could DRY it up.

You’re repeating the same font list twice. Consider merging this block with the next to reduce duplication.


14-19: Good catch for inline code styling—ditto on DRYness.

This block and the one above share the same font-family. You could combine them into one selector.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2fc0ce8 and 592ca36.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • app/globals.css (2 hunks)
  • app/layout.tsx (2 hunks)
  • components/docs/AnimatedHeading.tsx (1 hunks)
  • components/docs/sidebar-structure.ts (1 hunks)
  • content/docs/documentation-editors/markdown-guide.md (1 hunks)
  • lib/mdx.ts (1 hunks)
  • package.json (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • content/docs/documentation-editors/markdown-guide.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • app/layout.tsx
  • package.json
  • components/docs/AnimatedHeading.tsx
  • lib/mdx.ts
🔇 Additional comments (8)
components/docs/sidebar-structure.ts (1)

1-5: Nice interface definition!

The DocItem interface looks well-structured and clearly defines what a documentation item should contain.

app/globals.css (7)

1-1: Check import path and load order.

Make sure prism-tomorrow.css lives at app/prism-tomorrow.css and that the theme is applied correctly when your docs render.


34-41: Good removal of heading link decoration.

Clears underlines and shadows so headings stay clean.


43-51: Solid table container styling.

Borders, rounding, and shadow will make your tables pop.


58-65: Table header cell styling looks great.

Padding, uppercase, and spacing will improve readability.


67-71: Body cell styling is solid.

Consistent padding and borders make for neat rows.


79-81: Dark mode header looks good.

A darker header background improves contrast in dark mode.


83-86: Dark mode cell borders and background are consistent.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
components/docs/DocSidebar.tsx (1)

19-19: Good fix for Tailwind class naming

The conditional class based on level is correctly implemented now, avoiding string interpolation that wouldn't work with Tailwind in production.

🧹 Nitpick comments (32)
components/docs/DynamicCommandsTable.tsx (2)

17-26: Consider making the URL configurable

The GitHub URL is hardcoded, which might make it difficult to update later or use different URLs in different environments.

+const COMMANDS_URL = process.env.NEXT_PUBLIC_COMMANDS_URL || 
+ "https://raw.githubusercontent.com/EternalCodeTeam/EternalCore/refs/heads/master/raw_commands_docs.json";

useEffect(() => {
-  fetch("https://raw.githubusercontent.com/EternalCodeTeam/EternalCore/refs/heads/master/raw_commands_docs.json")
+  fetch(COMMANDS_URL)
   .then((res) => {

44-51: Use stable keys for better React performance

Using array index as key may cause issues if the list order changes. Consider using the command name if it's unique.

-{commands.map((c, i) => (
-  <tr key={i}>
+{commands.map((c) => (
+  <tr key={c.name}>
components/docs/DynamicFeaturesTable.tsx (2)

16-25: Consider making the URL configurable

Similar to the commands table, the GitHub URL is hardcoded. Making it configurable would improve flexibility.

+const FEATURES_URL = process.env.NEXT_PUBLIC_FEATURES_URL || 
+ "https://raw.githubusercontent.com/EternalCodeTeam/EternalCore/refs/heads/master/raw_features_docs.json";

useEffect(() => {
-  fetch("https://raw.githubusercontent.com/EternalCodeTeam/EternalCore/refs/heads/master/raw_features_docs.json")
+  fetch(FEATURES_URL)
   .then((res) => {

42-52: Use stable keys for better React performance

Using array index as key may cause issues if the list order changes. Consider using the feature name if it's unique.

-{features.map((f, i) => (
-  <tr key={i}>
+{features.map((f) => (
+  <tr key={f.name}>
content/docs/eternalcore/introduction.md (1)

7-8: Fix minor grammar issues

There are two small grammar issues to address:

  1. Remove the comma before "that everyone needs"
  2. Add "The" before "Plugin includes" at the start of a sentence
-Plugin for minecraft servers that includes most basic functions and commands, that everyone needs. It's easy to use and configure. It's also very lightweight and fast.
-Plugin includes full support for teleportation, warps, homes and chat management.
+Plugin for minecraft servers that includes most basic functions and commands that everyone needs. It's easy to use and configure. It's also very lightweight and fast.
+The plugin includes full support for teleportation, warps, homes and chat management.
🧰 Tools
🪛 LanguageTool

[typographical] ~7-~7: Make sure that the comma (,) is correct. Do not use a comma before a dependent clause that starts with ‘that’.
Context: ...cludes most basic functions and commands, that everyone needs. It's easy to use and co...

(COMMA_THAT_NOUN)


[uncategorized] ~7-~7: A determiner appears to be missing. Consider inserting it.
Context: ...e. It's also very lightweight and fast. Plugin includes full support for teleportation...

(AI_EN_LECTOR_MISSING_DETERMINER)

content/docs/eternalcore/homes.md (2)

5-6: Remove redundant text

The phrase "EternalCore Homes" appears twice in succession. Consider removing the duplicate at the beginning of line 6.

# 🏠 EternalCore Homes
-EternalCore Homes is a feature that allows players to set their own homes and teleport to them.
+This feature allows players to set their own homes and teleport to them.
🧰 Tools
🪛 LanguageTool

[grammar] ~5-~5: This phrase is duplicated. You should probably use “EternalCore Homes” only once.
Context: ...-- title: EternalCore - Homes --- # 🏠 EternalCore Homes EternalCore Homes is a feature that allows players to set...

(PHRASE_REPETITION)


9-9: Refine grammar

Remove the article "a" before "permission" since it's an uncountable noun in this context.

-It is possible to configure the maximum number of homes for a given permission.
+It is possible to configure the maximum number of homes for given permissions.
🧰 Tools
🪛 LanguageTool

[grammar] ~9-~9: ‘a’ may be redundant when used with the uncountable noun ‘permission’.
Context: ...nfigure the maximum number of homes for a given permission. ```yaml # Homes Section homes: # Ma...

(A_UNCOUNTABLE_NOUN)

content/docs/eternalcombat/features.md (1)

15-15: Fix grammar

Add "the" before "all features."

-EternalCombat allows you to customize your combat experience. You can find all features below.
+EternalCombat allows you to customize your combat experience. You can find all the features below.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~15-~15: You might be missing the article “the” here.
Context: ...our combat experience. You can find all features below. - Combat duration, - Combat mes...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

content/docs/eternalcore/faq.md (3)

13-13: Add "the" before file names

-You can disable command in `commands.yml` file.
+You can disable command in the `commands.yml` file.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~13-~13: You might be missing the article “the” here.
Context: ...## Solution: You can disable command in commands.yml file. ### Example: ```yam...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


41-41: Grammar improvements

Several grammar fixes needed in this sentence.

-I want to create in game title with timer, but it keeps flickering on users screen.
+I want to create an in-game title with a timer, but it keeps flickering on users' screen.
🧰 Tools
🪛 LanguageTool

[style] ~41-~41: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ... title from flickering? ### Problem: I want to create in game title with timer, but it...

(REP_WANT_TO_VB)


[uncategorized] ~41-~41: Possible missing article found.
Context: ...ckering? ### Problem: I want to create in game title with timer, but it keeps fli...

(AI_HYDRA_LEO_MISSING_AN)


[uncategorized] ~41-~41: You might be missing the article “a” here.
Context: ...em: I want to create in game title with timer, but it keeps flickering on users scree...

(AI_EN_LECTOR_MISSING_DETERMINER_A)


[uncategorized] ~41-~41: It seems likely that a singular genitive (’s) apostrophe is missing.
Context: ... with timer, but it keeps flickering on users screen. ### Solution: You can use `tim...

(AI_HYDRA_LEO_APOSTROPHE_S_XS)


44-44: Add "the" before file names

-You can use `times` key in configuration file.
+You can use the `times` key in the configuration file.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~44-~44: You might be missing the article “the” here.
Context: ...sers screen. ### Solution: You can use times key in configuration file. ### E...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~44-~44: You might be missing the article “the” here.
Context: ...## Solution: You can use times key in configuration file. ### Example: ```yaml teleportT...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

content/docs/contribute/guide.md (4)

24-24: Improve code example clarity

Remove the curly braces from the URL placeholder to avoid confusion.

-git clone "{URL you just copied}"
+git clone "URL-you-just-copied"

36-36: Improve code example clarity

The branch name format in this example should match the one used in step 5.

-git checkout -b <your-new-branch-name>
+git checkout -b your-new-branch-name

47-47: Match branch name pattern with previous example

-git push origin add-your-branch-name
+git push origin your-new-branch-name

56-56: Fix loose punctuation

Remove the unexpected ":>" at the end of the sentence.

-You have successfully made a contribution to this project. :> 
+You have successfully made a contribution to this project! 
🧰 Tools
🪛 LanguageTool

[uncategorized] ~56-~56: Loose punctuation mark.
Context: ...ly made a contribution to this project. :>

(UNLIKELY_OPENING_PUNCTUATION)

components/docs/DocSidebar.tsx (1)

16-16: Translate comments to English

Use English comments for better maintainability.

-// Styl głównej kategorii
+// Main category style

-// Styl podkategorii
+// Subcategory style

Also applies to: 28-28

content/docs/eternalcombat/installation.md (3)

9-9: Capitalize and format “JAR” consistently
In the header it reads “jar” in plain text. For clarity and consistency, change to inline code or uppercase, e.g.:

- ### Step 1: Download ⬇️ the plugin and place the jar in the `plugins` folder 📂
+ ### Step 1: Download ⬇️ the plugin and place the `JAR` in the `plugins` folder 📂

16-16: Add missing comma after the config path
Insert a comma after the path so the sentence reads more naturally:

- In `plugins/EternalCombat/config.yml` you can configure the plugin to your liking.
+ In `plugins/EternalCombat/config.yml`, you can configure the plugin to your liking.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~16-~16: A comma might be missing here.
Context: ...mize the plugin to your needs. With any questions feel free to ask. ## ⚡ Upgrading 📝 **...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


33-33: Use present tense for consistency
Change “experienced” to “experience” to match earlier notes:

- 📝 **Note**: If you experienced problems after updating the plugin, use a configuration backup…
+ 📝 **Note**: If you experience problems after updating the plugin, use a configuration backup…
🧰 Tools
🪛 LanguageTool

[uncategorized] ~33-~33: This verb may not be in the correct tense. Consider changing the tense to fit the context better.
Context: ... after the update. 📝 Note: If you experienced problems after updating the plugin, use...

(AI_EN_LECTOR_REPLACEMENT_VERB_TENSE)

content/docs/eternalcore/installation.md (2)

9-9: Capitalize and format “JAR” consistently
Change “jar” to inline code or uppercase for clarity:

- ### Step 1: Download ⬇️ the plugin and place the jar in the `plugins` folder 📂
+ ### Step 1: Download ⬇️ the plugin and place the `JAR` in the `plugins` folder 📂

30-30: Use present tense for consistency
Adjust “experienced” to “experience” in the upgrade note:

- 📝 **Note**: If you experienced problems after updating the plugin, use a configuration backup…
+ 📝 **Note**: If you experience problems after updating the plugin, use a configuration backup…
🧰 Tools
🪛 LanguageTool

[uncategorized] ~30-~30: This verb may not be in the correct tense. Consider changing the tense to fit the context better.
Context: ... after the update. 📝 Note: If you experienced problems after updating the plugin, use...

(AI_EN_LECTOR_REPLACEMENT_VERB_TENSE)

content/docs/eternalcore/using-api.md (7)

7-7: Add missing article “the”
Make the intro smoother:

- As part of open-source community, we support developers…
+ As part of the open-source community, we support developers…
🧰 Tools
🪛 LanguageTool

[uncategorized] ~7-~7: You might be missing the article “the” here.
Context: ...# EternalCore Developer API As part of open-source community, we support developers...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


11-12: Include “the” before key nouns
Improve clarity by adding “the”:

- To use our work in your plugin, You need to install correct artifact for your project. To use latest release check…
+ To use our work in your plugin, you need to install the correct artifact for your project. To use the latest release, check…
🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: You might be missing the article “the” here.
Context: ...ork in your plugin, You need to install correct artifact for your project. Our plugin s...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~12-~12: You might be missing the article “the” here.
Context: ...e Kotlin, Gradle Groovy and SBT. To use latest release check [maven repository](https:...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


102-104: Fix usage sentence grammar
Add comma and articles for readability:

- To use our API you need to create instance of `EternalCoreAPI` class. You can do it by using `EternalCoreApiProvider.provide()` method.
+ To use our API, you need to create an instance of the `EternalCoreAPI` class. You can do this by calling the `EternalCoreApiProvider.provide()` method.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~103-~103: Possible missing comma found.
Context: ...ill not work!** ## 📝 Usage To use our API you need to create instance of `Eternal...

(AI_HYDRA_LEO_MISSING_COMMA)


[uncategorized] ~103-~103: You might be missing the article “an” here.
Context: ...Usage To use our API you need to create instance of EternalCoreAPI class. You can do i...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ... our API you need to create instance of EternalCoreAPI class. You can do it by ...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ...lCoreAPIclass. You can do it by usingEternalCoreApiProvider.provide()` method...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


121-121: Clarify example phrasing
Add “of” and “an” for idiomatic English:

- Here is an example how to obtain instance of `AfkService`:
+ Here is an example of how to obtain an instance of `AfkService`:
🧰 Tools
🪛 LanguageTool

[uncategorized] ~121-~121: Possible missing preposition found.
Context: ...their own use cases. Here is an example how to obtain instance of AfkService: ``...

(AI_EN_LECTOR_MISSING_PREPOSITION)


[uncategorized] ~121-~121: You might be missing the article “an” here.
Context: ...cases. Here is an example how to obtain instance of AfkService: ```java public class ...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


138-138: Add comma and lowercase “you”
Improve flow and casing:

- After that You can use examples shown below.
+ After that, you can use the examples shown below.
🧰 Tools
🪛 LanguageTool

[typographical] ~138-~138: Consider adding a comma here.
Context: ... down the AfkService to your classes. After that You can use examples shown below. Chec...

(FOR_THAT_COMMA)


[uncategorized] ~138-~138: You might be missing the article “the” here.
Context: ...to your classes. After that You can use examples shown below. Check if the player is Af...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


159-159: Clarify CatboyService example phrasing
Add “of” and “an” for consistency:

- Here is an example how to obtain instance of `CatboyService`:
+ Here is an example of how to obtain an instance of `CatboyService`:
🧰 Tools
🪛 LanguageTool

[uncategorized] ~159-~159: Possible missing preposition found.
Context: ...their own use cases. Here is an example how to obtain instance of CatboyService: ...

(AI_EN_LECTOR_MISSING_PREPOSITION)


[uncategorized] ~159-~159: You might be missing the article “an” here.
Context: ...cases. Here is an example how to obtain instance of CatboyService: ```java public cla...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


176-176: Add comma and simplify wording
Improve readability:

- Using the instance of `CatboyService` the User is able to mark players as catboys and give them unique feature provided by `EternalCore`.
+ Using the instance of `CatboyService`, you can mark players as catboys and give them a unique feature provided by `EternalCore`.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~176-~176: A comma might be missing here.
Context: ... } } ``` Using the instance of CatboyService the User is able to mark players as cat...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[style] ~176-~176: As a shorter alternative for ‘able to’, consider using “can”.
Context: ...he instance of CatboyService the User is able to mark players as catboys and give them u...

(BE_ABLE_TO)


[uncategorized] ~176-~176: Possible missing article found.
Context: ...o mark players as catboys and give them unique feature provided by EternalCore. ```...

(AI_HYDRA_LEO_MISSING_A)


[uncategorized] ~176-~176: The grammatical number of this noun doesn’t look right. Consider replacing it.
Context: ...players as catboys and give them unique feature provided by EternalCore. ```java if ...

(AI_EN_LECTOR_REPLACEMENT_NOUN_NUMBER)

content/docs/documentation-editors/markdown-guide.md (1)

39-39: Remove stray character
There’s an extra “a” after “websites:”:

- Link to external websites:a
+ Link to external websites:
content/docs/eternalcombat/using-api.md (3)

7-7: Add missing article “the”
Smooth the opening sentence:

- As part of open-source community, we support developers…
+ As part of the open-source community, we support developers…
🧰 Tools
🪛 LanguageTool

[uncategorized] ~7-~7: You might be missing the article “the” here.
Context: ...PI --- # EternalCombat API As part of open-source community, we support developers...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


11-12: Include “the” before key nouns
Clarify the dependency instructions:

- To use our work in your plugin, You need to install correct artifact for your project. To use latest release check…
+ To use our work in your plugin, you need to install the correct artifact for your project. To use the latest release, check…
🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: You might be missing the article “the” here.
Context: ...ork in your plugin, You need to install correct artifact for your project. Our plugin s...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


102-104: Fix usage sentence grammar
Add comma and articles for readability:

- To use our API you need to create instance of `EternalCombatAPI` class. You can do it by using `EternalCombatAPI.getInstance()` method.
+ To use our API, you need to create an instance of the `EternalCombatAPI` class. You can do this by calling the `EternalCombatAPI.getInstance()` method.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~103-~103: A comma might be missing here.
Context: ...ill not work!** ## 📝 Usage To use our API you need to create instance of `Eternal...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~103-~103: You might be missing the article “an” here.
Context: ...Usage To use our API you need to create instance of EternalCombatAPI class. You can do...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ... our API you need to create instance of EternalCombatAPI class. You can do it b...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ...ombatAPIclass. You can do it by usingEternalCombatAPI.getInstance()` method. ...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 592ca36 and 3438429.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (24)
  • app/docs/[...slug]/page.tsx (1 hunks)
  • app/docs/layout.tsx (1 hunks)
  • app/prism-languages.ts (1 hunks)
  • components/docs/DocSidebar.tsx (1 hunks)
  • components/docs/DynamicCommandsTable.tsx (1 hunks)
  • components/docs/DynamicFeaturesTable.tsx (1 hunks)
  • components/docs/sidebar-structure.ts (1 hunks)
  • components/header/Navbar.tsx (1 hunks)
  • content/docs/contribute/guide.md (1 hunks)
  • content/docs/documentation-editors/markdown-guide.md (1 hunks)
  • content/docs/eternalcombat/features.md (1 hunks)
  • content/docs/eternalcombat/installation.md (1 hunks)
  • content/docs/eternalcombat/introduction.md (1 hunks)
  • content/docs/eternalcombat/using-api.md (1 hunks)
  • content/docs/eternalcore/faq.md (1 hunks)
  • content/docs/eternalcore/features.md (1 hunks)
  • content/docs/eternalcore/homes.md (1 hunks)
  • content/docs/eternalcore/installation.md (1 hunks)
  • content/docs/eternalcore/introduction.md (1 hunks)
  • content/docs/eternalcore/notifications.md (1 hunks)
  • content/docs/eternalcore/placeholders.md (1 hunks)
  • content/docs/eternalcore/using-api.md (1 hunks)
  • lib/mdx.ts (1 hunks)
  • package.json (1 hunks)
✅ Files skipped from review due to trivial changes (4)
  • content/docs/eternalcombat/introduction.md
  • content/docs/eternalcore/placeholders.md
  • content/docs/eternalcore/features.md
  • content/docs/eternalcore/notifications.md
🚧 Files skipped from review as they are similar to previous changes (6)
  • app/prism-languages.ts
  • components/header/Navbar.tsx
  • app/docs/layout.tsx
  • lib/mdx.ts
  • package.json
  • app/docs/[...slug]/page.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
components/docs/DocSidebar.tsx (1)
components/docs/sidebar-structure.ts (2)
  • DocItem (1-5)
  • docsStructure (7-46)
🪛 LanguageTool
content/docs/contribute/guide.md

[uncategorized] ~56-~56: Loose punctuation mark.
Context: ...ly made a contribution to this project. :>

(UNLIKELY_OPENING_PUNCTUATION)

content/docs/eternalcore/using-api.md

[uncategorized] ~7-~7: You might be missing the article “the” here.
Context: ...# EternalCore Developer API As part of open-source community, we support developers...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~11-~11: You might be missing the article “the” here.
Context: ...ork in your plugin, You need to install correct artifact for your project. Our plugin s...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~12-~12: You might be missing the article “the” here.
Context: ...e Kotlin, Gradle Groovy and SBT. To use latest release check [maven repository](https:...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~103-~103: Possible missing comma found.
Context: ...ill not work!** ## 📝 Usage To use our API you need to create instance of `Eternal...

(AI_HYDRA_LEO_MISSING_COMMA)


[uncategorized] ~103-~103: You might be missing the article “an” here.
Context: ...Usage To use our API you need to create instance of EternalCoreAPI class. You can do i...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ... our API you need to create instance of EternalCoreAPI class. You can do it by ...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ...lCoreAPIclass. You can do it by usingEternalCoreApiProvider.provide()` method...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~108-~108: You might be missing the article “an” here.
Context: ...iProvider.provide(); ``` After creating instance of api, the User gets access to various...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[uncategorized] ~121-~121: Possible missing preposition found.
Context: ...their own use cases. Here is an example how to obtain instance of AfkService: ``...

(AI_EN_LECTOR_MISSING_PREPOSITION)


[uncategorized] ~121-~121: You might be missing the article “an” here.
Context: ...cases. Here is an example how to obtain instance of AfkService: ```java public class ...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[typographical] ~138-~138: Consider adding a comma here.
Context: ... down the AfkService to your classes. After that You can use examples shown below. Chec...

(FOR_THAT_COMMA)


[uncategorized] ~138-~138: You might be missing the article “the” here.
Context: ...to your classes. After that You can use examples shown below. Check if the player is Af...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~159-~159: Possible missing preposition found.
Context: ...their own use cases. Here is an example how to obtain instance of CatboyService: ...

(AI_EN_LECTOR_MISSING_PREPOSITION)


[uncategorized] ~159-~159: You might be missing the article “an” here.
Context: ...cases. Here is an example how to obtain instance of CatboyService: ```java public cla...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[uncategorized] ~176-~176: A comma might be missing here.
Context: ... } } ``` Using the instance of CatboyService the User is able to mark players as cat...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[style] ~176-~176: As a shorter alternative for ‘able to’, consider using “can”.
Context: ...he instance of CatboyService the User is able to mark players as catboys and give them u...

(BE_ABLE_TO)


[uncategorized] ~176-~176: Possible missing article found.
Context: ...o mark players as catboys and give them unique feature provided by EternalCore. ```...

(AI_HYDRA_LEO_MISSING_A)


[uncategorized] ~176-~176: The grammatical number of this noun doesn’t look right. Consider replacing it.
Context: ...players as catboys and give them unique feature provided by EternalCore. ```java if ...

(AI_EN_LECTOR_REPLACEMENT_NOUN_NUMBER)

content/docs/eternalcombat/using-api.md

[uncategorized] ~7-~7: You might be missing the article “the” here.
Context: ...PI --- # EternalCombat API As part of open-source community, we support developers...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~11-~11: You might be missing the article “the” here.
Context: ...ork in your plugin, You need to install correct artifact for your project. Our plugin s...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~103-~103: A comma might be missing here.
Context: ...ill not work!** ## 📝 Usage To use our API you need to create instance of `Eternal...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~103-~103: You might be missing the article “an” here.
Context: ...Usage To use our API you need to create instance of EternalCombatAPI class. You can do...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ... our API you need to create instance of EternalCombatAPI class. You can do it b...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ...ombatAPIclass. You can do it by usingEternalCombatAPI.getInstance()` method. ...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~108-~108: You might be missing the article “an” here.
Context: ...tProvider.provide(); ``` After creating instance of api, the User gets access to various...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[uncategorized] ~124-~124: Possible missing preposition found.
Context: ...their own use cases. Here is an example how to obtain instance of FightManager: ...

(AI_EN_LECTOR_MISSING_PREPOSITION)


[uncategorized] ~124-~124: You might be missing the article “an” here.
Context: ...cases. Here is an example how to obtain instance of FightManager: ```java public clas...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[typographical] ~140-~140: Consider adding a comma here.
Context: ...own the FightManager to your classes. After that You can use examples shown below. Chec...

(FOR_THAT_COMMA)


[uncategorized] ~140-~140: You might be missing the article “the” here.
Context: ...to your classes. After that You can use examples shown below. Check if the player is in...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~142-~142: You might be missing the article “the” here.
Context: ...eck if the player is in combat by using FightManager class. Example: ```java i...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~164-~164: You might be missing the article “the” here.
Context: ... the player enters the fight or extends duration of the fight. The second type is the `...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~167-~167: Possible missing article found.
Context: ...vent types by using @EventHandler. In example below we check why the player was untag...

(AI_HYDRA_LEO_MISSING_THE)


[uncategorized] ~167-~167: Possible missing comma found.
Context: ...es by using @EventHandler. In example below we check why the player was untagged. ...

(AI_HYDRA_LEO_MISSING_COMMA)

content/docs/eternalcombat/features.md

[uncategorized] ~15-~15: You might be missing the article “the” here.
Context: ...our combat experience. You can find all features below. - Combat duration, - Combat mes...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~22-~22: You might be missing the article “a” here.
Context: ... - Disable block placing in areas above certain height, - Add combat-log to other entit...

(AI_EN_LECTOR_MISSING_DETERMINER_A)

content/docs/eternalcombat/installation.md

[uncategorized] ~16-~16: A comma might be missing here.
Context: ...mize the plugin to your needs. With any questions feel free to ask. ## ⚡ Upgrading 📝 **...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~33-~33: This verb may not be in the correct tense. Consider changing the tense to fit the context better.
Context: ... after the update. 📝 Note: If you experienced problems after updating the plugin, use...

(AI_EN_LECTOR_REPLACEMENT_VERB_TENSE)

content/docs/eternalcore/faq.md

[uncategorized] ~13-~13: You might be missing the article “the” here.
Context: ...## Solution: You can disable command in commands.yml file. ### Example: ```yam...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[style] ~28-~28: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...oblem: I want to format text in chat. I want to style it, color it, etc. ### Solution:...

(REP_WANT_TO_VB)


[style] ~41-~41: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ... title from flickering? ### Problem: I want to create in game title with timer, but it...

(REP_WANT_TO_VB)


[uncategorized] ~41-~41: Possible missing article found.
Context: ...ckering? ### Problem: I want to create in game title with timer, but it keeps fli...

(AI_HYDRA_LEO_MISSING_AN)


[uncategorized] ~41-~41: You might be missing the article “a” here.
Context: ...em: I want to create in game title with timer, but it keeps flickering on users scree...

(AI_EN_LECTOR_MISSING_DETERMINER_A)


[uncategorized] ~41-~41: It seems likely that a singular genitive (’s) apostrophe is missing.
Context: ... with timer, but it keeps flickering on users screen. ### Solution: You can use `tim...

(AI_HYDRA_LEO_APOSTROPHE_S_XS)


[uncategorized] ~44-~44: You might be missing the article “the” here.
Context: ...sers screen. ### Solution: You can use times key in configuration file. ### E...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~44-~44: You might be missing the article “the” here.
Context: ...## Solution: You can use times key in configuration file. ### Example: ```yaml teleportT...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

content/docs/eternalcore/homes.md

[grammar] ~5-~5: This phrase is duplicated. You should probably use “EternalCore Homes” only once.
Context: ...-- title: EternalCore - Homes --- # 🏠 EternalCore Homes EternalCore Homes is a feature that allows players to set...

(PHRASE_REPETITION)


[grammar] ~9-~9: ‘a’ may be redundant when used with the uncountable noun ‘permission’.
Context: ...nfigure the maximum number of homes for a given permission. ```yaml # Homes Section homes: # Ma...

(A_UNCOUNTABLE_NOUN)

content/docs/eternalcore/installation.md

[uncategorized] ~30-~30: This verb may not be in the correct tense. Consider changing the tense to fit the context better.
Context: ... after the update. 📝 Note: If you experienced problems after updating the plugin, use...

(AI_EN_LECTOR_REPLACEMENT_VERB_TENSE)

content/docs/eternalcore/introduction.md

[typographical] ~7-~7: Make sure that the comma (,) is correct. Do not use a comma before a dependent clause that starts with ‘that’.
Context: ...cludes most basic functions and commands, that everyone needs. It's easy to use and co...

(COMMA_THAT_NOUN)


[uncategorized] ~7-~7: A determiner appears to be missing. Consider inserting it.
Context: ...e. It's also very lightweight and fast. Plugin includes full support for teleportation...

(AI_EN_LECTOR_MISSING_DETERMINER)

🪛 markdownlint-cli2 (0.17.2)
content/docs/documentation-editors/markdown-guide.md

201-201: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

🪛 Biome (1.9.4)
components/docs/DocSidebar.tsx

[error] 22-22: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (2)
components/docs/sidebar-structure.ts (1)

1-46: Good sidebar structure!

The documentation structure is well-organized with clear hierarchical sections. This makes navigation intuitive for users.

content/docs/eternalcombat/features.md (1)

11-11: Note the TODO comment

There's a TODO comment to add a permissions table. Is this intended to be addressed in this PR or a future one?

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (45)
hooks/useNavigation.ts (1)

5-21: Simple and effective navigation hook.

This hook is well-structured and handles menu state nicely. The memoized callbacks are a good touch to prevent unnecessary re-renders.

Consider adding a brief comment to explain what this hook does for other developers.

+'/**
+ * Hook to manage navigation menu state
+ * @returns Object containing menu state and toggle functions
+ */
 export const useNavigation = () => {
   const [isMenuOpen, setIsMenuOpen] = useState(false);
components/docs/ui/AnimatedHeading.tsx (5)

58-60: Consider translating or making messages configurable

The "Skopiowano!" message appears to be in Polish. Consider translating it to English or making these messages configurable for internationalization.

- <span className="animate-fade-in ml-2 text-xs text-green-500">
-   Skopiowano!
- </span>
+ <span className="animate-fade-in ml-2 text-xs text-green-500">
+   Copied!
+ </span>

14-18: Add fallback for browsers without clipboard API

Some older browsers might not support the navigator.clipboard API. Consider adding a fallback method.

 if (navigator.clipboard) {
   navigator.clipboard.writeText(
     window.location.origin + window.location.pathname + `#${headingId}`
   );
+} else {
+  // Fallback for browsers without clipboard API
+  const textArea = document.createElement("textarea");
+  const url = window.location.origin + window.location.pathname + `#${headingId}`;
+  textArea.value = url;
+  document.body.appendChild(textArea);
+  textArea.focus();
+  textArea.select();
+  try {
+    document.execCommand("copy");
+  } catch (err) {
+    console.error("Failed to copy URL: ", err);
+  }
+  document.body.removeChild(textArea);
 }

48-48: Consider translating ARIA label to match UI language

The aria-label is in Polish. If your interface is primarily in English, consider translating this for consistency.

- aria-label="Kopiuj link do nagłówka"
+ aria-label="Copy link to heading"

19-19: Consider adding smooth scrolling for better UX

Setting window.location.hash causes abrupt jumps. Consider using smooth scrolling for a better user experience.

- window.location.hash = headingId;
+ // Update URL without causing an abrupt jump
+ history.pushState(null, "", `#${headingId}`);
+ // Optional: Smooth scroll to the element
+ document.getElementById(headingId)?.scrollIntoView({ behavior: "smooth" });

35-53: Extract duplicate styling to reduce redundancy

There's duplicate styling between the main span and the anchor tag. Consider extracting these styles to reduce redundancy.

+ const commonStyles = {
+   textDecoration: "none",
+   display: "flex",
+   alignItems: "center",
+ };

 <span
   style={{
-    textDecoration: "none",
-    display: "inline-flex",
-    alignItems: "center",
+    ...commonStyles,
+    display: "inline-flex",
   }}
 >
   {children}
   {id ? (
     <>
       <a
         href={`#${id}`}
         onClick={handleCopy}
         className="underline-none ml-2 flex select-none items-center text-base text-gray-400 opacity-0 transition-opacity group-hover:opacity-100"
         aria-label="Kopiuj link do nagłówka"
         style={{
-          textDecoration: "none",
-          display: "flex",
-          alignItems: "center",
+          ...commonStyles,
         }}
       >
content/docs/eternalcore/homes.mdx (2)

5-6: Avoid repetition in heading and first sentence

The phrase "EternalCore Homes" is repeated in both the heading and first sentence. Consider rewording to avoid repetition.

 # 🏠 EternalCore Homes
-EternalCore Homes is a feature that allows players to set their own homes and teleport to them.
+This feature allows players to set their own homes and teleport to them.
🧰 Tools
🪛 LanguageTool

[grammar] ~5-~5: This phrase is duplicated. You should probably use “EternalCore Homes” only once.
Context: ...-- title: EternalCore - Homes --- # 🏠 EternalCore Homes EternalCore Homes is a feature that allows players to set...

(PHRASE_REPETITION)


8-9: Improve grammar in sentence about permissions

The article 'a' is redundant when used with the uncountable noun 'permission'.

 ## 🔒 Homes limit per permission 
-It is possible to configure the maximum number of homes for a given permission.
+It is possible to configure the maximum number of homes for given permissions.

Alternatively:

 ## 🔒 Homes limit per permission 
-It is possible to configure the maximum number of homes for a given permission.
+It is possible to configure the maximum number of homes for each permission.
🧰 Tools
🪛 LanguageTool

[grammar] ~9-~9: ‘a’ may be redundant when used with the uncountable noun ‘permission’.
Context: ...nfigure the maximum number of homes for a given permission. ```yaml # Homes Section homes: # Ma...

(A_UNCOUNTABLE_NOUN)

content/docs/contribute/guide.mdx (4)

56-56: Consider using a more professional closing

The ":>" emoticon at the end seems informal for documentation. Consider using a more professional closing or removing it.

-You have successfully made a contribution to this project. :> 
+You have successfully made a contribution to this project!
🧰 Tools
🪛 LanguageTool

[uncategorized] ~56-~56: Loose punctuation mark.
Context: ...ly made a contribution to this project. :>

(UNLIKELY_OPENING_PUNCTUATION)


11-14: Fix punctuation consistency in list

The list has inconsistent punctuation. The last item ends with a period, but previous items don't.

 - [ChatFormatter](https://github.com/EternalCodeTeam/ChatFormatter)
 - [EternalCore](https://github.com/EternalCodeTeam/EternalCore)
 - [GitCheck](https://github.com/EternalCodeTeam/GitCheck)
-- [EternalCombat](https://github.com/EternalCodeTeam/EternalCombat).
+- [EternalCombat](https://github.com/EternalCodeTeam/EternalCombat)

24-24: Use a clearer example for the clone command

The placeholder in quotes might confuse users. Consider using a more explicit example.

-git clone "{URL you just copied}"
+git clone "https://github.com/yourusername/repository-name.git"

36-36: Use a more descriptive branch name example

The current placeholder might not clearly indicate what format to use. Consider using a more practical example.

-git checkout -b <your-new-branch-name>
+git checkout -b feature/add-new-functionality
content/docs/eternalcombat/features.mdx (2)

15-15: Add "the" before "all features".

For better readability, change "You can find all features below" to "You can find all the features below."

🧰 Tools
🪛 LanguageTool

[uncategorized] ~15-~15: You might be missing the article “the” here.
Context: ...our combat experience. You can find all features below. - Combat duration, - Combat mes...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


17-23: Fix list formatting and grammar.

The list of features ends with a comma and is missing an article in one item:

- - Disable block placing in areas above certain height,
+ - Disable block placing in areas above a certain height

Also, consider ending the list with a period instead of a comma on the last item.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~22-~22: You might be missing the article “a” here.
Context: ... - Disable block placing in areas above certain height, - Add combat-log to other entit...

(AI_EN_LECTOR_MISSING_DETERMINER_A)

components/docs/layout/DocSidebar.tsx (3)

16-17: Translate Polish comments to English.

The comment "Styl głównej kategorii" should be in English for consistency.

- // Styl głównej kategorii
+ // Main category style

22-22: Use optional chaining for better code style.

Replace the conditional check with optional chaining for cleaner code.

- {item.children && item.children.map((child) => renderDocItem(child, level + 1))}
+ {item.children?.map((child) => renderDocItem(child, level + 1))}
🧰 Tools
🪛 Biome (1.9.4)

[error] 22-22: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


28-28: Translate Polish comments to English.

The comment "Styl podkategorii" should be in English for consistency.

- // Styl podkategorii
+ // Subcategory style
components/ErrorBoundary.tsx (1)

25-27: Consider enhanced error logging.

For production environments, consider sending errors to a monitoring service instead of just logging to console.

components/docs/tables/DynamicFeaturesTable.tsx (3)

17-17: Consider making the URL configurable

The GitHub URL is hardcoded. It would be better to move this to an environment variable or config file for easier maintenance.


42-44: Avoid using index as key when possible

Using array index as the key prop can cause issues if items are reordered or filtered. Try using a unique identifier from the data instead.

-            <tr key={i}>
+            <tr key={f.name}>

47-49: Add error handling for missing description data

The code checks if description is an array but doesn't handle the case where it might be undefined or null.

-                {Array.isArray(f.description)
-                  ? f.description.map((d, j) => <div key={j}>{d}</div>)
-                  : f.description}
+                {Array.isArray(f.description)
+                  ? f.description.map((d, j) => <div key={j}>{d}</div>)
+                  : f.description || "-"}
content/docs/eternalcombat/installation.mdx (3)

16-16: Add a comma for better readability

Add a comma after "With any questions" to improve the sentence flow.

-In `plugins/EternalCombat/config.yml` you can configure the plugin to your liking. There are many options available, so you can customize the plugin to your needs. With any questions feel free to ask.
+In `plugins/EternalCombat/config.yml` you can configure the plugin to your liking. There are many options available, so you can customize the plugin to your needs. With any questions, feel free to ask.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~16-~16: A comma might be missing here.
Context: ...mize the plugin to your needs. With any questions feel free to ask. ## ⚡ Upgrading 📝 **...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


21-22: Add a direct download link

Consider adding a direct link or more specific instructions on where to download the plugin.

-Download the latest version of EternalCombat from the project website.
+Download the latest version of EternalCombat from [our GitHub releases page](https://github.com/EternalCodeTeam/EternalCombat/releases) or the project website.

33-33: Fix verb tense for consistency

Change "experienced" to "experience" to match the conditional context.

-📝 **Note**: If you experienced problems after updating the plugin, use a configuration backup to restore the previous settings and avoid data loss.
+📝 **Note**: If you experience problems after updating the plugin, use a configuration backup to restore the previous settings and avoid data loss.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~33-~33: This verb may not be in the correct tense. Consider changing the tense to fit the context better.
Context: ... after the update. 📝 Note: If you experienced problems after updating the plugin, use...

(AI_EN_LECTOR_REPLACEMENT_VERB_TENSE)

components/docs/layout/DocSearch.tsx (3)

48-54: Add accessibility attributes to the search input

The search input should have accessibility attributes for better screen reader support.

<input
  type="text"
  value={query}
  onChange={(e) => setQuery(e.target.value)}
  placeholder="Search documentation..."
+ aria-label="Search documentation"
+ role="searchbox"
  className="w-full rounded-lg border border-gray-300 bg-white px-4 py-2 pl-10 text-sm shadow-sm transition-shadow focus:border-gray-400 focus:shadow-lg focus:outline-none focus:ring-0 dark:border-gray-700 dark:bg-gray-800 dark:text-white dark:focus:border-gray-500"
/>

58-79: Add keyboard navigation support

The search results should be navigable using keyboard (up/down arrows). This improves accessibility.

#!/bin/bash
# Check for examples of keyboard navigation in search components
rg -A 5 "keydown" --glob="*.tsx" | grep -i "arrow\|key" | head -n 10

33-36: Display error message to the user

The error is logged to console but not shown to the user. Consider adding a user-friendly error message.

      } catch (error) {
        console.error("Search failed:", error);
        setResults([]);
+       // Consider adding a user-facing error notification here
      } finally {
components/docs/ui/DocCopyEnhancer.tsx (1)

8-8: Use English comments for better collaboration.

The comment "już jest" should be in English for consistency and clarity.

-      if (preEl.querySelector(".copy-btn")) return; // już jest
+      if (preEl.querySelector(".copy-btn")) return; // already exists
content/docs/eternalcore/notifications.mdx (2)

7-7: Fix grammatical issue.

The grammatical structure of this sentence needs adjustment.

-This plugin allows sending messages to different parts of Minecraft, including the chat, action bar, title, and subtitle. All messages can be formatted using [🔍 MiniMessages](https://docs.adventure.kyori.net/minimessage/format.html) or standard color codes. You can also use an online [🌐 message viewer](https://webui.adventure.kyori.net/)
+This plugin allows sending messages to different parts of Minecraft, including the chat, action bar, title, and subtitle. All message types can be formatted using [🔍 MiniMessages](https://docs.adventure.kyori.net/minimessage/format.html) or standard color codes. You can also use an online [🌐 message viewer](https://webui.adventure.kyori.net/)
🧰 Tools
🪛 LanguageTool

[uncategorized] ~7-~7: The grammatical number of this noun doesn’t look right. Consider replacing it.
Context: ...luding the chat, action bar, title, and subtitle. All messages can be formatted using [?...

(AI_EN_LECTOR_REPLACEMENT_NOUN_NUMBER)


149-149: Fix verb form in heading.

The verb "send" should be "sending" for grammatical correctness.

-#### Clear title/subtitle before send new
+#### Clear title/subtitle before sending new
🧰 Tools
🪛 LanguageTool

[uncategorized] ~149-~149: This verb may not be in the correct form. Consider using a different form for this context.
Context: .... #### Clear title/subtitle before send newyaml # Clears the title and subt...

(AI_EN_LECTOR_REPLACEMENT_VERB_FORM)

components/ui/Button.tsx (1)

48-50: Consider extracting the spinner to a separate component.

The loading spinner could be moved to its own component for reusability.

-        {isLoading ? (
-          <div className="mr-2 h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" />
-        ) : null}
+        {isLoading && <LoadingSpinner className="mr-2 h-4 w-4" />}

Then create a separate component:

// components/ui/LoadingSpinner.tsx
import { cn } from '@/lib/utils';

interface LoadingSpinnerProps {
  className?: string;
}

export const LoadingSpinner = ({ className }: LoadingSpinnerProps) => {
  return (
    <div className={cn('animate-spin rounded-full border-2 border-current border-t-transparent', className)} />
  );
};
components/docs/ui/CodeTabs.tsx (1)

27-70: Add validation for child components.

The component doesn't check if children are actually CodeTab components.

export const CodeTabs: React.FC<CodeTabsProps> = ({ children }) => {
+  // Validate children
+  React.Children.forEach(children, (child) => {
+    if (!React.isValidElement(child) || child.type !== CodeTab) {
+      console.warn('CodeTabs children should be CodeTab components');
+    }
+  });
+
  return (
    <div className="my-6 overflow-hidden rounded-xl bg-gray-800 shadow">
components/docs/tables/DynamicCommandsTable.tsx (1)

17-26: Consider making the URL configurable.

Hardcoding the GitHub URL could cause issues if the repository structure changes.

-    fetch("https://raw.githubusercontent.com/EternalCodeTeam/EternalCore/refs/heads/master/raw_commands_docs.json")
+    const commandsUrl = process.env.NEXT_PUBLIC_COMMANDS_URL || "https://raw.githubusercontent.com/EternalCodeTeam/EternalCore/refs/heads/master/raw_commands_docs.json";
+    fetch(commandsUrl)
content/docs/eternalcore/using-api.mdx (4)

7-7: Fix grammar in introduction.

Add "the" before "open-source community" for correct grammar.

-As part of open-source community, we support developers who want to create their own plugins using our API. We provide a simple and easy to use API that allows you to create your own plugins using our API.
+As part of the open-source community, we support developers who want to create their own plugins using our API. We provide a simple and easy to use API that allows you to create your own plugins using our API.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~7-~7: Possible missing article found.
Context: ...# EternalCore Developer API As part of open-source community, we support developers...

(AI_HYDRA_LEO_MISSING_THE)


103-103: Add missing comma.

Need a comma after "To use our API".

-To use our API you need to create instance of `EternalCoreAPI` class. You can do it by using `EternalCoreApiProvider.provide()` method.
+To use our API, you need to create instance of `EternalCoreAPI` class. You can do it by using `EternalCoreApiProvider.provide()` method.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~103-~103: Possible missing comma found.
Context: ...ill not work!** ## 📝 Usage To use our API you need to create instance of `Eternal...

(AI_HYDRA_LEO_MISSING_COMMA)


108-108: Fix article usage.

Add "an" before "instance of api".

-After creating instance of api, the User gets access to various classes used in our plugin and methods.
+After creating an instance of api, the User gets access to various classes used in our plugin and methods.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~108-~108: Possible missing article found.
Context: ...iProvider.provide(); ``` After creating instance of api, the User gets access to various...

(AI_HYDRA_LEO_MISSING_AN)


176-176: Fix grammar in feature description.

Add "a" before "unique feature" and consider using "can" instead of "able to".

-Using the instance of `CatboyService` the User is able to mark players as catboys and give them unique feature provided by `EternalCore`.
+Using the instance of `CatboyService` the User can mark players as catboys and give them a unique feature provided by `EternalCore`.
🧰 Tools
🪛 LanguageTool

[style] ~176-~176: As a shorter alternative for ‘able to’, consider using “can”.
Context: ...he instance of CatboyService the User is able to mark players as catboys and give them u...

(BE_ABLE_TO)


[uncategorized] ~176-~176: Possible missing article found.
Context: ...o mark players as catboys and give them unique feature provided by EternalCore. ```...

(AI_HYDRA_LEO_MISSING_A)

content/docs/eternalcore/installation.mdx (2)

15-15: Use en dash for version range.

For numerical ranges, it's better to use an en dash.

-- Minecraft server (Spigot/Paper 1.8.8 - 1.20.x)
+- Minecraft server (Spigot/Paper 1.8.8 – 1.20.x)
🧰 Tools
🪛 LanguageTool

[typographical] ~15-~15: If you want to indicate numerical ranges or time ranges, consider using an en dash.
Context: ...s - Minecraft server (Spigot/Paper 1.8.8 - 1.20.x) - Java 8 or higher - Server rest...

(DASH_RULE)


19-21: Remove word repetition.

There's a repetition of "download" that could be reworded.

-### Step 1: Download
-1. Download the latest version of EternalCore from our [GitHub releases](https://github.com/EternalCodeTeam/EternalCore/releases)
+### Step 1: Get the Plugin
+1. Get the latest version of EternalCore from our [GitHub releases](https://github.com/EternalCodeTeam/EternalCore/releases)
🧰 Tools
🪛 LanguageTool

[duplication] ~19-~19: Possible typo: you repeated a word.
Context: ...er - Server restart access ### Step 1: Download 1. Download the latest version of EternalCore from ...

(ENGLISH_WORD_REPEAT_RULE)

content/docs/eternalcombat/using-api.mdx (6)

7-7: Add missing article and hyphenate phrase
The phrase “As part of open-source community” should read “As part of the open-source community,” and it’s clearer to hyphenate “easy-to-use.”

- As part of open-source community, we support developers who want to create their own plugins using our API. We provide a simple and easy to use API that allows you to create your own plugins using our API.
+ As part of the open-source community, we support developers who want to create their own plugins using our API. We provide a simple and easy-to-use API that allows you to create your own plugins using our API.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~7-~7: You might be missing the article “the” here.
Context: ...PI --- # EternalCombat API As part of open-source community, we support developers...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


11-12: Add missing articles and punctuation
Insert “the” before “correct artifact” and “latest release,” and add commas for clarity.

- To use our work in your plugin, You need to install correct artifact for your project. Our plugin supports Maven, Gradle Kotlin, Gradle Groovy and SBT.
- To use latest release check [maven repository](https://repo.eternalcode.pl/#/releases/com/eternalcode/eternalcombat-api).
+ To use our work in your plugin, you need to install the correct artifact for your project. Our plugin supports Maven, Gradle Kotlin, Gradle Groovy, and SBT.
+ To use the latest release, check [maven repository](https://repo.eternalcode.pl/#/releases/com/eternalcode/eternalcombat-api).
🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: You might be missing the article “the” here.
Context: ...ork in your plugin, You need to install correct artifact for your project. Our plugin s...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~12-~12: You might be missing the article “the” here.
Context: ...e Kotlin, Gradle Groovy and SBT. To use latest release check [maven repository](https:...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


75-75: Split sentence and add article
Add “the” before “dependency” and replace the comma with a semicolon to improve readability.

- You must also add dependency inside `plugin.yml` or `paper-plugin.yml` file, this is required to load our plugin before your plugin, so they can access our API.
+ You must also add the dependency inside `plugin.yml` or `paper-plugin.yml` file; this is required to load our plugin before your plugin so they can access our API.

140-140: Lowercase “you” and add comma
Change “After that You can use examples shown below.” to “After that, you can use the examples shown below.”

- Then pass down the `FightManager` to your classes. After that You can use examples shown below.
+ Then pass down the `FightManager` to your classes. After that, you can use the examples shown below.
🧰 Tools
🪛 LanguageTool

[typographical] ~140-~140: Consider adding a comma here.
Context: ...own the FightManager to your classes. After that You can use examples shown below. Chec...

(FOR_THAT_COMMA)


[uncategorized] ~140-~140: You might be missing the article “the” here.
Context: ...to your classes. After that You can use examples shown below. Check if the player is in...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


161-161: Hyphenate header “Event-based API”
The header should read “## Event-based API” for consistency and clarity.

- ## Event base API
+ ## Event-based API

167-167: Add article and comma
Update “In example below we check why the player was untagged.” to “In the example below, we check why the player was untagged.”

- You can access both event types by using `@EventHandler`. In example below we check why the player was untagged.
+ You can access both event types by using `@EventHandler`. In the example below, we check why the player was untagged.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~167-~167: You might be missing the article “the” here.
Context: ...vent types by using @EventHandler. In example below we check why the player was untag...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~167-~167: A comma might be missing here.
Context: ...es by using @EventHandler. In example below we check why the player was untagged. ...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3438429 and c592b7e.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (47)
  • app/api/docs/search/route.ts (1 hunks)
  • app/docs/[...slug]/page.tsx (1 hunks)
  • app/docs/layout.tsx (1 hunks)
  • app/docs/page.tsx (1 hunks)
  • app/globals.css (2 hunks)
  • app/layout.tsx (3 hunks)
  • components/ErrorBoundary.tsx (1 hunks)
  • components/docs/layout/DocSearch.tsx (1 hunks)
  • components/docs/layout/DocSidebar.tsx (1 hunks)
  • components/docs/tables/DynamicCommandsTable.tsx (1 hunks)
  • components/docs/tables/DynamicFeaturesTable.tsx (1 hunks)
  • components/docs/ui/Alert.tsx (1 hunks)
  • components/docs/ui/AnimatedHeading.tsx (1 hunks)
  • components/docs/ui/CodeTabs.tsx (1 hunks)
  • components/docs/ui/DocCopyEnhancer.tsx (1 hunks)
  • components/faq/Faq.tsx (1 hunks)
  • components/features/Features.tsx (1 hunks)
  • components/header/Navbar.tsx (2 hunks)
  • components/projects/Projects.tsx (1 hunks)
  • components/team/Team.tsx (2 hunks)
  • components/ui/Button.tsx (1 hunks)
  • components/ui/LoadingSpinner.tsx (1 hunks)
  • config/navigation.ts (1 hunks)
  • content/docs/contribute/guide.mdx (1 hunks)
  • content/docs/documentation-editors/markdown-guide.mdx (1 hunks)
  • content/docs/eternalcombat/features.mdx (1 hunks)
  • content/docs/eternalcombat/installation.mdx (1 hunks)
  • content/docs/eternalcombat/introduction.mdx (1 hunks)
  • content/docs/eternalcombat/using-api.mdx (1 hunks)
  • content/docs/eternalcore/faq.mdx (1 hunks)
  • content/docs/eternalcore/features.mdx (1 hunks)
  • content/docs/eternalcore/homes.mdx (1 hunks)
  • content/docs/eternalcore/installation.mdx (1 hunks)
  • content/docs/eternalcore/introduction.mdx (1 hunks)
  • content/docs/eternalcore/notifications.mdx (1 hunks)
  • content/docs/eternalcore/placeholders.mdx (1 hunks)
  • content/docs/eternalcore/using-api.mdx (1 hunks)
  • hooks/useNavigation.ts (1 hunks)
  • lib/docs/sidebar-structure.ts (1 hunks)
  • lib/mdx.ts (1 hunks)
  • lib/prism/prism-languages.ts (1 hunks)
  • lib/prism/prism-tomorrow.css (1 hunks)
  • lib/utils.ts (1 hunks)
  • mdx.d.ts (1 hunks)
  • next.config.mjs (2 hunks)
  • package.json (1 hunks)
  • types/navigation.ts (1 hunks)
✅ Files skipped from review due to trivial changes (16)
  • components/projects/Projects.tsx
  • components/faq/Faq.tsx
  • components/features/Features.tsx
  • content/docs/eternalcombat/introduction.mdx
  • content/docs/eternalcore/placeholders.mdx
  • types/navigation.ts
  • lib/utils.ts
  • config/navigation.ts
  • lib/docs/sidebar-structure.ts
  • lib/prism/prism-tomorrow.css
  • content/docs/eternalcore/features.mdx
  • content/docs/documentation-editors/markdown-guide.mdx
  • lib/prism/prism-languages.ts
  • components/docs/ui/Alert.tsx
  • content/docs/eternalcore/faq.mdx
  • mdx.d.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • components/team/Team.tsx
  • components/header/Navbar.tsx
  • app/docs/page.tsx
  • app/api/docs/search/route.ts
  • app/docs/layout.tsx
  • app/globals.css
  • package.json
  • app/docs/[...slug]/page.tsx
  • lib/mdx.ts
🧰 Additional context used
🧬 Code Graph Analysis (3)
components/docs/layout/DocSidebar.tsx (1)
lib/docs/sidebar-structure.ts (2)
  • DocItem (1-5)
  • docsStructure (7-46)
app/layout.tsx (1)
components/ErrorBoundary.tsx (1)
  • ErrorBoundary (15-51)
components/ui/Button.tsx (1)
lib/utils.ts (1)
  • cn (4-6)
🪛 Biome (1.9.4)
components/docs/layout/DocSidebar.tsx

[error] 22-22: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 LanguageTool
content/docs/eternalcore/using-api.mdx

[uncategorized] ~7-~7: Possible missing article found.
Context: ...# EternalCore Developer API As part of open-source community, we support developers...

(AI_HYDRA_LEO_MISSING_THE)


[uncategorized] ~103-~103: Possible missing comma found.
Context: ...ill not work!** ## 📝 Usage To use our API you need to create instance of `Eternal...

(AI_HYDRA_LEO_MISSING_COMMA)


[uncategorized] ~108-~108: Possible missing article found.
Context: ...iProvider.provide(); ``` After creating instance of api, the User gets access to various...

(AI_HYDRA_LEO_MISSING_AN)


[typographical] ~138-~138: Consider adding a comma here.
Context: ... down the AfkService to your classes. After that You can use examples shown below. Chec...

(FOR_THAT_COMMA)


[style] ~176-~176: As a shorter alternative for ‘able to’, consider using “can”.
Context: ...he instance of CatboyService the User is able to mark players as catboys and give them u...

(BE_ABLE_TO)


[uncategorized] ~176-~176: Possible missing article found.
Context: ...o mark players as catboys and give them unique feature provided by EternalCore. ```...

(AI_HYDRA_LEO_MISSING_A)

content/docs/contribute/guide.mdx

[uncategorized] ~56-~56: Loose punctuation mark.
Context: ...ly made a contribution to this project. :>

(UNLIKELY_OPENING_PUNCTUATION)

content/docs/eternalcombat/using-api.mdx

[uncategorized] ~7-~7: You might be missing the article “the” here.
Context: ...PI --- # EternalCombat API As part of open-source community, we support developers...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~11-~11: You might be missing the article “the” here.
Context: ...ork in your plugin, You need to install correct artifact for your project. Our plugin s...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~12-~12: You might be missing the article “the” here.
Context: ...e Kotlin, Gradle Groovy and SBT. To use latest release check [maven repository](https:...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~103-~103: A comma might be missing here.
Context: ...ill not work!** ## 📝 Usage To use our API you need to create instance of `Eternal...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~103-~103: You might be missing the article “an” here.
Context: ...Usage To use our API you need to create instance of EternalCombatAPI class. You can do...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ... our API you need to create instance of EternalCombatAPI class. You can do it b...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ...ombatAPIclass. You can do it by usingEternalCombatAPI.getInstance()` method. ...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~108-~108: You might be missing the article “an” here.
Context: ...tProvider.provide(); ``` After creating instance of api, the User gets access to various...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[uncategorized] ~124-~124: Possible missing preposition found.
Context: ...their own use cases. Here is an example how to obtain instance of FightManager: ...

(AI_EN_LECTOR_MISSING_PREPOSITION)


[uncategorized] ~124-~124: You might be missing the article “an” here.
Context: ...cases. Here is an example how to obtain instance of FightManager: ```java public clas...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[typographical] ~140-~140: Consider adding a comma here.
Context: ...own the FightManager to your classes. After that You can use examples shown below. Chec...

(FOR_THAT_COMMA)


[uncategorized] ~140-~140: You might be missing the article “the” here.
Context: ...to your classes. After that You can use examples shown below. Check if the player is in...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~164-~164: You might be missing the article “the” here.
Context: ... the player enters the fight or extends duration of the fight. The second type is the `...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~167-~167: You might be missing the article “the” here.
Context: ...vent types by using @EventHandler. In example below we check why the player was untag...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~167-~167: A comma might be missing here.
Context: ...es by using @EventHandler. In example below we check why the player was untagged. ...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)

content/docs/eternalcombat/features.mdx

[uncategorized] ~15-~15: You might be missing the article “the” here.
Context: ...our combat experience. You can find all features below. - Combat duration, - Combat mes...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~22-~22: You might be missing the article “a” here.
Context: ... - Disable block placing in areas above certain height, - Add combat-log to other entit...

(AI_EN_LECTOR_MISSING_DETERMINER_A)

content/docs/eternalcombat/installation.mdx

[uncategorized] ~16-~16: A comma might be missing here.
Context: ...mize the plugin to your needs. With any questions feel free to ask. ## ⚡ Upgrading 📝 **...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~33-~33: This verb may not be in the correct tense. Consider changing the tense to fit the context better.
Context: ... after the update. 📝 Note: If you experienced problems after updating the plugin, use...

(AI_EN_LECTOR_REPLACEMENT_VERB_TENSE)

content/docs/eternalcore/homes.mdx

[grammar] ~5-~5: This phrase is duplicated. You should probably use “EternalCore Homes” only once.
Context: ...-- title: EternalCore - Homes --- # 🏠 EternalCore Homes EternalCore Homes is a feature that allows players to set...

(PHRASE_REPETITION)


[grammar] ~9-~9: ‘a’ may be redundant when used with the uncountable noun ‘permission’.
Context: ...nfigure the maximum number of homes for a given permission. ```yaml # Homes Section homes: # Ma...

(A_UNCOUNTABLE_NOUN)

content/docs/eternalcore/installation.mdx

[typographical] ~15-~15: If you want to indicate numerical ranges or time ranges, consider using an en dash.
Context: ...s - Minecraft server (Spigot/Paper 1.8.8 - 1.20.x) - Java 8 or higher - Server rest...

(DASH_RULE)


[duplication] ~19-~19: Possible typo: you repeated a word.
Context: ...er - Server restart access ### Step 1: Download 1. Download the latest version of EternalCore from ...

(ENGLISH_WORD_REPEAT_RULE)


[style] ~80-~80: Using many exclamation marks might seem excessive (in this case: 3 exclamation marks for a text that’s 1732 characters long)
Context: ...rnalCore plugin on your Minecraft server! 😊

(EN_EXCESSIVE_EXCLAMATION)

content/docs/eternalcore/introduction.mdx

[duplication] ~25-~25: Possible typo: you repeated a word.
Context: ...m** - Player teleportation - Random teleportation - Teleportation requests - Warp System - Create ...

(ENGLISH_WORD_REPEAT_RULE)

content/docs/eternalcore/notifications.mdx

[uncategorized] ~7-~7: The grammatical number of this noun doesn’t look right. Consider replacing it.
Context: ...luding the chat, action bar, title, and subtitle. All messages can be formatted using [?...

(AI_EN_LECTOR_REPLACEMENT_NOUN_NUMBER)


[uncategorized] ~149-~149: This verb may not be in the correct form. Consider using a different form for this context.
Context: .... #### Clear title/subtitle before send newyaml # Clears the title and subt...

(AI_EN_LECTOR_REPLACEMENT_VERB_FORM)

🔇 Additional comments (29)
hooks/useNavigation.ts (2)

1-4: Good use of 'use client' directive.

The directive correctly marks this component for client-side rendering, and your imports are clean and focused.


5-5: Watch out for potential naming conflicts.

Just be aware that 'useNavigation' is a common name that might also be used in navigation libraries like React Navigation. Consider a more specific name if you're using other navigation libraries.

components/ui/LoadingSpinner.tsx (1)

1-22: Well-implemented accessible component

This is a nicely implemented loading spinner with good accessibility attributes and size flexibility. Great job!

Consider these minor enhancements:

 interface LoadingSpinnerProps {
   size?: 'sm' | 'md' | 'lg';
   className?: string;
+  color?: string;
+  testId?: string;
 }

-export const LoadingSpinner = ({ size = 'md', className = '' }: LoadingSpinnerProps) => {
+export const LoadingSpinner = ({ 
+  size = 'md', 
+  className = '',
+  color = 'current',
+  testId = 'loading-spinner'
+}: LoadingSpinnerProps) => {
   const sizes = {
     sm: 'h-4 w-4',
     md: 'h-6 w-6',
     lg: 'h-8 w-8',
   };

   return (
     <div className={`flex items-center justify-center ${className}`}>
       <div
-        className={`${sizes[size]} animate-spin rounded-full border-2 border-current border-t-transparent`}
+        className={`${sizes[size]} animate-spin rounded-full border-2 border-${color} border-t-transparent`}
         role="status"
         aria-label="Loading"
+        data-testid={testId}
       />
     </div>
   );
 };
content/docs/eternalcore/introduction.mdx (2)

23-26: The teleportation feature section looks good.

The teleportation system features are well-organized and clearly explained.

🧰 Tools
🪛 LanguageTool

[duplication] ~25-~25: Possible typo: you repeated a word.
Context: ...m** - Player teleportation - Random teleportation - Teleportation requests - Warp System - Create ...

(ENGLISH_WORD_REPEAT_RULE)


43-51: Well-structured documentation links.

The documentation sections with direct links to other pages are clear and helpful for navigation.

components/ErrorBoundary.tsx (2)

15-23: Good implementation of error boundary.

The error boundary component is well structured with proper state management and error handling.


29-49: Clean fallback UI implementation.

The fallback UI is well-designed with proper dark mode support and a "Try again" button for recovery.

components/docs/tables/DynamicFeaturesTable.tsx (1)

1-57: The component works well and handles loading/error states nicely

The table component is well structured with proper conditional rendering for loading, error, and empty states. The responsive design with overflow handling is a good practice.

app/layout.tsx (4)

11-12: Good addition of Prism languages and ErrorBoundary

Adding syntax highlighting and error handling improves the user experience, especially for a documentation site.


20-39: Great enhancement of metadata

The expanded metadata with OpenGraph and Twitter properties will improve SEO and social sharing. The template structure is also a nice touch.


53-60: Good use of ErrorBoundary

Wrapping the main content in an ErrorBoundary is a good practice to prevent the entire app from crashing when errors occur.


62-63:

❓ Verification inconclusive

Analytics components placement issue

Placing the Analytics and SpeedInsights components outside the body tag might cause issues. They should typically be inside the body.


🏁 Script executed:

#!/bin/bash
# Check if the Next.js documentation recommends a specific placement for analytics components
rg -A 2 -B 2 "Analytics.*body|body.*Analytics" 

Length of output: 48


We couldn’t find any docs linking Analytics placement with the <body> tag. Could you double-check in Next.js’ docs or your team’s standards if these components must live inside <body>? Otherwise this looks fine here.

content/docs/eternalcombat/installation.mdx (1)

1-44: Well-structured installation guide

The documentation is clear, well-organized, and includes helpful emojis. The step-by-step instructions and warnings about potential issues are particularly useful.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~16-~16: A comma might be missing here.
Context: ...mize the plugin to your needs. With any questions feel free to ask. ## ⚡ Upgrading 📝 **...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~33-~33: This verb may not be in the correct tense. Consider changing the tense to fit the context better.
Context: ... after the update. 📝 Note: If you experienced problems after updating the plugin, use...

(AI_EN_LECTOR_REPLACEMENT_VERB_TENSE)

components/docs/layout/DocSearch.tsx (1)

1-89: Well-implemented search component

The search component is well-structured with debounced input, loading indicators, and clear result display. The code is clean and follows good practices.

content/docs/eternalcore/notifications.mdx (1)

1-154: Well-structured documentation with comprehensive examples.

The documentation provides clear and thorough examples for all notification types, with progressive complexity.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~7-~7: The grammatical number of this noun doesn’t look right. Consider replacing it.
Context: ...luding the chat, action bar, title, and subtitle. All messages can be formatted using [?...

(AI_EN_LECTOR_REPLACEMENT_NOUN_NUMBER)


[uncategorized] ~149-~149: This verb may not be in the correct form. Consider using a different form for this context.
Context: .... #### Clear title/subtitle before send newyaml # Clears the title and subt...

(AI_EN_LECTOR_REPLACEMENT_VERB_FORM)

components/ui/Button.tsx (1)

1-57: Well-structured button component with good variants.

The Button component is well-designed with clear organization of styles, variants, and sizes. It properly handles different states and has good accessibility features.

components/docs/ui/CodeTabs.tsx (1)

1-80: Good implementation of tabbed code interface.

The component provides a clean and accessible way to show code examples in multiple languages. The tabs are well-styled and the code handles child components properly.

next.config.mjs (6)

2-7: Correct imports for MDX support.

All necessary packages for MDX support are properly imported.


13-25: Good MDX configuration.

The MDX setup includes appropriate remark and rehype plugins for enhanced markdown support.


57-62: Proper experimental features configuration.

The experimental settings correctly enable MDX support and configure file resolution extensions.


64-64: Correct page extensions.

Adding 'mdx' to page extensions is necessary for Next.js to recognize MDX files as pages.


65-74: Good development configuration.

The webpack watch options improve development experience with polling for file changes.


77-77: Proper export configuration.

The export correctly combines both bundle analyzer and MDX plugins.

components/docs/tables/DynamicCommandsTable.tsx (3)

1-3: Correct client-side component setup.

The "use client" directive and React imports are properly set up.


5-10: Well-defined interface.

The Command interface clearly defines the structure of command data with appropriate optional properties.


28-30: Good loading and error states.

The component correctly handles loading and error states for a better user experience.

content/docs/eternalcore/installation.mdx (3)

8-10: Good use of Alert component.

The info alert provides helpful context for users.


58-60: Important warning about reloading.

This warning about not using /reload is crucial information for server admins.


67-72: Good support resources.

The support section provides clear paths for getting help.

vLuckyyy added 2 commits May 11, 2025 00:29
Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
…r with SVG folder icon, sticky search, and sticky sidebar
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (7)
components/docs/DocSidebar.tsx (2)

32-32: Good use of optional chaining

The optional chaining syntax is correctly implemented here, making the code safer. This addresses a previous review comment.


22-22: Good fix for Tailwind class naming

Using conditional statements instead of string interpolation for Tailwind classes ensures proper compilation. This addresses a previous review comment.

app/globals.css (3)

53-56: Table header colors need better contrast

The light background (#f8fafc) with white text will be hard to read. Choose a darker header background or darker text color.


73-75: Zebra striping has no effect

Both regular and "even" rows have the same background color (#f8fafc), so no stripes will appear. Use different colors for alternating rows.


88-90: Dark mode striping is also no-op

Same issue in dark mode - all rows have the same background color. Please use two different shades.

components/docs/CodeTabs.tsx (1)

27-78: 🛠️ Refactor suggestion

Add validation for child label props

Your component assumes all children have a label prop. This could cause errors if a child is missing the label.

export const CodeTabs: React.FC<CodeTabsProps> = ({ children }) => {
+  // Validate that children have label props
+  React.Children.forEach(children, (child) => {
+    if (React.isValidElement(child) && !child.props.label) {
+      console.warn('CodeTab component missing required "label" prop');
+    }
+  });

  return (
    <div className="my-8 overflow-hidden rounded-2xl bg-gradient-to-br from-gray-800/80 via-gray-900/80 to-gray-800/60 ring-1 ring-white/10 backdrop-blur-md">
content/docs/documentation-editors/markdown-guide.md (1)

220-226: 🛠️ Refactor suggestion

Fix nested code-fence error in Basic Code Block

The code fences are misnested. It should be a single JavaScript block.

-```markdown
-```javascript
+```javascript
function greet(name) {
  return `Hello, ${name}!`;
}
-```
-```
+```
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

226-226: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

🧹 Nitpick comments (12)
components/docs/Alert.tsx (3)

5-5: Consider adding a default alert type

The type prop is required, but it might be helpful to provide a default value (like "info") to make the component more flexible.


95-95: Consider a more flexible text size class

The prose-sm class might make the alert text too small for some content. Consider using prose instead for better readability.

-          <div className={`prose-sm ${styles.text}`}>{children}</div>
+          <div className={`prose ${styles.text}`}>{children}</div>

83-86: Add more semantic HTML for better accessibility

Consider using a more semantic HTML element like aside instead of a plain div for the alert container, which would better represent its purpose as supplementary content.

-    <div
+    <aside
       className={`my-6 rounded-lg p-4 shadow-sm backdrop-blur-sm ${styles.container}`}
     >
components/icons/arrow-down.tsx (1)

7-14: Add accessibility attributes to the SVG

The SVG is missing accessibility attributes. Add aria-hidden="true" since this is likely a decorative icon used with text.

    <svg
      className={className}
      width="24"
      height="24"
      viewBox="0 0 24 24"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
+     aria-hidden="true"
    >
components/docs/DocSearch.tsx (1)

62-83: Add "No results" message when search returns empty

When a search returns no results but the query is valid, it would be helpful to show a message indicating no results were found.

      {results.length > 0 && (
        <div className="absolute z-10 mt-2 w-full rounded-lg border border-gray-200 bg-white shadow-lg dark:border-gray-700 dark:bg-gray-800">
          {results.map((result) => (
            <button
              key={result.path}
              onClick={() => {
                router.push(result.path);
                setQuery("");
                setResults([]);
              }}
              className="w-full px-4 py-2 text-left hover:bg-gray-100 focus:outline-none dark:hover:bg-gray-700"
            >
              <div className="font-medium text-gray-900 dark:text-white">
                {result.title}
              </div>
              <div className="text-sm text-gray-500 dark:text-gray-400">
                {result.excerpt}
              </div>
            </button>
          ))}
        </div>
      )}
+     {query.length >= 2 && results.length === 0 && !isLoading && (
+       <div className="absolute z-10 mt-2 w-full rounded-lg border border-gray-200 bg-white p-4 text-center shadow-lg dark:border-gray-700 dark:bg-gray-800">
+         <p className="text-sm text-gray-500 dark:text-gray-400">No results found</p>
+       </div>
+     )}
components/docs/DocSidebar.tsx (2)

38-51: Add title attribute to links for longer names

For links with potentially long titles that might get truncated, adding a title attribute would improve the user experience by showing the full name on hover.

      <Link
        key={item.path}
        href={item.path}
+       title={item.title}
        className={`block rounded-lg transition-colors font-medium text-sm pl-4 py-1 ${
          isActive
            ? "bg-gray-100 text-gray-900 dark:bg-gray-800 dark:text-white"
            : "text-gray-700 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-800"
        }`}
        aria-current={isActive ? "page" : undefined}
      >
        {item.title}
      </Link>

16-52: Consider extracting renderDocItem to a separate component

The renderDocItem function is quite complex and could be extracted into a separate component for better maintainability and testing.

components/docs/CodeTabs.tsx (2)

11-25: Add type safety to icon selection

The current icon selection uses a type cast with as any, which bypasses TypeScript's type checking.

- const Icon = (SIIcons as any)[iconName];
+ // Check if the icon exists in SIIcons
+ const Icon = Object.prototype.hasOwnProperty.call(SIIcons, iconName) 
+   ? (SIIcons as Record<string, React.ComponentType<{ className: string, title: string, size: number }>>)[iconName] 
+   : undefined;

32-58: Extract tab rendering to a separate function

The tab rendering logic is quite complex. Consider extracting it to a separate function for better readability.

export const CodeTabs: React.FC<CodeTabsProps> = ({ children }) => {
+  const renderTab = (child: React.ReactNode, idx: number) => {
+    if (React.isValidElement(child)) {
+      const label = child.props.label;
+      return (
+        <Tab key={label + idx} as={React.Fragment}>
+          {({ selected }: { selected: boolean }) => (
+            <button
+              className={`relative rounded-xl px-4 py-2 text-sm font-semibold transition-colors duration-150 focus:outline-none
+                ${
+                  selected
+                    ? "bg-gray-700/60 text-white shadow-md"
+                    : "text-gray-300 hover:text-white hover:bg-gray-700/60"
+                }
+              `}
+              type="button"
+            >
+              <span className="flex items-center gap-1">
+                {getLanguageIcon(label)}
+                {label}
+              </span>
+            </button>
+          )}
+        </Tab>
+      );
+    }
+    return null;
+  };

  return (
    <div className="my-8 overflow-hidden rounded-2xl bg-gradient-to-br from-gray-800/80 via-gray-900/80 to-gray-800/60 ring-1 ring-white/10 backdrop-blur-md">
      <TabGroup>
        <TabList className="flex space-x-2 px-4 pt-4 pb-0">
-          {React.Children.map(children, (child, idx) => {
-            if (React.isValidElement(child)) {
-              const label = child.props.label;
-              return (
-                <Tab key={label + idx} as={React.Fragment}>
-                  {({ selected }: { selected: boolean }) => (
-                    <button
-                      className={`relative rounded-xl px-4 py-2 text-sm font-semibold transition-colors duration-150 focus:outline-none
-                        ${
-                          selected
-                            ? "bg-gray-700/60 text-white shadow-md"
-                            : "text-gray-300 hover:text-white hover:bg-gray-700/60"
-                        }
-                      `}
-                      type="button"
-                    >
-                      <span className="flex items-center gap-1">
-                        {getLanguageIcon(label)}
-                        {label}
-                      </span>
-                    </button>
-                  )}
-                </Tab>
-              );
-            }
-            return null;
-          })}
+          {React.Children.map(children, renderTab)}
content/docs/documentation-editors/markdown-guide.md (1)

39-39: Fix typo in external links section

There's a stray "a" at the end of "Link to external websites:a"

-Link to external websites:a
+Link to external websites:
app/docs/[...slug]/page.tsx (2)

29-50: Consider deeper nesting in flattenDocs

Your function works for the current structure, but might not handle deeper nested documentation levels if they're added later.

function flattenDocs(
  structure: {
    title: string;
    path: string;
    children?: { title: string; path: string }[];
  }[]
): { title: string; path: string }[] {
  const result: { title: string; path: string }[] = [];
  for (const item of structure) {
    if (item.children && item.children.length > 0) {
      for (const child of item.children) {
+       // Add recursive handling if child items could have children too
        result.push({ title: child.title, path: child.path });
      }
    } else {
      result.push({ title: item.title, path: item.path });
    }
  }
  return result;
}

161-182: Improve navigation accessibility

The navigation links could use aria-labels for better accessibility.

{prev ? (
  <a
    href={prev.path}
    className="rounded-lg border border-gray-200 bg-gray-100 px-4 py-2 no-underline transition-colors hover:bg-gray-200 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700"
+   aria-label={`Previous page: ${prev.title}`}
  >
    ← {prev.title}
  </a>
) : (
  <div />
)}
{next ? (
  <a
    href={next.path}
    className="rounded-lg bg-blue-600 px-4 py-2 text-white no-underline transition-colors hover:bg-blue-700"
+   aria-label={`Next page: ${next.title}`}
  >
    {next.title} →
  </a>
) : (
  <div />
)}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4f4ca27 and a91bdc5.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • app/docs/[...slug]/page.tsx (1 hunks)
  • app/docs/layout.tsx (1 hunks)
  • app/globals.css (2 hunks)
  • components/docs/Alert.tsx (1 hunks)
  • components/docs/CodeTabs.tsx (1 hunks)
  • components/docs/DocSearch.tsx (1 hunks)
  • components/docs/DocSidebar.tsx (1 hunks)
  • components/header/Navbar.tsx (2 hunks)
  • components/icons/arrow-down.tsx (1 hunks)
  • components/icons/hamburger.tsx (1 hunks)
  • content/docs/documentation-editors/markdown-guide.md (1 hunks)
  • package.json (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • components/icons/hamburger.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • package.json
  • app/docs/layout.tsx
🧰 Additional context used
🧬 Code Graph Analysis (3)
components/docs/DocSidebar.tsx (1)
components/docs/sidebar-structure.ts (2)
  • DocItem (1-5)
  • docsStructure (7-46)
components/header/Navbar.tsx (3)
components/icons/arrow-down.tsx (1)
  • ArrowDown (5-24)
components/icons/hamburger.tsx (1)
  • Hamburger (5-24)
components/icons/new-window.tsx (1)
  • NewWindow (3-20)
app/docs/[...slug]/page.tsx (2)
components/docs/sidebar-structure.ts (1)
  • docsStructure (7-46)
lib/mdx.ts (1)
  • components (12-24)
🪛 markdownlint-cli2 (0.17.2)
content/docs/documentation-editors/markdown-guide.md

226-226: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

🔇 Additional comments (23)
components/docs/Alert.tsx (1)

1-100: LGTM! Well-structured alert component

The alert component is well-implemented with comprehensive styling variations, dark mode support, and good icon integration. It will provide great visual cues in the documentation.

components/icons/arrow-down.tsx (1)

1-24: LGTM! Clean icon implementation

This SVG icon component follows best practices with the use of currentColor for styling flexibility and proper viewBox setup.

components/docs/DocSearch.tsx (1)

1-92: LGTM! Well-implemented search component

The search component has good error handling, debouncing for API calls, and a clean UI with loading indicator. The structure is well-organized and follows React best practices.

components/docs/DocSidebar.tsx (1)

1-71: LGTM! Well-structured sidebar with good accessibility

The sidebar component is well-implemented with proper accessibility attributes, optimized rendering with useMemo, and good conditional styling for active items.

components/header/Navbar.tsx (7)

42-44: Good memoization with useCallback

Nice job memoizing the toggle function! This helps prevent unnecessary re-renders.


47-56: Well implemented keyboard accessibility

Great work adding the Escape key handler! This is an important accessibility feature that helps users close the menu easily.


58-67: Good user experience with body scroll lock

Locking the body scroll when the menu is open prevents the page from scrolling in the background, which improves user experience. The cleanup on unmount is also properly handled.


70-74: Excellent accessibility attributes

Adding proper ARIA roles and labels makes the navigation more accessible to screen readers.


97-116: Nice menu toggle animation

The animated transition between hamburger and arrow icons provides good visual feedback.


119-154: Smooth mobile menu animations

The use of AnimatePresence and motion.div creates a polished user experience with smooth transitions.


157-173: Well-structured navigation with proper external link handling

The navigation links are well-organized with proper handling of external links (new tab, security attributes).

app/globals.css (3)

1-12: Good code font consistency

Setting consistent fonts for code blocks improves readability across the site.


34-41: Clean heading link styling

Removing text decoration from heading links improves readability while maintaining clickability.


92-98: Nice fade-in animation

The fade-in animation with vertical movement creates a smooth entry effect.

content/docs/documentation-editors/markdown-guide.md (3)

6-8: Good comprehensive documentation

This guide provides an excellent overview of all available markdown features in your documentation system.


153-213: Well-structured alert examples

The alert examples are clear and show different types and usage patterns. This will help documentation authors.


263-290: Great interactive code tabs example

The CodeTabs example demonstrates how to show code in multiple languages, which is very useful for API documentation.

app/docs/[...slug]/page.tsx (6)

1-10: Well-organized imports!

All the necessary imports for handling markdown, file operations, and UI components are present and clearly organized.


11-27: Clean interface definitions

The interfaces for document metadata, content, and navigation are well-structured and make the code easy to understand.


79-85: Clean navigation implementation

The navigation logic is simple and effective, handling edge cases properly.


87-112: Good SEO metadata handling

The metadata function properly handles SEO attributes including Open Graph and Twitter card data.


114-126: Nice loading skeleton UI

The loading fallback provides a good user experience with the animation effect.


138-160: Well-structured document rendering

The document layout with title, description, and content is clean and follows good semantic structure.

Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
content/docs/documentation-editors/markdown-guide.md (1)

216-222: Fix nested code fence in Basic Code Block
The fences are misnested. Use a single JavaScript code fence:

- ```markdown
- ```javascript
+ ```javascript
 function greet(name) {
   return `Hello, ${name}!`;
 }
- ```
- ```
+ ```
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

222-222: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

🧹 Nitpick comments (4)
content/docs/documentation-editors/markdown-guide.md (4)

1-4: Consider adding optional frontmatter fields

Great start! You might mention additional recommended fields like slug or sidebar_label to improve navigation control.


10-15: Use YAML in frontmatter code block

Change the code fence from txt to yaml for correct syntax highlighting:

- ```txt
+ ```yaml

35-35: Fix typo in external links section

Remove the stray a after "websites:":

- Link to external websites:a
+ Link to external websites:

232-236: Remove hidden characters before code fences

The zero-width spaces before the backticks can prevent proper rendering. Update the fences like:

- ​```javascript
+ ```javascript
 ...
- ​```
+ ```

Also applies to: 241-246, 250-253

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a91bdc5 and 1a5aeac.

📒 Files selected for processing (2)
  • app/docs/[...slug]/page.tsx (1 hunks)
  • content/docs/documentation-editors/markdown-guide.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/docs/[...slug]/page.tsx
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
content/docs/documentation-editors/markdown-guide.md

222-222: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
app/docs/[...slug]/page.tsx (1)

59-62: Add path validation for security

Your code needs protection from path traversal attacks. Add checks to validate the slug.

🧹 Nitpick comments (3)
app/docs/[...slug]/page.tsx (3)

156-164: Consider showing last modified date

Showing when a doc was last updated helps users know how fresh the content is. The data is already in doc.meta.lastModified.

        {doc.meta.description && (
          <p className="mb-6 text-xl text-gray-600 dark:text-gray-400">
            {doc.meta.description}
          </p>
        )}
+       {doc.meta.lastModified && (
+         <p className="text-sm text-gray-500 dark:text-gray-400 mb-4">
+           Last updated: {new Date(doc.meta.lastModified).toLocaleDateString()}
+         </p>
+       )}

165-173: Add error boundary around MDX rendering

Wrap the MDX component in an error boundary to handle rendering errors gracefully.

        <Suspense fallback={<LoadingFallback />}>
+         <ErrorBoundary fallback={<div className="p-4 text-red-500 border border-red-200 rounded">Error rendering markdown content</div>}>
            <MDXRemote
              source={doc.content}
              components={components}
              options={{
                mdxOptions,
              }}
            />
+         </ErrorBoundary>
        </Suspense>

You'll need to add:

import { ErrorBoundary } from 'react-error-boundary';

176-193: Improve navigation button accessibility

The blue navigation button may have contrast issues. Consider increasing contrast or adding an aria-label.

        {next ? (
          <a
            href={next.path}
+           aria-label={`Next page: ${next.title}`}
            className="rounded-lg bg-blue-600 px-4 py-2 text-white no-underline transition-colors hover:bg-blue-700"
          >
            {next.title} →
          </a>
        ) : (
          <div />
        )}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a5aeac and a389671.

📒 Files selected for processing (3)
  • app/docs/[...slug]/page.tsx (1 hunks)
  • app/docs/page.tsx (1 hunks)
  • components/docs/CodeTabs.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/docs/page.tsx
  • components/docs/CodeTabs.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
app/docs/[...slug]/page.tsx (5)
app/docs/page.tsx (2)
  • dynamic (5-5)
  • revalidate (6-6)
app/page.tsx (1)
  • dynamic (6-6)
app/projects/page.tsx (1)
  • dynamic (5-5)
components/docs/sidebar-structure.ts (1)
  • docsStructure (7-46)
lib/mdx.ts (1)
  • components (12-24)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (20)
content/docs/eternalcore/using-api.md (6)

1-3: Add document metadata to frontmatter
Including fields like author, date, or lastUpdated in the YAML frontmatter helps readers know who wrote the doc and when it was last revised.


5-5: Consider adding a Table of Contents
For a long API guide, a TOC at the top (or using a floating sidebar) can help readers quickly jump to sections.


7-7: Fix grammar and reduce repetition
“As part of the open-source community, we support developers who want to create plugins with our API.”
This avoids “using our API” twice and adds the missing article.


11-11: Clarify artifact installation sentence
Change to:
“To use the API in your plugin, install the correct artifact for your project.”
Also lowercase “You” to maintain sentence flow.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: You might be missing the article “the” here.
Context: ...ork in your plugin, You need to install correct artifact for your project. Our plugin s...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


14-14: Remove trailing colons in headings
Markdown style prefers no punctuation at the end of heading text. Please drop the : from “### Add repository” and “### Add dependency”.

Also applies to: 44-44

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

14-14: Trailing punctuation in heading
Punctuation: ':'

(MD026, no-trailing-punctuation)


103-103: Add missing articles and comma
Change to:
“To use our API, you need to create an instance of the EternalCoreAPI class.”
This adds the comma and the missing “an”.

🧰 Tools
🪛 LanguageTool

[typographical] ~103-~103: It seems that a comma is missing.
Context: ...ll not work!** ## 📝 Usage To use our API you need to create instance of `Eternal...

(IN_ORDER_TO_VB_COMMA)


[uncategorized] ~103-~103: You might be missing the article “an” here.
Context: ...sage To use our API you need to create instance of EternalCoreAPI class. You can do i...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ... our API you need to create instance of EternalCoreAPI class. You can do it by ...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ...lCoreAPIclass. You can do it by usingEternalCoreApiProvider.provide()` method...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

app/notification-generator/form/SoundTab.tsx (2)

16-23: Consider clarifying placeholder text

The placeholder "Np. ENTITY_PLAYER_LEVELUP" uses "Np." which might not be immediately clear to users. Consider using "e.g." or "Example:" for better clarity.

-      placeholder="Np. ENTITY_PLAYER_LEVELUP"
+      placeholder="e.g. ENTITY_PLAYER_LEVELUP"

52-54: Consider consistent placeholder format

Similar to the sound field, consider using "e.g." instead of "Np." in the volume and pitch placeholders for consistency and clarity.

-        placeholder="Np. 2.0"
+        placeholder="e.g. 2.0"
-        placeholder="Np. 1.0"
+        placeholder="e.g. 1.0"

Also applies to: 60-62

app/notification-generator/components/SoundIndicator.tsx (1)

15-26: Icon choice might be confusing

The SVG path shows a muted/crossed-out speaker icon, but this component appears when sound is playing. Consider using a regular speaker icon instead to match the actual state.

app/notification-generator/form/TitleTab.tsx (1)

15-29: Missing error handling for title fields

The title and subtitle FormFields don't receive error props, while the timing fields do. Consider adding error handling for consistency if validation exists for these fields.

     <FormField
       label="Title"
       name="title"
       value={notification.title}
       onChange={onChange}
       placeholder="Enter your title"
+      error={errors.title}
     />

     <FormField
       label="Subtitle"
       name="subtitle"
       value={notification.subtitle}
       onChange={onChange}
       placeholder="Enter your subtitle"
+      error={errors.subtitle}
     />
app/notification-generator/components/Title.tsx (1)

20-23: Consider mobile responsiveness

The fixed text sizes (text-3xl, text-xl) might be too large on small screens. Consider using responsive text classes like text-xl md:text-3xl for better mobile experience.

       className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 transform text-center transition-opacity duration-500"
       style={{ opacity: titleOpacity }}
     >
       {title && (
         <div 
-          className="font-minecraft mb-2 text-3xl font-bold text-white drop-shadow-[2px_2px_0px_rgba(0,0,0,0.5)]"
+          className="font-minecraft mb-2 text-xl md:text-3xl font-bold text-white drop-shadow-[2px_2px_0px_rgba(0,0,0,0.5)]"
         >
           {parseMinecraftText(title)}
         </div>
       )}
       {subtitle && (
         <div 
-          className="font-minecraft text-xl text-gray-300 drop-shadow-[2px_2px_0px_rgba(0,0,0,0.5)]"
+          className="font-minecraft text-base md:text-xl text-gray-300 drop-shadow-[2px_2px_0px_rgba(0,0,0,0.5)]"
         >
app/notification-generator/components/ActionBar.tsx (1)

28-42: Consider extracting text styling to a reusable constant.

The text shadow styling is quite complex and might be reused in other Minecraft-themed components. Consider extracting it to a shared constant for better maintainability.

+const MINECRAFT_TEXT_SHADOW = "2px 0 0 #000, -2px 0 0 #000, 0 2px 0 #000, 0 -2px 0 #000, 1px 1px #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000";

      <span
        className="font-minecraft"
        style={{
          color: "#fff",
          fontSize: "1.5rem",
-          textShadow:
-            "2px 0 0 #000, -2px 0 0 #000, 0 2px 0 #000, 0 -2px 0 #000, 1px 1px #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000",
+          textShadow: MINECRAFT_TEXT_SHADOW,
app/notification-generator/components/ChatMessage.tsx (1)

20-37: Consider extracting shared styling to reduce code duplication.

The styling for both single-line and multiline message containers is nearly identical. You could extract the shared classes into a variable.

+  const messageStyle = "font-minecraft relative px-4 text-white drop-shadow-[2px_2px_0px_rgba(0,0,0,0.5)]";
+  const containerStyle = { zIndex: 1, height: "32px", lineHeight: "32px" };

   {message.includes("\n") ? (
     message.split("\n").map((line, index) => (
       <div
         key={index}
-        className="font-minecraft relative px-4 text-white drop-shadow-[2px_2px_0px_rgba(0,0,0,0.5)]"
-        style={{ zIndex: 1, height: "32px", lineHeight: "32px" }}
+        className={messageStyle}
+        style={containerStyle}
       >
         {parseMinecraftText(line)}
       </div>
     ))
   ) : (
     <div
-      className="font-minecraft relative px-4 text-white drop-shadow-[2px_2px_0px_rgba(0,0,0,0.5)]"
-      style={{ zIndex: 1, height: "32px", lineHeight: "32px" }}
+      className={messageStyle}
+      style={containerStyle}
     >
       {parseMinecraftText(message)}
     </div>
   )}
app/notification-generator/MinecraftPreview.tsx (1)

3-3: Remove unused import.

The useMemo import is not being used in this component.

-import React, { useMemo } from "react";
+import React from "react";
app/notification-generator/form/validation.ts (1)

31-58: Consider making validateForm more generic.

The validateForm function manually checks specific fields instead of iterating through all notification fields. This makes it less maintainable.

 export const validateForm = (
   notification: Record<string, string>,
   validateFieldFn: (field: FieldType, value: string) => string
 ): Record<string, string> => {
   const errors: Record<string, string> = {};

-  if (notification.fadeIn) {
-    const error = validateFieldFn("fadeIn" as FieldType, notification.fadeIn);
-    if (error) errors.fadeIn = error;
-  }
-
-  if (notification.stay) {
-    const error = validateFieldFn("stay" as FieldType, notification.stay);
-    if (error) errors.stay = error;
-  }
-
-  if (notification.fadeOut) {
-    const error = validateFieldFn("fadeOut" as FieldType, notification.fadeOut);
-    if (error) errors.fadeOut = error;
-  }
-
-  if (notification.sound) {
-    const error = validateFieldFn("sound" as FieldType, notification.sound);
-    if (error) errors.sound = error;
-  }
+  Object.entries(notification).forEach(([field, value]) => {
+    if (value) {
+      const error = validateFieldFn(field as FieldType, value);
+      if (error) errors[field] = error;
+    }
+  });

   return errors;
 };
content/docs/eternalcore/notifications.md (2)

168-168: Fix grammar in heading.

The heading has incorrect verb form.

-#### Clear title/subtitle before send new
+#### Clear title/subtitle before sending new
🧰 Tools
🪛 LanguageTool

[uncategorized] ~168-~168: This verb may not be in the correct form. Consider using a different form for this context.
Context: .... #### Clear title/subtitle before send new yaml # Clears the title and sub...

(AI_EN_LECTOR_REPLACEMENT_VERB_FORM)


81-81: Remove trailing punctuation from heading.

Markdown headings shouldn't end with colons.

-### Examples combining multiple notifications:
+### Examples combining multiple notifications
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

81-81: Trailing punctuation in heading
Punctuation: ':'

(MD026, no-trailing-punctuation)

app/notification-generator/NotificationForm.tsx (1)

12-12: Unused import detected.

The validateForm function is imported but never used in this component.

-import { validateField, validateForm } from "./form/validation";
+import { validateField } from "./form/validation";
app/parser/minecraftTextParser.tsx (1)

58-67: Unused variables that serve no purpose.

These variables are declared but never used in the parsing logic.

-  let processedText = text;
-  let lastColor = '';
-  let lastStyle = '';
app/notification-generator/hooks.ts (1)

8-13: Improve time format flexibility

The parseTime function only accepts seconds format ("1.5s"). Consider supporting milliseconds and other common time formats for better usability.

const parseTime = useCallback((timeStr: string) => {
  if (!timeStr) return 0;
- const match = timeStr.match(/^(\d+(\.\d+)?)s$/);
+ const match = timeStr.match(/^(\d+(\.\d+)?)(s|ms)?$/);
  if (!match) return 0;
- return parseFloat(match[1]);
+ const value = parseFloat(match[1]);
+ const unit = match[3] || 's';
+ return unit === 'ms' ? value / 1000 : value;
}, []);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 97e6047 and ccfcf04.

⛔ Files ignored due to path filters (3)
  • public/fonts/Minecraftia-Regular.ttf is excluded by !**/*.ttf
  • public/mc-bg.png is excluded by !**/*.png
  • public/minecraft-bg.svg is excluded by !**/*.svg
📒 Files selected for processing (62)
  • app/api/docs/search/route.ts (1 hunks)
  • app/api/og/route.tsx (1 hunks)
  • app/docs/[...slug]/page.tsx (1 hunks)
  • app/docs/page.tsx (1 hunks)
  • app/layout.tsx (2 hunks)
  • app/not-found.tsx (1 hunks)
  • app/notification-generator/MinecraftPreview.tsx (1 hunks)
  • app/notification-generator/MiniMessageInfoBox.tsx (1 hunks)
  • app/notification-generator/NotificationCode.tsx (1 hunks)
  • app/notification-generator/NotificationForm.tsx (1 hunks)
  • app/notification-generator/SoundInfoBox.tsx (1 hunks)
  • app/notification-generator/components/ActionBar.tsx (1 hunks)
  • app/notification-generator/components/BackgroundImage.tsx (1 hunks)
  • app/notification-generator/components/ChatMessage.tsx (1 hunks)
  • app/notification-generator/components/SoundIndicator.tsx (1 hunks)
  • app/notification-generator/components/Title.tsx (1 hunks)
  • app/notification-generator/form/ActionBarTab.tsx (1 hunks)
  • app/notification-generator/form/AdvancedTab.tsx (1 hunks)
  • app/notification-generator/form/ChatTab.tsx (1 hunks)
  • app/notification-generator/form/FormField.tsx (1 hunks)
  • app/notification-generator/form/SoundTab.tsx (1 hunks)
  • app/notification-generator/form/Tab.tsx (1 hunks)
  • app/notification-generator/form/TitleTab.tsx (1 hunks)
  • app/notification-generator/form/constants.ts (1 hunks)
  • app/notification-generator/form/validation.ts (1 hunks)
  • app/notification-generator/hooks.ts (1 hunks)
  • app/notification-generator/layout.tsx (1 hunks)
  • app/notification-generator/minecraft-font.css (1 hunks)
  • app/notification-generator/page.tsx (1 hunks)
  • app/notification-generator/types.ts (1 hunks)
  • app/page.tsx (1 hunks)
  • app/parser/minecraftTextParser.tsx (1 hunks)
  • app/prism-languages.ts (1 hunks)
  • app/providers.tsx (1 hunks)
  • components/Analytics.tsx (1 hunks)
  • components/CookieConsentModal.tsx (1 hunks)
  • components/OgImage.tsx (1 hunks)
  • components/SectionTitle.tsx (1 hunks)
  • components/SpeedInsights.tsx (1 hunks)
  • components/about/About.tsx (3 hunks)
  • components/docs/DocCopyEnhancer.tsx (1 hunks)
  • components/docs/DocSearch.tsx (1 hunks)
  • components/docs/ErrorBoundary.tsx (1 hunks)
  • components/docs/ui/AlertBox.tsx (1 hunks)
  • components/faq/Faq.tsx (4 hunks)
  • components/features/Features.tsx (3 hunks)
  • components/footer/Footer.tsx (1 hunks)
  • components/header/Navbar.tsx (2 hunks)
  • components/header/ToolsDropdown.tsx (1 hunks)
  • components/header/hero/Hero.tsx (2 hunks)
  • components/header/hero/button/BackgroundHeroButton.tsx (1 hunks)
  • components/header/hero/button/TransparentHeroButton.tsx (1 hunks)
  • content/docs/eternalcombat/using-api.md (1 hunks)
  • content/docs/eternalcore/notifications.md (1 hunks)
  • content/docs/eternalcore/using-api.md (1 hunks)
  • hooks/useCookieConsent.ts (1 hunks)
  • lib/mdx-config.mjs (1 hunks)
  • lib/mdx-config.ts (1 hunks)
  • lib/mdx.tsx (1 hunks)
  • lib/og-utils.ts (1 hunks)
  • next.config.mjs (2 hunks)
  • reset.d.ts (1 hunks)
✅ Files skipped from review due to trivial changes (10)
  • reset.d.ts
  • app/notification-generator/minecraft-font.css
  • app/notification-generator/layout.tsx
  • app/notification-generator/MiniMessageInfoBox.tsx
  • app/notification-generator/SoundInfoBox.tsx
  • lib/mdx-config.ts
  • app/notification-generator/form/constants.ts
  • lib/mdx-config.mjs
  • app/notification-generator/components/BackgroundImage.tsx
  • app/notification-generator/NotificationCode.tsx
🚧 Files skipped from review as they are similar to previous changes (27)
  • app/not-found.tsx
  • components/about/About.tsx
  • components/SectionTitle.tsx
  • components/SpeedInsights.tsx
  • lib/og-utils.ts
  • app/docs/page.tsx
  • app/api/og/route.tsx
  • components/Analytics.tsx
  • app/prism-languages.ts
  • components/OgImage.tsx
  • app/providers.tsx
  • components/features/Features.tsx
  • components/header/hero/Hero.tsx
  • components/header/hero/button/BackgroundHeroButton.tsx
  • hooks/useCookieConsent.ts
  • lib/mdx.tsx
  • components/docs/ui/AlertBox.tsx
  • app/api/docs/search/route.ts
  • components/footer/Footer.tsx
  • components/docs/DocCopyEnhancer.tsx
  • components/CookieConsentModal.tsx
  • components/docs/ErrorBoundary.tsx
  • app/page.tsx
  • content/docs/eternalcombat/using-api.md
  • app/docs/[...slug]/page.tsx
  • components/docs/DocSearch.tsx
  • components/faq/Faq.tsx
🧰 Additional context used
🧬 Code Graph Analysis (15)
app/notification-generator/form/AdvancedTab.tsx (1)
app/notification-generator/types.ts (2)
  • NotificationConfig (1-14)
  • FieldType (21-21)
app/notification-generator/components/ChatMessage.tsx (1)
app/parser/minecraftTextParser.tsx (1)
  • parseMinecraftText (3-175)
app/notification-generator/components/Title.tsx (1)
app/parser/minecraftTextParser.tsx (1)
  • parseMinecraftText (3-175)
app/notification-generator/form/Tab.tsx (1)
app/notification-generator/types.ts (1)
  • TabType (20-20)
components/header/ToolsDropdown.tsx (1)
components/icons/arrow-down.tsx (1)
  • ArrowDown (5-24)
app/notification-generator/page.tsx (4)
app/notification-generator/types.ts (1)
  • NotificationConfig (1-14)
app/notification-generator/NotificationForm.tsx (1)
  • NotificationForm (19-135)
app/notification-generator/NotificationCode.tsx (1)
  • NotificationCode (9-91)
app/notification-generator/MinecraftPreview.tsx (1)
  • MinecraftPreview (13-67)
app/notification-generator/form/TitleTab.tsx (3)
app/notification-generator/types.ts (2)
  • NotificationConfig (1-14)
  • FieldType (21-21)
app/notification-generator/form/FormField.tsx (1)
  • FormField (18-97)
app/notification-generator/MiniMessageInfoBox.tsx (1)
  • MiniMessageInfoBox (3-18)
app/notification-generator/form/validation.ts (1)
app/notification-generator/types.ts (1)
  • FieldType (21-21)
app/notification-generator/MinecraftPreview.tsx (2)
app/notification-generator/types.ts (1)
  • MinecraftPreviewProps (16-18)
app/notification-generator/hooks.ts (2)
  • useTitleAnimation (4-68)
  • useSoundEffect (70-83)
app/notification-generator/NotificationForm.tsx (8)
app/notification-generator/types.ts (3)
  • NotificationConfig (1-14)
  • TabType (20-20)
  • FieldType (21-21)
app/notification-generator/form/validation.ts (1)
  • validateField (3-29)
app/notification-generator/form/ChatTab.tsx (1)
  • ChatTab (12-25)
app/notification-generator/form/ActionBarTab.tsx (1)
  • ActionBarTab (12-23)
app/notification-generator/form/TitleTab.tsx (1)
  • TitleTab (13-61)
app/notification-generator/form/SoundTab.tsx (1)
  • SoundTab (14-67)
app/notification-generator/form/AdvancedTab.tsx (1)
  • AdvancedTab (10-30)
app/notification-generator/form/Tab.tsx (1)
  • Tab (13-36)
app/notification-generator/form/FormField.tsx (1)
app/notification-generator/types.ts (1)
  • FieldType (21-21)
components/header/hero/button/TransparentHeroButton.tsx (1)
components/icons/arrow-forward-hero.tsx (1)
  • ArrowForwardHeroIcon (3-18)
app/notification-generator/form/ActionBarTab.tsx (3)
app/notification-generator/types.ts (2)
  • NotificationConfig (1-14)
  • FieldType (21-21)
app/notification-generator/form/FormField.tsx (1)
  • FormField (18-97)
app/notification-generator/MiniMessageInfoBox.tsx (1)
  • MiniMessageInfoBox (3-18)
app/notification-generator/hooks.ts (1)
app/notification-generator/types.ts (1)
  • NotificationConfig (1-14)
components/header/Navbar.tsx (4)
components/icons/arrow-down.tsx (1)
  • ArrowDown (5-24)
components/icons/hamburger.tsx (1)
  • Hamburger (5-24)
components/icons/new-window.tsx (1)
  • NewWindow (3-20)
components/header/ToolsDropdown.tsx (1)
  • ToolsDropdown (8-101)
🪛 LanguageTool
content/docs/eternalcore/using-api.md

[uncategorized] ~11-~11: You might be missing the article “the” here.
Context: ...ork in your plugin, You need to install correct artifact for your project. Our plugin s...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[typographical] ~103-~103: It seems that a comma is missing.
Context: ...ll not work!** ## 📝 Usage To use our API you need to create instance of `Eternal...

(IN_ORDER_TO_VB_COMMA)


[uncategorized] ~103-~103: You might be missing the article “an” here.
Context: ...sage To use our API you need to create instance of EternalCoreAPI class. You can do i...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ... our API you need to create instance of EternalCoreAPI class. You can do it by ...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~103-~103: You might be missing the article “the” here.
Context: ...lCoreAPIclass. You can do it by usingEternalCoreApiProvider.provide()` method...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[uncategorized] ~109-~109: You might be missing the article “an” here.
Context: ...Provider.provide(); ``` After creating instance of api, the User gets access to various...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[typographical] ~139-~139: Consider adding a comma here.
Context: ... down the AfkService to your classes. After that You can use examples shown below. Chec...

(FOR_THAT_COMMA)


[uncategorized] ~139-~139: You might be missing the article “the” here.
Context: ...to your classes. After that You can use examples shown below. Check if the player is Af...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[style] ~177-~177: As a shorter alternative for ‘able to’, consider using “can”.
Context: ...he instance of CatboyService the User is able to mark players as catboys and give them u...

(BE_ABLE_TO)

content/docs/eternalcore/notifications.md

[uncategorized] ~168-~168: This verb may not be in the correct form. Consider using a different form for this context.
Context: .... #### Clear title/subtitle before send new yaml # Clears the title and sub...

(AI_EN_LECTOR_REPLACEMENT_VERB_FORM)

🪛 markdownlint-cli2 (0.17.2)
content/docs/eternalcore/using-api.md

14-14: Trailing punctuation in heading
Punctuation: ':'

(MD026, no-trailing-punctuation)


44-44: Trailing punctuation in heading
Punctuation: ':'

(MD026, no-trailing-punctuation)

content/docs/eternalcore/notifications.md

81-81: Trailing punctuation in heading
Punctuation: ':'

(MD026, no-trailing-punctuation)

🔇 Additional comments (45)
next.config.mjs (5)

2-8: MDX integration looks good!

The MDX setup correctly imports the configuration and creates the wrapper with proper extension matching. This will enable markdown files to work as pages.


11-11: Page extensions updated properly.

Adding "md" and "mdx" extensions allows markdown files to be treated as Next.js pages, which is exactly what's needed for the documentation system.


40-42: Good image optimization settings.

The explicit formats and detailed size arrays will help optimize image loading across different devices. AVIF and WebP formats provide better compression than traditional formats.


44-59: Solid performance and security configurations.

These settings improve the app in several ways:

  • Removes the X-Powered-By header for security
  • Enables compression for faster loading
  • Optimizes package imports for better bundle sizes
  • Configures server actions with proper origin restrictions

62-62: Export change aligns with MDX integration.

Switching from the bundle analyzer wrapper to the MDX wrapper makes sense since MDX support is the main goal here.

components/header/hero/button/TransparentHeroButton.tsx (4)

8-11: Animation setup looks good!

The intersection observer configuration is well-structured with appropriate threshold and triggerOnce settings.


15-25: Clean animation logic implementation

The useCallback and useEffect pattern properly handles the animation state changes. The dependency array is correct and the animation controls are used appropriately.


34-35: Good accessibility improvements

The aria-label provides clear context and the updated styling with hover states enhances user experience across light and dark modes.


37-40: Nice touch with the animated icon

The ArrowForwardHeroIcon with hover translation creates a polished interactive feel. The aria-hidden attribute is correctly applied since the icon is decorative.

app/notification-generator/form/AdvancedTab.tsx (2)

5-8: Well-defined component interface

The props interface is clear and properly typed, making the component easy to understand and use.


14-26: Clean checkbox implementation

The form controls are properly linked with id/htmlFor, and the styling supports both light and dark themes. The onChange handler correctly passes the field name and boolean value.

app/notification-generator/form/ActionBarTab.tsx (2)

7-10: Clear and focused component interface

The props interface is well-defined with proper typing, making the component's contract explicit.


14-22: Good component composition

The use of FormField for consistency and MiniMessageInfoBox for user guidance creates a helpful and cohesive user experience.

app/notification-generator/form/SoundTab.tsx (2)

26-45: Well-implemented dropdown with helpful context

The sound category dropdown is properly implemented with good styling and the help text clearly explains the user impact of the setting.


47-65: Smart grid layout for related fields

The two-column grid for volume and pitch makes good use of space and groups related settings together logically.

app/notification-generator/components/SoundIndicator.tsx (2)

8-9: Good conditional rendering pattern!

The early return when sound is falsy or playSound is false is clean and efficient.


34-34: Nice touch with displayName!

Setting the displayName helps with debugging and React DevTools.

app/notification-generator/form/ChatTab.tsx (1)

12-25: Clean and well-structured form tab!

The component properly uses FormField for input handling and includes helpful guidance with MiniMessageInfoBox. The placeholder text clearly explains the multiline feature.

app/notification-generator/form/TitleTab.tsx (1)

31-58: Good grid layout for timing fields!

The 3-column grid layout works well for the related timing fields. The placeholder examples (e.g. "1s", "2s") are helpful for users.

app/notification-generator/components/Title.tsx (2)

17-17: Good early return pattern!

Clean conditional rendering when title shouldn't be shown.


24-37: Nice conditional rendering and styling!

The component properly checks for title/subtitle content before rendering, and the Minecraft-themed styling with drop shadows ensures good readability against backgrounds.

app/notification-generator/components/ActionBar.tsx (1)

1-52: Great component structure and styling!

The ActionBar component is well implemented with good performance optimization using React.memo and proper early return pattern. The Minecraft-themed styling with the complex text shadow creates the authentic game-like appearance.

components/header/ToolsDropdown.tsx (2)

1-101: Excellent dropdown implementation with great accessibility!

This component demonstrates excellent practices with proper event handling, accessibility attributes, keyboard navigation, and smooth animations. The click-outside detection and escape key handling work perfectly together.


51-53: Great accessibility attributes!

Perfect use of ARIA attributes for screen readers and assistive technologies. The aria-haspopup, aria-expanded, and aria-controls attributes provide excellent accessibility support.

app/notification-generator/types.ts (1)

1-21: Clean and well-structured type definitions!

The interfaces and type aliases provide excellent TypeScript support for the notification generator. The NotificationConfig covers all necessary properties and the union types ensure type safety throughout the feature.

app/notification-generator/form/Tab.tsx (2)

1-36: Nicely animated tab component!

Great use of framer-motion for smooth animations and transitions. The conditional styling and active state indicator with layoutId create an excellent user experience. The component is clean and well-typed.


29-34: Excellent use of layout animations!

The layoutId="activeTab" creates smooth transitions when switching between tabs. This is a great pattern for animated tab indicators that provides professional polish to the UI.

app/notification-generator/components/ChatMessage.tsx (1)

8-9: Good use of memoization and early return.

The React.memo optimization and early return for empty messages are solid patterns.

app/notification-generator/MinecraftPreview.tsx (1)

13-16: Good use of custom hooks for state management.

The separation of title animation and sound effect logic into custom hooks makes the component clean and testable.

app/notification-generator/page.tsx (3)

29-99: YAML generation logic looks solid with good fallback handling.

The useEffect correctly regenerates YAML when notification state changes. The logic handles multiline chat messages, timing parameters, and sound configuration properly with sensible defaults.


101-104: Simple and effective preview refresh mechanism.

Using a key increment to force component re-render is a clean approach for triggering preview animations.


106-213: Well-structured UI with comprehensive animations.

The layout uses a responsive grid and motion components effectively. The animation timing and transitions create a smooth user experience.

content/docs/eternalcore/notifications.md (1)

1-175: Excellent documentation with comprehensive examples.

The documentation covers all notification types with clear syntax examples. The interactive generator link is a great addition for user experience.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~168-~168: This verb may not be in the correct form. Consider using a different form for this context.
Context: .... #### Clear title/subtitle before send new yaml # Clears the title and sub...

(AI_EN_LECTOR_REPLACEMENT_VERB_FORM)

🪛 markdownlint-cli2 (0.17.2)

81-81: Trailing punctuation in heading
Punctuation: ':'

(MD026, no-trailing-punctuation)

app/notification-generator/NotificationForm.tsx (3)

27-46: Smart validation handling with performance optimization.

The handleChange callback properly validates specific fields and clears errors when needed. Using useCallback prevents unnecessary re-renders.


49-65: Clean reset functionality.

The reset form callback properly clears both notification state and errors, returning to a clean initial state.


68-83: Well-organized tab content rendering.

The switch statement clearly maps each tab to its corresponding component, with proper error prop passing where needed.

app/parser/minecraftTextParser.tsx (1)

133-175: Tag parsing function is well-designed but unreachable.

The recursive tag parsing logic is solid and handles nested formatting correctly. However, it's currently unreachable due to the early return in the main loop.

app/notification-generator/hooks.ts (1)

70-83: Clean and simple implementation

The sound effect hook is well-implemented with proper cleanup. The 1-second timeout provides good user feedback for sound triggers.

components/header/Navbar.tsx (4)

3-38: Well-structured navigation setup

The NavLink interface and centralized NAV_LINKS array provide good type safety and maintainability. The separation of internal and external links is handled cleanly.


50-88: Excellent accessibility and UX implementation

The event handling is comprehensive with proper cleanup, focus management, and body scroll locking. These features greatly improve the user experience and accessibility.


142-204: Smooth and accessible mobile menu

The framer-motion animations create a polished user experience. The staggered list item animations and proper ARIA attributes make this both visually appealing and accessible.


206-242: Consistent desktop navigation implementation

The desktop menu maintains consistency with the mobile version by sharing the same link data and styling patterns. External link handling is properly implemented with security attributes.

app/layout.tsx (3)

1-28: Comprehensive font and build configuration

The expanded Poppins font configuration with multiple weights, swap display, and fallbacks provides excellent typography. The static generation with hourly revalidation is a good balance for performance.


30-108: Excellent SEO and metadata setup

The metadata configuration is comprehensive with proper Open Graph, Twitter cards, and robot directives. The dynamic OG image generation and theme colors enhance the user experience across platforms.


116-150: Well-structured and accessible layout

The layout properly uses semantic HTML with accessibility attributes. The addition of cookie consent management, analytics, and documentation enhancements creates a complete user experience.

Comment on lines 37 to 43
<AnimatePresence>
{notification.actionbar && (
<div>
<ActionBar message={notification.actionbar} />
</div>
)}
</AnimatePresence>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Missing positioning for ActionBar component.

The ActionBar is missing absolute positioning unlike other notification elements, which may cause layout issues.

 <AnimatePresence>
   {notification.actionbar && (
-    <div>
+    <div className="absolute bottom-16 left-1/2 transform -translate-x-1/2">
       <ActionBar message={notification.actionbar} />
     </div>
   )}
 </AnimatePresence>
📝 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.

Suggested change
<AnimatePresence>
{notification.actionbar && (
<div>
<ActionBar message={notification.actionbar} />
</div>
)}
</AnimatePresence>
<AnimatePresence>
{notification.actionbar && (
<div className="absolute bottom-16 left-1/2 transform -translate-x-1/2">
<ActionBar message={notification.actionbar} />
</div>
)}
</AnimatePresence>
🤖 Prompt for AI Agents
In app/notification-generator/MinecraftPreview.tsx around lines 37 to 43, the
ActionBar component is missing absolute positioning, unlike other notification
elements. To fix this, wrap the ActionBar in a div with appropriate CSS styles
to apply absolute positioning, ensuring it aligns consistently with other
notification elements and prevents layout issues.

Comment on lines 28 to 49
const fadeInInterval = setInterval(() => {
setTitleOpacity((prev) => {
if (prev >= 1) {
clearInterval(fadeInInterval);
return 1;
}
return prev + 0.1;
});
}, fadeIn * 100);

const stayTimeout = setTimeout(() => {
const fadeOutInterval = setInterval(() => {
setTitleOpacity((prev) => {
if (prev <= 0) {
clearInterval(fadeOutInterval);
setShowTitle(false);
return 0;
}
return prev - 0.1;
});
}, fadeOut * 100);
}, (fadeIn + stay) * 1000);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix animation timing and cleanup issues

The animation has timing calculation problems and incomplete cleanup that could cause memory leaks.

const fadeInInterval = setInterval(() => {
  setTitleOpacity((prev) => {
    if (prev >= 1) {
      clearInterval(fadeInInterval);
      return 1;
    }
    return prev + 0.1;
  });
-}, fadeIn * 100);
+}, (fadeIn * 1000) / 10);

const stayTimeout = setTimeout(() => {
+ let fadeOutInterval: NodeJS.Timeout;
- const fadeOutInterval = setInterval(() => {
+ fadeOutInterval = setInterval(() => {
    setTitleOpacity((prev) => {
      if (prev <= 0) {
        clearInterval(fadeOutInterval);
        setShowTitle(false);
        return 0;
      }
      return prev - 0.1;
    });
-  }, fadeOut * 100);
+  }, (fadeOut * 1000) / 10);
}, (fadeIn + stay) * 1000);

return () => {
  clearTimeout(stayTimeout);
  clearInterval(fadeInInterval);
+ if (fadeOutInterval) clearInterval(fadeOutInterval);
};

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In app/notification-generator/hooks.ts around lines 28 to 49, the animation
timing calculations are inconsistent because fadeIn and fadeOut are multiplied
by 100 in setInterval but stay is multiplied by 1000 in setTimeout, causing
timing issues. Also, the intervals and timeouts are not cleared on component
unmount, risking memory leaks. Fix this by using consistent time units
(milliseconds) for all timers and ensure all intervals and timeouts are cleared
properly in a cleanup function, such as in a useEffect return callback.

Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
app/notification-generator/form/SoundTab.tsx (1)

64-86: Consider adding validation for slider ranges

The slider fields are properly configured, but you might want to add client-side validation to ensure the volume (0.0-1.0) and pitch (0.5-2.0) ranges are enforced before passing to the parent component.

app/notification-generator/form/SliderField.tsx (1)

27-29: Handle edge case for invalid initial values

The fallback to midpoint is good, but consider what happens if min or max are invalid numbers. This could cause NaN issues.

  const [sliderValue, setSliderValue] = useState<number>(
-    value ? parseFloat(value) : (min + max) / 2
+    value && !isNaN(parseFloat(value)) ? parseFloat(value) : (min + max) / 2
  );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ccfcf04 and e52ddf9.

📒 Files selected for processing (6)
  • app/notification-generator/NotificationForm.tsx (1 hunks)
  • app/notification-generator/SoundInfoBox.tsx (1 hunks)
  • app/notification-generator/form/SliderField.tsx (1 hunks)
  • app/notification-generator/form/SoundDropdown.tsx (1 hunks)
  • app/notification-generator/form/SoundTab.tsx (1 hunks)
  • app/notification-generator/page.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • app/notification-generator/SoundInfoBox.tsx
  • app/notification-generator/NotificationForm.tsx
  • app/notification-generator/page.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
app/notification-generator/form/SoundDropdown.tsx

[error] 171-171: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 174-174: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 190-190: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 193-193: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)

🔇 Additional comments (5)
app/notification-generator/form/SoundTab.tsx (1)

21-30: Good use of forwardRef pattern!

The component correctly exposes the stopSound method through the ref, allowing parent components to control audio playback. The implementation is clean and follows React best practices.

app/notification-generator/form/SliderField.tsx (2)

32-39: Good value synchronization logic

The useEffect properly handles external value changes and bounds the value within the min/max range. This prevents invalid slider states.


75-84: Nice animation for error messages

The framer-motion animation provides smooth feedback when validation errors appear. Good user experience enhancement!

app/notification-generator/form/SoundDropdown.tsx (2)

157-217: Good audio handling with proper cleanup

The audio playback logic properly handles volume/pitch validation, error cases, and cleanup. The fallback error messages provide good user feedback.

🧰 Tools
🪛 Biome (1.9.4)

[error] 171-171: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 174-174: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 190-190: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 193-193: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


104-113: Smart fallback data strategy

Providing default sounds when the API fails ensures the component remains functional. Good resilience approach!

let volumeValue = 1.0; // Default value
if (typeof volume === "string") {
const parsedVolume = parseFloat(volume);
if (!isNaN(parsedVolume) && isFinite(parsedVolume)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix unsafe isFinite usage

Static analysis correctly identifies unsafe isFinite usage. Use Number.isFinite instead to avoid type coercion issues.

-        if (!isNaN(parsedVolume) && isFinite(parsedVolume)) {
+        if (!isNaN(parsedVolume) && Number.isFinite(parsedVolume)) {
          volumeValue = Math.min(Math.max(parsedVolume, 0), 1.0);
        }
-      } else if (typeof volume === "number" && isFinite(volume)) {
+      } else if (typeof volume === "number" && Number.isFinite(volume)) {
        volumeValue = Math.min(Math.max(volume, 0), 1.0);
      }

-        if (!isNaN(parsedPitch) && isFinite(parsedPitch)) {
+        if (!isNaN(parsedPitch) && Number.isFinite(parsedPitch)) {
          pitchValue = Math.min(Math.max(parsedPitch, 0.5), 2.0);
        }
-      } else if (typeof pitch === "number" && isFinite(pitch)) {
+      } else if (typeof pitch === "number" && Number.isFinite(pitch)) {
        pitchValue = Math.min(Math.max(pitch, 0.5), 2.0);
      }

Also applies to: 174-174, 190-190, 193-193

🧰 Tools
🪛 Biome (1.9.4)

[error] 171-171: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)

🤖 Prompt for AI Agents
In app/notification-generator/form/SoundDropdown.tsx at lines 171, 174, 190, and
193, replace all uses of the global isFinite function with Number.isFinite to
prevent unsafe type coercion. Update the conditions by changing
isFinite(parsedVolume) to Number.isFinite(parsedVolume) to ensure proper type
checking.

Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (13)
components/ui/AlertBox.tsx (3)

41-114: Consider moving large configuration to separate file.

The alertStyles object is quite large and makes the component file lengthy. Consider extracting it to a separate constants file for better maintainability.

// Create a new file: components/ui/AlertBox.constants.ts
+export const alertStyles = {
+  // ... move the entire alertStyles object here
+};

// Then import in AlertBox.tsx
+import { alertStyles } from './AlertBox.constants';
-const alertStyles = {
-  // ... remove from here
-};

128-138: Default titles could be more descriptive.

Some default titles like "Read this!" for warnings could be more specific and helpful to users.

-  warning: "Read this!",
+  warning: "Warning",

155-156: Remove extra blank lines.

There are unnecessary blank lines that should be cleaned up.

  const defaultTitle = defaultTitles[type];

-

  const ariaLabel = typeof title === "string" ? title : `${type} alert`;
components/ui/Dropdown.tsx (1)

61-61: Move inline styles to CSS classes for better maintainability.

The component uses several inline styles that could be moved to CSS classes:

  • Button outline/boxShadow removal (line 61, 103)
  • Scrollbar hiding styles (lines 83-89, 92-98)

Consider creating CSS utility classes for these common styles to improve maintainability and reduce code duplication.

Also applies to: 83-89, 92-98, 103-103

components/notification-generator/ActionBar.tsx (1)

10-47: Consider extracting inline styles for better maintainability.

The extensive inline styles work but make the component harder to maintain. Consider moving the complex styling to CSS classes or styled components.

+const actionBarStyles = {
+  container: {
+    bottom: "12%",
+    transform: "translateX(-50%)",
+    width: "100%",
+    textAlign: "center" as const,
+    pointerEvents: "none" as const,
+    zIndex: 10,
+  },
+  text: {
+    color: "#fff",
+    fontSize: "1.5rem",
+    textShadow: "2px 0 0 #000, -2px 0 0 #000, 0 2px 0 #000, 0 -2px 0 #000, 1px 1px #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000",
+    fontWeight: "normal",
+    lineHeight: 1.2,
+    userSelect: "none" as const,
+  }
+};

-      style={{
-        bottom: "12%",
-        transform: "translateX(-50%)",
-        width: "100%",
-        textAlign: "center",
-        pointerEvents: "none",
-        zIndex: 10,
-        background: "none",
-        border: "none",
-        boxShadow: "none",
-        padding: 0,
-      }}
+      style={actionBarStyles.container}
components/notification-generator/ChatMessage.tsx (1)

20-37: Consider extracting common styling to reduce duplication.

The multiline and single line rendering have identical styling. Extract this to a common constant or component.

+const messageLineStyles = {
+  className: "font-minecraft relative px-4 text-white drop-shadow-[2px_2px_0px_rgba(0,0,0,0.5)]",
+  style: { zIndex: 1, height: "32px", lineHeight: "32px" }
+};

+const MessageLine = ({ children }: { children: React.ReactNode }) => (
+  <div {...messageLineStyles}>
+    {children}
+  </div>
+);

{message.includes("\n") ? (
  message.split("\n").map((line, index) => (
-    <div
-      key={index}
-      className="font-minecraft relative px-4 text-white drop-shadow-[2px_2px_0px_rgba(0,0,0,0.5)]"
-      style={{ zIndex: 1, height: "32px", lineHeight: "32px" }}
-    >
+    <MessageLine key={index}>
      {parseMinecraftText(line)}
-    </div>
+    </MessageLine>
  ))
) : (
-  <div
-    className="font-minecraft relative px-4 text-white drop-shadow-[2px_2px_0px_rgba(0,0,0,0.5)]"
-    style={{ zIndex: 1, height: "32px", lineHeight: "32px" }}
-  >
+  <MessageLine>
    {parseMinecraftText(message)}
-  </div>
+  </MessageLine>
)}
components/notification-generator/form/FormField.tsx (1)

73-94: Add IDs to error and help text for accessibility.

Screen readers need these IDs to announce the messages properly.

       {error ? (
         <motion.p 
+          id={`${name}-error`}
           className="text-xs text-red-500"
           initial={{ opacity: 0 }}
           animate={{ opacity: 1 }}
           exit={{ opacity: 0 }}
           transition={{ duration: 0.1 }}
         >
           {error}
         </motion.p>
       ) : helpText ? (
         <motion.p 
+          id={`${name}-help`}
           className="text-xs text-gray-500 dark:text-gray-400"
           initial={{ opacity: 0 }}
           animate={{ opacity: 1 }}
           transition={{ duration: 0.1, delay: 0.1 }}
         >
           {helpText}
         </motion.p>
       ) : null}
components/notification-generator/form/SoundDropdown.tsx (1)

65-126: Consider extracting sound fetching to a custom hook.

This would make the component more readable and the logic reusable.

The sound fetching logic could be moved to a custom hook like useSoundData() to separate concerns and make the component cleaner. Would you like me to create this refactor?

components/notification-generator/MinecraftPreview.tsx (1)

29-65: Consider adding wrapper positioning classes

The AnimatePresence blocks use basic div wrappers. Consider adding consistent positioning classes to improve layout predictability, especially for the ActionBar and Title components that might need specific positioning.

-        {notification.actionbar && (
-          <div>
-            <ActionBar message={notification.actionbar} />
-          </div>
-        )}
+        {notification.actionbar && (
+          <div className="absolute bottom-16 left-1/2 transform -translate-x-1/2">
+            <ActionBar message={notification.actionbar} />
+          </div>
+        )}
components/notification-generator/minecraftTextParser.tsx (1)

59-62: Remove unused variables

These variables are declared but never used in the function.

-  let processedText = text;
-  let lastColor = '';
-  let lastStyle = '';
components/notification-generator/form/validation.ts (1)

31-58: Simplify validateForm function

The function takes a validateFieldFn parameter but only uses the local validateField. This makes the API more complex than needed.

-export const validateForm = (
-  notification: Record<string, string>,
-  validateFieldFn: (field: FieldType, value: string) => string
-): Record<string, string> => {
+export const validateForm = (
+  notification: Record<string, string>
+): Record<string, string> => {
   const errors: Record<string, string> = {};
   
   if (notification.fadeIn) {
-    const error = validateFieldFn("fadeIn" as FieldType, notification.fadeIn);
+    const error = validateField("fadeIn", notification.fadeIn);
     if (error) errors.fadeIn = error;
   }
   // ... rest of the function
components/notification-generator/form/SoundTab.tsx (2)

3-3: Remove unused imports

The useState and useEffect imports are not used in this component.

-import { useRef, forwardRef, useImperativeHandle, useState, useEffect } from "react";
+import { useRef, forwardRef, useImperativeHandle } from "react";

65-65: Improve type safety

The type casting here could be made safer by ensuring the field name is actually a valid FieldType.

-onChange={(name, value) => onChange(name as FieldType, value)}
+onChange={(name: string, value: string) => {
+  if (name === 'volume' || name === 'pitch') {
+    onChange(name, value);
+  }
+}}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4f9804f and 8b9151a.

📒 Files selected for processing (35)
  • app/notification-generator/layout.tsx (1 hunks)
  • app/notification-generator/page.tsx (1 hunks)
  • app/privacy-policy/page.tsx (1 hunks)
  • components/header/polygon/PolygonLeft.tsx (0 hunks)
  • components/header/polygon/PolygonRight.tsx (0 hunks)
  • components/notification-generator/ActionBar.tsx (1 hunks)
  • components/notification-generator/BackgroundImage.tsx (1 hunks)
  • components/notification-generator/ChatMessage.tsx (1 hunks)
  • components/notification-generator/MinecraftPreview.tsx (1 hunks)
  • components/notification-generator/MiniMessageInfoBox.tsx (1 hunks)
  • components/notification-generator/NotificationCode.tsx (1 hunks)
  • components/notification-generator/NotificationForm.tsx (1 hunks)
  • components/notification-generator/SoundIndicator.tsx (1 hunks)
  • components/notification-generator/SoundInfoBox.tsx (1 hunks)
  • components/notification-generator/Title.tsx (1 hunks)
  • components/notification-generator/form/ActionBarTab.tsx (1 hunks)
  • components/notification-generator/form/AdvancedTab.tsx (1 hunks)
  • components/notification-generator/form/ChatTab.tsx (1 hunks)
  • components/notification-generator/form/FormField.tsx (1 hunks)
  • components/notification-generator/form/SliderField.tsx (1 hunks)
  • components/notification-generator/form/SoundDropdown.tsx (1 hunks)
  • components/notification-generator/form/SoundTab.tsx (1 hunks)
  • components/notification-generator/form/Tab.tsx (1 hunks)
  • components/notification-generator/form/TitleTab.tsx (1 hunks)
  • components/notification-generator/form/constants.ts (1 hunks)
  • components/notification-generator/form/validation.ts (1 hunks)
  • components/notification-generator/hooks.ts (1 hunks)
  • components/notification-generator/minecraft-font.css (1 hunks)
  • components/notification-generator/minecraftTextParser.tsx (1 hunks)
  • components/notification-generator/types.ts (1 hunks)
  • components/ui/AlertBox.tsx (1 hunks)
  • components/ui/Dropdown.tsx (1 hunks)
  • hooks/useCookieConsent.ts (1 hunks)
  • lib/cookie-utils.ts (1 hunks)
  • lib/mdx.tsx (1 hunks)
💤 Files with no reviewable changes (2)
  • components/header/polygon/PolygonRight.tsx
  • components/header/polygon/PolygonLeft.tsx
✅ Files skipped from review due to trivial changes (7)
  • components/notification-generator/types.ts
  • components/notification-generator/SoundInfoBox.tsx
  • components/notification-generator/minecraft-font.css
  • components/notification-generator/BackgroundImage.tsx
  • components/notification-generator/MiniMessageInfoBox.tsx
  • components/notification-generator/form/constants.ts
  • components/notification-generator/NotificationCode.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • app/notification-generator/layout.tsx
  • lib/cookie-utils.ts
  • app/privacy-policy/page.tsx
  • lib/mdx.tsx
  • hooks/useCookieConsent.ts
  • app/notification-generator/page.tsx
🧰 Additional context used
🧬 Code Graph Analysis (14)
components/notification-generator/MinecraftPreview.tsx (2)
components/notification-generator/types.ts (1)
  • MinecraftPreviewProps (16-18)
components/notification-generator/hooks.ts (2)
  • useTitleAnimation (4-68)
  • useSoundEffect (70-83)
components/notification-generator/form/ActionBarTab.tsx (3)
components/notification-generator/types.ts (2)
  • NotificationConfig (1-14)
  • FieldType (21-21)
components/notification-generator/form/FormField.tsx (1)
  • FormField (18-97)
components/notification-generator/MiniMessageInfoBox.tsx (1)
  • MiniMessageInfoBox (3-18)
components/notification-generator/ChatMessage.tsx (1)
components/notification-generator/minecraftTextParser.tsx (1)
  • parseMinecraftText (3-175)
components/notification-generator/form/AdvancedTab.tsx (1)
components/notification-generator/types.ts (2)
  • NotificationConfig (1-14)
  • FieldType (21-21)
components/notification-generator/form/FormField.tsx (1)
components/notification-generator/types.ts (1)
  • FieldType (21-21)
components/notification-generator/Title.tsx (1)
components/notification-generator/minecraftTextParser.tsx (1)
  • parseMinecraftText (3-175)
components/notification-generator/form/ChatTab.tsx (3)
components/notification-generator/types.ts (2)
  • NotificationConfig (1-14)
  • FieldType (21-21)
components/notification-generator/form/FormField.tsx (1)
  • FormField (18-97)
components/notification-generator/MiniMessageInfoBox.tsx (1)
  • MiniMessageInfoBox (3-18)
components/notification-generator/form/TitleTab.tsx (3)
components/notification-generator/types.ts (2)
  • NotificationConfig (1-14)
  • FieldType (21-21)
components/notification-generator/form/FormField.tsx (1)
  • FormField (18-97)
components/notification-generator/MiniMessageInfoBox.tsx (1)
  • MiniMessageInfoBox (3-18)
components/notification-generator/form/validation.ts (1)
components/notification-generator/types.ts (1)
  • FieldType (21-21)
components/notification-generator/form/Tab.tsx (1)
components/notification-generator/types.ts (1)
  • TabType (20-20)
components/notification-generator/hooks.ts (1)
components/notification-generator/types.ts (1)
  • NotificationConfig (1-14)
components/ui/Dropdown.tsx (1)
components/icons/arrow-down.tsx (1)
  • ArrowDown (5-24)
components/ui/AlertBox.tsx (1)
lib/utils.ts (1)
  • cn (9-11)
components/notification-generator/NotificationForm.tsx (8)
components/notification-generator/types.ts (3)
  • NotificationConfig (1-14)
  • TabType (20-20)
  • FieldType (21-21)
components/notification-generator/form/SoundTab.tsx (2)
  • SoundTabRef (19-21)
  • SoundTab (23-86)
components/notification-generator/form/validation.ts (1)
  • validateField (3-29)
components/notification-generator/form/ChatTab.tsx (1)
  • ChatTab (12-25)
components/notification-generator/form/ActionBarTab.tsx (1)
  • ActionBarTab (12-23)
components/notification-generator/form/TitleTab.tsx (1)
  • TitleTab (13-61)
components/notification-generator/form/AdvancedTab.tsx (1)
  • AdvancedTab (10-30)
components/notification-generator/form/Tab.tsx (1)
  • Tab (13-36)
🪛 Biome (1.9.4)
components/notification-generator/form/SoundDropdown.tsx

[error] 172-172: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 175-175: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 191-191: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 194-194: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)

🔇 Additional comments (21)
components/ui/AlertBox.tsx (3)

1-18: Good setup with proper imports and client directive.

The imports are clean and all necessary dependencies are included. The "use client" directive is appropriate for this animated component.


19-39: Well-defined types and interfaces.

The AlertBoxType union and AlertBoxProps interface are comprehensive and well-documented. Good use of JSDoc comments for prop descriptions.


146-193: Excellent component implementation with good accessibility.

The component is well-implemented with proper memoization, smooth animations, and comprehensive accessibility features. The ARIA roles and labels are correctly applied for different alert types.

components/ui/Dropdown.tsx (2)

38-50: Great implementation of outside click handling.

The useEffect properly handles cleanup and uses mousedown event which is more reliable than click for this use case.


54-74: Excellent accessibility implementation.

The button has proper ARIA attributes (aria-expanded, aria-haspopup) and the arrow animation provides good visual feedback.

components/notification-generator/form/ActionBarTab.tsx (1)

12-23: Clean and focused component implementation.

The component has a clear single responsibility and uses proper TypeScript interfaces. The integration with FormField and MiniMessageInfoBox is well done.

components/notification-generator/form/AdvancedTab.tsx (1)

10-30: Well-implemented form component with good accessibility.

The checkbox implementation follows HTML best practices with proper label association and the TypeScript interfaces are correctly defined for boolean handling.

components/notification-generator/SoundIndicator.tsx (1)

8-32: Excellent use of React.memo and clean conditional rendering.

The memoization will prevent unnecessary re-renders, and the conditional rendering logic is clear and efficient. The inline SVG and proper displayName setting are good practices.

components/notification-generator/form/ChatTab.tsx (1)

1-25: Clean and well-structured component!

The implementation follows React best practices with proper TypeScript interfaces and clean imports. The component is simple and focused on a single responsibility.

components/notification-generator/Title.tsx (1)

1-44: Good use of React.memo and clean conditional rendering.

The component is well-structured with proper optimization. The text parsing integration looks solid and the styling approach is consistent.

components/notification-generator/form/TitleTab.tsx (1)

13-61: Nice clean implementation!

The component structure is clear and makes good use of the FormField component. The grid layout for timing fields is a nice touch.

components/notification-generator/MinecraftPreview.tsx (1)

13-16: LGTM! Clean component structure

The component properly uses custom hooks and manages the notification preview state well. The separation of concerns between animation and sound logic is good.

components/notification-generator/NotificationForm.tsx (2)

47-66: LGTM! Proper cleanup in reset function

Good implementation of the reset function with proper sound cleanup and state reset. The useCallback optimization is appropriate here.


27-45: 🛠️ Refactor suggestion

Fix unnecessary re-renders in handleChange callback

The errors dependency in the useCallback will cause the function to recreate every time errors change, potentially causing unnecessary re-renders of child components.

-  }, [notification, setNotification, errors]);
+  }, [notification, setNotification]);

The errors check inside can use the current errors state without needing it as a dependency.

Likely an incorrect or invalid review comment.

components/notification-generator/form/validation.ts (1)

15-19:

❓ Verification inconclusive

Verify sound validation regex

The current regex only allows uppercase letters and underscores, which might be too restrictive for Minecraft sound names. Consider if lowercase or other characters should be allowed.


🏁 Script executed:

#!/bin/bash
# Check Minecraft sound naming conventions
rg -A 5 -B 5 "sound.*[a-z]" --type=ts --type=tsx

Length of output: 78


Review and adjust sound regex

The current regex in components/notification-generator/form/validation.ts only allows uppercase letters and underscores (plus an optional space). Minecraft sound event IDs are lowercase and often include dots and underscores (e.g. entity.cow.ambient). Please update the pattern to allow lowercase letters, periods, and underscores or confirm that your sound names follow the existing format.

• File: components/notification-generator/form/validation.ts

  • Case "sound": replace /^[A-Z_]+(\s+[A-Z_]+)?$/ with a regex that matches lowercase, dots, and underscores (for example: /^[a-z0-9_\.]+$/).

Simplify validateForm

The validateForm function’s signature currently takes an extra parameter that isn’t needed. Remove it and make sure all intended fields (including any you’ve added recently) are covered by the validation logic.

components/notification-generator/form/SoundTab.tsx (1)

23-86: Well-structured component implementation

The forwardRef pattern is correctly implemented with proper type definitions. The useImperativeHandle usage allows parent components to control sound playback effectively.

components/notification-generator/hooks.ts (1)

70-83: Simple and effective sound hook

The useSoundEffect hook is well-implemented with proper cleanup and straightforward state management.

components/notification-generator/form/SliderField.tsx (4)

27-39: Good initialization and bounds checking

The component properly initializes the slider value and ensures it stays within bounds when props change.


42-46: Efficient change handling

Using useCallback here prevents unnecessary re-renders and the formatting to 2 decimals ensures consistent value display.


125-143: Excellent accessibility implementation

The dropdown button properly uses ARIA attributes (aria-expanded, aria-haspopup) and the animated chevron provides good visual feedback.


106-115: Proper click-outside handling

The event listener is correctly added and removed to prevent memory leaks, and the ref-based outside click detection works well.

Comment on lines 169 to 197
let volumeValue = 1.0;
if (typeof volume === "string") {
const parsedVolume = parseFloat(volume);
if (!isNaN(parsedVolume) && isFinite(parsedVolume)) {
volumeValue = Math.min(Math.max(parsedVolume, 0), 1.0);
}
} else if (typeof volume === "number" && isFinite(volume)) {
volumeValue = Math.min(Math.max(volume, 0), 1.0);
}


try {
newAudio.volume = volumeValue;
} catch (err) {
console.error("Error setting volume:", err);
newAudio.volume = 1.0;
}


let pitchValue = 1.0;
if (typeof pitch === "string") {
const parsedPitch = parseFloat(pitch);
if (!isNaN(parsedPitch) && isFinite(parsedPitch)) {
pitchValue = Math.min(Math.max(parsedPitch, 0.5), 2.0);
}
} else if (typeof pitch === "number" && isFinite(pitch)) {
pitchValue = Math.min(Math.max(pitch, 0.5), 2.0);
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Replace global isFinite with Number.isFinite.

Using the global version can cause unexpected type coercion.

     let volumeValue = 1.0;
     if (typeof volume === "string") {
       const parsedVolume = parseFloat(volume);
-      if (!isNaN(parsedVolume) && isFinite(parsedVolume)) {
+      if (!isNaN(parsedVolume) && Number.isFinite(parsedVolume)) {
         volumeValue = Math.min(Math.max(parsedVolume, 0), 1.0);
       }
-    } else if (typeof volume === "number" && isFinite(volume)) {
+    } else if (typeof volume === "number" && Number.isFinite(volume)) {
       volumeValue = Math.min(Math.max(volume, 0), 1.0);
     }
     
     // ...
     
     let pitchValue = 1.0; 
     if (typeof pitch === "string") {
       const parsedPitch = parseFloat(pitch);
-      if (!isNaN(parsedPitch) && isFinite(parsedPitch)) {
+      if (!isNaN(parsedPitch) && Number.isFinite(parsedPitch)) {
         pitchValue = Math.min(Math.max(parsedPitch, 0.5), 2.0);
       }
-    } else if (typeof pitch === "number" && isFinite(pitch)) {
+    } else if (typeof pitch === "number" && Number.isFinite(pitch)) {
       pitchValue = Math.min(Math.max(pitch, 0.5), 2.0);
     }
📝 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.

Suggested change
let volumeValue = 1.0;
if (typeof volume === "string") {
const parsedVolume = parseFloat(volume);
if (!isNaN(parsedVolume) && isFinite(parsedVolume)) {
volumeValue = Math.min(Math.max(parsedVolume, 0), 1.0);
}
} else if (typeof volume === "number" && isFinite(volume)) {
volumeValue = Math.min(Math.max(volume, 0), 1.0);
}
try {
newAudio.volume = volumeValue;
} catch (err) {
console.error("Error setting volume:", err);
newAudio.volume = 1.0;
}
let pitchValue = 1.0;
if (typeof pitch === "string") {
const parsedPitch = parseFloat(pitch);
if (!isNaN(parsedPitch) && isFinite(parsedPitch)) {
pitchValue = Math.min(Math.max(parsedPitch, 0.5), 2.0);
}
} else if (typeof pitch === "number" && isFinite(pitch)) {
pitchValue = Math.min(Math.max(pitch, 0.5), 2.0);
}
let volumeValue = 1.0;
if (typeof volume === "string") {
const parsedVolume = parseFloat(volume);
if (!isNaN(parsedVolume) && Number.isFinite(parsedVolume)) {
volumeValue = Math.min(Math.max(parsedVolume, 0), 1.0);
}
} else if (typeof volume === "number" && Number.isFinite(volume)) {
volumeValue = Math.min(Math.max(volume, 0), 1.0);
}
try {
newAudio.volume = volumeValue;
} catch (err) {
console.error("Error setting volume:", err);
newAudio.volume = 1.0;
}
let pitchValue = 1.0;
if (typeof pitch === "string") {
const parsedPitch = parseFloat(pitch);
if (!isNaN(parsedPitch) && Number.isFinite(parsedPitch)) {
pitchValue = Math.min(Math.max(parsedPitch, 0.5), 2.0);
}
} else if (typeof pitch === "number" && Number.isFinite(pitch)) {
pitchValue = Math.min(Math.max(pitch, 0.5), 2.0);
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 172-172: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 175-175: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 191-191: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 194-194: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)

🤖 Prompt for AI Agents
In components/notification-generator/form/SoundDropdown.tsx between lines 169
and 197, replace all uses of the global isFinite function with Number.isFinite
to avoid unexpected type coercion. This means updating the checks that currently
use isFinite(volume) and isFinite(pitch) to use Number.isFinite(volume) and
Number.isFinite(pitch) respectively, ensuring more reliable type checking.

…erated yaml.

Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (5)
package.json (3)

33-34: Major React 19 upgrade requires compatibility verification

The React 19 upgrade includes significant breaking changes that need to be addressed throughout the codebase.


59-59: Next.js 15 upgrade requires breaking changes review

The Next.js 15 upgrade includes several breaking changes including async request APIs and caching behavior changes.


40-40: Remove unused rehype-prism-plus dependency

This dependency is not being used in the codebase and should be removed.

components/notification-generator/form/SoundDropdown.tsx (1)

181-184: Replace global isFinite with Number.isFinite

The global isFinite function can cause unexpected type coercion and should be replaced with Number.isFinite.

Also applies to: 200-203

🧰 Tools
🪛 Biome (1.9.4)

[error] 181-181: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 184-184: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)

components/notification-generator/minecraftTextParser.tsx (1)

88-94: ⚠️ Potential issue

Fix obfuscated text handling issue.

The obfuscated text handling still has the same issue flagged in previous reviews - it consumes the entire remaining string and prevents further parsing.

This prevents proper parsing of mixed formatting codes after obfuscated text. Consider applying the obfuscated style only to the appropriate text segment without early return.

🧹 Nitpick comments (5)
components/docs/AnimatedLayout.tsx (1)

10-10: Remove unnecessary forwardRef

The component uses forwardRef but doesn't actually forward any ref. Since no ref is being used, you can simplify this to a regular function component.

-const AnimatedLayout: React.FC<AnimatedLayoutProps> = ({ children }) => {
+const AnimatedLayout = ({ children }: AnimatedLayoutProps) => {

And remove the forwardRef wrapper entirely.

components/notification-generator/form/SoundDropdown.tsx (1)

21-22: Consider making external URLs configurable

Hard-coding external URLs makes the component less flexible and harder to test. Consider making these configurable through props or environment variables.

+interface SoundDropdownProps {
+  value: string;
+  onChange: (value: string) => void;
+  volume?: number | string;
+  pitch?: number | string;
+  soundsJsonUrl?: string;
+  soundBaseUrl?: string;
+}

-const SOUNDS_JSON_URL = "https://raw.githubusercontent.com/InventivetalentDev/minecraft-assets/1.21.5/assets/minecraft/sounds.json";
-const SOUND_BASE_URL = "https://raw.githubusercontent.com/InventivetalentDev/minecraft-assets/1.21.5/assets/minecraft/sounds/";
components/docs/DocCopyEnhancer.tsx (2)

67-181: Consider a more consistent React approach

The component mixes React patterns (CopyButton component) with direct DOM manipulation. While functional, this creates inconsistency and makes the code harder to maintain.

Consider using React portals consistently or moving entirely to DOM manipulation. The current CopyButton component suggests you want a React approach, but it's not being used in the actual implementation.


105-108: Extract SVG constants to reduce duplication

The SVG code is repeated and hard-coded. Consider extracting these to constants for better maintainability.

+const COPY_SVG = '<svg class="w-4 h-4" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M16 8v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8m4-4h6a2 2 0 0 1 2 2v2H4V6a2 2 0 0 1 2-2z"/></svg>';
+const CHECK_SVG = '<svg class="w-4 h-4" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"/></svg>';

-        const icon = isCopied
-          ? '<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"/></svg>'
-          : '<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M16 8v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8m4-4h6a2 2 0 0 1 2 2v2H4V6a2 2 0 0 1 2-2z"/></svg>';
+        const icon = isCopied ? CHECK_SVG : COPY_SVG;
app/notification-generator/page.tsx (1)

26-28: Consider renaming the preview key for clarity.

The previewKey variable name could be more descriptive to indicate its purpose as a re-render trigger.

-  const [previewKey, setPreviewKey] = useState(0); // Used to force re-render of preview
+  const [previewRefreshKey, setPreviewRefreshKey] = useState(0); // Used to force re-render of preview
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8b9151a and 43dc926.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (24)
  • app/docs/layout.tsx (1 hunks)
  • app/minimessage-demo/page.tsx (1 hunks)
  • app/notification-generator/layout.tsx (1 hunks)
  • app/notification-generator/page.tsx (1 hunks)
  • components/docs/AnimatedHeading.tsx (1 hunks)
  • components/docs/AnimatedLayout.tsx (1 hunks)
  • components/docs/CodeTabs.tsx (1 hunks)
  • components/docs/DocCopyEnhancer.tsx (1 hunks)
  • components/docs/DocHeader.tsx (1 hunks)
  • components/docs/DocSearch.tsx (1 hunks)
  • components/docs/DocSidebar.tsx (1 hunks)
  • components/notification-generator/ActionBar.tsx (1 hunks)
  • components/notification-generator/ChatMessage.module.css (1 hunks)
  • components/notification-generator/ChatMessage.tsx (1 hunks)
  • components/notification-generator/MinecraftPreview.tsx (1 hunks)
  • components/notification-generator/NotificationCode.tsx (1 hunks)
  • components/notification-generator/NotificationForm.tsx (1 hunks)
  • components/notification-generator/Title.tsx (1 hunks)
  • components/notification-generator/form/SoundDropdown.tsx (1 hunks)
  • components/notification-generator/form/Tab.tsx (1 hunks)
  • components/notification-generator/hooks.ts (1 hunks)
  • components/notification-generator/minecraft-font.css (1 hunks)
  • components/notification-generator/minecraftTextParser.tsx (1 hunks)
  • package.json (1 hunks)
✅ Files skipped from review due to trivial changes (4)
  • app/minimessage-demo/page.tsx
  • components/notification-generator/ChatMessage.module.css
  • app/notification-generator/layout.tsx
  • components/docs/DocHeader.tsx
🚧 Files skipped from review as they are similar to previous changes (13)
  • components/notification-generator/ChatMessage.tsx
  • components/notification-generator/minecraft-font.css
  • components/notification-generator/NotificationCode.tsx
  • components/notification-generator/Title.tsx
  • app/docs/layout.tsx
  • components/notification-generator/NotificationForm.tsx
  • components/notification-generator/MinecraftPreview.tsx
  • components/docs/AnimatedHeading.tsx
  • components/notification-generator/form/Tab.tsx
  • components/notification-generator/ActionBar.tsx
  • components/docs/CodeTabs.tsx
  • components/notification-generator/hooks.ts
  • components/docs/DocSearch.tsx
🧰 Additional context used
🧬 Code Graph Analysis (3)
components/docs/DocCopyEnhancer.tsx (1)
lib/utils.ts (1)
  • cn (9-11)
app/notification-generator/page.tsx (4)
components/notification-generator/types.ts (1)
  • NotificationConfig (1-14)
components/notification-generator/NotificationForm.tsx (1)
  • NotificationForm (19-152)
components/notification-generator/NotificationCode.tsx (1)
  • NotificationCode (10-95)
components/notification-generator/MinecraftPreview.tsx (1)
  • MinecraftPreview (13-90)
components/docs/DocSidebar.tsx (2)
components/docs/sidebar-structure.ts (2)
  • DocItem (1-5)
  • docsStructure (7-56)
lib/utils.ts (1)
  • cn (9-11)
🪛 Biome (1.9.4)
components/notification-generator/form/SoundDropdown.tsx

[error] 181-181: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 184-184: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 200-200: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 203-203: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)

components/notification-generator/minecraftTextParser.tsx

[error] 33-33: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)


[error] 33-33: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)


[error] 24-24: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (3)
components/docs/DocSidebar.tsx (1)

1-190: Excellent implementation of the documentation sidebar!

The component demonstrates solid React best practices with proper memoization, accessibility features, and smooth animations. The hierarchical navigation structure works well with the documentation system.

app/notification-generator/page.tsx (2)

30-85: YAML generation logic looks solid.

The generateYaml function handles all notification types properly, including multiline chat messages and optional parameters with sensible defaults.


91-93: Simple and effective preview refresh mechanism.

Using a key increment to force re-render is a clean approach for triggering preview animations.

Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (3)
components/animations/AnimatedElement.tsx (2)

72-114: Consider refactoring the large switch statement.

The switch statement works but creates a lot of repetitive code. Consider using a dynamic approach to reduce duplication.

-  switch (as) {
-    case "div":
-      return <motion.div {...commonProps}>{children}</motion.div>;
-    case "section":
-      return <motion.section {...commonProps}>{children}</motion.section>;
-    // ... many more cases
-    default:
-      return <motion.div {...commonProps}>{children}</motion.div>;
-  }
+  const MotionComponent = motion[as as keyof typeof motion] || motion.div;
+  return <MotionComponent {...commonProps}>{children}</MotionComponent>;

This approach is cleaner and automatically supports all motion elements without manual case handling.


63-64: Animation logic could be clearer.

The conditional logic for interactive vs non-interactive animations is complex and hard to follow.

Consider simplifying with helper functions:

-  initial: interactive ? "initial" : "hidden",
-  animate: inView ? (interactive ? "initial" : "visible") : (interactive ? "initial" : "hidden"),
+  initial: interactive ? "initial" : "hidden",
+  animate: interactive ? "initial" : (inView ? "visible" : "hidden"),

Or extract to helper functions for better readability.

components/ui/button.tsx (1)

116-174: Simplify the verbose prop spreading.

The manual prop spreading is very long. Consider using destructuring and spread operator instead.

-      const motionProps = {
-        ref,
-        className: buttonClasses,
-        whileHover: finalAnimationProps.hover,
-        whileTap: finalAnimationProps.tap,
-        transition: finalAnimationProps.transition,
-        disabled: isLoading || props.disabled,
-        type: props.type,
-        name: props.name,
-        value: props.value,
-        // ... many more lines
-      } as HTMLMotionProps<"button">;
+      return (
+        <motion.button
+          ref={ref}
+          className={buttonClasses}
+          whileHover={finalAnimationProps.hover}
+          whileTap={finalAnimationProps.tap}
+          transition={finalAnimationProps.transition}
+          disabled={isLoading || props.disabled}
+          {...props}
+        >
+          {buttonContent}
+        </motion.button>
+      );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 43dc926 and 14b5ada.

📒 Files selected for processing (24)
  • app/docs/layout.tsx (1 hunks)
  • app/page.tsx (1 hunks)
  • components/AnimatedHome.tsx (1 hunks)
  • components/about/About.tsx (1 hunks)
  • components/animations/AnimatedContainer.tsx (1 hunks)
  • components/animations/AnimatedElement.tsx (1 hunks)
  • components/animations/AnimatedSection.tsx (1 hunks)
  • components/animations/AnimationUtils.tsx (1 hunks)
  • components/animations/index.ts (1 hunks)
  • components/docs/AnimatedHeading.tsx (1 hunks)
  • components/docs/DocHeader.tsx (1 hunks)
  • components/docs/DocSidebar.tsx (1 hunks)
  • components/faq/Faq.tsx (2 hunks)
  • components/features/Features.tsx (1 hunks)
  • components/header/ThemeSwitchButton.tsx (1 hunks)
  • components/header/hero/Hero.tsx (1 hunks)
  • components/header/hero/button/BackgroundHeroButton.tsx (1 hunks)
  • components/header/hero/button/TransparentHeroButton.tsx (1 hunks)
  • components/notification-generator/NotificationForm.tsx (1 hunks)
  • components/projects/ProjectButton.tsx (1 hunks)
  • components/team/Team.tsx (3 hunks)
  • components/ui/button.tsx (1 hunks)
  • components/ui/tab.tsx (1 hunks)
  • components/ui/tabs.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • components/animations/index.ts
  • components/animations/AnimationUtils.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
  • components/docs/AnimatedHeading.tsx
  • components/header/ThemeSwitchButton.tsx
  • app/docs/layout.tsx
  • components/notification-generator/NotificationForm.tsx
  • components/docs/DocHeader.tsx
  • components/faq/Faq.tsx
  • components/header/hero/Hero.tsx
🧰 Additional context used
🧬 Code Graph Analysis (10)
components/about/About.tsx (1)
components/icons/terminal-fill.tsx (1)
  • TerminalIcon (3-18)
components/projects/ProjectButton.tsx (1)
components/icons/github.tsx (1)
  • GitHubIcon (3-18)
components/header/hero/button/BackgroundHeroButton.tsx (1)
components/icons/people-group.tsx (1)
  • PeopleGroupIcon (3-18)
components/ui/tab.tsx (2)
lib/utils.ts (1)
  • cn (9-11)
components/ui/button.tsx (1)
  • Button (192-192)
components/animations/AnimatedSection.tsx (1)
components/animations/AnimationUtils.tsx (5)
  • fadeInUp (26-33)
  • fadeInDown (36-43)
  • fadeInLeft (46-53)
  • fadeInRight (56-63)
  • fadeIn (14-23)
components/animations/AnimatedElement.tsx (1)
components/animations/AnimationUtils.tsx (6)
  • fadeInUp (26-33)
  • fadeInDown (36-43)
  • fadeInLeft (46-53)
  • fadeInRight (56-63)
  • scaleAnimation (85-95)
  • fadeIn (14-23)
components/ui/button.tsx (1)
lib/utils.ts (1)
  • cn (9-11)
components/ui/tabs.tsx (2)
lib/utils.ts (1)
  • cn (9-11)
components/ui/tab.tsx (1)
  • Tab (98-98)
components/docs/DocSidebar.tsx (2)
components/docs/sidebar-structure.ts (2)
  • DocItem (1-5)
  • docsStructure (7-56)
lib/utils.ts (1)
  • cn (9-11)
components/features/Features.tsx (4)
components/icons/java.tsx (1)
  • JavaIcon (3-34)
components/icons/linux.tsx (1)
  • LinuxIcon (3-48)
components/icons/tab-new.tsx (1)
  • TabNew (3-18)
components/SectionTitle.tsx (1)
  • SectionTitle (9-34)
🔇 Additional comments (16)
components/AnimatedHome.tsx (1)

1-25: Nice clean animation wrapper!

The component structure looks great. Good use of accessibility attributes and the animation setup follows best practices.

components/projects/ProjectButton.tsx (1)

3-13: Good refactor to the Button component!

The switch from motion.button to the custom Button component makes the code more consistent. The leftIcon prop and accessibility are properly maintained.

app/page.tsx (2)

8-19: Great metadata setup!

The metadata export looks comprehensive with title, description, canonical URL, and Open Graph image. Nice use of the generateOgImageMetadata utility.


21-22: Clean component simplification!

Moving the complexity to AnimatedHome keeps this page component nice and simple.

components/about/About.tsx (4)

6-6: Good move to animation components!

Using the centralized animation components makes the code cleaner and more consistent across the app.


14-19: Nice accessibility improvement!

Adding aria-labelledby="about-heading" makes the section more accessible for screen readers.


30-35: Better image setup!

The shadow styling and improved alt text "Software development team collaborating" makes this more descriptive and visually appealing.


39-76: Well-structured animation timing!

The staggered delays (0.2s for container, 0.1s stagger) create a nice cascading effect for the text elements.

components/team/Team.tsx (2)

9-183: Nice animation refactor!

Great job switching to the new animation wrapper components. The code is much cleaner and easier to maintain now.


96-96: Clean headers syntax

components/animations/AnimatedSection.tsx (1)

1-76: Well-structured animation component!

This component follows good practices with proper prop filtering and accessibility support. The intersection observer integration is clean.

components/ui/tabs.tsx (2)

23-108: Excellent accessibility and animation implementation!

The component properly handles ARIA roles, keyboard navigation, and smooth animations. The state management and callback patterns are well-implemented.


110-112: Simple and effective memoization.

The TabItem wrapper correctly uses React.memo for performance optimization while keeping the implementation clean.

components/docs/DocSidebar.tsx (1)

68-156: Great component structure!

The memoized component with proper accessibility attributes and animation variants is well implemented. The hover effects and layout animations add nice polish.

components/features/Features.tsx (1)

7-86: Excellent refactor to animation components!

This clean refactor replaces manual framer-motion logic with reusable animation components. The centralized feature data and alternating animation directions work well together.

components/ui/button.tsx (1)

26-95: Well-designed button component!

Great use of variants, proper accessibility support, and clean loading state handling. The animation logic is solid too.

Comment on lines 52 to 313
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.h3>
);
} else if (as === "h4") {
return (
<motion.h4
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.h4>
);
} else if (as === "h5") {
return (
<motion.h5
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.h5>
);
} else if (as === "h6") {
return (
<motion.h6
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.h6>
);
} else if (as === "ul") {
return (
<motion.ul
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.ul>
);
} else if (as === "ol") {
return (
<motion.ol
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.ol>
);
} else if (as === "li") {
return (
<motion.li
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.li>
);
} else {
// Default to div if the element type is not supported
return (
<motion.div
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.div>
);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Major refactor needed to reduce code repetition.

This approach creates 200+ lines of nearly identical code. Consider using dynamic element creation instead.

-  // Use a type-safe approach with conditional rendering
-  if (as === "div") {
-    return (
-      <motion.div
-        ref={ref}
-        className={className}
-        variants={containerVariants}
-        initial="hidden"
-        animate={inView ? "visible" : "hidden"}
-        {...props}
-      >
-        {children}
-      </motion.div>
-    );
-  } else if (as === "section") {
-    // ... many more similar blocks
+  const MotionComponent = motion[as] as any;
+  
+  return (
+    <MotionComponent
+      ref={ref}
+      className={className}
+      variants={containerVariants}
+      initial="hidden"
+      animate={inView ? "visible" : "hidden"}
+      {...props}
+    >
+      {children}
+    </MotionComponent>
+  );
📝 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.

Suggested change
if (as === "div") {
return (
<motion.div
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.div>
);
} else if (as === "section") {
return (
<motion.section
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.section>
);
} else if (as === "article") {
return (
<motion.article
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.article>
);
} else if (as === "main") {
return (
<motion.main
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.main>
);
} else if (as === "header") {
return (
<motion.header
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.header>
);
} else if (as === "footer") {
return (
<motion.footer
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.footer>
);
} else if (as === "nav") {
return (
<motion.nav
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.nav>
);
} else if (as === "aside") {
return (
<motion.aside
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.aside>
);
} else if (as === "span") {
return (
<motion.span
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.span>
);
} else if (as === "p") {
return (
<motion.p
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.p>
);
} else if (as === "h1") {
return (
<motion.h1
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.h1>
);
} else if (as === "h2") {
return (
<motion.h2
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.h2>
);
} else if (as === "h3") {
return (
<motion.h3
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.h3>
);
} else if (as === "h4") {
return (
<motion.h4
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.h4>
);
} else if (as === "h5") {
return (
<motion.h5
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.h5>
);
} else if (as === "h6") {
return (
<motion.h6
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.h6>
);
} else if (as === "ul") {
return (
<motion.ul
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.ul>
);
} else if (as === "ol") {
return (
<motion.ol
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.ol>
);
} else if (as === "li") {
return (
<motion.li
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.li>
);
} else {
// Default to div if the element type is not supported
return (
<motion.div
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</motion.div>
);
}
const MotionComponent = motion[as] as any;
return (
<MotionComponent
ref={ref}
className={className}
variants={containerVariants}
initial="hidden"
animate={inView ? "visible" : "hidden"}
{...props}
>
{children}
</MotionComponent>
);
🤖 Prompt for AI Agents
In components/animations/AnimatedContainer.tsx around lines 52 to 313, the code
has excessive repetition with multiple if-else blocks rendering similar motion
elements for different tags. Refactor by dynamically creating the motion element
based on the "as" prop using a variable or a mapping, then render a single
motion component with the common props and children. This will drastically
reduce code duplication and improve maintainability.

Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

♻️ Duplicate comments (3)
components/notification-generator/form/FormField.tsx (1)

115-243: The accessibility issues from the previous review are still present.

The form fields still lack proper label association and ARIA attributes for screen readers.

package.json (1)

42-42: Remove unused rehype-prism-plus dependency

As noted in previous reviews, this package isn't used in your MDX config.

components/notification-generator/form/SoundDropdown.tsx (1)

179-179: Use Number.isFinite instead of global isFinite

The global isFinite can cause unexpected type coercion. Replace with Number.isFinite for safer type checking.

Also applies to: 182-182, 196-196, 199-199

🧰 Tools
🪛 Biome (1.9.4)

[error] 179-179: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)

🧹 Nitpick comments (13)
components/animations/AnimatedSection.tsx (1)

38-38: Consider clarifying the triggerOnce logic.

The condition preserveAnimation ? true : triggerOnce works correctly but could be clearer about the intended behavior.

-    triggerOnce: preserveAnimation ? true : triggerOnce,
+    triggerOnce: preserveAnimation || triggerOnce,
components/notification-generator/form/FormField.tsx (2)

84-96: Optimize state updates in color management.

Multiple state updates can cause unnecessary re-renders. Consider batching them.

 const addColor = () => {
-  setColors([...colors, "#000000"]);
-  setActiveColorIndex(colors.length);
+  setColors(prev => {
+    const newColors = [...prev, "#000000"];
+    setActiveColorIndex(newColors.length - 1);
+    return newColors;
+  });
 };

127-206: Improve color picker positioning and cleanup.

The color picker popup may overflow screen boundaries and needs better positioning logic.

Consider using a portal or proper dropdown positioning library to handle edge cases where the picker extends beyond the viewport.

app/api/docs/search-index/route.ts (4)

6-7: Use English for comments

The comment is in Polish - consider using English for better team collaboration.

-// Funkcja do rekurencyjnego wyszukiwania plików markdown w katalogu
+// Function to recursively find markdown files in directory

23-24: Use English for comments

The comment should be in English for international teams.

-// Funkcja do generowania indeksu wyszukiwania
+// Function to generate search index

35-39: Improve text cleaning for excerpts

The current text cleaning is basic. Consider a more robust approach for better search results.

-    const excerpt = markdownContent
-      .replace(/[#*`_~]/g, '')
-      .replace(/\n/g, ' ')
-      .trim()
-      .substring(0, 150);
+    const excerpt = markdownContent
+      .replace(/[#*`_~\[\]]/g, '') // Remove more markdown syntax
+      .replace(/!\[.*?\]\(.*?\)/g, '') // Remove images
+      .replace(/\[.*?\]\(.*?\)/g, '') // Remove links
+      .replace(/\s+/g, ' ') // Normalize whitespace
+      .trim()
+      .substring(0, 150);

25-26: Consider adding performance optimizations

For large documentation sets, this could be slow. Consider adding caching or incremental updates.

components/ui/tooltip.tsx (2)

20-22: Consider making delay configurable

The 500ms delay is hardcoded but might not suit all use cases.

interface TooltipProps {
  children: React.ReactNode;
  content: string;
+  delay?: number;
}

export const Tooltip = ({
  children,
  content,
+  delay = 500,
}: TooltipProps) => {
  // ...
  const handleMouseEnter = () => {
    timeoutRef.current = setTimeout(() => {
      setIsVisible(true);
-    }, 500);
+    }, delay);
  };

59-59: Complete or remove commented arrow code

The commented tooltip arrow suggests incomplete implementation.

-            {/* <div className="tooltip-arrow" data-popper-arrow></div> */}
components/docs/DocSearch.tsx (2)

89-89: Improve type safety for Orama database

Using any type reduces type safety. Consider creating a proper type for the Orama database.

-const [oramaDb, setOramaDb] = useState<any>(null);
+const [oramaDb, setOramaDb] = useState<Awaited<ReturnType<typeof create>> | null>(null);

171-171: Remove unnecessary dependency from useEffect

The query dependency causes extra effect runs since debouncedQuery already handles the query changes.

-}, [debouncedQuery, oramaDb, minQueryLength, query]);
+}, [debouncedQuery, oramaDb, minQueryLength]);
components/header/Navbar.tsx (2)

63-72: Consider potential scroll lock conflicts

Body scroll locking could conflict if multiple components try to control it simultaneously.

Consider using a shared scroll lock hook or library that handles multiple consumers:

+import { useScrollLock } from '@/hooks/useScrollLock';
+
-useEffect(() => {
-  if (isMenuOpen) {
-    document.body.style.overflow = "hidden";
-  } else {
-    document.body.style.overflow = "unset";
-  }
-  return () => {
-    document.body.style.overflow = "unset";
-  };
-}, [isMenuOpen]);
+useScrollLock(isMenuOpen);

98-102: Extract banner content for configurability

The hardcoded banner text should be configurable or moved to a separate component for easier management.

+const BANNER_CONFIG = {
+  show: true,
+  text: "We launched the new Notification generator, fully interactive and customizable!",
+  link: "/notification-generator",
+  linkText: "Check it out →"
+};
+
-<span className="font-semibold">We launched the new Notification generator, fully interactive and customizable!</span>
+<span className="font-semibold">{BANNER_CONFIG.text}</span>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7fb03df and f965ab6.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • app/api/docs/search-index/route.ts (1 hunks)
  • app/docs/layout.tsx (1 hunks)
  • app/notification-generator/layout.tsx (1 hunks)
  • app/notification-generator/page.tsx (1 hunks)
  • components/animations/AnimatedSection.tsx (1 hunks)
  • components/docs/DocHeader.tsx (1 hunks)
  • components/docs/DocSearch.tsx (1 hunks)
  • components/docs/DocSidebar.tsx (1 hunks)
  • components/docs/ReadingTime.tsx (1 hunks)
  • components/header/Navbar.tsx (2 hunks)
  • components/icons/arrow-back.tsx (1 hunks)
  • components/icons/arrow-forward.tsx (1 hunks)
  • components/icons/close.tsx (1 hunks)
  • components/notification-generator/form/FormField.tsx (1 hunks)
  • components/notification-generator/form/SoundDropdown.tsx (1 hunks)
  • components/notification-generator/form/SoundTable.tsx (1 hunks)
  • components/notification-generator/form/TitleTab.tsx (1 hunks)
  • components/ui/tooltip.tsx (1 hunks)
  • package.json (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • components/icons/close.tsx
🚧 Files skipped from review as they are similar to previous changes (8)
  • app/notification-generator/layout.tsx
  • components/docs/ReadingTime.tsx
  • app/docs/layout.tsx
  • components/notification-generator/form/TitleTab.tsx
  • components/docs/DocHeader.tsx
  • app/notification-generator/page.tsx
  • components/docs/DocSidebar.tsx
  • components/icons/arrow-forward.tsx
🧰 Additional context used
🧬 Code Graph Analysis (5)
components/ui/tooltip.tsx (1)
lib/utils.ts (1)
  • cn (9-11)
components/animations/AnimatedSection.tsx (2)
components/docs/DocHeader.tsx (1)
  • fadeInUp (12-24)
components/animations/AnimationUtils.tsx (5)
  • fadeInUp (26-33)
  • fadeInDown (36-43)
  • fadeInLeft (46-53)
  • fadeInRight (56-63)
  • fadeIn (14-23)
components/notification-generator/form/SoundTable.tsx (5)
components/notification-generator/form/SoundDropdown.tsx (1)
  • Sound (15-20)
components/ui/button.tsx (1)
  • Button (192-192)
components/icons/close.tsx (1)
  • CloseIcon (3-18)
components/icons/arrow-back.tsx (1)
  • ArrowBack (3-18)
components/icons/arrow-forward.tsx (1)
  • ArrowForward (3-18)
components/header/Navbar.tsx (4)
components/icons/arrow-down.tsx (1)
  • ArrowDown (5-24)
components/icons/hamburger.tsx (1)
  • Hamburger (5-24)
components/icons/new-window.tsx (1)
  • NewWindow (3-20)
components/header/ToolsDropdown.tsx (1)
  • ToolsDropdown (8-101)
components/docs/DocSearch.tsx (3)
hooks/useDebounce.ts (1)
  • useDebounce (3-17)
hooks/useClickOutside.ts (1)
  • useClickOutside (3-23)
lib/utils.ts (1)
  • cn (9-11)
🪛 Biome (1.9.4)
components/notification-generator/form/SoundDropdown.tsx

[error] 179-179: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 182-182: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 196-196: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 199-199: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)

🔇 Additional comments (14)
components/animations/AnimatedSection.tsx (6)

1-8: Imports look good and well-organized.

The component properly imports all necessary dependencies. Good use of the "use client" directive for Next.js.


9-21: Interface is comprehensive and well-typed.

The props interface covers all necessary configuration options with good TypeScript typing. Nice inclusion of accessibility props.


43-56: Animation variant selection is clean and straightforward.

The switch statement provides clear mapping between animation types and variants.


61-61: Good practice filtering out non-DOM props.

Properly prevents the animationType prop from reaching the DOM element.


63-65: Memoization logic is well-implemented.

The dependency array correctly handles the preserveAnimation behavior by re-memoizing only when pathname changes if preserveAnimation is enabled.


67-81: Component rendering is well-structured.

Good use of motion.section with proper prop spreading and conditional children rendering.

components/notification-generator/form/FormField.tsx (1)

23-34: Well-structured component with good prop design.

The component interface is clean and the default values are sensible.

components/icons/arrow-back.tsx (1)

1-18: Clean icon implementation!

The component follows good practices with proper TypeScript types, currentColor for theme support, and flexible prop spreading.

package.json (1)

32-32: Unusual to include npm as a dependency

Adding npm as a runtime dependency is uncommon. Verify this is intentional and not meant for devDependencies.

components/docs/DocSearch.tsx (1)

252-266: Great search result rendering logic

The conditional rendering handles all states properly - loading, results, and no results. The accessibility roles and animations enhance the user experience.

components/header/Navbar.tsx (3)

14-38: Excellent navigation link structure

The NavLink interface and centralized NAV_LINKS array provide good type safety and maintainability. The external link handling is properly implemented.


50-60: Good keyboard accessibility implementation

The Escape key handler with focus return follows accessibility best practices for modal-like interactions.


149-211: Excellent mobile menu implementation

The animated mobile menu with proper ARIA attributes and focus management creates a great user experience. The integration of ToolsDropdown is seamless.

components/notification-generator/form/SoundTable.tsx (1)

173-330: Nice table implementation!

The component handles all the essentials well - search, sort, pagination, and visual feedback for selected items. Good UX touches like auto-focus and debounced search.

@EternalCodeTeam EternalCodeTeam deleted a comment from coderabbitai bot Jun 8, 2025
Signed-off-by: Martin Sulikowski <vLuckyyy.biznes@gmail.com>
Copy link

coderabbitai bot commented Jun 8, 2025

Walkthrough

This update introduces a wide range of new features and improvements. It adds a dynamic documentation system with search, animated navigation, and enhanced code highlighting. There’s a new notification generator tool styled after Minecraft, complete with a live preview and YAML code output. The site’s layout, metadata, and accessibility are improved, including cookie consent management and SEO enhancements. Animations are now handled through reusable components for smoother transitions. The documentation and team sections are more interactive, with better navigation and search. Several new icons, UI components, and markdown guides are included, making the site more user-friendly and visually appealing.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

app/api/docs/search-index/route.ts

Oops! Something went wrong! :(

ESLint: 9.28.0

ESLint couldn't find an eslint.config.(js|mjs|cjs) file.

From ESLint v9.0.0, the default configuration file is now eslint.config.js.
If you are using a .eslintrc.* file, please follow the migration guide
to update your configuration file to the new format:

https://eslint.org/docs/latest/use/configure/migration-guide

If you still have problems after following the migration guide, please stop by
https://eslint.org/chat/help to chat with the team.

app/api/og/route.tsx

Oops! Something went wrong! :(

ESLint: 9.28.0

ESLint couldn't find an eslint.config.(js|mjs|cjs) file.

From ESLint v9.0.0, the default configuration file is now eslint.config.js.
If you are using a .eslintrc.* file, please follow the migration guide
to update your configuration file to the new format:

https://eslint.org/docs/latest/use/configure/migration-guide

If you still have problems after following the migration guide, please stop by
https://eslint.org/chat/help to chat with the team.

app/api/team/route.ts

Oops! Something went wrong! :(

ESLint: 9.28.0

ESLint couldn't find an eslint.config.(js|mjs|cjs) file.

From ESLint v9.0.0, the default configuration file is now eslint.config.js.
If you are using a .eslintrc.* file, please follow the migration guide
to update your configuration file to the new format:

https://eslint.org/docs/latest/use/configure/migration-guide

If you still have problems after following the migration guide, please stop by
https://eslint.org/chat/help to chat with the team.

  • 97 others
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 18

♻️ Duplicate comments (19)
components/ui/tooltip.tsx (1)

18-18: Previous ID conflict issue resolved!

The use of useId() properly addresses the hardcoded tooltip ID concern from earlier reviews.

components/docs/DynamicFeaturesTable.tsx (3)

16-27: Add error handling and caching for the fetch request.

The current fetch implementation could be improved with better error handling and caching.


44-54: Don't use array indices as React keys.

Using array indices as keys can cause issues when the array changes. Use unique identifiers instead.


33-57: Add accessibility attributes to the table.

The table should include proper ARIA roles and attributes for better accessibility.

app/globals.css (3)

173-176: Table header colors need better contrast.

You set a very light background (#f8fafc) with white text—this will be hard to read. Please choose a darker header background or a darker text color.


193-195: Zebra striping has no effect.

You set the same background for all rows and even rows. Please adjust odd/even colors so the stripes actually show.


206-208: Dark mode striping is also no-op.

Same background for every row means no stripe. Please pick two shades for dark mode as well.

components/header/hero/button/BackgroundHeroButton.tsx (1)

30-37: ⚠️ Potential issue

Animation controls still not connected to Button

The animation setup looks good, but the Button component still isn't receiving the animation controls. You need to pass the animate={controls} and initial={{ opacity: 0, y: 20 }} props to make the animations work.

<Button
  ref={ref}
  variant="primary"
+ animate={controls}
+ initial={{ opacity: 0, y: 20 }}
  leftIcon={<PeopleGroupIcon className="mb-[0.5px]" aria-hidden="true" />}
  aria-label="View our team"
>
content/docs/documentation-editors/markdown-guide.md (1)

222-230: Fix the code block example

The nested code fences need fixing to show the correct example.

-````markdown
-```javascript
+```javascript
 function greet(name) {
   return `Hello, ${name}!`;
 }
-```
-````
-
-````
+```
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

230-230: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

components/docs/DocCopyEnhancer.tsx (2)

19-65: React component looks good but isn't being used

The CopyButton React component is well-implemented with proper accessibility attributes and animations, but it's not actually used anywhere in the component. The DOM manipulation approach below doesn't include these accessibility improvements.


103-109: Missing accessibility attributes in DOM manipulation

The DOM-created buttons lack the accessibility improvements that exist in the unused React component above. The SVG icons don't have aria-hidden="true" and the button lacks aria-label.

const updateButtonState = (isCopied: boolean) => {
  copyStatesRef.current.set(preEl, isCopied);
  const icon = isCopied
-   ? '<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"/></svg>'
-   : '<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M16 8v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8m4-4h6a2 2 0 0 1 2 2v2H4V6a2 2 0 0 1 2-2z"/></svg>';
+   ? '<svg class="w-4 h-4" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"/></svg>'
+   : '<svg class="w-4 h-4" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M16 8v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8m4-4h6a2 2 0 0 1 2 2v2H4V6a2 2 0 0 1 2-2z"/></svg>';
  button.innerHTML = `${icon}${isCopied ? "Copied!" : "Copy"}`;
+ button.setAttribute("aria-label", isCopied ? "Copied to clipboard" : "Copy code to clipboard");
};
components/docs/CodeTabs.tsx (1)

79-84: Add validation for missing label props.

The component assumes all children have label props but doesn't validate this assumption.

Consider adding validation:

  {React.Children.map(children, (child, idx) => {
    if (!React.isValidElement<CodeTabProps>(child)) return null;

+   if (!child.props.label) {
+     console.warn('CodeTab component missing required "label" prop');
+     return null;
+   }

    const { label, disabled } = child.props;
components/notification-generator/minecraftTextParser.tsx (3)

24-24: Security risk with dangerouslySetInnerHTML.

Using dangerouslySetInnerHTML with external content could allow XSS attacks if MiniMessage doesn't properly sanitize output.

Consider validating or sanitizing the HTML output before rendering, or use a safer approach that doesn't rely on dangerouslySetInnerHTML.

🧰 Tools
🪛 Biome (1.9.4)

[error] 24-24: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)


33-33: Fix regex control character warnings.

Static analysis flags the control characters in the regex as problematic.

Escape the control characters properly:

- return input.replace(/\x00|\u0000|[\r\n\v\u2028\u2029]/g, '');
+ return input.replace(/[\x00\u0000\r\n\v\u2028\u2029]/g, '');
🧰 Tools
🪛 Biome (1.9.4)

[error] 33-33: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)


[error] 33-33: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)


88-94: Obfuscated text handling needs fixing.

The obfuscated text logic consumes the entire remaining string and returns early, preventing proper parsing of mixed formatting codes.

The current approach stops parsing when it hits obfuscated text, which breaks mixed formatting. Consider applying obfuscated styling without early return.

components/notification-generator/form/SoundTable.tsx (1)

58-58: ⚠️ Potential issue

Add proper typing for oramaDb

Using any skips TypeScript's safety checks. Import and use the proper Orama database type.

-  const [oramaDb, setOramaDb] = useState<any>(null);
+  const [oramaDb, setOramaDb] = useState<ReturnType<typeof create> | null>(null);
app/docs/[...slug]/page.tsx (2)

65-85: ⚠️ Potential issue

Add path security validation

The slug parameter comes from user input and could contain path traversal attempts like ../. Validate the slug before using it in file paths.

 const getDocBySlug = cache(async (slug: string[]): Promise<Doc | null> => {
+  // Validate slug to prevent path traversal
+  if (slug.some(segment => segment.includes('..') || segment.includes('/'))) {
+    console.error(`Invalid slug: ${slug.join('/')}`);
+    return null;
+  }
   const docsDirectory = path.join(process.cwd(), "content/docs");
   const fullPath = path.join(docsDirectory, slug.join("/") + ".md");

52-58: 🛠️ Refactor suggestion

Fix performance issue with spread in reducer

Using spread operators in reducers creates O(n²) complexity. Use push instead for better performance.

-    return structure.reduce<{ title: string; path: string }[]>((acc, item) => {
-      if (item.children?.length) {
-        acc.push(...item.children);
-      } else {
-        acc.push({ title: item.title, path: item.path });
-      }
-      return acc;
-    }, []);
+    const result: { title: string; path: string }[] = [];
+    structure.forEach((item) => {
+      if (item.children?.length) {
+        result.push(...item.children);
+      } else {
+        result.push({ title: item.title, path: item.path });
+      }
+    });
+    return result;
components/docs/DocSearch.tsx (1)

234-316: Missing keyboard navigation for search results.

Users should be able to navigate results with arrow keys for better accessibility.

🧹 Nitpick comments (40)
components/notification-generator/BackgroundImage.tsx (1)

7-9: Make background image decorative. Replace alt text with alt="" and add aria-hidden="true" so assistive tech skips it.

components/icons/stop.tsx (1)

3-3: Consider using named export for consistency.

Other icon components in the project use named exports. Consider changing to export function Stop for consistency.

components/icons/arrow-forward-hero.tsx (1)

5-11: Add accessibility attributes to SVG icon.

This SVG is decorative, so add aria-hidden="true" and focusable="false" to hide it from assistive tech.

components/AnimatedHome.tsx (1)

11-18: Use semantic main element for accessibility.

Consider replacing <motion.div> with <motion.main> to provide a proper page landmark.

components/notification-generator/MiniMessageInfoBox.tsx (2)

1-1: Use absolute import for AlertBox.

To match other components, import from @/components/ui/AlertBox.


6-6: Use <strong> instead of <b> for semantics.

Replace <b> with <strong> around "MiniMessage" for better accessibility.

components/notification-generator/SoundIndicator.tsx (1)

15-26: Icon choice seems backwards for the use case.

The SVG shows a muted speaker (with X) but this component displays when sound IS playing. Consider using a regular speaker icon instead.

         <path
           fillRule="evenodd"
-          d="M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.707.707L4.586 13H2a1 1 0 01-1-1V8a1 1 0 011-1h2.586l3.707-3.707a1 1 0 011.09-.217zM12.293 7.293a1 1 0 011.414 0L15 8.586l1.293-1.293a1 1 0 111.414 1.414L16.414 10l1.293 1.293a1 1 0 01-1.414 1.414L15 11.414l-1.293 1.293a1 1 0 01-1.414-1.414L13.586 10l-1.293-1.293a1 1 0 010-1.414z"
+          d="M10 3.5a1.5 1.5 0 00-1.5 1.5v10a1.5 1.5 0 003 0V5a1.5 1.5 0 00-1.5-1.5zM3.5 6A1.5 1.5 0 002 7.5v5A1.5 1.5 0 003.5 14h2.793l2.853 2.854A1 1 0 0011 16V4a1 1 0 00-1.854-.854L6.293 6H3.5z"
           clipRule="evenodd"
         />
content/docs/contribute/guide.md (1)

67-67: Consider standard punctuation.

The ":>" emoticon might confuse readers. Consider using a standard emoji or exclamation mark instead.

-You have successfully made a contribution to this project. :>
+You have successfully made a contribution to this project! 🎉
🧰 Tools
🪛 LanguageTool

[uncategorized] ~67-~67: Loose punctuation mark.
Context: ...ly made a contribution to this project. :>

(UNLIKELY_OPENING_PUNCTUATION)

app/api/docs/search-index/route.ts (1)

23-49: Verify the content directory path and improve excerpt cleaning.

The search index generation has a few areas for improvement:

  1. The hardcoded content/docs path might not exist in all environments
  2. The excerpt cleaning is basic and could miss markdown formatting

Consider this improvement for more robust excerpt cleaning:

-    const excerpt = markdownContent
-      .replace(/[#*`_~]/g, '')
-      .replace(/\n/g, ' ')
-      .trim()
-      .substring(0, 150);
+    const excerpt = markdownContent
+      .replace(/```[\s\S]*?```/g, '') // Remove code blocks
+      .replace(/`[^`]+`/g, '') // Remove inline code
+      .replace(/[#*_~\[\]]/g, '') // Remove markdown symbols
+      .replace(/\s+/g, ' ') // Normalize whitespace
+      .trim()
+      .substring(0, 150);
app/providers.tsx (1)

11-19: Simplify the mount effect implementation.

The mounting pattern correctly prevents hydration issues, but the useCallback wrapper for handleMount is unnecessary since it has no dependencies and only runs once.

- const handleMount = useCallback(() => {
-   setMounted(true);
- }, []);
- 
- useEffect(() => {
-   handleMount();
- }, [handleMount]);
+ useEffect(() => {
+   setMounted(true);
+ }, []);
components/OgImage.tsx (1)

10-37: Consider improving the alt text for better accessibility.

The metadata generation is well-structured, but the alt text could be more descriptive than just the title to better serve screen reader users.

-          alt: title,
+          alt: subtitle ? `${title}: ${subtitle}` : `Open Graph image for ${title}`,
app/prism-tomorrow.css (1)

5-6: Consider using CSS custom properties for theme colors.

The repeated background color #181c23 could be defined as a CSS custom property to improve maintainability and theme consistency.

+:root {
+  --prism-bg: #181c23;
+  --prism-bg-alt: #23272e;
+}
+
 code[class*="language-"],
 pre[class*="language-"] {
   color: #ccc;
-  background: #181c23 !important;
+  background: var(--prism-bg) !important;

Also applies to: 30-30, 35-35, 42-42

components/SpeedInsights.tsx (1)

8-8: Consider hydration safety for initial state.

The initial state uses canLoadAnalytics() which might differ between server and client, potentially causing hydration mismatches.

Consider initializing with false and updating in useEffect:

-const [shouldLoad, setShouldLoad] = useState(canLoadAnalytics());
+const [shouldLoad, setShouldLoad] = useState(false);
+
+useEffect(() => {
+  setShouldLoad(canLoadAnalytics());
+}, []);
components/notification-generator/NotificationCode.tsx (1)

12-41: Consider simplifying animation complexity.

The component has many nested motion elements with individual timing controls. This might impact performance and could feel overwhelming to users.

Consider grouping animations or using fewer motion wrappers:

-<motion.pre 
-  className="overflow-x-auto rounded-md bg-gray-100 p-4 font-mono text-sm dark:bg-gray-900"
-  initial={{ opacity: 0 }}
-  animate={{ opacity: 1 }}
-  transition={{ duration: 0.3, delay: 0.1 }}
->
-  <motion.code 
-    className="text-gray-800 dark:text-gray-200"
-    initial={{ opacity: 0 }}
-    animate={{ opacity: 1 }}
-    transition={{ duration: 0.3, delay: 0.2 }}
-  >
-    {yamlCode}
-  </motion.code>
-</motion.pre>
+<pre className="overflow-x-auto rounded-md bg-gray-100 p-4 font-mono text-sm dark:bg-gray-900">
+  <code className="text-gray-800 dark:text-gray-200">
+    {yamlCode}
+  </code>
+</pre>
components/header/hero/button/TransparentHeroButton.tsx (1)

8-11: Consider using triggerOnce: true for better UX.

The animation will retrigger every time the element enters/exits the viewport, which might be distracting for users scrolling back and forth.

const { ref, inView } = useInView({
-  triggerOnce: false,
+  triggerOnce: true,
  threshold: 0.1,
});
components/notification-generator/ActionBar.tsx (1)

12-43: Consider moving inline styles to CSS classes.

The extensive inline styling works but could be cleaner as CSS classes or styled components for better maintainability.

+const actionBarStyles = {
+  container: "absolute left-1/2 pointer-events-none z-10",
+  text: "font-minecraft text-white text-2xl"
+};

<div
-  className="absolute left-1/2"
-  style={{
-    bottom: "12%",
-    transform: "translateX(-50%)",
-    // ... other styles
-  }}
+  className={actionBarStyles.container}
+  style={{ bottom: "12%", transform: "translateX(-50%)" }}
>
components/docs/DynamicCommandsTable.tsx (1)

18-20: Consider making the API URL configurable.

The hardcoded GitHub URL works but could be moved to an environment variable or config for easier maintenance.

components/header/ToolsDropdown.tsx (1)

55-60: Focus management could be more robust.

The setTimeout approach works but isn't ideal for focus management.

- setTimeout(() => dropdownRef.current?.querySelector("a")?.focus(), 0);
+ requestAnimationFrame(() => dropdownRef.current?.querySelector("a")?.focus());
components/notification-generator/ChatMessage.tsx (1)

34-66: Simplify the conditional rendering logic.

The code duplicates styling between multiline and single line cases. Consider extracting the common styling.

+ const messageStyle = {
+   position: 'relative' as const,
+   zIndex: 1,
+   minHeight: 32,
+   lineHeight: '32px',
+   whiteSpace: 'pre-line' as const,
+   wordBreak: 'break-word' as const,
+ };

+ const MessageDiv = ({ children, style = {} }: { children: React.ReactNode, style?: React.CSSProperties }) => (
+   <div
+     className="font-minecraft px-4 text-white drop-shadow-[2px_2px_0px_rgba(0,0,0,0.5)]"
+     style={{ ...messageStyle, ...style }}
+   >
+     {children}
+   </div>
+ );

  {message.includes("\n") ? (
-   <div style={{ position: 'relative', zIndex: 1, width: '100%' }}>
+   <div style={{ position: 'relative', zIndex: 1, width: '100%' }}>
      {message.split("\n").map((line, index) => (
-       <div
-         key={index}
-         className="font-minecraft px-4 text-white drop-shadow-[2px_2px_0px_rgba(0,0,0,0.5)]"
-         style={{
-           display: 'block',
-           minHeight: 32,
-           lineHeight: '32px',
-           whiteSpace: 'pre-line',
-           wordBreak: 'break-word',
-         }}
-       >
+       <MessageDiv key={index} style={{ display: 'block' }}>
          <MinecraftText text={line} />
-       </div>
+       </MessageDiv>
      ))}
    </div>
  ) : (
-   <div
-     className="font-minecraft px-4 text-white drop-shadow-[2px_2px_0px_rgba(0,0,0,0.5)]"
-     style={{
-       position: 'relative',
-       zIndex: 1,
-       minHeight: 32,
-       lineHeight: '32px',
-       whiteSpace: 'pre-line',
-       wordBreak: 'break-word',
-     }}
-   >
+   <MessageDiv>
      <MinecraftText text={message} />
-   </div>
+   </MessageDiv>
  )}
components/docs/ReadingTime.tsx (1)

15-18: Add input validation for edge cases.

The calculation works well but could handle empty content more gracefully.

 const calculateReadingTime = (text: string, wordsPerMinute: number): number => {
+  if (!text || text.trim().length === 0) return 1;
   const words = text.trim().split(/\s+/).length;
   return Math.ceil(words / wordsPerMinute);
 };
components/docs/DocHeader.tsx (1)

12-50: Consider reusing existing animation variants.

The animation variants are well-crafted but duplicate similar ones in AnimationUtils.tsx. Consider importing from the centralized animation utilities to maintain consistency.

-export const fadeInUp = {
-  hidden: { opacity: 0, y: 20 },
-  visible: { 
-    opacity: 1, 
-    y: 0,
-    transition: { 
-      type: "spring", 
-      stiffness: 100, 
-      damping: 15,
-      mass: 0.8
-    }
-  }
-};
+import { fadeInUp, staggerContainer } from "@/components/animations/AnimationUtils";
content/docs/eternalcombat/installation.md (1)

40-40: Fix grammar in heading.

Change "Backup" to "Back up" as this is the verb form.

-1. **Backup Your Configuration**
+1. **Back up Your Configuration**
🧰 Tools
🪛 LanguageTool

[grammar] ~40-~40: The word ‘Backup’ is a noun. Do you mean the verb “Back up”?
Context: ...🔄 Upgrading ### Upgrade Process 1. Backup Your Configuration ```bash cp ...

(SENT_START_BACKUP)

components/ui/AlertBox.tsx (1)

41-114: Consider refactoring the repetitive style patterns.

The alertStyles object has a lot of repeated patterns. You could create a helper function to generate styles for each type, reducing code duplication.

+const createAlertStyle = (color: string, role: string) => ({
+  container: `bg-${color}-500/10 border border-${color}-500/20 dark:bg-${color}-500/10 dark:border-${color}-500/20`,
+  icon: `text-${color}-500 dark:text-${color}-400`,
+  text: `text-${color}-800 dark:text-${color}-200`,
+  title: `text-${color}-900 dark:text-${color}-100`,
+  role,
+});
app/notification-generator/page.tsx (2)

30-85: Consider breaking down the YAML generation logic.

The generateYaml function handles many different cases and could be split into smaller, focused functions for better maintainability.

+const formatChatSection = (chat: string) => {
+  if (!chat) return [];
+  if (chat.includes("\n")) {
+    const lines = chat.split("\n");
+    return ["chat:", ...lines.map(line => `  - "${line}"`)];
+  }
+  return [`chat: "${chat}"`];
+};

+const formatTimesSection = (fadeIn: string, stay: string, fadeOut: string) => {
+  if (!fadeIn && !stay && !fadeOut) return [];
+  const times = `${fadeIn || "0s"} ${stay || "0s"} ${fadeOut || "0s"}`;
+  return [`times: "${times}"`];
+};

108-209: Consider creating reusable animation components.

There are many similar motion.div components with repeated animation configurations. You could create reusable animated wrapper components.

+const AnimatedCard = ({ children, delay = 0, direction = "up", ...props }) => (
+  <motion.div
+    initial={{ opacity: 0, y: direction === "up" ? 20 : -20 }}
+    animate={{ opacity: 1, y: 0 }}
+    transition={{ duration: 0.4, delay }}
+    {...props}
+  >
+    {children}
+  </motion.div>
+);
components/notification-generator/form/validation.ts (1)

15-18: Consider making sound validation more flexible.

The regex ^[A-Z_]+(\s+[A-Z_]+)?$ might be too restrictive. Minecraft sounds can have different formats and namespaces.

-      if (value && !/^[A-Z_]+(\s+[A-Z_]+)?$/.test(value)) {
+      if (value && !/^[a-zA-Z0-9_:]+(\s+[a-zA-Z0-9_:]+)*$/.test(value)) {
         return "Invalid sound format";
       }
components/team/Team.tsx (1)

190-194: Clean up unused motion properties

The motion.div has some unnecessary style properties that aren't needed with the new animation approach.

<motion.div
  className="text-center text-gray-500 dark:text-gray-400"
  variants={cardVariants}
  initial="hidden"
  animate="visible"
- style={{ background: "transparent", boxShadow: "none", border: "none", padding: 0, cursor: "pointer" }}
+ style={{ cursor: "pointer" }}
>
components/CookiePreferencesMenu.tsx (1)

127-143: Consider user feedback for the Save button

The Save button closes the modal but doesn't provide feedback about what was saved. Users might be confused about whether their preferences were actually saved.

<button
  onClick={() => setIsOpen(false)}
  className="inline-flex flex-1 items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
>
- Save
+ Save Preferences
</button>

Consider adding a brief "Settings saved!" toast message for better user feedback.

app/docs/layout.tsx (2)

74-74: Replace Polish comment with English.

The comment should be in English to maintain code consistency and readability for all team members.

-              {/* Przyciski Next/Previous będą renderowane w page.tsx */}
+              {/* Next/Previous buttons will be rendered in page.tsx */}

66-66: Move inline style to CSS class.

The inline minHeight style should be moved to Tailwind classes for better maintainability.

-            <AnimatedSection animationType="fadeUp" className="w-full" style={{ minHeight: '60vh' }}>
+            <AnimatedSection animationType="fadeUp" className="w-full min-h-[60vh]">
components/notification-generator/hooks.ts (1)

40-42: Consider smoother animation steps.

The fixed 0.1 opacity increment might cause jerky animations for short fade durations. Consider using dynamic steps based on duration.

-          return prev + 0.1;
+          return Math.min(prev + (1 / (fadeIn * 10)), 1);
components/CookieConsentModal.tsx (1)

43-48: Add aria-label for better accessibility.

The close button should have an accessible label for screen readers.

            <button
              onClick={() => setIsOpen(false)}
              className="ml-4 text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+             aria-label="Close cookie consent modal"
            >
components/ui/tabs.tsx (2)

63-63: Make the key more unique

Using ${label}-${idx} could cause React key warnings if you have duplicate labels. Consider using a more unique approach.

-              key={`${label}-${idx}`}
+              key={`tab-${idx}`}

110-114: Remove unnecessary memoization

The TabItem component just returns its children without any processing. The memoization adds overhead without benefit.

-export const TabItem = React.memo(function TabItem({ children }: TabItemProps) {
-  return <>{children}</>;
-});
-
-TabItem.displayName = "TabItem";
+export const TabItem: React.FC<TabItemProps> = ({ children }) => {
+  return <>{children}</>;
+};
components/notification-generator/form/SoundTable.tsx (1)

41-386: Consider splitting this large component

This component handles search, sorting, pagination, and playback all in one place. Breaking it into smaller components would make it easier to maintain.

Consider extracting:

  • SearchBar component (lines 257-278)
  • SoundTableHeader component (lines 282-298)
  • PaginationControls component (lines 356-383)
components/animations/AnimationUtils.tsx (1)

66-76: Optimize stagger timing

The stagger delay of 0.15s might feel slow for user interaction. Consider reducing it to 0.1s for snappier animations.

export const staggerContainer: Variants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
-     staggerChildren: 0.15,
+     staggerChildren: 0.1,
      ease: "easeInOut",
      duration: 0.5
    }
  }
};
components/animations/AnimatedElement.tsx (1)

72-114: Consider dynamic tag rendering

The large switch statement could be simplified using dynamic rendering.

-switch (as) {
-  case "div":
-    return <motion.div {...commonProps}>{children}</motion.div>;
-  case "section":
-    return <motion.section {...commonProps}>{children}</motion.section>;
-  // ... all other cases
-  default:
-    return <motion.div {...commonProps}>{children}</motion.div>;
-}
+const MotionComponent = motion[as] || motion.div;
+return <MotionComponent {...commonProps}>{children}</MotionComponent>;
components/notification-generator/form/SliderField.tsx (1)

71-72: Consider making gradient colors customizable

The gradient colors are hardcoded. You could accept them as optional props for more flexibility.

 interface SliderFieldProps {
   label: string;
   name: string;
   value: string;
   onChange: (name: string, value: string) => void;
   min: number;
   max: number;
   step: number;
   error?: string;
+  activeColor?: string;
+  inactiveColor?: string;
 }
components/ui/Dropdown.tsx (1)

61-61: Remove inline styles

The inline styles for outline and boxShadow could be handled with Tailwind classes for consistency.

-style={{ outline: "none", boxShadow: "none" }}
+className="... focus:outline-none focus:ring-0"

Also applies to: 103-103

components/docs/DocSearch.tsx (1)

127-127: Replace any with proper type for better type safety.

Using any reduces type safety benefits. Consider using the proper Orama type.

-  const [oramaDb, setOramaDb] = useState<any>(null);
+  const [oramaDb, setOramaDb] = useState<Awaited<ReturnType<typeof create>> | null>(null);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a502807 and f33bec7.

⛔ Files ignored due to path filters (4)
  • bun.lock is excluded by !**/*.lock
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • public/fonts/Minecraftia-Regular.ttf is excluded by !**/*.ttf
  • public/mc-bg.png is excluded by !**/*.png
📒 Files selected for processing (107)
  • .eslintrc.json (1 hunks)
  • app/api/docs/search-index/route.ts (1 hunks)
  • app/api/og/route.tsx (1 hunks)
  • app/api/team/route.ts (1 hunks)
  • app/docs/[...slug]/page.tsx (1 hunks)
  • app/docs/layout.tsx (1 hunks)
  • app/docs/page.tsx (1 hunks)
  • app/globals.css (2 hunks)
  • app/layout.tsx (2 hunks)
  • app/not-found.tsx (1 hunks)
  • app/notification-generator/layout.tsx (1 hunks)
  • app/notification-generator/page.tsx (1 hunks)
  • app/page.tsx (1 hunks)
  • app/prism-languages.ts (1 hunks)
  • app/prism-tomorrow.css (1 hunks)
  • app/privacy-policy/page.tsx (1 hunks)
  • app/projects/page.tsx (1 hunks)
  • app/providers.tsx (1 hunks)
  • app/team/page.tsx (1 hunks)
  • components/Analytics.tsx (1 hunks)
  • components/AnimatedHome.tsx (1 hunks)
  • components/CookieConsentModal.tsx (1 hunks)
  • components/CookiePreferencesMenu.tsx (1 hunks)
  • components/OgImage.tsx (1 hunks)
  • components/SectionTitle.tsx (1 hunks)
  • components/SpeedInsights.tsx (1 hunks)
  • components/about/About.tsx (1 hunks)
  • components/animations/AnimatedContainer.tsx (1 hunks)
  • components/animations/AnimatedElement.tsx (1 hunks)
  • components/animations/AnimatedSection.tsx (1 hunks)
  • components/animations/AnimationUtils.tsx (1 hunks)
  • components/animations/index.ts (1 hunks)
  • components/docs/AnimatedHeading.tsx (1 hunks)
  • components/docs/AnimatedLayout.tsx (1 hunks)
  • components/docs/CodeBlock.tsx (1 hunks)
  • components/docs/CodeTabs.tsx (1 hunks)
  • components/docs/DocCopyEnhancer.tsx (1 hunks)
  • components/docs/DocHeader.tsx (1 hunks)
  • components/docs/DocSearch.tsx (1 hunks)
  • components/docs/DocSidebar.tsx (1 hunks)
  • components/docs/DynamicCommandsTable.tsx (1 hunks)
  • components/docs/DynamicFeaturesTable.tsx (1 hunks)
  • components/docs/EditOnGitHub.tsx (1 hunks)
  • components/docs/ErrorBoundary.tsx (1 hunks)
  • components/docs/Inline.tsx (1 hunks)
  • components/docs/ReadingTime.tsx (1 hunks)
  • components/docs/ShortLink.tsx (1 hunks)
  • components/docs/sidebar-structure.ts (1 hunks)
  • components/faq/Faq.tsx (2 hunks)
  • components/features/Features.tsx (1 hunks)
  • components/footer/Footer.tsx (1 hunks)
  • components/header/Navbar.tsx (2 hunks)
  • components/header/ThemeSwitchButton.tsx (1 hunks)
  • components/header/ToolsDropdown.tsx (1 hunks)
  • components/header/hero/Hero.tsx (1 hunks)
  • components/header/hero/button/BackgroundHeroButton.tsx (1 hunks)
  • components/header/hero/button/TransparentHeroButton.tsx (1 hunks)
  • components/header/hero/terminal/TerminalTab.tsx (1 hunks)
  • components/header/polygon/PolygonLeft.tsx (0 hunks)
  • components/header/polygon/PolygonRight.tsx (0 hunks)
  • components/icons/arrow-back.tsx (1 hunks)
  • components/icons/arrow-down.tsx (1 hunks)
  • components/icons/arrow-forward-hero.tsx (1 hunks)
  • components/icons/arrow-forward.tsx (1 hunks)
  • components/icons/close.tsx (1 hunks)
  • components/icons/hamburger.tsx (1 hunks)
  • components/icons/play.tsx (1 hunks)
  • components/icons/stop.tsx (1 hunks)
  • components/notification-generator/ActionBar.tsx (1 hunks)
  • components/notification-generator/BackgroundImage.tsx (1 hunks)
  • components/notification-generator/ChatMessage.module.css (1 hunks)
  • components/notification-generator/ChatMessage.tsx (1 hunks)
  • components/notification-generator/MinecraftPreview.tsx (1 hunks)
  • components/notification-generator/MiniMessageInfoBox.tsx (1 hunks)
  • components/notification-generator/NotificationCode.tsx (1 hunks)
  • components/notification-generator/NotificationForm.tsx (1 hunks)
  • components/notification-generator/SoundIndicator.tsx (1 hunks)
  • components/notification-generator/SoundInfoBox.tsx (1 hunks)
  • components/notification-generator/Title.tsx (1 hunks)
  • components/notification-generator/form/ActionBarTab.tsx (1 hunks)
  • components/notification-generator/form/AdvancedTab.tsx (1 hunks)
  • components/notification-generator/form/ChatTab.tsx (1 hunks)
  • components/notification-generator/form/FormField.tsx (1 hunks)
  • components/notification-generator/form/SliderField.tsx (1 hunks)
  • components/notification-generator/form/SoundTab.tsx (1 hunks)
  • components/notification-generator/form/SoundTable.tsx (1 hunks)
  • components/notification-generator/form/Tab.tsx (1 hunks)
  • components/notification-generator/form/TitleTab.tsx (1 hunks)
  • components/notification-generator/form/constants.ts (1 hunks)
  • components/notification-generator/form/validation.ts (1 hunks)
  • components/notification-generator/hooks.ts (1 hunks)
  • components/notification-generator/minecraft-font.css (1 hunks)
  • components/notification-generator/minecraftTextParser.tsx (1 hunks)
  • components/notification-generator/types.ts (1 hunks)
  • components/projects/ProjectButton.tsx (1 hunks)
  • components/projects/ProjectItem.tsx (1 hunks)
  • components/team/Team.tsx (3 hunks)
  • components/ui/AlertBox.tsx (1 hunks)
  • components/ui/Dropdown.tsx (1 hunks)
  • components/ui/button.tsx (1 hunks)
  • components/ui/tab.tsx (1 hunks)
  • components/ui/tabs.tsx (1 hunks)
  • components/ui/tooltip.tsx (1 hunks)
  • content/docs/contribute/guide.md (1 hunks)
  • content/docs/documentation-editors/markdown-guide.md (1 hunks)
  • content/docs/eternalcombat/features.md (1 hunks)
  • content/docs/eternalcombat/installation.md (1 hunks)
⛔ Files not processed due to max files limit (23)
  • content/docs/eternalcombat/introduction.md
  • content/docs/eternalcombat/using-api.md
  • content/docs/eternalcore/faq.md
  • content/docs/eternalcore/features.md
  • content/docs/eternalcore/homes.md
  • content/docs/eternalcore/installation.md
  • content/docs/eternalcore/introduction.md
  • content/docs/eternalcore/notifications.md
  • content/docs/eternalcore/placeholders.md
  • content/docs/eternalcore/using-api.md
  • hooks/useClickOutside.ts
  • hooks/useCookieConsent.ts
  • hooks/useDebounce.ts
  • lib/cookie-utils.ts
  • lib/mdx-config.mjs
  • lib/mdx.tsx
  • lib/og-utils.ts
  • lib/utils.ts
  • next-sitemap.config.js
  • next.config.mjs
  • package.json
  • reset.d.ts
  • tailwind.config.ts
💤 Files with no reviewable changes (2)
  • components/header/polygon/PolygonRight.tsx
  • components/header/polygon/PolygonLeft.tsx
🧰 Additional context used
🧬 Code Graph Analysis (42)
components/notification-generator/SoundInfoBox.tsx (1)
components/ui/AlertBox.tsx (1)
  • AlertBox (140-187)
app/docs/page.tsx (4)
app/layout.tsx (2)
  • dynamic (18-18)
  • revalidate (19-19)
app/docs/[...slug]/page.tsx (2)
  • dynamic (22-22)
  • revalidate (23-23)
app/page.tsx (1)
  • dynamic (5-5)
app/projects/page.tsx (1)
  • dynamic (6-6)
components/ui/tooltip.tsx (1)
lib/utils.ts (1)
  • cn (9-11)
components/OgImage.tsx (1)
lib/og-utils.ts (1)
  • generateOgImageUrl (2-28)
components/notification-generator/ChatMessage.tsx (1)
components/notification-generator/minecraftTextParser.tsx (1)
  • MinecraftText (8-29)
components/notification-generator/form/AdvancedTab.tsx (1)
components/notification-generator/types.ts (2)
  • NotificationConfig (1-14)
  • FieldType (21-21)
components/notification-generator/MinecraftPreview.tsx (2)
components/notification-generator/types.ts (1)
  • MinecraftPreviewProps (16-18)
components/notification-generator/hooks.ts (2)
  • useTitleAnimation (4-72)
  • useSoundEffect (74-93)
components/docs/Inline.tsx (1)
lib/utils.ts (1)
  • cn (9-11)
components/Analytics.tsx (1)
lib/cookie-utils.ts (1)
  • canLoadAnalytics (44-47)
components/docs/EditOnGitHub.tsx (2)
lib/utils.ts (1)
  • cn (9-11)
components/icons/github.tsx (1)
  • GitHubIcon (3-18)
components/notification-generator/form/TitleTab.tsx (3)
components/notification-generator/types.ts (2)
  • NotificationConfig (1-14)
  • FieldType (21-21)
components/notification-generator/form/FormField.tsx (1)
  • FormField (23-311)
components/notification-generator/MiniMessageInfoBox.tsx (1)
  • MiniMessageInfoBox (3-18)
components/notification-generator/MiniMessageInfoBox.tsx (1)
components/ui/AlertBox.tsx (1)
  • AlertBox (140-187)
components/docs/ShortLink.tsx (1)
lib/utils.ts (1)
  • cn (9-11)
components/header/ToolsDropdown.tsx (1)
components/icons/arrow-down.tsx (1)
  • ArrowDown (5-24)
components/notification-generator/form/ChatTab.tsx (3)
components/notification-generator/types.ts (2)
  • NotificationConfig (1-14)
  • FieldType (21-21)
components/notification-generator/form/FormField.tsx (1)
  • FormField (23-311)
components/notification-generator/MiniMessageInfoBox.tsx (1)
  • MiniMessageInfoBox (3-18)
components/notification-generator/ActionBar.tsx (1)
components/notification-generator/minecraftTextParser.tsx (1)
  • MinecraftText (8-29)
app/notification-generator/layout.tsx (3)
app/layout.tsx (1)
  • metadata (47-108)
app/docs/layout.tsx (1)
  • metadata (19-41)
app/page.tsx (1)
  • metadata (8-19)
components/notification-generator/Title.tsx (1)
components/notification-generator/minecraftTextParser.tsx (1)
  • MinecraftText (8-29)
components/notification-generator/form/ActionBarTab.tsx (3)
components/notification-generator/types.ts (2)
  • NotificationConfig (1-14)
  • FieldType (21-21)
components/notification-generator/form/FormField.tsx (1)
  • FormField (23-311)
components/notification-generator/MiniMessageInfoBox.tsx (1)
  • MiniMessageInfoBox (3-18)
components/header/hero/button/TransparentHeroButton.tsx (1)
components/icons/arrow-forward-hero.tsx (1)
  • ArrowForwardHeroIcon (3-18)
components/notification-generator/form/Tab.tsx (1)
components/notification-generator/types.ts (1)
  • TabType (20-20)
components/notification-generator/hooks.ts (1)
components/notification-generator/types.ts (1)
  • NotificationConfig (1-14)
components/ui/AlertBox.tsx (1)
lib/utils.ts (1)
  • cn (9-11)
components/docs/DocCopyEnhancer.tsx (1)
lib/utils.ts (1)
  • cn (9-11)
components/ui/tabs.tsx (2)
lib/utils.ts (1)
  • cn (9-11)
components/ui/tab.tsx (1)
  • Tab (74-74)
components/docs/ReadingTime.tsx (1)
lib/utils.ts (1)
  • cn (9-11)
components/docs/DocSidebar.tsx (2)
components/docs/sidebar-structure.ts (2)
  • DocItem (1-5)
  • docsStructure (7-56)
lib/utils.ts (1)
  • cn (9-11)
components/SpeedInsights.tsx (1)
lib/cookie-utils.ts (1)
  • canLoadAnalytics (44-47)
components/ui/tab.tsx (2)
lib/utils.ts (1)
  • cn (9-11)
components/ui/button.tsx (1)
  • Button (192-192)
components/docs/DocHeader.tsx (1)
components/animations/AnimationUtils.tsx (2)
  • fadeInUp (26-33)
  • staggerContainer (66-76)
app/docs/[...slug]/page.tsx (9)
app/layout.tsx (2)
  • dynamic (18-18)
  • revalidate (19-19)
app/docs/page.tsx (2)
  • dynamic (4-4)
  • revalidate (5-5)
components/docs/sidebar-structure.ts (1)
  • docsStructure (7-56)
components/docs/DocHeader.tsx (1)
  • DocHeader (52-101)
components/docs/ReadingTime.tsx (1)
  • ReadingTime (20-42)
components/docs/ShortLink.tsx (1)
  • ShortLink (13-83)
components/docs/EditOnGitHub.tsx (1)
  • EditOnGitHub (11-32)
components/docs/ErrorBoundary.tsx (1)
  • ErrorBoundary (14-54)
lib/mdx.tsx (1)
  • components (11-34)
components/notification-generator/form/validation.ts (1)
components/notification-generator/types.ts (1)
  • FieldType (21-21)
components/docs/AnimatedHeading.tsx (1)
components/docs/DocHeader.tsx (1)
  • fadeDownScale (26-39)
components/ui/button.tsx (1)
lib/utils.ts (1)
  • cn (9-11)
components/notification-generator/form/FormField.tsx (2)
components/notification-generator/types.ts (1)
  • FieldType (21-21)
components/ui/button.tsx (1)
  • Button (192-192)
components/docs/CodeTabs.tsx (2)
lib/utils.ts (1)
  • cn (9-11)
components/notification-generator/form/Tab.tsx (1)
  • Tab (13-45)
components/animations/AnimatedElement.tsx (1)
components/animations/AnimationUtils.tsx (6)
  • fadeInUp (26-33)
  • fadeInDown (36-43)
  • fadeInLeft (46-53)
  • fadeInRight (56-63)
  • scaleAnimation (85-95)
  • fadeIn (14-23)
components/ui/Dropdown.tsx (1)
components/icons/arrow-down.tsx (1)
  • ArrowDown (5-24)
components/footer/Footer.tsx (4)
components/icons/round-tiktok.tsx (1)
  • TikTokIcon (3-18)
components/icons/youtube.tsx (1)
  • YouTubeIcon (3-18)
components/icons/github.tsx (1)
  • GitHubIcon (3-18)
components/icons/discord.tsx (1)
  • DiscordIcon (3-18)
components/animations/AnimationUtils.tsx (1)
components/docs/DocHeader.tsx (2)
  • fadeInUp (12-24)
  • staggerContainer (41-50)
components/animations/AnimatedSection.tsx (2)
components/animations/AnimationUtils.tsx (5)
  • fadeInUp (26-33)
  • fadeInDown (36-43)
  • fadeInLeft (46-53)
  • fadeInRight (56-63)
  • fadeIn (14-23)
components/docs/DocHeader.tsx (1)
  • fadeInUp (12-24)
components/header/Navbar.tsx (4)
components/icons/arrow-down.tsx (1)
  • ArrowDown (5-24)
components/icons/hamburger.tsx (1)
  • Hamburger (5-24)
components/icons/new-window.tsx (1)
  • NewWindow (3-20)
components/header/ToolsDropdown.tsx (1)
  • ToolsDropdown (8-101)
🪛 LanguageTool
content/docs/contribute/guide.md

[uncategorized] ~67-~67: Loose punctuation mark.
Context: ...ly made a contribution to this project. :>

(UNLIKELY_OPENING_PUNCTUATION)

content/docs/eternalcombat/installation.md

[grammar] ~40-~40: The word ‘Backup’ is a noun. Do you mean the verb “Back up”?
Context: ...🔄 Upgrading ### Upgrade Process 1. Backup Your Configuration ```bash cp ...

(SENT_START_BACKUP)

content/docs/documentation-editors/markdown-guide.md

[uncategorized] ~19-~19: Loose punctuation mark.
Context: ...Available frontmatter fields: - title: The page title (required) - `descriptio...

(UNLIKELY_OPENING_PUNCTUATION)

🪛 markdownlint-cli2 (0.17.2)
content/docs/documentation-editors/markdown-guide.md

230-230: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

🪛 Biome (1.9.4)
components/notification-generator/form/SoundTab.tsx

[error] 177-177: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 180-180: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 195-195: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)


[error] 198-198: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)

components/notification-generator/minecraftTextParser.tsx

[error] 33-33: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)


[error] 33-33: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)


[error] 24-24: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (159)
components/SectionTitle.tsx (3)

3-7: Good interface structure!

The SectionTitleProps interface is well-defined with clear types and the optional id property adds flexibility for navigation purposes.


15-18: Clean conditional id implementation.

The conditional id attribute works correctly - React will omit the attribute when id is undefined, keeping the DOM clean.


25-28: Nice accessibility improvement!

The aria-label provides helpful context for screen readers by connecting the description to its title. This follows good accessibility practices.

.eslintrc.json (1)

2-2: Use of core web vitals preset looks good. Good to see we’re using the focused Next.js rules.

components/icons/arrow-back.tsx (1)

1-19: Nice icon component. Clean implementation with props spread.

components/icons/arrow-down.tsx (1)

1-24: ArrowDown icon looks good. Straightforward SVG component.

components/notification-generator/BackgroundImage.tsx (1)

4-14: Good memoized background component. Using React.memo and Next/Image for performance is smart.

components/header/hero/terminal/TerminalTab.tsx (1)

34-34: Tab label updated to match branding. Removing "Terminal" simplifies the title nicely.

app/api/team/route.ts (1)

3-3: Good cleanup!

Removing the redundant comment makes the code cleaner since 3600 clearly represents one hour in seconds.

components/notification-generator/SoundInfoBox.tsx (1)

1-11: Clean and simple component!

Nice straightforward implementation that provides clear user guidance for the sound selection feature.

app/team/page.tsx (3)

3-4: Good additions!

Adding the Hero component and OG metadata generation follows the consistent pattern used across other pages.


8-11: Nice metadata enhancement!

The OG image metadata will improve social sharing previews with proper title and subtitle.


17-17: Perfect placement!

The Hero component is properly positioned above the Team component in the layout.

components/icons/play.tsx (1)

1-18: Well-crafted icon component!

Good implementation with proper props handling and currentColor for theming support. The SVG structure is clean and follows React best practices.

components/projects/ProjectItem.tsx (1)

79-81: Good image optimization practices!

The priority loading for the first two items and quality settings follow Next.js best practices for performance.

app/projects/page.tsx (3)

3-4: Good additions for improved UX and SEO.

Adding the Hero component and OG metadata generation enhances both user experience and social sharing.


12-15: Proper metadata implementation.

The OG image metadata generation follows the established pattern and improves social media previews.


21-21: Hero component placement looks good.

Positioning the Hero component above the main content is the right approach for visual hierarchy.

components/icons/close.tsx (1)

3-18: Well-implemented icon component.

Clean SVG structure with proper TypeScript typing and flexible prop handling. The close icon is clearly recognizable.

components/notification-generator/form/constants.ts (1)

2-14: Looks good.

Constant provides clear options for sound categories.

components/notification-generator/ChatMessage.module.css (1)

1-20: Styles look good.

Scrollbar styling is consistent and cross-browser.

components/docs/Inline.tsx (1)

1-24: Clean implementation for inline styling!

The component is well-structured with proper TypeScript interfaces, comprehensive light/dark theme support, and good extensibility through the optional className prop.

components/projects/ProjectButton.tsx (1)

7-13: Good refactor to use the standardized Button component!

The transition from framer-motion to the custom Button component aligns well with the UI standardization efforts. The implementation is clean and maintains all necessary functionality.

app/not-found.tsx (1)

4-33: Well-designed 404 page with good UX!

The component provides a clear, accessible error page with helpful navigation options. The responsive design and dark mode support are implemented correctly.

components/icons/hamburger.tsx (1)

1-24: Simple and effective hamburger icon component!

The implementation is clean with proper TypeScript typing and flexible styling through className. The SVG structure follows standard practices and will work well across different themes.

app/notification-generator/layout.tsx (2)

1-24: Comprehensive metadata setup looks good!

The SEO and social media metadata is well-structured with proper Open Graph and Twitter card configurations. The keywords and descriptions are relevant to the notification generator tool.


26-36: Simple and effective layout component.

The layout provides appropriate spacing and constraints for the notification generator page. The styling classes create good visual hierarchy.

app/docs/page.tsx (2)

4-5: Good use of static generation with revalidation.

The static generation settings match other pages in the project and provide appropriate caching for a redirect page.


7-9: Clean redirect implementation.

The redirect to the introduction page provides a good default entry point for the documentation section.

app/prism-languages.ts (2)

1-31: Excellent language coverage for documentation.

The comprehensive set of Prism language imports covers all major programming languages and tools likely needed for documentation. The organized import groups make the code easy to maintain.


33-38: Well-crafted TypeScript language definition.

The TypeScript customization properly extends JavaScript and includes comprehensive keyword and builtin type patterns that will provide accurate syntax highlighting.

components/animations/index.ts (1)

1-4: Clean barrel export pattern.

This index file properly centralizes the animation components and utilities, making them easy to import throughout the codebase.

components/docs/AnimatedLayout.tsx (2)

12-32: Well-structured animation layout with good timing.

The nested motion divs create a nice layered animation effect. The spring parameters and delay provide smooth, natural-feeling transitions for documentation content.


6-8: Clean TypeScript interface.

The props interface is simple and properly typed for the component's needs.

components/notification-generator/SoundIndicator.tsx (1)

8-10: Clean conditional rendering logic.

Good use of early return and React.memo for performance optimization.

content/docs/contribute/guide.md (1)

1-67: Excellent contribution guide.

Clear step-by-step instructions that are beginner-friendly. Good structure and practical examples throughout.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~67-~67: Loose punctuation mark.
Context: ...ly made a contribution to this project. :>

(UNLIKELY_OPENING_PUNCTUATION)

components/docs/ErrorBoundary.tsx (2)

23-29: Proper error boundary implementation.

Correct use of both lifecycle methods for catching and logging errors.


34-48: User-friendly error UI design.

Good use of progressive disclosure with collapsible technical details. Clear messaging and proper dark mode support.

components/header/ThemeSwitchButton.tsx (2)

12-14: Good performance optimization.

Using useCallback prevents unnecessary re-renders when the component updates.


26-29: Nice accessibility improvements.

Adding aria-hidden to icons and dynamic aria-label makes this more screen reader friendly.

app/api/docs/search-index/route.ts (2)

6-21: The recursive file search looks good and is safe.

The function properly handles directory traversal and file filtering for markdown files.


51-62: Good error handling in the API route.

The try-catch structure properly handles errors and returns appropriate HTTP status codes.

components/icons/arrow-forward.tsx (1)

3-18: The spread props issue has been fixed.

The component now properly spreads {...props} to the SVG element, addressing the previous review concern. The implementation looks good with proper TypeScript typing.

components/docs/EditOnGitHub.tsx (3)

1-9: Clean imports and well-defined interface.

The TypeScript interface is properly defined with required and optional props.


15-15: Good security practice with URL encoding.

Using encodeURIComponent for the file path prevents potential security issues with special characters.


17-32: Excellent accessibility and styling implementation.

The component includes proper ARIA attributes, security attributes for external links, and good styling with dark mode support.

components/Analytics.tsx (4)

7-8: Good initialization with consent checking.

The component properly initializes state based on current consent status.


10-12: Proper use of useCallback for performance.

The callback is memoized to prevent unnecessary re-renders.


14-24: Comprehensive event listening for consent changes.

The component listens to both storage events and custom consent events, ensuring it responds to consent changes from any source.


26-29: Privacy-compliant conditional rendering.

The component only loads analytics when consent is given, which is the correct approach for privacy compliance.

components/notification-generator/form/ActionBarTab.tsx (1)

1-23: Clean and well-structured component implementation.

The component follows React best practices with proper TypeScript typing and clear separation of concerns. The interface correctly uses shared types and the component renders appropriate child components for the action bar functionality.

app/providers.tsx (1)

25-34: Good theme provider configuration.

The new theme provider props properly enable system theme detection and disable transitions to prevent flash effects. This integrates well with the theming system.

components/notification-generator/Title.tsx (1)

11-42: Well-implemented component with good performance optimizations.

The component effectively uses React.memo for performance and includes proper conditional rendering. The integration with MinecraftText follows established patterns, and the styling approach with absolute positioning and opacity transitions works well for the Minecraft notification display.

components/notification-generator/form/TitleTab.tsx (3)

7-11: Well-designed interface with proper error handling.

The props interface correctly extends shared types and includes error handling support, enabling proper validation feedback in the form.


31-61: Smart layout and configuration for timing fields.

The grid layout for timing fields is visually clean, and disabling editor buttons for these fields makes sense since they expect time format strings (e.g., "1s") rather than rich text content.


13-64: Comprehensive form tab implementation.

The component provides a complete interface for title configuration with proper separation between text content fields and timing parameters. The integration with validation and user guidance components creates a good user experience.

components/notification-generator/form/AdvancedTab.tsx (1)

1-30: LGTM! Clean and accessible checkbox implementation.

The component correctly handles the titleHide boolean field with proper accessibility attributes and dark mode styling.

components/OgImage.tsx (1)

39-42: Component returns null - confirm this is intentional.

The component renders nothing but serves as a metadata utility. This pattern works but consider adding a comment explaining the purpose.

+// This component is used for metadata generation only and doesn't render any UI
 export default function OgImage({ title, subtitle, image }: OgImageProps) {
   return null;
 }
components/docs/CodeBlock.tsx (1)

1-24: Excellent code block implementation with performance and accessibility in mind.

The use of memo, proper prop inheritance, and comprehensive accessibility attributes make this a solid component for the documentation system.

components/notification-generator/form/ChatTab.tsx (1)

1-25: Clean and well-structured form tab component.

The integration with FormField and inclusion of helpful guidance through MiniMessageInfoBox creates a good user experience for chat message input.

app/page.tsx (3)

1-3: Clean import organization.

The imports are well-organized and follow Next.js conventions. The addition of metadata types and OG image generation shows good SEO planning.


8-19: Well-structured metadata implementation.

The metadata configuration includes proper SEO elements with canonical URL and Open Graph image generation. This will improve social sharing and search engine visibility.


21-23: Good component abstraction.

Moving to a single AnimatedHome component simplifies the page structure while maintaining functionality. This follows the single responsibility principle nicely.

app/api/og/route.tsx (2)

5-5: Good choice for edge runtime.

Using edge runtime for image generation improves performance and reduces cold start times.


105-108: Good error handling implementation.

The error handling properly logs issues and returns appropriate HTTP status codes.

components/docs/sidebar-structure.ts (2)

1-5: Well-designed interface.

The DocItem interface is clean and properly typed. The optional children property makes it flexible for nested navigation.


7-56: Excellent documentation organization.

The structure is logically organized by product areas and follows consistent URL patterns. This will make navigation intuitive for users.

app/prism-tomorrow.css (2)

3-24: Comprehensive base styling.

The base styles cover all essential properties with proper browser compatibility and good defaults for code presentation.


45-117: Well-organized token styling.

The token colors create a cohesive dark theme with good contrast. The color choices help distinguish different code elements effectively.

components/SpeedInsights.tsx (1)

14-24: Well-implemented event listener management.

Good use of proper cleanup functions and memoized callbacks. The dual event listeners for both storage changes and custom consent events ensure the component stays synchronized.

components/notification-generator/NotificationCode.tsx (1)

63-91: Good use of staggered animations for list items.

The step-by-step instructions with individual animation delays create a nice progressive reveal effect. The content is clear and helpful.

components/header/hero/button/TransparentHeroButton.tsx (1)

15-32: Excellent refactoring addressing previous review feedback.

The animation controls are now properly connected, and the component uses the new Button component with improved styling and accessibility. The hover effects and icon usage look great.

app/privacy-policy/page.tsx (3)

12-19: Well-structured content organization.

Good use of semantic HTML with proper heading hierarchy and clear prose styling. The content clearly explains the organization's identity and purpose.


89-96: Proper external link security.

Good use of security attributes on external links to prevent potential security issues.


131-159: Excellent use of AlertBox for contact information.

The contact details are well-presented using the AlertBox component, making them easily discoverable. Email and Discord links are properly formatted with good hover states.

components/notification-generator/minecraft-font.css (1)

1-23: Well-structured font implementation!

The font face definition and CSS classes are properly set up with good performance optimizations like font-display: swap and comprehensive unicode range coverage.

components/notification-generator/ActionBar.tsx (1)

8-9: Good performance optimization and null handling!

Using React.memo and early return for empty messages is a smart approach.

components/docs/DynamicCommandsTable.tsx (1)

17-28: Solid data fetching with good error handling!

The fetch logic properly handles errors and loading states, making the component reliable.

components/ui/tooltip.tsx (2)

20-31: Nice hover delay and cleanup handling!

The 500ms delay prevents accidental tooltip triggers, and the timeout cleanup prevents memory leaks.


44-63: Smooth animations with proper accessibility!

The Framer Motion animations are subtle and the ARIA attributes make the tooltip accessible to screen readers.

components/header/ToolsDropdown.tsx (4)

14-31: Good event handling pattern!

The click outside detection is well implemented with proper cleanup in the useEffect.


34-44: Escape key handling looks solid.

Clean implementation of keyboard event handling with proper listener management.


48-71: Excellent accessibility implementation!

Great use of ARIA attributes and keyboard navigation support.


72-98: Nice animation and menu structure.

The framer-motion implementation is clean and the menu structure follows accessibility best practices.

app/globals.css (4)

1-1: Good modular approach with CSS imports.

Clean separation of Prism theme from main styles.


6-139: Comprehensive syntax highlighting styles.

The Prism integration looks well-structured with proper token colors and line number support.


210-222: Nice animation implementation.

The fadein animation with cubic-bezier timing looks smooth and well-crafted.


228-237: Toast icon positioning fixes look good.

Proper handling of toast notification icon layout with flexbox.

components/notification-generator/MinecraftPreview.tsx (3)

1-16: Great component structure!

Nice use of custom hooks and clean separation between different notification types. The memoization setup will help with performance.


18-57: Smart performance optimization with useMemo

Each notification component is properly memoized with the right dependencies. This prevents unnecessary re-renders when other parts of the notification config change.


59-90: Good accessibility and styling

The component has proper ARIA attributes and maintains a 16:9 aspect ratio. The AnimatePresence wrapping each component enables smooth transitions.

components/docs/ShortLink.tsx (3)

28-34: Memory leak issue resolved!

Great fix! The cleanup function in useEffect properly clears the timeout when the component unmounts, addressing the previous memory leak concern.


36-51: Solid async handling

The copy function handles loading states well and includes proper error handling. The clipboard API usage is correct.


53-82: Good accessibility and user feedback

The button states clearly show loading, success, and default states with proper ARIA labels. Users get clear visual feedback for each action.

components/notification-generator/form/Tab.tsx (1)

17-44: Accessibility improvements implemented!

Perfect! The tab now includes all the proper ARIA attributes mentioned in previous reviews. The role="tab", aria-selected, and tabIndex handling will make this work great with screen readers and keyboard navigation.

components/docs/ReadingTime.tsx (1)

20-42: Well-implemented reading time component.

The component follows React best practices with memo optimization, good accessibility, and clean prop interface. The default 200 WPM is reasonable for technical documentation.

components/docs/DocHeader.tsx (1)

52-101: Clean and accessible header component.

The component structure is excellent with proper conditional rendering, good accessibility, and smooth animations. The layout handles optional props well.

components/header/hero/Hero.tsx (2)

7-7: Good adoption of animation abstractions.

The import statement shows proper integration with the centralized animation system.


11-69: Excellent refactor to animation components.

The conversion from direct framer-motion to animation abstractions is clean and maintains the same visual behavior while improving code organization. The accessibility attributes and semantic structure are preserved.

content/docs/eternalcombat/installation.md (1)

1-92: Comprehensive and well-structured documentation.

The installation guide covers all necessary steps with clear instructions, proper prerequisites, upgrade procedures, and helpful troubleshooting. The Alert component usage for community links is appropriate.

🧰 Tools
🪛 LanguageTool

[grammar] ~40-~40: The word ‘Backup’ is a noun. Do you mean the verb “Back up”?
Context: ...🔄 Upgrading ### Upgrade Process 1. Backup Your Configuration ```bash cp ...

(SENT_START_BACKUP)

components/about/About.tsx (1)

6-77: Nice animation refactor!

The switch to centralized animation components makes the code cleaner and more maintainable. Good accessibility improvements too!

components/docs/DocSidebar.tsx (1)

1-207: Well-built sidebar component!

Great implementation with smooth animations, proper accessibility attributes, and correct active state handling for nested items. The performance optimizations with React.memo are a nice touch.

components/ui/AlertBox.tsx (1)

154-186: Nice animation and accessibility implementation!

The component has smooth animations and proper accessibility features. The layout animation, ARIA roles, and screen reader considerations are well implemented.

components/notification-generator/types.ts (1)

1-21: Clean and well-structured type definitions!

The interfaces are clear and provide good type safety for the notification generator. The union types will help prevent runtime errors.

app/notification-generator/page.tsx (1)

91-93: Good use of key prop for preview re-rendering!

Using the previewKey to force re-rendering of the preview component is a clean solution for the replay functionality.

components/notification-generator/form/validation.ts (1)

3-29: Well-structured validation logic!

The function handles different field types appropriately and provides clear error messages. The early return for empty values is a good practice.

components/docs/DocCopyEnhancer.tsx (1)

172-177: Good cleanup handling

The cleanup logic properly disconnects the observer and clears the copy states map. This prevents potential memory leaks.

components/docs/AnimatedHeading.tsx (2)

32-44: Clipboard error handling looks good

The error handling with try-catch properly addresses the previous review feedback about clipboard failures.


76-96: Accessibility is well implemented

The button includes proper aria-label, title, and the status message has aria-live="polite" for screen readers. This addresses the previous accessibility concerns.

components/team/Team.tsx (2)

9-11: Good refactoring to centralized animations

Using the new animation wrappers creates better consistency across components and centralizes animation logic.


40-44: Nice touch with the blue hover effect

The new blue hover color (#2563eb) for social icons creates better visual feedback than the previous gray.

components/CookiePreferencesMenu.tsx (2)

15-25: Good accessibility on the settings button

The fixed-position button has proper aria-label and smooth animations. The positioning works well for user access.


60-66: Smart approach for necessary cookies

Making necessary cookies always checked and disabled is the right approach for GDPR compliance.

app/docs/layout.tsx (2)

11-17: Good font configuration with proper fallbacks.

The Poppins font setup includes appropriate weights, subsets, and fallback fonts for better performance and accessibility.


19-41: Comprehensive metadata setup for SEO.

The metadata configuration covers all essential elements including Open Graph, Twitter cards, and proper robot directives.

components/ui/tab.tsx (2)

15-27: Well-structured component with proper TypeScript patterns.

Good use of forwardRef and clean prop destructuring with proper defaults.


48-68: Clean animation implementation.

The single render path eliminates the duplication issue from previous reviews. The motion.div for the active tab indicator is properly implemented with good animation settings.

components/notification-generator/hooks.ts (3)

7-8: Good use of refs for cleanup management.

Using refs to track intervals and timeouts ensures proper cleanup and addresses the previous memory leak concerns.


10-15: Robust time parsing with validation.

The regex pattern correctly validates time format (e.g., "1.5s") and provides fallback for invalid inputs.


58-61: Proper cleanup implementation.

The cleanup function correctly clears both intervals and timeouts, preventing memory leaks.

components/CookieConsentModal.tsx (3)

16-22: Smart conditional rendering logic.

The modal only displays when consent is uninitialized and matches default state, preventing unnecessary prompts.


81-87: Correct implementation for necessary cookies.

Properly disabling the necessary cookies checkbox while keeping it checked ensures users understand these cannot be opted out.


26-31: Smooth animation with proper positioning.

The framer-motion animation provides good user experience with appropriate easing and positioning.

components/notification-generator/NotificationForm.tsx (4)

34-46: Great validation approach!

The validation logic properly handles specific fields and clears errors when needed. The field list check ensures only relevant fields get validated.


48-66: Solid reset functionality.

Good use of refs to stop sound playback and proper state cleanup. The callback dependency array is correct.


87-98: Clean tab rendering with good performance.

Using useMemo for tab generation is smart, and the capitalization logic works well for display labels.


112-119: Excellent accessibility implementation.

Proper ARIA attributes including role="tablist", aria-label, and semantic structure make this very accessible.

components/footer/Footer.tsx (4)

13-23: Well-designed TypeScript interfaces.

Clean interface design that clearly separates link properties and section structure. The optional isExternal flag is a nice touch.


153-184: Excellent data-driven rendering.

Smart conditional rendering based on isExternal flag with proper security attributes (target="_blank" and rel="noopener noreferrer").


121-124: Good accessibility enhancement.

Adding role="contentinfo" to the footer is the right approach for screen readers.


192-192: Smart dynamic copyright year.

Using new Date().getFullYear() prevents the copyright from becoming outdated.

components/docs/CodeTabs.tsx (2)

23-44: Robust icon mapping with good fallback.

The dynamic icon name generation is clever, and the emoji fallback ensures something always renders. The memoization helps performance.


107-119: Smooth shared layout animation.

Using layoutId="activeTab" creates nice tab transition effects. The spring animation settings look good.

components/notification-generator/minecraftTextParser.tsx (1)

36-51: Clean legacy to MiniMessage conversion.

The mapping table is comprehensive and the conversion logic handles the formatting codes properly.

components/animations/AnimatedContainer.tsx (1)

59-96: Great job fixing the code repetition!

The dynamic component approach with the mapping is much cleaner than having multiple if-else blocks. This makes the code easier to maintain.

components/features/Features.tsx (1)

7-84: Nice refactoring with the animation components!

The code is much cleaner with the new animation abstractions. The alternating fadeLeft/fadeRight animations based on index is a nice touch.

components/animations/AnimatedSection.tsx (4)

1-8: Good client directive and imports

The imports are well-organized and all necessary dependencies are included.


9-21: Comprehensive interface design

The props interface covers all animation customization needs with good defaults and accessibility support.


43-56: Clean animation variant selection

The switch statement clearly maps animation types to their variants.


67-81: Solid component rendering

The motion.section implementation correctly handles all props and animation states.

components/animations/AnimationUtils.tsx (2)

6-11: Good shared spring configuration

Using a consistent spring configuration across animations ensures uniform feel.


85-112: Well-designed interactive animations

The scale and page transition variants are well-configured for smooth user interactions.

components/ui/button.tsx (3)

7-24: Good type definitions

The interfaces are comprehensive and well-structured for button customization.


45-60: Complete variant and size system

The styling system covers all common button needs with proper dark mode support.


88-95: Good content composition logic

The button content handling with loading state and icons is well-implemented.

components/animations/AnimatedElement.tsx (1)

8-19: Well-designed flexible interface

The props support both animation customization and HTML tag flexibility.

components/notification-generator/form/SoundTab.tsx (1)

68-129: Good error handling with fallback sounds!

Nice implementation with the fallback sound list when the remote fetch fails. This ensures the feature remains functional even when the external resource is unavailable.

components/faq/Faq.tsx (2)

3-11: Great refactoring to use reusable animation components!

Moving from direct framer-motion usage to the abstracted animation components improves consistency across the codebase and makes animations easier to maintain.


75-112: Excellent accessibility improvements!

The addition of ARIA attributes (aria-expanded, aria-controls, aria-labelledby) makes the FAQ accordion much more accessible for screen reader users.

app/docs/[...slug]/page.tsx (1)

186-196: Great job adding the ErrorBoundary!

The MDX content is now properly wrapped in an ErrorBoundary, preventing page crashes if there are rendering errors. This addresses the previous review feedback nicely.

components/header/Navbar.tsx (1)

126-146: Great accessibility improvements!

The menu toggle button has proper ARIA attributes and the animated icon transition is smooth.

content/docs/eternalcombat/features.md (1)

1-97: Nice documentation structure!

The features documentation is well-organized with clear sections and proper markdown formatting.

components/notification-generator/form/FormField.tsx (1)

1-311: Great job implementing the accessibility improvements!

The form field component has proper ARIA attributes, input validation, and a nice rich text editing experience.

app/layout.tsx (6)

1-16: Nice privacy-focused approach!

Moving analytics to local components for consent management is a great choice.


18-19: Good performance setup!

Static generation with hourly updates is a solid choice for documentation sites.


21-28: Smart font loading!

The preload and swap settings will help avoid layout shifts. Good fallback choices too.


30-39: Great mobile setup!

Allowing zoom up to 5x is good for accessibility. Theme colors matching the design is a nice touch.


42-108: Excellent SEO setup!

Really thorough metadata configuration. The dynamic OG images will make sharing look professional.


116-147: Clean layout structure!

Love the accessibility touches - the main content landmark and skip navigation support are great additions.

Comment on lines +42 to +48
<Image
src={image}
alt="EternalCode Logo"
width={120}
height={120}
style={{ marginRight: "20px" }}
/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify Image component compatibility with edge runtime.

The Next.js Image component may not work properly in edge runtime. Consider using a regular img tag or verify compatibility.


🏁 Script executed:

#!/bin/bash
# Check if Next.js Image component works in edge runtime
rg -A 5 -B 5 "Image.*edge.*runtime|edge.*runtime.*Image"

Length of output: 58


Could you check which Image you’re using in this edge route? Let’s verify the import source:


🏁 Script executed:

#!/bin/bash
# Show how Image is imported in the OG route
rg "import .*Image" -n app/api/og/route.tsx
# Check if @vercel/og is in use
rg "@vercel/og" -n app/api/og/route.tsx

Length of output: 211


Use a plain <img> tag in the OG edge function

The Next.js Image component isn’t supported inside an edge‐based OG handler. Swap it out for a standard <img> to avoid runtime errors.

  • File: app/api/og/route.tsx (lines 42–48)
  • Replace:
    <Image
      src={image}
      alt="EternalCode Logo"
      width={120}
      height={120}
      style={{ marginRight: "20px" }}
    />
    With:
    <img
      src={image}
      alt="EternalCode Logo"
      width={120}
      height={120}
      style={{ marginRight: "20px" }}
    />
🤖 Prompt for AI Agents
In app/api/og/route.tsx around lines 42 to 48, the Next.js Image component is
used inside an edge runtime OG handler, which is not supported and can cause
runtime errors. Replace the <Image> component with a standard <img> tag, keeping
the same src, alt, width, height, and style attributes to ensure compatibility
with the edge environment.

Comment on lines +46 to +47
{commands.map((c, i) => (
<tr key={i}>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use unique keys instead of array index.

Using array index as React key can cause rendering issues when the list changes.

-{commands.map((c, i) => (
-  <tr key={i}>
+{commands.map((c) => (
+  <tr key={c.name}>
📝 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.

Suggested change
{commands.map((c, i) => (
<tr key={i}>
{commands.map((c) => (
<tr key={c.name}>
🤖 Prompt for AI Agents
In components/docs/DynamicCommandsTable.tsx around lines 46 to 47, the React
list items use the array index as the key, which can cause rendering issues when
the list changes. Replace the array index key with a unique and stable
identifier from the command object, such as an ID or a unique property, to
ensure consistent and correct rendering.

Comment on lines +36 to +38
{message.split("\n").map((line, index) => (
<div
key={index}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid using array index as key.

Using array indices as keys can cause rendering issues when the array changes.

- {message.split("\n").map((line, index) => (
-   <div key={index}>
+ {message.split("\n").map((line, index) => (
+   <div key={`line-${index}-${line.slice(0, 10)}`}>
📝 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.

Suggested change
{message.split("\n").map((line, index) => (
<div
key={index}
{message.split("\n").map((line, index) => (
- <div key={index}>
+ <div key={`line-${index}-${line.slice(0, 10)}`}>
{line}
</div>
))}
🤖 Prompt for AI Agents
In components/notification-generator/ChatMessage.tsx around lines 36 to 38, the
code uses the array index as the key in the map function, which can cause
rendering issues when the array changes. To fix this, generate a unique and
stable key for each line, such as by using a hash of the line content combined
with the index or another unique identifier, instead of just the index.


### External Links

Link to external websites:a
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the typo

Remove the extra "a" at the end of line 36.

-Link to external websites:a
+Link to external websites:
📝 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.

Suggested change
Link to external websites:a
Link to external websites:
🤖 Prompt for AI Agents
In content/docs/documentation-editors/markdown-guide.md at line 36, there is an
extra "a" character at the end of the line after "Link to external websites:".
Remove this trailing "a" to correct the typo.

```
````

````
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove empty code block

This empty code block should be removed as it's not serving any purpose.

-````

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

230-230: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In content/docs/documentation-editors/markdown-guide.md at line 230, there is an
empty code block consisting of only backticks that serves no purpose. Remove
this empty code block entirely to clean up the markdown content.

Comment on lines +63 to +69
initial: interactive ? "initial" : "hidden",
animate: inView ? (interactive ? "initial" : "visible") : (interactive ? "initial" : "hidden"),
whileHover: interactive ? "hover" : undefined,
whileTap: interactive ? "tap" : undefined,
transition: { delay },
...filteredProps,
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix interactive animation logic

The animation states for interactive mode are incorrect. Interactive elements should still animate in/out of view.

const commonProps = {
  ref,
  className,
  variants: animationVariant,
-  initial: interactive ? "initial" : "hidden",
-  animate: inView ? (interactive ? "initial" : "visible") : (interactive ? "initial" : "hidden"),
+  initial: "hidden",
+  animate: inView ? "visible" : "hidden",
  whileHover: interactive ? "hover" : undefined,
  whileTap: interactive ? "tap" : undefined,
  transition: { delay },
  ...filteredProps,
};
📝 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.

Suggested change
initial: interactive ? "initial" : "hidden",
animate: inView ? (interactive ? "initial" : "visible") : (interactive ? "initial" : "hidden"),
whileHover: interactive ? "hover" : undefined,
whileTap: interactive ? "tap" : undefined,
transition: { delay },
...filteredProps,
};
const commonProps = {
ref,
className,
variants: animationVariant,
initial: "hidden",
animate: inView ? "visible" : "hidden",
whileHover: interactive ? "hover" : undefined,
whileTap: interactive ? "tap" : undefined,
transition: { delay },
...filteredProps,
};
🤖 Prompt for AI Agents
In components/animations/AnimatedElement.tsx around lines 63 to 69, the
animation logic for interactive elements is incorrect because it prevents them
from animating in and out of view. Update the logic so that interactive elements
use "visible" when inView is true and "hidden" when false, instead of always
using "initial". This will ensure interactive elements animate properly when
entering and leaving the viewport.

let volumeValue = 1.0;
if (typeof notification.volume === "string") {
const parsedVolume = parseFloat(notification.volume);
if (!isNaN(parsedVolume) && isFinite(parsedVolume)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Replace isFinite with Number.isFinite for safer type checking

The isFinite function can cause unexpected behavior due to type coercion. Use Number.isFinite instead for more predictable results.

-        if (!isNaN(parsedVolume) && isFinite(parsedVolume)) {
+        if (!isNaN(parsedVolume) && Number.isFinite(parsedVolume)) {
-      } else if (typeof notification.volume === "number" && isFinite(notification.volume)) {
+      } else if (typeof notification.volume === "number" && Number.isFinite(notification.volume)) {
-        if (!isNaN(parsedPitch) && isFinite(parsedPitch)) {
+        if (!isNaN(parsedPitch) && Number.isFinite(parsedPitch)) {
-      } else if (typeof notification.pitch === "number" && isFinite(notification.pitch)) {
+      } else if (typeof notification.pitch === "number" && Number.isFinite(notification.pitch)) {

Also applies to: 180-180, 195-195, 198-198

🧰 Tools
🪛 Biome (1.9.4)

[error] 177-177: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)

🤖 Prompt for AI Agents
In components/notification-generator/form/SoundTab.tsx at lines 177, 180, 195,
and 198, replace all uses of the global isFinite function with Number.isFinite
to avoid type coercion issues. This change ensures safer and more predictable
type checking by using the Number object's isFinite method.

Comment on lines +154 to +165
{options.map((option) => (
<div
key={option.value}
className="block w-full px-4 py-2 text-left text-gray-900 transition-colors duration-150 hover:bg-blue-50 hover:text-blue-700 focus:bg-blue-100 focus:text-blue-700 dark:text-white dark:hover:bg-gray-800 dark:hover:text-blue-400 dark:focus:bg-gray-800 dark:focus:text-blue-400 rounded-md outline-none cursor-pointer"
onClick={() => {
onChange(option.value);
setIsOpen(false);
}}
>
{option.label}
</div>
))}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add keyboard navigation support

The dropdown options need keyboard accessibility for arrow key navigation and better focus management.

 <div 
   key={option.value}
   className="block w-full px-4 py-2 text-left text-gray-900 transition-colors duration-150 hover:bg-blue-50 hover:text-blue-700 focus:bg-blue-100 focus:text-blue-700 dark:text-white dark:hover:bg-gray-800 dark:hover:text-blue-400 dark:focus:bg-gray-800 dark:focus:text-blue-400 rounded-md outline-none cursor-pointer"
+  tabIndex={0}
+  role="option"
+  aria-selected={option.value === value}
   onClick={() => {
     onChange(option.value);
     setIsOpen(false);
   }}
+  onKeyDown={(e) => {
+    if (e.key === "Enter" || e.key === " ") {
+      onChange(option.value);
+      setIsOpen(false);
+    }
+  }}
 >
📝 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.

Suggested change
{options.map((option) => (
<div
key={option.value}
className="block w-full px-4 py-2 text-left text-gray-900 transition-colors duration-150 hover:bg-blue-50 hover:text-blue-700 focus:bg-blue-100 focus:text-blue-700 dark:text-white dark:hover:bg-gray-800 dark:hover:text-blue-400 dark:focus:bg-gray-800 dark:focus:text-blue-400 rounded-md outline-none cursor-pointer"
onClick={() => {
onChange(option.value);
setIsOpen(false);
}}
>
{option.label}
</div>
))}
{options.map((option) => (
<div
key={option.value}
className="block w-full px-4 py-2 text-left text-gray-900 transition-colors duration-150 hover:bg-blue-50 hover:text-blue-700 focus:bg-blue-100 focus:text-blue-700 dark:text-white dark:hover:bg-gray-800 dark:hover:text-blue-400 dark:focus:bg-gray-800 dark:focus:text-blue-400 rounded-md outline-none cursor-pointer"
tabIndex={0}
role="option"
aria-selected={option.value === value}
onClick={() => {
onChange(option.value);
setIsOpen(false);
}}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
onChange(option.value);
setIsOpen(false);
}
}}
>
{option.label}
</div>
))}
🤖 Prompt for AI Agents
In components/notification-generator/form/SliderField.tsx around lines 154 to
165, the dropdown options lack keyboard navigation support. Enhance
accessibility by adding keyboard event handlers to allow arrow key navigation
between options and proper focus management. Implement onKeyDown handlers to
move focus up and down the list with arrow keys, and ensure options are
focusable by adding tabIndex attributes. This will improve usability for
keyboard users.

Comment on lines +98 to +102
<div className="w-full bg-[#f0f1f2] dark:bg-[#1F2A37] text-gray-800 dark:text-white text-center py-2 px-4 text-sm font-medium flex items-center justify-center gap-2 z-[60] border-b border-gray-200 dark:border-gray-700">
<span className="inline-block bg-white/60 dark:bg-white/10 rounded px-2 py-0.5 mr-2 text-xs font-bold uppercase tracking-wide text-blue-700 dark:text-blue-300">New</span>
<span className="font-semibold">We launched the new Notification generator, fully interactive and customizable!</span>
<a href="/notification-generator" className="ml-2 text-blue-700 dark:text-blue-300 font-semibold underline underline-offset-2 hover:text-indigo-700 dark:hover:text-indigo-300 transition-colors">Check it out &rarr;</a>
</div>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Make notification banner dynamic

The notification content is hardcoded. Consider making it configurable or dismissible for better user experience.

You could:

  • Store notification state in a context or prop
  • Add a dismiss button with close functionality
  • Make the content configurable through props or CMS
🤖 Prompt for AI Agents
In components/header/Navbar.tsx around lines 98 to 102, the notification banner
content is hardcoded, limiting flexibility and user control. Refactor the
component to accept notification content as props or from context to make it
configurable. Add a dismiss button that updates state to hide the banner when
clicked, storing this state locally or in context to persist dismissal. This
will make the notification dynamic and improve user experience.

Comment on lines +92 to +98
<style>
{`
.absolute::-webkit-scrollbar {
display: none;
}
`}
</style>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Move embedded styles to CSS

The embedded <style> tag isn't the best approach. Consider using Tailwind utilities or CSS modules instead.

-<style>
-  {`
-    .absolute::-webkit-scrollbar {
-      display: none;
-    }
-  `}
-</style>

Add to your global CSS or use Tailwind's scrollbar utilities:

/* In your global CSS */
.scrollbar-hide::-webkit-scrollbar {
  display: none;
}
.scrollbar-hide {
  -ms-overflow-style: none;
  scrollbar-width: none;
}

Then add the class to your dropdown div.

🤖 Prompt for AI Agents
In components/ui/Dropdown.tsx around lines 92 to 98, the embedded <style> tag
hiding the scrollbar should be removed. Instead, move the scrollbar hiding
styles to a global CSS file or use Tailwind's utilities by defining a class like
"scrollbar-hide" with the provided CSS rules. Then, apply this "scrollbar-hide"
class to the dropdown container div to achieve the same effect without inline
styles.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant