From bc41d2dac1a41a741f321e5fd4ce0ba8e4b9e65f Mon Sep 17 00:00:00 2001 From: Dhrubaraj Pati Date: Mon, 26 Jan 2026 20:52:20 +0530 Subject: [PATCH 01/14] Fix next.config.js for Vercel deployment --- next.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/next.config.js b/next.config.js index b321514..e368af6 100644 --- a/next.config.js +++ b/next.config.js @@ -4,7 +4,7 @@ const nextConfig = { eslint: { ignoreDuringBuilds: true, }, - images: { unoptimized: true }, + images: { unoptimized: true }, //fix this }; module.exports = nextConfig; From ebd6a69ace166abe1a2bdeaf5f47ee579a4c76a8 Mon Sep 17 00:00:00 2001 From: Dhrubaraj Pati Date: Mon, 26 Jan 2026 20:54:58 +0530 Subject: [PATCH 02/14] fix deployment bug --- next.config.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/next.config.js b/next.config.js index e368af6..8ca0b49 100644 --- a/next.config.js +++ b/next.config.js @@ -1,10 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - output: 'export', - eslint: { - ignoreDuringBuilds: true, - }, - images: { unoptimized: true }, //fix this + images: { unoptimized: true }, }; module.exports = nextConfig; From 2221ffd99b0755e23bb44122b274454d0638968a Mon Sep 17 00:00:00 2001 From: Dhrubaraj Pati Date: Tue, 27 Jan 2026 12:41:33 +0530 Subject: [PATCH 03/14] feat: enhance UI with updated animations, refined typography, improved layout, and redesigned tab components. --- app/picker/page.tsx | 71 +-- components/color-picker/color-analysis.tsx | 464 ++++++++++-------- .../color-picker/image-color-picker.tsx | 186 ++++--- .../color-picker/manual-color-picker.tsx | 228 ++++----- 4 files changed, 506 insertions(+), 443 deletions(-) diff --git a/app/picker/page.tsx b/app/picker/page.tsx index 7213301..3e32ced 100644 --- a/app/picker/page.tsx +++ b/app/picker/page.tsx @@ -13,70 +13,83 @@ export default function PickerPage() { const [selectedColor, setSelectedColor] = useState("#2596be"); const containerVariants: Variants = { - hidden: { opacity: 0, y: 30 }, + hidden: { opacity: 0 }, visible: { opacity: 1, - y: 0, transition: { - duration: 0.6, + staggerChildren: 0.1, + duration: 0.8, ease: "easeOut", - staggerChildren: 0.15, }, }, }; const itemVariants: Variants = { - hidden: { opacity: 0, y: 20 }, + hidden: { opacity: 0, y: 30, filter: "blur(10px)" }, visible: { opacity: 1, y: 0, - transition: { duration: 0.5, ease: "easeOut" }, + filter: "blur(0px)", + transition: { duration: 0.6, ease: "circOut" }, }, }; return ( -
-
+
+ {/* Background Pattern */} +
+
+
-
+
+ {/* Header Section */} -

- Color Picker & Analyzer +

+ Color Picker & Analyzer

-

- Extract colors from images or pick manually, then analyze and - explore +

+ Extract colors from images or pick manually, then analyze and explore palettes with our professional-grade tools.

- {/* Tabs Section */} - + {/* Main Interactive Section */} + +
+ - - - Pick from Image - - - Color Picker - - +
+ + + Pick from Image + + + Manual Picker + + +
- + - + - {/* Color Analysis */} + {/* Analysis Section */} diff --git a/components/color-picker/color-analysis.tsx b/components/color-picker/color-analysis.tsx index 2f4fd0d..c087640 100644 --- a/components/color-picker/color-analysis.tsx +++ b/components/color-picker/color-analysis.tsx @@ -63,101 +63,100 @@ export default function ColorAnalysis({ color }: ColorAnalysisProps) { }; return ( -
- - - {/* Tab List */} - - {[ - { value: "formats", label: "Formats" }, - { value: "variations", label: "Variations" }, - { value: "combinations", label: "Combos" }, - { value: "contrast", label: "Contrast" }, - { value: "analysis", label: "Analysis" }, - { value: "blindness", label: "Blindness" }, - ].map((tab) => ( - - {tab.label} - - ))} - - -
- - - {activeTab === "formats" && ( - - )} - - {activeTab === "variations" && ( - - )} - - {activeTab === "combinations" && ( - - )} - - {activeTab === "contrast" && ( - - )} - - {activeTab === "analysis" && ( - - )} - - {activeTab === "blindness" && ( - - )} - - -
-
+
+ +
+ + {/* Tab List */} +
+ + {[ + { value: "formats", label: "Formats" }, + { value: "variations", label: "Variations" }, + { value: "combinations", label: "Combos" }, + { value: "contrast", label: "Contrast" }, + { value: "analysis", label: "Analysis" }, + { value: "blindness", label: "Blindness" }, + ].map((tab) => ( + + {tab.label} + + ))} + +
+ +
+ + + {activeTab === "formats" && ( + + )} + + {activeTab === "variations" && ( + + )} + + {activeTab === "combinations" && ( + + )} + + {activeTab === "contrast" && ( + + )} + + {activeTab === "analysis" && ( + + )} + + {activeTab === "blindness" && ( + + )} + + +
+
+
); @@ -173,65 +172,76 @@ function FormatsTab({ copyToClipboard, }: any) { return ( -
+
-

Technical Formats

- copyToClipboard(color.toUpperCase(), "HEX")} - /> - - copyToClipboard(`rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`, "RGB") - } - /> - - copyToClipboard(`hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`, "HSL") - } - /> - - copyToClipboard(`hsv(${hsv.h}, ${hsv.s}%, ${hsv.v}%)`, "HSV") - } - /> +

