fix: resolve hydration errors in playground

- Fix nested button error in color history by using div with role=button
- Add keyboard accessibility (Enter/Space) to color history swatches
- Add type guard for ColorInfo.name to handle object values
- Add aria-label to remove button for better accessibility

Fixes React hydration errors and improves accessibility.
This commit is contained in:
valknarness
2025-11-07 13:53:23 +01:00
parent 0ac49c0600
commit fd2cea8f47
2 changed files with 12 additions and 4 deletions

View File

@@ -137,12 +137,19 @@ function PlaygroundContent() {
</div> </div>
<div className="grid grid-cols-5 gap-2"> <div className="grid grid-cols-5 gap-2">
{recentColors.map((entry) => ( {recentColors.map((entry) => (
<button <div
key={entry.timestamp} key={entry.timestamp}
className="group relative aspect-square rounded-lg border-2 border-border hover:border-primary transition-all hover:scale-110 focus:outline-none focus:ring-2 focus:ring-ring" className="group relative aspect-square rounded-lg border-2 border-border hover:border-primary transition-all hover:scale-110 cursor-pointer"
style={{ backgroundColor: entry.color }} style={{ backgroundColor: entry.color }}
onClick={() => setColor(entry.color)} onClick={() => setColor(entry.color)}
title={entry.color} title={entry.color}
role="button"
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
setColor(entry.color);
}
}}
> >
<div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity bg-black/30 rounded-lg"> <div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity bg-black/30 rounded-lg">
<button <button
@@ -152,11 +159,12 @@ function PlaygroundContent() {
toast.success('Color removed from history'); toast.success('Color removed from history');
}} }}
className="p-1 bg-destructive rounded-full hover:bg-destructive/80" className="p-1 bg-destructive rounded-full hover:bg-destructive/80"
aria-label="Remove color"
> >
<X className="h-3 w-3 text-destructive-foreground" /> <X className="h-3 w-3 text-destructive-foreground" />
</button> </button>
</div> </div>
</button> </div>
))} ))}
</div> </div>
</div> </div>

View File

@@ -80,7 +80,7 @@ export function ColorInfo({ info, className }: ColorInfoProps) {
<div className="text-xs text-muted-foreground">Type</div> <div className="text-xs text-muted-foreground">Type</div>
<div className="text-sm font-medium">{info.is_light ? 'Light' : 'Dark'}</div> <div className="text-sm font-medium">{info.is_light ? 'Light' : 'Dark'}</div>
</div> </div>
{info.name && ( {info.name && typeof info.name === 'string' && (
<div className="space-y-1"> <div className="space-y-1">
<div className="text-xs text-muted-foreground">Named</div> <div className="text-xs text-muted-foreground">Named</div>
<div className="text-sm font-medium">{info.name}</div> <div className="text-sm font-medium">{info.name}</div>