Initial commit
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
"use client";
|
||||
import { RotateCcw } from "lucide-react";
|
||||
import { useSettings } from "./SettingsProvider";
|
||||
|
||||
const DEFAULT_PRIMARY_HEX = "#4dc4d4";
|
||||
const DEFAULT_SECONDARY_HEX = "#b772f0";
|
||||
|
||||
export function AccentColorPickers() {
|
||||
const { settings, set } = useSettings();
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<ColorRow
|
||||
label="Primary Accent"
|
||||
description="Used for buttons, toggles, focus rings, and the cyan side of accent gradients."
|
||||
value={settings.accentPrimary}
|
||||
fallback={DEFAULT_PRIMARY_HEX}
|
||||
onChange={(v) => set("accentPrimary", v)}
|
||||
onReset={() => set("accentPrimary", "")}
|
||||
/>
|
||||
<ColorRow
|
||||
label="Secondary Accent"
|
||||
description="Used for the violet side of accent gradients, glows, and ambient page lighting."
|
||||
value={settings.accentSecondary}
|
||||
fallback={DEFAULT_SECONDARY_HEX}
|
||||
onChange={(v) => set("accentSecondary", v)}
|
||||
onReset={() => set("accentSecondary", "")}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ColorRow({
|
||||
label,
|
||||
description,
|
||||
value,
|
||||
fallback,
|
||||
onChange,
|
||||
onReset,
|
||||
}: {
|
||||
label: string;
|
||||
description?: string;
|
||||
value: string;
|
||||
fallback: string;
|
||||
onChange: (v: string) => void;
|
||||
onReset: () => void;
|
||||
}) {
|
||||
const isDefault = value === "";
|
||||
const display = value || fallback;
|
||||
|
||||
return (
|
||||
<div className="flex items-start justify-between gap-4 py-2">
|
||||
<div className="min-w-0">
|
||||
<div className="text-sm font-medium">{label}</div>
|
||||
{description && (
|
||||
<div className="text-xs text-[var(--color-fg-muted)] mt-0.5">{description}</div>
|
||||
)}
|
||||
<div className="text-[10px] font-mono uppercase tracking-wider text-[var(--color-fg-muted)] mt-1">
|
||||
{isDefault ? "default" : display}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 flex-shrink-0">
|
||||
<label
|
||||
className="relative w-9 h-9 rounded-lg border border-[var(--color-glass-border-strong)] bg-[var(--color-glass)] cursor-pointer overflow-hidden grid place-items-center hover:border-[color-mix(in_oklch,var(--color-cyan)_50%,var(--color-glass-border))] transition-colors"
|
||||
title={`Change ${label.toLowerCase()}`}
|
||||
>
|
||||
<span
|
||||
className="absolute inset-1 rounded-md"
|
||||
style={{ background: display }}
|
||||
aria-hidden
|
||||
/>
|
||||
<input
|
||||
type="color"
|
||||
value={display}
|
||||
onChange={(e) => onChange(e.target.value.toLowerCase())}
|
||||
className="absolute inset-0 opacity-0 cursor-pointer"
|
||||
aria-label={label}
|
||||
/>
|
||||
</label>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onReset}
|
||||
disabled={isDefault}
|
||||
aria-label={`Reset ${label.toLowerCase()}`}
|
||||
title="Reset to default"
|
||||
className="w-9 h-9 grid place-items-center rounded-lg border border-[var(--color-glass-border-strong)] bg-[var(--color-glass)] text-[var(--color-fg-dim)] hover:text-[var(--color-fg)] hover:border-[color-mix(in_oklch,var(--color-cyan)_50%,var(--color-glass-border))] transition-colors disabled:opacity-30 disabled:cursor-not-allowed disabled:hover:border-[var(--color-glass-border-strong)]"
|
||||
>
|
||||
<RotateCcw className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user