fix: Blueprint catalog dark theme — match app-wide dark styling
Add dark: variants to all Blueprint field catalog and card components: - Modal: dark:bg-gray-900, borders dark:border-gray-700 - Sidebar: dark:bg-gray-800/50, active dark:bg-brand-950/40 - Field cards: dark:bg-gray-800/50 (inactive), dark:bg-brand-950/30 (active) - Type icons: dark:bg-gray-700 (inactive), dark:bg-brand-900/50 (active) - Toggle: dark:bg-gray-600 (off track) - Inputs: dark:bg-gray-800, dark:border-gray-600, dark:text-gray-100 - Labels/text: dark:text-gray-200/300/400/500 throughout - Custom field form: dark:bg-gray-800/50, dark:border-gray-600 Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -19,13 +19,13 @@ import type { CatalogField } from "~/lib/blueprint-field-catalog.js";
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
const INPUT_CLS =
|
const INPUT_CLS =
|
||||||
"px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500 text-sm";
|
"px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500 text-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder:text-gray-400 dark:placeholder:text-gray-500";
|
||||||
|
|
||||||
const BTN_PRIMARY =
|
const BTN_PRIMARY =
|
||||||
"px-4 py-2 bg-brand-600 text-white rounded-lg hover:bg-brand-700 text-sm font-medium disabled:opacity-50";
|
"px-4 py-2 bg-brand-600 text-white rounded-lg hover:bg-brand-700 text-sm font-medium disabled:opacity-50";
|
||||||
|
|
||||||
const BTN_SECONDARY =
|
const BTN_SECONDARY =
|
||||||
"px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 text-sm font-medium";
|
"px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-200 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 text-sm font-medium";
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Types
|
// Types
|
||||||
@@ -395,13 +395,13 @@ export function BlueprintFieldCatalog({
|
|||||||
className="fixed inset-0 bg-black/50 z-50 flex items-start justify-center overflow-y-auto py-8"
|
className="fixed inset-0 bg-black/50 z-50 flex items-start justify-center overflow-y-auto py-8"
|
||||||
onClick={handleBackdropClick}
|
onClick={handleBackdropClick}
|
||||||
>
|
>
|
||||||
<div className="bg-white rounded-xl shadow-2xl w-full max-w-4xl mx-4 flex flex-col max-h-[90vh]">
|
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-2xl w-full max-w-4xl mx-4 flex flex-col max-h-[90vh]">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between px-6 py-4 border-b border-gray-200 shrink-0">
|
<div className="flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700 shrink-0">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">
|
||||||
Configure Fields:{" "}
|
Configure Fields:{" "}
|
||||||
<span className="text-gray-600 font-normal">{blueprintName}</span>
|
<span className="text-gray-600 dark:text-gray-400 font-normal">{blueprintName}</span>
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-xs text-gray-400 mt-0.5">
|
<p className="text-xs text-gray-400 mt-0.5">
|
||||||
{enabledCount} field{enabledCount !== 1 ? "s" : ""} enabled
|
{enabledCount} field{enabledCount !== 1 ? "s" : ""} enabled
|
||||||
@@ -410,7 +410,7 @@ export function BlueprintFieldCatalog({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
className="text-gray-400 hover:text-gray-600 text-2xl leading-none"
|
className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 text-2xl leading-none"
|
||||||
aria-label="Close"
|
aria-label="Close"
|
||||||
>
|
>
|
||||||
x
|
x
|
||||||
@@ -418,7 +418,7 @@ export function BlueprintFieldCatalog({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Tabs */}
|
{/* Tabs */}
|
||||||
<div className="flex border-b border-gray-200 px-6 shrink-0">
|
<div className="flex border-b border-gray-200 dark:border-gray-700 px-6 shrink-0">
|
||||||
{(["fields", "presets"] as const).map((tab) => (
|
{(["fields", "presets"] as const).map((tab) => (
|
||||||
<button
|
<button
|
||||||
key={tab}
|
key={tab}
|
||||||
@@ -427,7 +427,7 @@ export function BlueprintFieldCatalog({
|
|||||||
className={`px-4 py-2.5 text-sm font-medium border-b-2 -mb-px transition-colors ${
|
className={`px-4 py-2.5 text-sm font-medium border-b-2 -mb-px transition-colors ${
|
||||||
activeTab === tab
|
activeTab === tab
|
||||||
? "border-brand-500 text-brand-600"
|
? "border-brand-500 text-brand-600"
|
||||||
: "border-transparent text-gray-500 hover:text-gray-700"
|
: "border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{tab === "fields" ? "Fields" : "Role Presets"}
|
{tab === "fields" ? "Fields" : "Role Presets"}
|
||||||
@@ -440,15 +440,15 @@ export function BlueprintFieldCatalog({
|
|||||||
{/* Search + category sidebar layout */}
|
{/* Search + category sidebar layout */}
|
||||||
<div className="flex flex-1 overflow-hidden">
|
<div className="flex flex-1 overflow-hidden">
|
||||||
{/* Category sidebar */}
|
{/* Category sidebar */}
|
||||||
<div className="w-48 shrink-0 border-r border-gray-200 bg-gray-50/50 overflow-y-auto hidden md:block">
|
<div className="w-48 shrink-0 border-r border-gray-200 dark:border-gray-700 bg-gray-50/50 dark:bg-gray-800/50 overflow-y-auto hidden md:block">
|
||||||
<nav className="py-2">
|
<nav className="py-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setActiveCategory(null)}
|
onClick={() => setActiveCategory(null)}
|
||||||
className={`w-full text-left px-4 py-2 text-sm transition-colors ${
|
className={`w-full text-left px-4 py-2 text-sm transition-colors ${
|
||||||
activeCategory === null
|
activeCategory === null
|
||||||
? "bg-brand-50 text-brand-700 font-medium"
|
? "bg-brand-50 dark:bg-brand-950/40 text-brand-700 dark:text-brand-300 font-medium"
|
||||||
: "text-gray-600 hover:bg-gray-100"
|
: "text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
All Fields
|
All Fields
|
||||||
@@ -491,7 +491,7 @@ export function BlueprintFieldCatalog({
|
|||||||
{/* Main content */}
|
{/* Main content */}
|
||||||
<div className="flex-1 flex flex-col overflow-hidden">
|
<div className="flex-1 flex flex-col overflow-hidden">
|
||||||
{/* Search bar */}
|
{/* Search bar */}
|
||||||
<div className="px-4 py-3 border-b border-gray-100 shrink-0">
|
<div className="px-4 py-3 border-b border-gray-100 dark:border-gray-700 shrink-0">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
@@ -527,7 +527,7 @@ export function BlueprintFieldCatalog({
|
|||||||
<span className="text-xs text-gray-400 transition-transform group-hover:text-gray-600">
|
<span className="text-xs text-gray-400 transition-transform group-hover:text-gray-600">
|
||||||
{isCollapsed ? "\u25B6" : "\u25BC"}
|
{isCollapsed ? "\u25B6" : "\u25BC"}
|
||||||
</span>
|
</span>
|
||||||
<h3 className="text-sm font-semibold text-gray-700 uppercase tracking-wider">
|
<h3 className="text-sm font-semibold text-gray-700 dark:text-gray-300 uppercase tracking-wider">
|
||||||
{cat.name}
|
{cat.name}
|
||||||
</h3>
|
</h3>
|
||||||
<span className="text-xs text-gray-400">
|
<span className="text-xs text-gray-400">
|
||||||
@@ -571,7 +571,7 @@ export function BlueprintFieldCatalog({
|
|||||||
? "\u25B6"
|
? "\u25B6"
|
||||||
: "\u25BC"}
|
: "\u25BC"}
|
||||||
</span>
|
</span>
|
||||||
<h3 className="text-sm font-semibold text-gray-700 uppercase tracking-wider">
|
<h3 className="text-sm font-semibold text-gray-700 dark:text-gray-300 uppercase tracking-wider">
|
||||||
Custom Fields
|
Custom Fields
|
||||||
</h3>
|
</h3>
|
||||||
<span className="text-xs text-gray-400">
|
<span className="text-xs text-gray-400">
|
||||||
@@ -618,7 +618,7 @@ export function BlueprintFieldCatalog({
|
|||||||
|
|
||||||
{/* Add custom field */}
|
{/* Add custom field */}
|
||||||
{showCustomForm ? (
|
{showCustomForm ? (
|
||||||
<div className="border border-dashed border-gray-300 rounded-lg p-4 space-y-3 bg-gray-50/50">
|
<div className="border border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-4 space-y-3 bg-gray-50/50 dark:bg-gray-800/50">
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
|
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<label className="text-xs font-medium text-gray-600">
|
<label className="text-xs font-medium text-gray-600">
|
||||||
@@ -727,7 +727,7 @@ export function BlueprintFieldCatalog({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Footer */}
|
{/* Footer */}
|
||||||
<div className="flex items-center justify-between gap-3 px-6 py-4 border-t border-gray-200 shrink-0">
|
<div className="flex items-center justify-between gap-3 px-6 py-4 border-t border-gray-200 dark:border-gray-700 shrink-0">
|
||||||
<span className="text-xs text-gray-400">
|
<span className="text-xs text-gray-400">
|
||||||
{enabledCount} field{enabledCount !== 1 ? "s" : ""} will be
|
{enabledCount} field{enabledCount !== 1 ? "s" : ""} will be
|
||||||
saved
|
saved
|
||||||
|
|||||||
@@ -83,8 +83,8 @@ export function FieldCard({ field, overrides, onChange }: FieldCardProps) {
|
|||||||
<div
|
<div
|
||||||
className={`border rounded-lg transition-all ${
|
className={`border rounded-lg transition-all ${
|
||||||
isActive
|
isActive
|
||||||
? "border-brand-300 bg-brand-50/40 shadow-sm"
|
? "border-brand-300 bg-brand-50/40 shadow-sm dark:border-brand-700 dark:bg-brand-950/30"
|
||||||
: "border-gray-200 bg-white"
|
: "border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800/50"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{/* Header row */}
|
{/* Header row */}
|
||||||
@@ -99,8 +99,8 @@ export function FieldCard({ field, overrides, onChange }: FieldCardProps) {
|
|||||||
<span
|
<span
|
||||||
className={`w-8 h-8 rounded-md flex items-center justify-center text-sm font-bold shrink-0 ${
|
className={`w-8 h-8 rounded-md flex items-center justify-center text-sm font-bold shrink-0 ${
|
||||||
isActive
|
isActive
|
||||||
? "bg-brand-100 text-brand-700"
|
? "bg-brand-100 text-brand-700 dark:bg-brand-900/50 dark:text-brand-300"
|
||||||
: "bg-gray-100 text-gray-400"
|
: "bg-gray-100 text-gray-400 dark:bg-gray-700 dark:text-gray-500"
|
||||||
}`}
|
}`}
|
||||||
title={TYPE_LABELS[field.type]}
|
title={TYPE_LABELS[field.type]}
|
||||||
>
|
>
|
||||||
@@ -112,16 +112,16 @@ export function FieldCard({ field, overrides, onChange }: FieldCardProps) {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span
|
<span
|
||||||
className={`font-medium text-sm truncate ${
|
className={`font-medium text-sm truncate ${
|
||||||
isActive ? "text-gray-900" : "text-gray-500"
|
isActive ? "text-gray-900 dark:text-gray-100" : "text-gray-500 dark:text-gray-400"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{field.label}
|
{field.label}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-xs text-gray-400 font-mono hidden sm:inline">
|
<span className="text-xs text-gray-400 dark:text-gray-500 font-mono hidden sm:inline">
|
||||||
{field.key}
|
{field.key}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-gray-400 truncate">{field.description}</p>
|
<p className="text-xs text-gray-400 dark:text-gray-500 truncate">{field.description}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Toggle switch */}
|
{/* Toggle switch */}
|
||||||
@@ -135,7 +135,7 @@ export function FieldCard({ field, overrides, onChange }: FieldCardProps) {
|
|||||||
handleToggle();
|
handleToggle();
|
||||||
}}
|
}}
|
||||||
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 ${
|
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 ${
|
||||||
isActive ? "bg-brand-600" : "bg-gray-300"
|
isActive ? "bg-brand-600" : "bg-gray-300 dark:bg-gray-600"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
@@ -151,7 +151,7 @@ export function FieldCard({ field, overrides, onChange }: FieldCardProps) {
|
|||||||
<div className="px-4 pb-4 pt-1 border-t border-brand-200/50 space-y-3">
|
<div className="px-4 pb-4 pt-1 border-t border-brand-200/50 space-y-3">
|
||||||
{/* Default value input */}
|
{/* Default value input */}
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<label className="text-xs font-medium text-gray-600">
|
<label className="text-xs font-medium text-gray-600 dark:text-gray-300">
|
||||||
Default Value
|
Default Value
|
||||||
</label>
|
</label>
|
||||||
<DefaultValueInput
|
<DefaultValueInput
|
||||||
@@ -164,7 +164,7 @@ export function FieldCard({ field, overrides, onChange }: FieldCardProps) {
|
|||||||
|
|
||||||
{/* Toggles row */}
|
{/* Toggles row */}
|
||||||
<div className="flex flex-wrap items-center gap-4">
|
<div className="flex flex-wrap items-center gap-4">
|
||||||
<label className="flex items-center gap-1.5 text-sm text-gray-700 cursor-pointer select-none">
|
<label className="flex items-center gap-1.5 text-sm text-gray-700 dark:text-gray-200 cursor-pointer select-none">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={overrides.required}
|
checked={overrides.required}
|
||||||
@@ -173,7 +173,7 @@ export function FieldCard({ field, overrides, onChange }: FieldCardProps) {
|
|||||||
/>
|
/>
|
||||||
Required
|
Required
|
||||||
</label>
|
</label>
|
||||||
<label className="flex items-center gap-1.5 text-sm text-gray-700 cursor-pointer select-none">
|
<label className="flex items-center gap-1.5 text-sm text-gray-700 dark:text-gray-200 cursor-pointer select-none">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={overrides.showInList}
|
checked={overrides.showInList}
|
||||||
@@ -186,7 +186,7 @@ export function FieldCard({ field, overrides, onChange }: FieldCardProps) {
|
|||||||
|
|
||||||
{/* Description override */}
|
{/* Description override */}
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<label className="text-xs font-medium text-gray-600">
|
<label className="text-xs font-medium text-gray-600 dark:text-gray-300">
|
||||||
Helper Text
|
Helper Text
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -221,7 +221,7 @@ function DefaultValueInput({
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case FieldType.BOOLEAN:
|
case FieldType.BOOLEAN:
|
||||||
return (
|
return (
|
||||||
<label className="flex items-center gap-2 text-sm text-gray-700 cursor-pointer select-none">
|
<label className="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-200 cursor-pointer select-none">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={Boolean(value)}
|
checked={Boolean(value)}
|
||||||
@@ -367,7 +367,7 @@ function MultiSelectDefaultInput({
|
|||||||
{options.map((opt) => (
|
{options.map((opt) => (
|
||||||
<label
|
<label
|
||||||
key={opt.value}
|
key={opt.value}
|
||||||
className="flex items-center gap-1.5 text-sm text-gray-700 cursor-pointer select-none"
|
className="flex items-center gap-1.5 text-sm text-gray-700 dark:text-gray-200 cursor-pointer select-none"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
|||||||
Reference in New Issue
Block a user