Skip to content

Conversation

@alimortazavi-pr
Copy link

@alimortazavi-pr alimortazavi-pr commented Nov 16, 2025

Closes #

📝 Description

Add interactive CLI tool for theme generation with user prompts for color customization.

This PR introduces a command-line interface that allows users to generate custom light and dark theme files for Hero UI by interactively entering color values through prompts.

⛳️ Current behavior (updates)

Currently, users need to manually create theme configuration files or use existing themes without an easy way to generate custom themes with their preferred color schemes.

🚀 New behavior

  • Added interactive CLI tool using prompt-sync that:
    • Prompts users for theme name
    • Collects color inputs for default, primary, secondary, success, warning, and danger colors
    • Validates that all required inputs are provided
    • Generates both light and dark theme JSON files automatically
    • Saves output files with naming convention: {themeName}-light.json and {themeName}-dark.json

Users can now run the script and easily create custom themes by answering a series of prompts, making theme generation much more accessible.

💣 Is this a breaking change (Yes/No):

No

This is a new feature that adds functionality without modifying existing code or APIs. Existing Hero UI users are not affected.

📝 Additional Information

  • Dependencies added: prompt-sync for CLI input handling
  • The tool uses the existing formatter-and-generator module
  • Generated files follow the Hero UI theme structure
  • Input validation ensures all required colors are provided before generation

Summary by CodeRabbit

  • New Features

    • Introduced an interactive CLI tool to generate custom light and dark color themes with automatic shade variations
    • Creates reusable theme JSON configuration files from user-provided hex colors
    • Supports primary, secondary, success, warning, and danger color categories for comprehensive theming
  • Documentation

    • Added installation and usage instructions for the theme builder
  • Chores

    • Added project configuration and dependencies

@changeset-bot
Copy link

changeset-bot bot commented Nov 16, 2025

⚠️ No Changeset found

Latest commit: 86cc8a8

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Nov 16, 2025

@alimortazavi-pr is attempting to deploy a commit to the HeroUI Inc Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 16, 2025

Walkthrough

This PR introduces a new theme-builder CLI tool within the theme-builder directory. The tool includes utility modules for generating color shades from hex values and transforming light themes to dark themes, an interactive CLI script for collecting theme configuration, and project metadata. The theme builder generates light and dark theme JSON files based on user-provided colors.

Changes

Cohort / File(s) Summary
Color Generation Utilities
theme-builder/shades-gen.js, theme-builder/dark-gen.js
New modules exporting shadesOf(hex) and darkGenerator(light) functions for generating color shade variations and inverting light themes to dark equivalents via key remapping
Theme Composition
theme-builder/formatter-and-generator.js
New module exporting formatterAndGenerator function that accepts six color parameters and returns an object containing light and dark theme structures using shadesOf and darkGenerator utilities
CLI Interface
theme-builder/index.js
New interactive CLI script that prompts for theme name and six hex color values, invokes formatterAndGenerator, and writes light and dark JSON theme files
Project Configuration
theme-builder/.gitignore, theme-builder/package.json
Adds node_modules ignore rule and project metadata including name, scripts, dependencies (prompt-sync), devDependencies (nodemon), and Node engine requirement
Documentation
theme-builder/readme.md
User-facing guide covering installation, CLI prompts, and output file format

Sequence Diagram

sequenceDiagram
    participant User
    participant CLI as index.js
    participant FG as formatterAndGenerator
    participant Shades as shadesOf
    participant Dark as darkGenerator
    participant FS as File System

    User->>CLI: Run theme-builder
    CLI->>User: Prompt for theme name & colors
    User->>CLI: Provide hex values
    CLI->>FG: Call with collected colors
    
    FG->>Shades: shadesOf(primaryColor)
    Shades-->>FG: Color shade object
    FG->>Dark: darkGenerator(shades)
    Dark-->>FG: Inverted dark theme
    
    FG->>Shades: shadesOf(secondaryColor)
    Shades-->>FG: Color shade object
    FG->>Dark: darkGenerator(shades)
    Dark-->>FG: Inverted dark theme
    
    Note over FG: Repeat for success, warning, danger, default colors
    
    FG-->>CLI: {light: {...}, dark: {...}}
    CLI->>FS: Write <theme>-light.json
    CLI->>FS: Write <theme>-dark.json
    FS-->>User: Theme files created
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • theme-builder/shades-gen.js — Requires careful review of hex-to-RGB conversion logic, color interpolation algorithm, and validation of edge cases for hex input handling
  • theme-builder/formatter-and-generator.js — Verify correct composition of color categories and proper mapping of light/dark theme generation paths
  • theme-builder/index.js — Assess CLI prompt validation loops, error handling, and file I/O operations for correctness

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add hero ui theme builder' directly and clearly describes the main change: introducing a new theme builder tool for Hero UI.
Description check ✅ Passed The description follows the repository template with all major sections completed: description, current behavior, new behavior, breaking change status, and additional information are all present and substantive.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