+ + Technical Formats +

+
+ copyToClipboard(color.toUpperCase(), "HEX")} + /> + + copyToClipboard(`rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`, "RGB") + } + /> + + copyToClipboard(`hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`, "HSL") + } + /> + + copyToClipboard(`hsv(${hsv.h}, ${hsv.s}%, ${hsv.v}%)`, "HSV") + } + /> +
+
-

Practical Formats

- - copyToClipboard( - `cmyk(${cmyk.c}%, ${cmyk.m}%, ${cmyk.y}%, ${cmyk.k}%)`, - "CMYK" - ) - } - /> - - copyToClipboard(`#${color.slice(1).toUpperCase()}`, "Android") - } - /> +

+ + Practical Formats +

+
+ + copyToClipboard( + `cmyk(${cmyk.c}%, ${cmyk.m}%, ${cmyk.y}%, ${cmyk.k}%)`, + "CMYK" + ) + } + /> + + copyToClipboard(`#${color.slice(1).toUpperCase()}`, "Android") + } + /> +
); @@ -245,21 +255,21 @@ function VariationsTab({ copyToClipboard, }: any) { return ( -
+
+
+
- -

Color Properties

- - - - - -
+
+
+

+ + Color Properties +

+
+ + + + + +
+
- -

Creative Aspects

- 180 && hsl.h < 300 ? "Cool" : "Warm"} - /> - 70 ? "High" : hsl.s > 40 ? "Medium" : "Low"} - /> - 70 - ? "Light & Airy" - : hsl.l < 30 - ? "Dark & Mysterious" - : "Balanced" - } - /> -
+
+

+ + Creative Aspects +

