Conversation
- Add hex color input to palettes page and color modal - Automatically apply custom palette when valid 6-char hex is entered - Ensure palette is never undefined (defaults to gray) - Clean UI with minimal additional elements 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Extract generatePaletteFromHex to lib/palettes/generate-palette-from-hex.ts - Update imports in all files using the function - Better separation of concerns and modularity 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Share custom hex state between modal and page via context - Persist custom palette across page refreshes using cookies - Sync custom palette display between components - Fix duplicate useColorTheme destructuring 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull Request Overview
Implements custom color palette support by adding hex color input functionality that generates complete Radix-based color palettes. This allows users to create personalized color themes from any 6-digit hex color input.
Key changes include:
- Added color generation libraries (bezier-easing, colorjs.io) for palette creation
- Implemented hex-to-Radix and Radix-to-shadcn conversion utilities
- Enhanced color palette provider with custom hex state management and persistence
- Updated UI components to support live custom palette generation and application
Reviewed Changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| package.json | Added bezier-easing and colorjs.io dependencies for color manipulation |
| lib/palettes/generators/radix-to-shadcn.ts | Converts Radix 12-step color scales to shadcn CSS variables |
| lib/palettes/generators/hex-to-radix.ts | Generates Radix-compatible color scales from hex input |
| lib/palettes/generate-palette-from-hex.ts | Main function orchestrating custom palette generation |
| lib/palettes/color-palettes.ts | Moved generatePaletteFromHex function to separate module |
| components/color-palette/color-palette-provider.tsx | Enhanced with custom hex state and cookie persistence |
| components/color-palette/color-palette-modal.tsx | Updated to use shared custom hex state |
| components/color-palette/color-palette-button.tsx | Updated import path for color palettes |
| app/layout.tsx | Updated import path for color palettes |
| app/(preview)/preview-theme-provider.tsx | Updated import path for color palettes |
| app/(preview)/layout.tsx | Updated import path for color palettes |
| app/(main)/palettes/page.tsx | Integrated with shared custom hex state and auto-application |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)
components/color-palette/color-palette-modal.tsx:1
- The hex normalization logic (checking for '#' prefix and adding it if missing) is duplicated in multiple places. Consider extracting this to a utility function for better maintainability.
"use client";
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| // Families to consider when synthesizing a scale (same set as upstream) | ||
| const grayScaleNames = [ | ||
| "gray", | ||
| "mauve", | ||
| "slate", | ||
| "sage", | ||
| "olive", | ||
| "sand", | ||
| ] as const; | ||
| const scaleNames = [ | ||
| ...grayScaleNames, | ||
| "tomato", | ||
| "red", | ||
| "ruby", | ||
| "crimson", | ||
| "pink", | ||
| "plum", | ||
| "purple", | ||
| "violet", | ||
| "iris", | ||
| "indigo", | ||
| "blue", | ||
| "cyan", | ||
| "teal", | ||
| "jade", | ||
| "green", | ||
| "grass", | ||
| "brown", | ||
| "orange", | ||
| "sky", | ||
| "mint", | ||
| "lime", | ||
| "yellow", | ||
| "amber", | ||
| ] as const; | ||
|
|
There was a problem hiding this comment.
These hardcoded color scale arrays duplicate data that appears to exist in the color palettes. Consider extracting these from the existing colorPalettes data to maintain a single source of truth and avoid potential inconsistencies.
| // Families to consider when synthesizing a scale (same set as upstream) | |
| const grayScaleNames = [ | |
| "gray", | |
| "mauve", | |
| "slate", | |
| "sage", | |
| "olive", | |
| "sand", | |
| ] as const; | |
| const scaleNames = [ | |
| ...grayScaleNames, | |
| "tomato", | |
| "red", | |
| "ruby", | |
| "crimson", | |
| "pink", | |
| "plum", | |
| "purple", | |
| "violet", | |
| "iris", | |
| "indigo", | |
| "blue", | |
| "cyan", | |
| "teal", | |
| "jade", | |
| "green", | |
| "grass", | |
| "brown", | |
| "orange", | |
| "sky", | |
| "mint", | |
| "lime", | |
| "yellow", | |
| "amber", | |
| ] as const; | |
| // Families to consider when synthesizing a scale (now extracted from colorPalettes) | |
| const grayScaleNames = colorPalettes | |
| .filter((p) => p.family === "gray") | |
| .map((p) => p.id) as const; | |
| const scaleNames = colorPalettes | |
| .map((p) => p.id) as const; |
| const palette = colorPalettes.find((p) => p.id === name); | ||
| const steps = palette | ||
| ? isLight | ||
| ? palette.radix.light | ||
| : palette.radix.dark | ||
| : undefined; | ||
| const arr = (steps || []).map((str) => toOklch(str)) as Array12<Color>; |
There was a problem hiding this comment.
If a palette is not found or has empty steps, the map operation on an empty array will create an empty array, but it's cast to Array12 which requires exactly 12 elements. This could cause runtime errors when the array is accessed with specific indices.
| const hex = getCookie("custom-color"); | ||
| if (hex && /^#[A-Fa-f0-9]{6}$/.test(hex)) { |
There was a problem hiding this comment.
The hex color validation regex is duplicated in multiple places throughout the codebase. Consider extracting this to a shared utility function to ensure consistency and easier maintenance.
No description provided.