📝 Customizable high-level summaries are now available!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide custom instructions to shape the summary (bullet lists, tables, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example:

"Create a concise high-level summary as a bullet-point list. Then include a Markdown table showing lines added and removed by each contributing author."


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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@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: 7

🧹 Nitpick comments (6)
theme-builder/readme.md (1)

7-17: Clarify execution steps and validation behavior.

The documentation doesn't explain that the tool validates required inputs (loops until non-empty). Consider adding:

  • Clear command: npm start from the theme-builder directory
  • Input validation behavior (required fields can't be empty)
  • Expected HEX color format with # prefix
  • Location where output files are created
theme-builder/index.js (1)

5-5: Remove async keyword from main function.

Since formatterAndGenerator is not async, the main function doesn't need to be async either.

-async function main() {
+function main() {
theme-builder/package.json (1)

1-25: Add repository and issue tracking fields.

The package.json is missing standard fields for a published package:

  • repository - Where the source code lives
  • bugs - Where to report issues
  • homepage - Project homepage/docs

Add these fields after line 5:

  "repository": {
    "type": "git",
    "url": "https://github.com/heroui-inc/heroui.git",
    "directory": "theme-builder"
  },
  "bugs": {
    "url": "https://github.com/heroui-inc/heroui/issues"
  },
  "homepage": "https://github.com/heroui-inc/heroui/tree/canary/theme-builder#readme",
theme-builder/dark-gen.js (1)

1-13: Document the shade inversion logic.

The keyChecker mapping inverts light/dark shade indices (light 50 → dark 950, etc.), but there's no explanation of why or how this works with Hero UI's theming system.

Add a comment:

// Maps light theme shade keys to their dark theme equivalents
// Light shades get inverted: lightest (50) becomes darkest (950), etc.
// This ensures proper contrast when switching between light and dark modes
const keyChecker = {
theme-builder/shades-gen.js (1)

1-29: Add JSDoc documentation.

The shade generation logic is complex and would benefit from documentation explaining:

  • The 11 shade values and their purpose
  • How the interpolation works for light vs dark shades
  • Expected input format
/**
 * Generates a palette of 11 shades from a base hex color.
 * @param {string} hex - Base color in hex format (e.g., "#3b82f6" or "3b82f6")
 * @returns {Object} Object with keys 50-950 containing interpolated hex colors
 * - Shade 500 is the base color
 * - Shades 50-400 interpolate from base to white (lighter)
 * - Shades 600-950 interpolate from black to base (darker)
 */
function shadesOf(hex) {
theme-builder/formatter-and-generator.js (1)

12-64: Consider reducing code duplication.

The light and dark theme generation repeats the same structure for 6 color categories. This could be refactored to be more maintainable.

function formatterAndGenerator({ defaultColor, primaryColor, secondaryColor, successColor, warningColor, dangerColor }) {
  const colorMap = {
    default: defaultColor,
    primary: primaryColor,
    secondary: secondaryColor,
    success: successColor,
    warning: warningColor,
    danger: dangerColor,
  };

  const lightColors = {};
  const darkColors = {};

  for (const [name, color] of Object.entries(colorMap)) {
    const shades = shadesOf(color);
    lightColors[name] = { DEFAULT: color, ...shades };
    darkColors[name] = { DEFAULT: color, ...darkGenerator(shades) };
  }

  return { light: lightColors, dark: darkColors };
}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 91e010f and 86cc8a8.

📒 Files selected for processing (7)
  • theme-builder/.gitignore (1 hunks)
  • theme-builder/dark-gen.js (1 hunks)
  • theme-builder/formatter-and-generator.js (1 hunks)
  • theme-builder/index.js (1 hunks)
  • theme-builder/package.json (1 hunks)
  • theme-builder/readme.md (1 hunks)
  • theme-builder/shades-gen.js (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
theme-builder/shades-gen.js (1)
theme-builder/formatter-and-generator.js (1)
  • shadesOf (1-1)
theme-builder/dark-gen.js (1)
theme-builder/formatter-and-generator.js (1)
  • darkGenerator (2-2)
theme-builder/formatter-and-generator.js (1)
theme-builder/index.js (1)
  • formatterAndGenerator (3-3)
🪛 markdownlint-cli2 (0.18.1)
theme-builder/readme.md

3-3: Bare URL used

(MD034, no-bare-urls)

🔇 Additional comments (4)
theme-builder/.gitignore (1)

1-1: LGTM!

The gitignore entry correctly excludes node_modules from version control.

theme-builder/formatter-and-generator.js (1)

4-70: Function signature is synchronous, not async.

This function is not declared as async, yet index.js awaits it. While this works (non-async functions can be awaited), it's misleading. The issue is flagged in index.js but noted here for context.

theme-builder/package.json (1)

26-30: Dependencies verified—no security issues found.

Both prompt-sync@^4.2.0 and nodemon@^3.0.1 are valid versions with no known security vulnerabilities. The prompt-sync version matches the latest release, and the nodemon version constraint allows up to the latest 3.x release.

theme-builder/shades-gen.js (1)

18-25: The shade interpolation logic is correct—review concern is based on a misunderstanding.

The getColor() function uses standard linear interpolation: result = end + percentage * (start - end), where higher percentages move the result toward the start value.

For dark shades (600–950):

  • startColor = black, endColor = baseColor
  • Shade 600: percentage = 0.2 → 80% baseColor + 20% black (lighter dark)
  • Shade 950: percentage = 0.9 → 10% baseColor + 90% black (darkest) ✓

For light shades (50–400):

  • startColor = baseColor, endColor = white
  • Shade 50: percentage = 0.1 → 90% white + 10% baseColor (lightest)
  • Shade 400: percentage = 0.8 → 20% white + 80% baseColor (lighter but darker than 50) ✓

The progression correctly produces shade 950 as the darkest and shade 50 as the lightest, matching Hero UI's expected color scale.

Comment on lines +14 to +20
function darkGenerator(light) {
let dark = {};
Object.entries(light).forEach(([key, value]) => {
dark[keyChecker[key]] = value;
});
return dark;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add input validation and handle undefined keys.

The function has no safeguards:

  1. No input validation - Doesn't check if light is an object or has expected keys
  2. Silent undefined assignment - If light contains keys not in keyChecker (like "DEFAULT"), dark[undefined] = value occurs, which is a bug

Apply this diff:

 function darkGenerator(light) {
+  if (!light || typeof light !== 'object') {
+    throw new Error('darkGenerator expects an object');
+  }
   let dark = {};
   Object.entries(light).forEach(([key, value]) => {
+    // Skip non-numeric keys like "DEFAULT"
+    if (!(key in keyChecker)) {
+      dark[key] = value;
+      return;
+    }
     dark[keyChecker[key]] = value;
   });
   return dark;
 }
📝 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
function darkGenerator(light) {
let dark = {};
Object.entries(light).forEach(([key, value]) => {
dark[keyChecker[key]] = value;
});
return dark;
}
function darkGenerator(light) {
if (!light || typeof light !== 'object') {
throw new Error('darkGenerator expects an object');
}
let dark = {};
Object.entries(light).forEach(([key, value]) => {
// Skip non-numeric keys like "DEFAULT"
if (!(key in keyChecker)) {
dark[key] = value;
return;
}
dark[keyChecker[key]] = value;
});
return dark;
}
🤖 Prompt for AI Agents
In theme-builder/dark-gen.js around lines 14 to 20, the darkGenerator lacks
input validation and can assign to undefined when a light key is not present in
keyChecker; validate that the input light is a non-null object (throw or return
an empty object for invalid input), iterate Object.entries only after that
check, and for each [key,value] ensure keyChecker has that key (use
Object.prototype.hasOwnProperty.call(keyChecker,key) or key in keyChecker)
before assigning to dark[keyChecker[key]]; skip unknown keys (or log/warn) so
you never set dark[undefined], and preserve existing behavior for valid
mappings.

Comment on lines +4 to +11
function formatterAndGenerator({
defaultColor,
primaryColor,
secondaryColor,
successColor,
warningColor,
dangerColor,
}) {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add input validation for color parameters.

The function doesn't validate that the color inputs are valid hex strings before passing them to shadesOf, which will throw errors for invalid inputs.

Add validation at the start of the function:

function formatterAndGenerator({
  defaultColor,
  primaryColor,
  secondaryColor,
  successColor,
  warningColor,
  dangerColor,
}) {
  // Validate all colors are provided
  const colors = { defaultColor, primaryColor, secondaryColor, successColor, warningColor, dangerColor };
  for (const [name, value] of Object.entries(colors)) {
    if (!value || typeof value !== 'string') {
      throw new Error(`${name} is required and must be a string`);
    }
  }
🤖 Prompt for AI Agents
In theme-builder/formatter-and-generator.js around lines 4 to 11, the function
accepts color params but does not validate them before calling shadesOf, so
invalid values will throw; add input validation at the start that collects all
color params into an object, ensures each is present and a string, and validates
each against a hex color regex (accepting #RGB or #RRGGBB); for any
missing/invalid value throw a descriptive Error like "<name> is required and
must be a valid hex color (e.g. #RRGGBB)" so callers get clear feedback instead
of shields failing inside shadesOf.

Comment on lines +6 to +39
let themeNameInput = prompt("Enter theme name: ");
while (!themeNameInput) {
themeNameInput = prompt("Enter theme name: ");
}

let defaultColorInput = prompt("Enter default colors: ");
while (!defaultColorInput) {
defaultColorInput = prompt("Enter default colors: ");
}

let primaryColorInput = prompt("Enter primary HEX: ");
while (!primaryColorInput) {
primaryColorInput = prompt("Enter primary HEX: ");
}

let secondaryColorInput = prompt("Enter secondary HEX: ");
while (!secondaryColorInput) {
secondaryColorInput = prompt("Enter secondary HEX: ");
}

let successColorInput = prompt("Enter success HEX: ");
while (!successColorInput) {
successColorInput = prompt("Enter success HEX: ");
}

let warningColorInput = prompt("Enter warning HEX: ");
while (!warningColorInput) {
warningColorInput = prompt("Enter warning HEX: ");
}

let dangerColorInput = prompt("Enter danger HEX: ");
while (!dangerColorInput) {
dangerColorInput = prompt("Enter danger HEX: ");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add input validation and reduce code duplication.

The input collection has several issues:

  1. No HEX color validation - The tool accepts any string for color inputs, which will cause errors downstream when shadesOf attempts to parse invalid hex values.
  2. Code duplication - Seven nearly-identical validation loops.
  3. No input trimming - Whitespace in inputs could cause issues.
  4. Confusing prompt - Line 11 says "default colors" (plural) but expects a single hex value.

Consider refactoring with a helper function:

function promptWithValidation(message, validator) {
  let input;
  while (true) {
    input = prompt(message).trim();
    if (!input) {
      console.log("This field is required.");
      continue;
    }
    if (validator && !validator(input)) {
      console.log("Invalid input format.");
      continue;
    }
    return input;
  }
}

function isValidHex(value) {
  return /^#?[0-9A-Fa-f]{6}$|^#?[0-9A-Fa-f]{3}$/.test(value);
}

// Usage:
const themeNameInput = promptWithValidation("Enter theme name: ");
const defaultColorInput = promptWithValidation("Enter default HEX color: ", isValidHex);
const primaryColorInput = promptWithValidation("Enter primary HEX: ", isValidHex);
// ... etc
🤖 Prompt for AI Agents
In theme-builder/index.js around lines 6 to 39, the input collection loops are
duplicated, do not trim inputs, mislabel the default color prompt, and accept
invalid hex values; refactor by extracting a helper like
promptWithValidation(message, validator) that trims input, requires non-empty
responses, and uses a hex validator for color fields, update prompt text to
"Enter default HEX color:" and apply the helper to themeName (no validator) and
all color fields (use isValidHex that accepts 3- or 6-digit hex with optional
leading #), and replace the repeated while-loops with calls to this helper to
reduce duplication and ensure proper validation.

Comment on lines +41 to +48
const result = await formatterAndGenerator({
defaultColor: defaultColorInput,
primaryColor: primaryColorInput,
secondaryColor: secondaryColorInput,
successColor: successColorInput,
warningColor: warningColorInput,
dangerColor: dangerColorInput,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove unnecessary await.

The formatterAndGenerator function is not async (as seen in formatter-and-generator.js), so awaiting it is unnecessary and misleading.

Apply this diff:

-  const result = await formatterAndGenerator({
+  const result = formatterAndGenerator({
     defaultColor: defaultColorInput,
     primaryColor: primaryColorInput,
     secondaryColor: secondaryColorInput,
     successColor: successColorInput,
     warningColor: warningColorInput,
     dangerColor: dangerColorInput,
   });
📝 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
const result = await formatterAndGenerator({
defaultColor: defaultColorInput,
primaryColor: primaryColorInput,
secondaryColor: secondaryColorInput,
successColor: successColorInput,
warningColor: warningColorInput,
dangerColor: dangerColorInput,
});
const result = formatterAndGenerator({
defaultColor: defaultColorInput,
primaryColor: primaryColorInput,
secondaryColor: secondaryColorInput,
successColor: successColorInput,
warningColor: warningColorInput,
dangerColor: dangerColorInput,
});
🤖 Prompt for AI Agents
In theme-builder/index.js around lines 41 to 48, the code uses "await" when
calling formatterAndGenerator even though that function is synchronous; remove
the unnecessary await and call formatterAndGenerator directly (assign its return
value to result without awaiting) so the call reflects the actual synchronous
behavior and eliminates misleading async usage.

Comment on lines +50 to +57
fs.writeFileSync(
`${themeNameInput}-light.json`,
JSON.stringify({ light: result.light })
);
fs.writeFileSync(
`${themeNameInput}-dark.json`,
JSON.stringify({ dark: result.dark })
);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add error handling, formatting, and user feedback.

The file write operations have several issues:

  1. No error handling - fs.writeFileSync can throw (permission errors, disk full, etc.)
  2. Poor formatting - JSON output lacks indentation, making it hard to read
  3. No user feedback - Users don't know if files were created successfully
  4. Blocking I/O - Synchronous file operations in an async function

Apply this diff:

+  try {
     fs.writeFileSync(
       `${themeNameInput}-light.json`,
-      JSON.stringify({ light: result.light })
+      JSON.stringify({ light: result.light }, null, 2)
     );
     fs.writeFileSync(
       `${themeNameInput}-dark.json`,
-      JSON.stringify({ dark: result.dark })
+      JSON.stringify({ dark: result.dark }, null, 2)
     );
+    console.log(`\n✓ Theme files created successfully:`);
+    console.log(`  - ${themeNameInput}-light.json`);
+    console.log(`  - ${themeNameInput}-dark.json`);
+  } catch (error) {
+    console.error(`\n✗ Error writing theme files: ${error.message}`);
+    process.exit(1);
+  }
📝 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
fs.writeFileSync(
`${themeNameInput}-light.json`,
JSON.stringify({ light: result.light })
);
fs.writeFileSync(
`${themeNameInput}-dark.json`,
JSON.stringify({ dark: result.dark })
);
try {
fs.writeFileSync(
`${themeNameInput}-light.json`,
JSON.stringify({ light: result.light }, null, 2)
);
fs.writeFileSync(
`${themeNameInput}-dark.json`,
JSON.stringify({ dark: result.dark }, null, 2)
);
console.log(`\n✓ Theme files created successfully:`);
console.log(` - ${themeNameInput}-light.json`);
console.log(` - ${themeNameInput}-dark.json`);
} catch (error) {
console.error(`\n✗ Error writing theme files: ${error.message}`);
process.exit(1);
}
🤖 Prompt for AI Agents
In theme-builder/index.js around lines 50 to 57, the synchronous
fs.writeFileSync calls should be replaced with asynchronous, non-blocking writes
using fs.promises.writeFile inside a try/catch; format JSON with indentation
(e.g., JSON.stringify(obj, null, 2)) before writing, wrap both write operations
in await calls (or Promise.all) to avoid blocking, and on success emit user
feedback (console.log or process.stdout.write) indicating file paths written; on
error catch and log the full error (including error.message), and either rethrow
or exit with a non-zero code so failures are visible to the caller.

Comment on lines +3 to +5
Clone your repo: git clone https://github.com/alimortazavi-pr/nextui-theme-builder.git
cd into folder.
npm install (adds prompt-sync for inputs; I skipped nodemon for now—dev it raw).
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix repository reference and markdown formatting.

The repository URL references "nextui-theme-builder" but this PR is for "heroui". Additionally, the bare URL should be formatted as a proper markdown link.

Apply this diff:

-Clone your repo: git clone https://github.com/alimortazavi-pr/nextui-theme-builder.git
+Clone your repo: `git clone https://github.com/heroui-inc/heroui.git`
 cd into folder.
-npm install (adds prompt-sync for inputs; I skipped nodemon for now—dev it raw).
+Run `npm install` in the theme-builder directory to install dependencies (prompt-sync for interactive inputs).
📝 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
Clone your repo: git clone https://github.com/alimortazavi-pr/nextui-theme-builder.git
cd into folder.
npm install (adds prompt-sync for inputs; I skipped nodemon for now—dev it raw).
Clone your repo: `git clone https://github.com/heroui-inc/heroui.git`
cd into folder.
Run `npm install` in the theme-builder directory to install dependencies (prompt-sync for interactive inputs).
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

3-3: Bare URL used

(MD034, no-bare-urls)

🤖 Prompt for AI Agents
In theme-builder/readme.md around lines 3 to 5, update the repository reference
from "nextui-theme-builder" to "heroui" and convert the bare clone URL into a
proper Markdown link; replace the raw URL with a markdown link to
https://github.com/alimortazavi-pr/heroui and keep the accompanying instructions
(cd into folder, npm install) unchanged, optionally wrapping the shell commands
in inline code formatting for clarity.

Comment on lines +31 to +52
function hexToRgbArray(hex) {
const originalHex = hex;

hex = hex.replace("#", "");
if (hex.length === 3) hex = hex + hex;

const r = hex.substring(0, 2);
const g = hex.substring(2, 4);
const b = hex.substring(4, 6);

const rgb = [r, g, b].map((channel) => {
try {
channel = parseInt(channel, 16);
if (channel < 0 || channel > 255) throw new Error();
return channel;
} catch {
throw new Error(`Invalid hex color provided: ${originalHex}`);
}
});

return rgb;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix critical bug in hex color expansion.

Line 35 has a logic error: hex = hex + hex for a 3-character hex like "abc" produces "abcabc" (6 chars but wrong), when it should produce "aabbcc".

Apply this diff:

   hex = hex.replace("#", "");
-  if (hex.length === 3) hex = hex + hex;
+  if (hex.length === 3) {
+    hex = hex.split('').map(c => c + c).join('');
+  }
+  
+  if (hex.length !== 6) {
+    throw new Error(`Invalid hex color provided: ${originalHex}`);
+  }
🤖 Prompt for AI Agents
theme-builder/shades-gen.js around lines 31 to 52, the 3-character hex expansion
uses `hex = hex + hex` which transforms "abc" into "abcabc" instead of "aabbcc";
replace that line with logic that expands each of the three characters by
repeating it (e.g., map each char to char+char and join) so 3-char inputs become
6-char RRGGBB strings before parsing, leaving the rest of hexToRgbArray
unchanged and preserving error handling.

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