+
+ 180 && hsl.h < 300 ? "Cool" : "Warm"} + /> + 70 ? "High" : hsl.s > 40 ? "Medium" : "Low"} + /> + 70 + ? "Light & Airy" + : hsl.l < 30 + ? "Dark & Mysterious" + : "Balanced" + } + /> +
+
); } @@ -376,14 +396,14 @@ function BlindnessTab({ color, protanopia, deuteranopia, tritanopia }: any) { function FormatCard({ label, value, onCopy, copied }: any) { return ( -
+
-

{label}

-

+

{label}

+

{value}

-
@@ -392,17 +412,17 @@ function FormatCard({ label, value, onCopy, copied }: any) { function PaletteSection({ title, colors, copiedValue, copyToClipboard }: any) { return ( -
-

{title}

-
+
+

{title}

+
{colors.map((c: string, i: number) => ( -
+
@@ -416,31 +436,41 @@ function ContrastCard({ backgroundColor, textColor, ratio, label }: any) { const passesAA = ratio >= 4.5; const passesAAA = ratio >= 7; return ( - +
-

Sample Text

-

{label}

+

Abc

+

{label}

-

- Contrast: {ratio.toFixed(2)}:1 -

-

- WCAG AA: {passesAA ? "Pass ✓" : "Fail ✗"} -

-

- WCAG AAA: {passesAAA ? "Pass ✓" : "Fail ✗"} -

- + +
+
+ Contrast Ratio + {ratio.toFixed(2)}:1 +
+
+ WCAG AA + + {passesAA ? "PASS" : "FAIL"} + +
+
+ WCAG AAA + + {passesAAA ? "PASS" : "FAIL"} + +
+
+
); } function PropertyRow({ label, value }: any) { return ( -
- {label} +
+ {label} {value}
); @@ -448,15 +478,15 @@ function PropertyRow({ label, value }: any) { function BlindnessCard({ label, color }: any) { return ( - +
-

{label}

-

{color}

+

{label}

+

{color}

- +
); } diff --git a/components/color-picker/image-color-picker.tsx b/components/color-picker/image-color-picker.tsx index f4491cc..01cd98a 100644 --- a/components/color-picker/image-color-picker.tsx +++ b/components/color-picker/image-color-picker.tsx @@ -59,7 +59,7 @@ export default function ImageColorPicker({ const imageData = ctx?.getImageData(0, 0, canvas.width, canvas.height); if (imageData) { - const colors = extractColorsFromImage(imageData, 8); + const colors = extractColorsFromImage(imageData, 10); setExtractedColors(colors); if (colors.length > 0) { onColorSelect(colors[0]); @@ -81,6 +81,7 @@ export default function ImageColorPicker({ }, [image, onColorSelect]); const handleCanvasClick = (e: React.MouseEvent) => { + // ... logic same as before ... const canvas = canvasRef.current; const ctx = canvas?.getContext("2d"); if (!canvas || !ctx) return; @@ -131,9 +132,11 @@ export default function ImageColorPicker({ }; return ( -
- -
+
+ +
+ + {/* Upload / Image Area */}
- + + {!image ? ( +
fileInputRef.current?.click()} + className="w-full relative group cursor-pointer" + > +
+
+
+ +
+
+

Upload an Image

+

+ Drag and drop or click to browse. We support JPG, PNG, and WebP. +

+
+
+
+ ) : ( +
+
+

+ + Source Image +

+ +
+ +
+ + {/* + Note: The canvas click logic was duplicated in original code on both canvas and img. + The canvas is hidden, so we rely on img onClick. + */} + Uploaded +
+ Click anywhere to pick color +
+
+
+ )}
+ {/* Extracted Colors Grid */} {image && ( -
-
- - Uploaded -
+
+
+

+ + Extracted Palette +

+ + {extractedColors.length} Colors Found +
-
-

Extracted Color Palette

-
- {extractedColors.length === 0 ? ( -
- No colors extracted — try another image. -
- ) : ( - extractedColors.map((color, index) => ( -
setHoveredColor(color)} - onMouseLeave={() => setHoveredColor(null)} - > - + > + {color} + {copiedColor === color ? : }
- )) - )} -
+
+ )) + )}
)} - {!image && ( -
- -

Upload an image to extract colors

-

- Click on the image to pick specific colors -

-
- )}
diff --git a/components/color-picker/manual-color-picker.tsx b/components/color-picker/manual-color-picker.tsx index aad1741..01d2e89 100644 --- a/components/color-picker/manual-color-picker.tsx +++ b/components/color-picker/manual-color-picker.tsx @@ -43,145 +43,129 @@ export default function ManualColorPicker({ color, onChange }: ManualColorPicker } return ( - -
-
-
-
- + +
+ +
+ {/* Left Column: Preview & Inputs */} +
+
+
-
- -
- - handleHexChange(e.target.value)} - className="font-mono" - /> -
- -
- - onChange(e.target.value)} - className="w-full h-12 rounded-lg cursor-pointer border" - /> + > +
+
+ + {color} + +
+
-
-
-
-

RGB

-
-
-
- - {rgb.r} -
- handleRgbChange("r", parseInt(e.target.value))} - className="w-full" - style={{ - background: `linear-gradient(to right, rgb(0,${rgb.g},${rgb.b}), rgb(255,${rgb.g},${rgb.b}))` - }} +
+ {/* HEX Input */} +
+ +
+
+ handleHexChange(e.target.value)} + className="font-mono pl-10 h-11 bg-background/50 border-border/50 focus:border-primary/50 transition-all font-medium tracking-wide" />
-
-
- - {rgb.g} -
+
+ + {/* Native Picker */} +
+ +
handleRgbChange("g", parseInt(e.target.value))} - className="w-full" - style={{ - background: `linear-gradient(to right, rgb(${rgb.r},0,${rgb.b}), rgb(${rgb.r},255,${rgb.b}))` - }} + id="color-input" + type="color" + value={color} + onChange={(e) => onChange(e.target.value)} + className="absolute -top-[50%] -left-[50%] w-[200%] h-[200%] cursor-pointer p-0 m-0 opacity-0 z-10" /> -
-
-
- - {rgb.b} +
+
+ Open System Picker
- handleRgbChange("b", parseInt(e.target.value))} - className="w-full" - style={{ - background: `linear-gradient(to right, rgb(${rgb.r},${rgb.g},0), rgb(${rgb.r},${rgb.g},255))` - }} - />
+
-
-

HSL

-
-
-
- - {hsl.h}° -
- handleHslChange("h", parseInt(e.target.value))} - className="w-full" - /> -
-
-
- - {hsl.s}% + {/* Right Column: Sliders */} +
+ + {/* RGB Section */} +
+

+ + + + RGB Channels +

+
+ {[ + { label: 'R', channel: 'r', val: rgb.r, max: 255, gradient: `linear-gradient(to right, rgb(0,${rgb.g},${rgb.b}), rgb(255,${rgb.g},${rgb.b}))` }, + { label: 'G', channel: 'g', val: rgb.g, max: 255, gradient: `linear-gradient(to right, rgb(${rgb.r},0,${rgb.b}), rgb(${rgb.r},255,${rgb.b}))` }, + { label: 'B', channel: 'b', val: rgb.b, max: 255, gradient: `linear-gradient(to right, rgb(${rgb.r},${rgb.g},0), rgb(${rgb.r},${rgb.g},255))` } + ].map((item) => ( +
+
+ {item.label} + {item.val} +
+ handleRgbChange(item.channel as any, parseInt(e.target.value))} + className="w-full h-2 rounded-full appearance-none cursor-pointer hover:opacity-90 transition-opacity" + style={{ background: item.gradient }} + />
- handleHslChange("s", parseInt(e.target.value))} - className="w-full" - /> -
-
-
- - {hsl.l}% + ))} +
+
+ + {/* HSL Section */} +
+

+ HSL + Model Control +

+
+ {[ + { label: 'Hue', channel: 'h', val: hsl.h, max: 360, unit: '°', bg: 'linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%)' }, + { label: 'Saturation', channel: 's', val: hsl.s, max: 100, unit: '%', bg: 'linear-gradient(to right, gray, disabled)' }, // Custom bg for S needed + { label: 'Lightness', channel: 'l', val: hsl.l, max: 100, unit: '%', bg: 'linear-gradient(to right, black, white)' } + ].map((item) => ( +
+
+ {item.label} + {item.val}{item.unit} +
+ handleHslChange(item.channel as any, parseInt(e.target.value))} + className="w-full h-2 rounded-full appearance-none cursor-pointer bg-muted" + style={item.channel === 'h' ? { background: item.bg } : undefined} + />
- handleHslChange("l", parseInt(e.target.value))} - className="w-full" - /> -
+ ))}
+
From e57dedd54269d4c09b5b162a744b665dcea3f9be Mon Sep 17 00:00:00 2001 From: Dhrubaraj Pati Date: Tue, 27 Jan 2026 12:56:18 +0530 Subject: [PATCH 04/14] feat: enhance Contrast Checker UI with new background patterns, updated typography, refined color input components, and improved card styling. --- app/contrast-checker/page.tsx | 287 +++++++++++++++++++--------------- 1 file changed, 159 insertions(+), 128 deletions(-) diff --git a/app/contrast-checker/page.tsx b/app/contrast-checker/page.tsx index 6085b46..e852ba8 100644 --- a/app/contrast-checker/page.tsx +++ b/app/contrast-checker/page.tsx @@ -37,69 +37,77 @@ export default function ContrastCheckerPage() { }; return ( -
-
+
+
+
{/* Navbar stays static */} {/* Page Content */} -
-
+
+
{/* Header Section */} -

+

Contrast Checker

-

- Check color contrast ratios and ensure your designs meet WCAG - accessibility standards +

+ Check color contrast ratios and ensure your designs meet WCAG accessibility standards with our real-time analyzer.

{/* Color Selection + WCAG Compliance */} {/* Color Selection Card */} - -
+ +
+
-

Color Selection

+

+ + Color Selection +

-
+
{/* Foreground Color */} -
-