refactor: use shadcn Card component in pastel app
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { PaletteGrid } from '@/components/pastel/PaletteGrid';
|
||||
import { ExportMenu } from '@/components/pastel/ExportMenu';
|
||||
import { useLighten, useDarken, useSaturate, useDesaturate, useRotate } from '@/lib/pastel/api/queries';
|
||||
@@ -102,8 +103,11 @@ export default function BatchPage() {
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
{/* Input */}
|
||||
<div className="space-y-6">
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Input Colors</h2>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Input Colors</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-sm text-muted-foreground mb-4">
|
||||
Enter colors (one per line or comma-separated). Supports hex format
|
||||
</p>
|
||||
@@ -118,11 +122,14 @@ export default function BatchPage() {
|
||||
<p className="text-xs text-muted-foreground mt-2">
|
||||
{parseColors(inputColors).length} valid colors found
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Operation</h2>
|
||||
<div className="space-y-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Operation</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<Select
|
||||
value={operation}
|
||||
onValueChange={(value) => setOperation(value as Operation)}
|
||||
@@ -170,30 +177,38 @@ export default function BatchPage() {
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Output */}
|
||||
<div className="space-y-6">
|
||||
{outputColors.length > 0 ? (
|
||||
<>
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">
|
||||
Output Colors ({outputColors.length})
|
||||
</h2>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<PaletteGrid colors={outputColors} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<ExportMenu colors={outputColors} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>
|
||||
) : (
|
||||
<div className="p-12 border rounded-lg bg-card text-center text-muted-foreground">
|
||||
<Card>
|
||||
<CardContent className="p-12 text-center text-muted-foreground">
|
||||
<Download className="h-12 w-12 mx-auto mb-4 opacity-50" />
|
||||
<p>Enter colors and click Process to see results</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { useSimulateColorBlindness } from '@/lib/pastel/api/queries';
|
||||
import { Loader2, Eye, Plus, X } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
@@ -77,9 +78,9 @@ export default function ColorBlindPage() {
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
{/* Controls */}
|
||||
<div className="space-y-6">
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h2 className="text-sm font-medium">Colors to Test</h2>
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0">
|
||||
<CardTitle className="text-sm font-medium">Colors to Test</CardTitle>
|
||||
<Button
|
||||
onClick={addColor}
|
||||
variant="outline"
|
||||
@@ -89,9 +90,9 @@ export default function ColorBlindPage() {
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
Add Color
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
||||
<div className="space-y-4">
|
||||
<CardContent className="space-y-4">
|
||||
{colors.map((color, index) => (
|
||||
<div key={index} className="flex items-start gap-3">
|
||||
<div className="flex-1">
|
||||
@@ -112,12 +113,14 @@ export default function ColorBlindPage() {
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Blindness Type</h2>
|
||||
<div className="space-y-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Blindness Type</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<Select
|
||||
value={blindnessType}
|
||||
onValueChange={(value) => setBlindnessType(value as ColorBlindnessType)}
|
||||
@@ -153,17 +156,20 @@ export default function ColorBlindPage() {
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Results */}
|
||||
<div className="space-y-6">
|
||||
{simulations.length > 0 ? (
|
||||
<>
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Simulation Results</h2>
|
||||
<p className="text-sm text-muted-foreground mb-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Simulation Results</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<p className="text-sm text-muted-foreground mb-2">
|
||||
Compare original colors (left) with how they appear to people with{' '}
|
||||
{blindnessType} (right)
|
||||
</p>
|
||||
@@ -196,9 +202,11 @@ export default function ColorBlindPage() {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="p-6 border rounded-lg bg-card bg-blue-50 dark:bg-blue-950/20">
|
||||
<Card className="bg-blue-50 dark:bg-blue-950/20 border-blue-100 dark:border-blue-900/30 shadow-none">
|
||||
<CardContent className="pt-6">
|
||||
<h3 className="font-semibold mb-2 flex items-center gap-2">
|
||||
<Eye className="h-5 w-5" />
|
||||
Accessibility Tip
|
||||
@@ -207,14 +215,17 @@ export default function ColorBlindPage() {
|
||||
Ensure important information isn't conveyed by color alone. Use text
|
||||
labels, patterns, or icons to make your design accessible to everyone
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>
|
||||
) : (
|
||||
<div className="p-12 border rounded-lg bg-card text-center text-muted-foreground">
|
||||
<Card>
|
||||
<CardContent className="p-12 text-center text-muted-foreground">
|
||||
<Eye className="h-12 w-12 mx-auto mb-4 opacity-50" />
|
||||
<p>Add colors and click Simulate to see how they appear</p>
|
||||
<p className="text-sm mt-2">with different types of color blindness</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useState, useEffect } from 'react';
|
||||
import { ColorPicker } from '@/components/pastel/ColorPicker';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { getContrastRatio, hexToRgb, checkWCAGCompliance } from '@/lib/pastel/utils/color';
|
||||
import { ArrowLeftRight, Check, X } from 'lucide-react';
|
||||
|
||||
@@ -68,12 +69,14 @@ export default function ContrastPage() {
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
{/* Color Pickers */}
|
||||
<div className="space-y-6">
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h2 className="text-sm font-medium">Foreground Color</h2>
|
||||
</div>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Foreground Color</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ColorPicker color={foreground} onChange={setForeground} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
@@ -86,17 +89,24 @@ export default function ContrastPage() {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Background Color</h2>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Background Color</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ColorPicker color={background} onChange={setBackground} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Results */}
|
||||
<div className="space-y-6">
|
||||
{/* Preview */}
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Preview</h2>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Preview</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div
|
||||
className="rounded-lg p-8 text-center"
|
||||
style={{ backgroundColor: background, color: foreground }}
|
||||
@@ -104,12 +114,16 @@ export default function ContrastPage() {
|
||||
<p className="text-xl font-bold mb-2">Normal Text (16px)</p>
|
||||
<p className="text-3xl font-bold">Large Text (24px)</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Contrast Ratio */}
|
||||
{ratio !== null && (
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Contrast Ratio</h2>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Contrast Ratio</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-center mb-6">
|
||||
<div className="text-5xl font-bold">{ratio.toFixed(2)}:1</div>
|
||||
<p className="text-sm text-muted-foreground mt-2">
|
||||
@@ -122,14 +136,17 @@ export default function ContrastPage() {
|
||||
: 'Poor contrast'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* WCAG Compliance */}
|
||||
{compliance && (
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">WCAG 2.1 Compliance</h2>
|
||||
<div className="space-y-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">WCAG 2.1 Compliance</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold mb-2">Level AA</h3>
|
||||
<div className="space-y-2">
|
||||
@@ -161,8 +178,8 @@ export default function ContrastPage() {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { useGenerateDistinct } from '@/lib/pastel/api/queries';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
@@ -49,11 +50,12 @@ export default function DistinctPage() {
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
{/* Controls */}
|
||||
<div className="lg:col-span-1">
|
||||
<div className="p-6 border rounded-lg bg-card space-y-6">
|
||||
<div>
|
||||
<h2 className="text-sm font-medium mb-4">Settings</h2>
|
||||
</div>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Settings</CardTitle>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent className="space-y-6">
|
||||
<div>
|
||||
<label htmlFor="count" className="text-sm font-medium mb-2 block">
|
||||
Number of Colors
|
||||
@@ -109,22 +111,29 @@ export default function DistinctPage() {
|
||||
This may take a few moments..
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Results */}
|
||||
<div className="lg:col-span-2 space-y-6">
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">
|
||||
Generated Colors {colors.length > 0 && `(${colors.length})`}
|
||||
</h2>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<PaletteGrid colors={colors} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{colors.length > 0 && (
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<ExportMenu colors={colors} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { PaletteGrid } from '@/components/pastel/PaletteGrid';
|
||||
import { ExportMenu } from '@/components/pastel/ExportMenu';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { useGenerateGradient } from '@/lib/pastel/api/queries';
|
||||
import { Loader2, Plus, X } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
@@ -59,8 +60,11 @@ export default function GradientPage() {
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
{/* Controls */}
|
||||
<div className="space-y-6">
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Color Stops</h2>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Color Stops</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="space-y-4">
|
||||
{stops.map((stop, index) => (
|
||||
<div key={index} className="flex items-start gap-3">
|
||||
@@ -87,11 +91,14 @@ export default function GradientPage() {
|
||||
Add Stop
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Settings</h2>
|
||||
<div className="space-y-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Settings</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div>
|
||||
<label htmlFor="count" className="text-sm font-medium mb-2 block">
|
||||
Number of Colors
|
||||
@@ -120,34 +127,44 @@ export default function GradientPage() {
|
||||
'Generate Gradient'
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Preview */}
|
||||
<div className="space-y-6">
|
||||
{gradient && gradient.length > 0 && (
|
||||
<>
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Gradient Preview</h2>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Gradient Preview</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div
|
||||
className="h-32 rounded-lg"
|
||||
style={{
|
||||
background: `linear-gradient(to right, ${gradient.join(', ')})`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">
|
||||
Colors ({gradient.length})
|
||||
</h2>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<PaletteGrid colors={gradient} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<ExportMenu colors={gradient} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { useGeneratePalette } from '@/lib/pastel/api/queries';
|
||||
import { Loader2, Palette } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
@@ -70,14 +71,20 @@ export default function HarmonyPage() {
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
{/* Controls */}
|
||||
<div className="space-y-6">
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Base Color</h2>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Base Color</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ColorPicker color={baseColor} onChange={setBaseColor} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Harmony Type</h2>
|
||||
<div className="space-y-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Harmony Type</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<Select
|
||||
value={harmonyType}
|
||||
onValueChange={(value) => setHarmonyType(value as HarmonyType)}
|
||||
@@ -116,32 +123,40 @@ export default function HarmonyPage() {
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Results */}
|
||||
<div className="space-y-6">
|
||||
{palette.length > 0 && (
|
||||
<>
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">
|
||||
Generated Palette ({palette.length} colors)
|
||||
</h2>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<PaletteGrid colors={palette} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<ExportMenu colors={palette} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>
|
||||
)}
|
||||
|
||||
{palette.length === 0 && (
|
||||
<div className="p-12 border rounded-lg bg-card text-center text-muted-foreground">
|
||||
<Card>
|
||||
<CardContent className="p-12 text-center text-muted-foreground">
|
||||
<Palette className="h-12 w-12 mx-auto mb-4 opacity-50" />
|
||||
<p>Select a harmony type and click Generate to create your palette</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { useNamedColors } from '@/lib/pastel/api/queries';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
import { parse_color } from '@valknarthing/pastel-wasm';
|
||||
@@ -76,7 +77,8 @@ export default function NamedColorsPage() {
|
||||
</div>
|
||||
|
||||
{/* Colors Grid */}
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
{isLoading && (
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
|
||||
@@ -115,7 +117,8 @@ export default function NamedColorsPage() {
|
||||
No colors match your search
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -6,6 +6,7 @@ import { ColorPicker } from '@/components/pastel/ColorPicker';
|
||||
import { ColorDisplay } from '@/components/pastel/ColorDisplay';
|
||||
import { ColorInfo } from '@/components/pastel/ColorInfo';
|
||||
import { ManipulationPanel } from '@/components/pastel/ManipulationPanel';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { useColorInfo } from '@/lib/pastel/api/queries';
|
||||
import { useColorHistory } from '@/lib/pastel/stores/historyStore';
|
||||
import { Loader2, Share2, History, X } from 'lucide-react';
|
||||
@@ -84,30 +85,36 @@ function PlaygroundContent() {
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
{/* Left Column: Color Picker and Display */}
|
||||
<div className="space-y-6">
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Color Picker</h2>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Color Picker</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ColorPicker color={color} onChange={setColor} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h2 className="text-sm font-medium">Preview</h2>
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0">
|
||||
<CardTitle className="text-sm font-medium">Preview</CardTitle>
|
||||
<Button onClick={handleShare} variant="outline" size="sm">
|
||||
<Share2 className="h-4 w-4 mr-2" />
|
||||
Share
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex justify-center">
|
||||
<ColorDisplay color={color} size="xl" />
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{recentColors.length > 0 && (
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0">
|
||||
<div className="flex items-center gap-2">
|
||||
<History className="h-5 w-5" />
|
||||
<h2 className="text-sm font-medium">Recent Colors</h2>
|
||||
<CardTitle className="text-sm font-medium">Recent Colors</CardTitle>
|
||||
</div>
|
||||
<Button
|
||||
onClick={clearHistory}
|
||||
@@ -117,7 +124,8 @@ function PlaygroundContent() {
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-5 gap-2">
|
||||
{recentColors.map((entry) => (
|
||||
<div
|
||||
@@ -150,15 +158,18 @@ function PlaygroundContent() {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right Column: Color Information */}
|
||||
<div className="space-y-6">
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Color Information</h2>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Color Information</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{isLoading && (
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
|
||||
@@ -173,12 +184,17 @@ function PlaygroundContent() {
|
||||
)}
|
||||
|
||||
{colorInfo && <ColorInfo info={colorInfo} />}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Color Manipulation</h2>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Color Manipulation</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ManipulationPanel color={color} onColorChange={setColor} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useState } from 'react';
|
||||
import { ColorPicker } from '@/components/pastel/ColorPicker';
|
||||
import { ColorDisplay } from '@/components/pastel/ColorDisplay';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { useTextColor } from '@/lib/pastel/api/queries';
|
||||
import { Loader2, Palette, Plus, X, CheckCircle2, XCircle } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
@@ -66,9 +67,9 @@ export default function TextColorPage() {
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
{/* Input */}
|
||||
<div className="space-y-6">
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h2 className="text-sm font-medium">Background Colors</h2>
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0">
|
||||
<CardTitle className="text-sm font-medium">Background Colors</CardTitle>
|
||||
<Button
|
||||
onClick={addBackground}
|
||||
disabled={backgrounds.length >= 10}
|
||||
@@ -78,8 +79,9 @@ export default function TextColorPage() {
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
Add
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent className="space-y-4">
|
||||
<div className="space-y-4">
|
||||
{backgrounds.map((color, index) => (
|
||||
<div key={index} className="flex items-center gap-3">
|
||||
@@ -119,31 +121,37 @@ export default function TextColorPage() {
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="p-6 border rounded-lg bg-card bg-blue-50 dark:bg-blue-950/20">
|
||||
<Card className="bg-blue-50 dark:bg-blue-950/20 border-blue-100 dark:border-blue-900/30 shadow-none">
|
||||
<CardContent className="pt-6">
|
||||
<h3 className="font-semibold mb-2">How it works</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
This tool analyzes each background color and automatically selects either black
|
||||
or white text to ensure maximum readability. The algorithm guarantees WCAG AA
|
||||
compliance (4.5:1 contrast ratio) for normal text
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Results */}
|
||||
<div className="space-y-6">
|
||||
{results.length > 0 ? (
|
||||
<>
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<h2 className="text-sm font-medium mb-4">Optimized Results</h2>
|
||||
<div className="space-y-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">Optimized Results</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{results.map((result, index) => (
|
||||
<div
|
||||
<Card
|
||||
key={index}
|
||||
className="p-4 border rounded-lg"
|
||||
className="overflow-hidden shadow-none"
|
||||
style={{ backgroundColor: result.background }}
|
||||
>
|
||||
<CardContent className="p-4">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<ColorDisplay color={result.background} size="sm" />
|
||||
@@ -202,16 +210,19 @@ export default function TextColorPage() {
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>
|
||||
) : (
|
||||
<div className="p-12 border rounded-lg bg-card text-center text-muted-foreground">
|
||||
<Card>
|
||||
<CardContent className="p-12 text-center text-muted-foreground">
|
||||
<Palette className="h-12 w-12 mx-auto mb-4 opacity-50" />
|
||||
<p>Add background colors and click Optimize to see results</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user