refactor: migrate remaining components to new design system

Migrates 38 files: tree-editor forms, session modals, step library,
common components, library views, tree preview, and misc UI to use
design tokens (bg-card, border-border, text-foreground, bg-accent,
bg-gradient-brand) replacing old monochrome patterns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-02-15 21:31:22 -05:00
parent 5e710fcffd
commit fe94f16b61
38 changed files with 384 additions and 384 deletions

View File

@@ -60,23 +60,23 @@ export function Modal({ isOpen, onClose, title, children, footer, size = 'md' }:
{/* Modal Content */} {/* Modal Content */}
<div <div
className={cn( className={cn(
'relative flex w-full flex-col border border-white/[0.06] bg-[#0a0a0a] shadow-lg', 'relative flex w-full flex-col border border-border bg-card shadow-lg',
'max-h-[100vh] rounded-t-2xl sm:max-h-[85vh] sm:rounded-2xl', 'max-h-[100vh] rounded-t-2xl sm:max-h-[85vh] sm:rounded-2xl',
'animate-scale-in', 'animate-scale-in',
sizeClasses[size] sizeClasses[size]
)} )}
> >
{/* Header - Fixed at top */} {/* Header - Fixed at top */}
<div className="flex flex-shrink-0 items-center justify-between border-b border-white/[0.06] px-4 py-3 sm:px-6 sm:py-4"> <div className="flex flex-shrink-0 items-center justify-between border-b border-border px-4 py-3 sm:px-6 sm:py-4">
<h2 id="modal-title" className="text-lg font-semibold text-white"> <h2 id="modal-title" className="text-lg font-semibold text-foreground">
{title} {title}
</h2> </h2>
<button <button
onClick={onClose} onClick={onClose}
className={cn( className={cn(
'rounded-md p-1.5 text-white/40 transition-colors sm:p-1', 'rounded-md p-1.5 text-muted-foreground transition-colors sm:p-1',
'hover:bg-white/10 hover:text-white', 'hover:bg-accent hover:text-foreground',
'focus:outline-none focus:ring-2 focus:ring-white/20' 'focus:outline-none focus:ring-2 focus:ring-primary/20'
)} )}
aria-label="Close modal" aria-label="Close modal"
> >
@@ -91,7 +91,7 @@ export function Modal({ isOpen, onClose, title, children, footer, size = 'md' }:
{/* Footer - Fixed at bottom */} {/* Footer - Fixed at bottom */}
{footer && ( {footer && (
<div className="flex-shrink-0 border-t border-white/[0.06] px-4 py-3 sm:px-6 sm:py-4"> <div className="flex-shrink-0 border-t border-border px-4 py-3 sm:px-6 sm:py-4">
{footer} {footer}
</div> </div>
)} )}

View File

@@ -2,8 +2,8 @@ export function PageLoader() {
return ( return (
<div className="flex h-screen items-center justify-center bg-black"> <div className="flex h-screen items-center justify-center bg-black">
<div className="flex flex-col items-center gap-4"> <div className="flex flex-col items-center gap-4">
<div className="h-12 w-12 animate-spin rounded-full border-4 border-white/20 border-t-white" /> <div className="h-12 w-12 animate-spin rounded-full border-4 border-border border-t-foreground" />
<p className="text-sm text-white/40">Loading...</p> <p className="text-sm text-muted-foreground">Loading...</p>
</div> </div>
</div> </div>
) )

View File

@@ -19,7 +19,7 @@ export function PasswordInput({ className, ...props }: PasswordInputProps) {
<button <button
type="button" type="button"
onClick={() => setVisible((v) => !v)} onClick={() => setVisible((v) => !v)}
className="absolute right-2 top-1/2 -translate-y-1/2 rounded p-1 text-white/40 hover:bg-white/10 hover:text-white" className="absolute right-2 top-1/2 -translate-y-1/2 rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
tabIndex={-1} tabIndex={-1}
title={visible ? 'Hide password' : 'Show password'} title={visible ? 'Hide password' : 'Show password'}
> >

View File

@@ -19,17 +19,17 @@ export function RouteError() {
return ( return (
<div className="flex min-h-screen flex-col items-center justify-center bg-black p-8"> <div className="flex min-h-screen flex-col items-center justify-center bg-black p-8">
<div className="max-w-md text-center"> <div className="max-w-md text-center">
<h1 className="mb-2 text-4xl font-bold text-white">Oops!</h1> <h1 className="mb-2 text-4xl font-bold text-foreground">Oops!</h1>
<h2 className="mb-2 text-xl font-semibold text-red-400">{errorMessage}</h2> <h2 className="mb-2 text-xl font-semibold text-red-400">{errorMessage}</h2>
{errorDetails && ( {errorDetails && (
<p className="mb-4 text-white/70">{errorDetails}</p> <p className="mb-4 text-muted-foreground">{errorDetails}</p>
)} )}
<div className="flex justify-center gap-4"> <div className="flex justify-center gap-4">
<button <button
onClick={() => navigate(-1)} onClick={() => navigate(-1)}
className={cn( className={cn(
'rounded-xl border border-white/10 px-4 py-2 text-sm font-medium text-white/60', 'rounded-xl border border-border px-4 py-2 text-sm font-medium text-muted-foreground',
'hover:bg-white/10 hover:text-white' 'hover:bg-accent hover:text-foreground'
)} )}
> >
Go Back Go Back
@@ -37,8 +37,8 @@ export function RouteError() {
<button <button
onClick={() => navigate('/trees')} onClick={() => navigate('/trees')}
className={cn( className={cn(
'rounded-xl bg-white px-4 py-2 text-sm font-medium text-black', 'rounded-xl bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20',
'hover:bg-white/90' 'hover:opacity-90'
)} )}
> >
Go Home Go Home

View File

@@ -48,14 +48,14 @@ export function StarRating({
sizeClasses[size], sizeClasses[size],
star <= value star <= value
? 'fill-yellow-400 text-yellow-400' ? 'fill-yellow-400 text-yellow-400'
: 'fill-none text-white/30', : 'fill-none text-muted-foreground',
!readonly && 'hover:text-yellow-300' !readonly && 'hover:text-yellow-300'
)} )}
/> />
</button> </button>
))} ))}
{showCount && ( {showCount && (
<span className="ml-1 text-sm text-white/40"> <span className="ml-1 text-sm text-muted-foreground">
({value}/5) ({value}/5)
</span> </span>
)} )}

View File

@@ -37,8 +37,8 @@ export function TagBadges({
'rounded-full transition-colors', 'rounded-full transition-colors',
size === 'sm' ? 'px-2 py-0.5 text-xs' : 'px-2.5 py-1 text-sm', size === 'sm' ? 'px-2 py-0.5 text-xs' : 'px-2.5 py-1 text-sm',
variant === 'default' variant === 'default'
? 'bg-white/10 text-white/70 hover:bg-white/15' ? 'bg-accent text-muted-foreground hover:bg-accent'
: 'bg-white/5 text-white/40 hover:bg-white/10', : 'bg-accent/50 text-muted-foreground hover:bg-accent',
!onTagClick && 'cursor-default' !onTagClick && 'cursor-default'
)} )}
> >
@@ -50,7 +50,7 @@ export function TagBadges({
className={cn( className={cn(
'rounded-full', 'rounded-full',
size === 'sm' ? 'px-2 py-0.5 text-xs' : 'px-2.5 py-1 text-sm', size === 'sm' ? 'px-2 py-0.5 text-xs' : 'px-2.5 py-1 text-sm',
'bg-white/5 text-white/40' 'bg-accent/50 text-muted-foreground'
)} )}
title={tags.slice(maxVisible).join(', ')} title={tags.slice(maxVisible).join(', ')}
> >

View File

@@ -123,10 +123,10 @@ export function TagInput({
<div <div
className={cn( className={cn(
'flex flex-wrap gap-1.5 rounded-xl border px-2 py-1.5', 'flex flex-wrap gap-1.5 rounded-xl border px-2 py-1.5',
'bg-black/50 text-white', 'bg-card text-foreground',
'focus-within:border-white/30 focus-within:ring-1 focus-within:ring-white/20', 'focus-within:border-primary focus-within:ring-1 focus-within:ring-primary/20',
disabled ? 'cursor-not-allowed opacity-50' : '', disabled ? 'cursor-not-allowed opacity-50' : '',
'border-white/10' 'border-border'
)} )}
onClick={() => inputRef.current?.focus()} onClick={() => inputRef.current?.focus()}
> >
@@ -136,7 +136,7 @@ export function TagInput({
key={tag} key={tag}
className={cn( className={cn(
'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs', 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs',
'bg-white/10 text-white/70' 'bg-accent text-muted-foreground'
)} )}
> >
{tag} {tag}
@@ -147,7 +147,7 @@ export function TagInput({
e.stopPropagation() e.stopPropagation()
removeTag(tag) removeTag(tag)
}} }}
className="rounded-full p-0.5 hover:bg-white/20" className="rounded-full p-0.5 hover:bg-accent"
> >
<X className="h-3 w-3" /> <X className="h-3 w-3" />
</button> </button>
@@ -184,8 +184,8 @@ export function TagInput({
placeholder={tags.length === 0 ? placeholder : ''} placeholder={tags.length === 0 ? placeholder : ''}
disabled={disabled} disabled={disabled}
className={cn( className={cn(
'flex-1 min-w-[80px] border-0 bg-transparent px-1 py-0.5 text-sm text-white', 'flex-1 min-w-[80px] border-0 bg-transparent px-1 py-0.5 text-sm text-foreground',
'placeholder:text-white/40', 'placeholder:text-muted-foreground',
'focus:outline-none focus:ring-0' 'focus:outline-none focus:ring-0'
)} )}
/> />
@@ -196,8 +196,8 @@ export function TagInput({
{showSuggestions && suggestions.length > 0 && ( {showSuggestions && suggestions.length > 0 && (
<div <div
className={cn( className={cn(
'absolute z-10 mt-1 w-full rounded-xl border border-white/[0.06]', 'absolute z-10 mt-1 w-full rounded-xl border border-border',
'bg-[#0a0a0a] shadow-lg' 'bg-card shadow-lg'
)} )}
> >
{suggestions.map((suggestion, index) => ( {suggestions.map((suggestion, index) => (
@@ -206,13 +206,13 @@ export function TagInput({
type="button" type="button"
onClick={() => addTag(suggestion.name)} onClick={() => addTag(suggestion.name)}
className={cn( className={cn(
'flex w-full items-center justify-between px-3 py-2 text-sm text-white/70', 'flex w-full items-center justify-between px-3 py-2 text-sm text-muted-foreground',
'hover:bg-white/10', 'hover:bg-accent',
index === selectedIndex && 'bg-white/10' index === selectedIndex && 'bg-accent'
)} )}
> >
<span>{suggestion.name}</span> <span>{suggestion.name}</span>
<span className="text-xs text-white/40"> <span className="text-xs text-muted-foreground">
{suggestion.usage_count} trees {suggestion.usage_count} trees
</span> </span>
</button> </button>
@@ -225,8 +225,8 @@ export function TagInput({
type="button" type="button"
onClick={() => addTag(inputValue)} onClick={() => addTag(inputValue)}
className={cn( className={cn(
'flex w-full items-center gap-2 border-t border-white/[0.06] px-3 py-2 text-sm', 'flex w-full items-center gap-2 border-t border-border px-3 py-2 text-sm',
'hover:bg-white/10 text-white' 'hover:bg-accent text-foreground'
)} )}
> >
<Plus className="h-4 w-4" /> <Plus className="h-4 w-4" />
@@ -237,7 +237,7 @@ export function TagInput({
)} )}
{/* Helper text */} {/* Helper text */}
<p className="mt-1 text-xs text-white/40"> <p className="mt-1 text-xs text-muted-foreground">
{tags.length}/{maxTags} tags. Press Enter, Tab, comma, or semicolon to add. {tags.length}/{maxTags} tags. Press Enter, Tab, comma, or semicolon to add.
</p> </p>
</div> </div>

View File

@@ -15,7 +15,7 @@ export function ProtectedRoute({ requiredRole, children }: ProtectedRouteProps)
if (isLoading) { if (isLoading) {
return ( return (
<div className="flex h-screen items-center justify-center"> <div className="flex h-screen items-center justify-center">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-white/20 border-t-white" /> <div className="h-8 w-8 animate-spin rounded-full border-4 border-border border-t-foreground" />
</div> </div>
) )
} }

View File

@@ -89,8 +89,8 @@ export function AddToFolderMenu({ treeId, onFolderCreated }: AddToFolderMenuProp
setIsOpen(!isOpen) setIsOpen(!isOpen)
}} }}
className={cn( className={cn(
'rounded-md border border-white/10 p-1.5 text-white/60', 'rounded-md border border-border p-1.5 text-muted-foreground',
'hover:bg-white/10 hover:text-white' 'hover:bg-accent hover:text-foreground'
)} )}
title="Add to folder" title="Add to folder"
aria-label="Add to folder" aria-label="Add to folder"
@@ -101,14 +101,14 @@ export function AddToFolderMenu({ treeId, onFolderCreated }: AddToFolderMenuProp
{isOpen && ( {isOpen && (
<div <div
className={cn( className={cn(
'absolute right-0 top-full z-20 mt-1 w-48 rounded-md border border-white/10', 'absolute right-0 top-full z-20 mt-1 w-48 rounded-md border border-border',
'bg-black/90 backdrop-blur-sm py-1 shadow-lg' 'bg-card backdrop-blur-sm py-1 shadow-lg'
)} )}
> >
{isLoading ? ( {isLoading ? (
<div className="px-3 py-2 text-sm text-white/40">Loading...</div> <div className="px-3 py-2 text-sm text-muted-foreground">Loading...</div>
) : folders.length === 0 ? ( ) : folders.length === 0 ? (
<div className="px-3 py-2 text-sm text-white/40">No folders yet</div> <div className="px-3 py-2 text-sm text-muted-foreground">No folders yet</div>
) : ( ) : (
folders.map((folder) => ( folders.map((folder) => (
<button <button
@@ -117,7 +117,7 @@ export function AddToFolderMenu({ treeId, onFolderCreated }: AddToFolderMenuProp
e.stopPropagation() e.stopPropagation()
toggleFolder(folder.id) toggleFolder(folder.id)
}} }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-white/70 hover:bg-white/[0.06] hover:text-white" className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<div <div
className="h-3 w-3 rounded-sm" className="h-3 w-3 rounded-sm"
@@ -125,13 +125,13 @@ export function AddToFolderMenu({ treeId, onFolderCreated }: AddToFolderMenuProp
/> />
<span className="flex-1 truncate text-left">{folder.name}</span> <span className="flex-1 truncate text-left">{folder.name}</span>
{treeFolderIds.has(folder.id) && ( {treeFolderIds.has(folder.id) && (
<Check className="h-4 w-4 text-white" /> <Check className="h-4 w-4 text-foreground" />
)} )}
</button> </button>
)) ))
)} )}
<div className="border-t border-white/10 my-1" /> <div className="border-t border-border my-1" />
<button <button
onClick={(e) => { onClick={(e) => {
@@ -139,7 +139,7 @@ export function AddToFolderMenu({ treeId, onFolderCreated }: AddToFolderMenuProp
setIsOpen(false) setIsOpen(false)
onFolderCreated?.() onFolderCreated?.()
}} }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-white/70 hover:bg-white/[0.06] hover:text-white" className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<Plus className="h-4 w-4" /> <Plus className="h-4 w-4" />
Create new folder Create new folder

View File

@@ -113,8 +113,8 @@ function FolderItem({
onClick={() => onFolderSelect(folder.id)} onClick={() => onFolderSelect(folder.id)}
className={cn( className={cn(
'flex w-full items-center gap-1 rounded-md py-1.5 text-sm', 'flex w-full items-center gap-1 rounded-md py-1.5 text-sm',
'transition-colors hover:bg-white/[0.06]', 'transition-colors hover:bg-accent',
selectedFolderId === folder.id && 'bg-white/10 text-white font-medium' selectedFolderId === folder.id && 'bg-accent text-foreground font-medium'
)} )}
style={{ paddingLeft: `${8 + depth * 16}px`, paddingRight: '8px' }} style={{ paddingLeft: `${8 + depth * 16}px`, paddingRight: '8px' }}
> >
@@ -125,7 +125,7 @@ function FolderItem({
e.stopPropagation() e.stopPropagation()
onToggleExpand(folder.id) onToggleExpand(folder.id)
}} }}
className="shrink-0 p-0.5 hover:bg-white/[0.06] rounded" className="shrink-0 p-0.5 hover:bg-accent rounded"
> >
{isExpanded ? ( {isExpanded ? (
<ChevronDown className="h-3 w-3" /> <ChevronDown className="h-3 w-3" />
@@ -138,7 +138,7 @@ function FolderItem({
)} )}
<Folder className="h-4 w-4 shrink-0" style={{ color: folder.color }} /> <Folder className="h-4 w-4 shrink-0" style={{ color: folder.color }} />
<span className="flex-1 truncate text-left">{folder.name}</span> <span className="flex-1 truncate text-left">{folder.name}</span>
<span className="text-xs text-white/40 group-hover:hidden">{folder.tree_count}</span> <span className="text-xs text-muted-foreground group-hover:hidden">{folder.tree_count}</span>
</button> </button>
{/* Folder menu button - replaces tree count on hover */} {/* Folder menu button - replaces tree count on hover */}
@@ -150,7 +150,7 @@ function FolderItem({
className={cn( className={cn(
'absolute right-1 top-1/2 -translate-y-1/2 rounded p-1', 'absolute right-1 top-1/2 -translate-y-1/2 rounded p-1',
'hidden group-hover:block', 'hidden group-hover:block',
'hover:bg-white/[0.06]' 'hover:bg-accent'
)} )}
> >
<MoreVertical className="h-3 w-3" /> <MoreVertical className="h-3 w-3" />
@@ -160,8 +160,8 @@ function FolderItem({
{menuOpenId === folder.id && ( {menuOpenId === folder.id && (
<div <div
className={cn( className={cn(
'absolute right-0 top-full z-10 mt-1 w-40 rounded-md border border-white/10', 'absolute right-0 top-full z-10 mt-1 w-40 rounded-md border border-border',
'bg-black/90 backdrop-blur-sm py-1 shadow-lg' 'bg-card backdrop-blur-sm py-1 shadow-lg'
)} )}
> >
<button <button
@@ -170,7 +170,7 @@ function FolderItem({
onEditFolder(folder) onEditFolder(folder)
onMenuToggle(null) onMenuToggle(null)
}} }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-white/70 hover:bg-white/[0.06] hover:text-white" className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<Pencil className="h-3 w-3" /> <Pencil className="h-3 w-3" />
Edit Edit
@@ -182,7 +182,7 @@ function FolderItem({
onAddSubfolder(folder.id) onAddSubfolder(folder.id)
onMenuToggle(null) onMenuToggle(null)
}} }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-white/70 hover:bg-white/[0.06] hover:text-white" className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<FolderPlus className="h-3 w-3" /> <FolderPlus className="h-3 w-3" />
Add Subfolder Add Subfolder
@@ -362,7 +362,7 @@ export function FolderSidebar({
/> />
)} )}
<div className={cn( <div className={cn(
'w-56 shrink-0 border-r border-white/[0.06] bg-transparent', 'w-56 shrink-0 border-r border-border bg-transparent',
'hidden md:block', 'hidden md:block',
mobileOpen && 'fixed inset-y-0 left-0 z-50 block animate-slide-in-left md:relative md:animate-none' mobileOpen && 'fixed inset-y-0 left-0 z-50 block animate-slide-in-left md:relative md:animate-none'
)}> )}>
@@ -370,10 +370,10 @@ export function FolderSidebar({
{/* Mobile close button */} {/* Mobile close button */}
{mobileOpen && ( {mobileOpen && (
<div className="mb-3 flex items-center justify-between md:hidden"> <div className="mb-3 flex items-center justify-between md:hidden">
<span className="text-sm font-medium text-white">Folders</span> <span className="text-sm font-medium text-foreground">Folders</span>
<button <button
onClick={onMobileClose} onClick={onMobileClose}
className="rounded-md p-1.5 text-white/40 hover:bg-white/[0.06]" className="rounded-md p-1.5 text-muted-foreground hover:bg-accent"
aria-label="Close folders" aria-label="Close folders"
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
@@ -382,7 +382,7 @@ export function FolderSidebar({
)} )}
<button <button
onClick={() => setIsExpanded(!isExpanded)} onClick={() => setIsExpanded(!isExpanded)}
className="flex w-full items-center gap-2 text-sm font-medium text-white" className="flex w-full items-center gap-2 text-sm font-medium text-foreground"
> >
{isExpanded ? ( {isExpanded ? (
<ChevronDown className="h-4 w-4" /> <ChevronDown className="h-4 w-4" />
@@ -399,8 +399,8 @@ export function FolderSidebar({
onClick={() => onFolderSelect(null)} onClick={() => onFolderSelect(null)}
className={cn( className={cn(
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm', 'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm',
'transition-colors hover:bg-white/[0.06]', 'transition-colors hover:bg-accent',
selectedFolderId === null && 'bg-white/10 text-white font-medium' selectedFolderId === null && 'bg-accent text-foreground font-medium'
)} )}
> >
<Folder className="h-4 w-4" /> <Folder className="h-4 w-4" />
@@ -409,7 +409,7 @@ export function FolderSidebar({
{/* Loading state */} {/* Loading state */}
{isLoading ? ( {isLoading ? (
<div className="px-2 py-1.5 text-sm text-white/40">Loading...</div> <div className="px-2 py-1.5 text-sm text-muted-foreground">Loading...</div>
) : ( ) : (
<> <>
{/* User folders (hierarchical) */} {/* User folders (hierarchical) */}
@@ -439,7 +439,7 @@ export function FolderSidebar({
onClick={() => onCreateFolder(null)} onClick={() => onCreateFolder(null)}
className={cn( className={cn(
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm', 'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm',
'text-white/50 transition-colors hover:bg-white/[0.06] hover:text-white' 'text-muted-foreground transition-colors hover:bg-accent hover:text-foreground'
)} )}
> >
<Plus className="h-4 w-4" /> <Plus className="h-4 w-4" />
@@ -454,8 +454,8 @@ export function FolderSidebar({
{contextMenu && ( {contextMenu && (
<div <div
className={cn( className={cn(
'fixed z-50 w-44 rounded-md border border-white/10', 'fixed z-50 w-44 rounded-md border border-border',
'bg-black/90 backdrop-blur-sm py-1 shadow-lg' 'bg-card backdrop-blur-sm py-1 shadow-lg'
)} )}
style={{ left: contextMenu.x, top: contextMenu.y }} style={{ left: contextMenu.x, top: contextMenu.y }}
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
@@ -465,7 +465,7 @@ export function FolderSidebar({
onEditFolder(contextMenu.folder) onEditFolder(contextMenu.folder)
closeContextMenu() closeContextMenu()
}} }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-white/70 hover:bg-white/[0.06] hover:text-white" className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<Pencil className="h-3 w-3" /> <Pencil className="h-3 w-3" />
Edit Edit
@@ -476,7 +476,7 @@ export function FolderSidebar({
handleAddSubfolder(contextMenu.folder.id) handleAddSubfolder(contextMenu.folder.id)
closeContextMenu() closeContextMenu()
}} }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-white/70 hover:bg-white/[0.06] hover:text-white" className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<FolderPlus className="h-3 w-3" /> <FolderPlus className="h-3 w-3" />
Add Subfolder Add Subfolder

View File

@@ -21,7 +21,7 @@ const sortOptions: { value: SortBy; label: string }[] = [
export function SortDropdown({ value, onChange, className }: SortDropdownProps) { export function SortDropdown({ value, onChange, className }: SortDropdownProps) {
return ( return (
<div className={cn('relative inline-flex items-center', className)}> <div className={cn('relative inline-flex items-center', className)}>
<span className="mr-2 flex items-center gap-1.5 text-sm text-white/40"> <span className="mr-2 flex items-center gap-1.5 text-sm text-muted-foreground">
<ArrowUpDown className="h-4 w-4" /> <ArrowUpDown className="h-4 w-4" />
<span className="hidden sm:inline">Sort:</span> <span className="hidden sm:inline">Sort:</span>
</span> </span>
@@ -29,8 +29,8 @@ export function SortDropdown({ value, onChange, className }: SortDropdownProps)
value={value} value={value}
onChange={(e) => onChange(e.target.value as SortBy)} onChange={(e) => onChange(e.target.value as SortBy)}
className={cn( className={cn(
'rounded-md border border-white/10 bg-black/50 px-3 py-1.5 text-sm', 'rounded-md border border-border bg-card px-3 py-1.5 text-sm',
'text-white focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20' 'text-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20'
)} )}
> >
{sortOptions.map((option) => ( {sortOptions.map((option) => (

View File

@@ -70,12 +70,12 @@ export function TreeTableView({
} }
return ( return (
<div className="overflow-x-auto rounded-2xl border border-white/[0.06]"> <div className="overflow-x-auto rounded-2xl border border-border">
<table className="w-full"> <table className="w-full">
<thead className="bg-white/[0.02] sticky top-0 z-10"> <thead className="bg-accent/50 sticky top-0 z-10">
<tr className="border-b border-white/[0.06]"> <tr className="border-b border-border">
<th <th
className="px-4 py-3 text-left text-sm font-medium text-white/50 cursor-pointer hover:text-white" className="px-4 py-3 text-left text-sm font-medium text-muted-foreground cursor-pointer hover:text-foreground"
onClick={() => handleSort('name')} onClick={() => handleSort('name')}
> >
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
@@ -83,11 +83,11 @@ export function TreeTableView({
{getSortIcon('name')} {getSortIcon('name')}
</div> </div>
</th> </th>
<th className="hidden md:table-cell px-4 py-3 text-left text-sm font-medium text-white/50"> <th className="hidden md:table-cell px-4 py-3 text-left text-sm font-medium text-muted-foreground">
Description Description
</th> </th>
<th <th
className="hidden lg:table-cell px-4 py-3 text-left text-sm font-medium text-white/50 cursor-pointer hover:text-white" className="hidden lg:table-cell px-4 py-3 text-left text-sm font-medium text-muted-foreground cursor-pointer hover:text-foreground"
onClick={() => handleSort('category')} onClick={() => handleSort('category')}
> >
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
@@ -95,11 +95,11 @@ export function TreeTableView({
{getSortIcon('category')} {getSortIcon('category')}
</div> </div>
</th> </th>
<th className="hidden xl:table-cell px-4 py-3 text-left text-sm font-medium text-white/50"> <th className="hidden xl:table-cell px-4 py-3 text-left text-sm font-medium text-muted-foreground">
Tags Tags
</th> </th>
<th <th
className="hidden sm:table-cell px-4 py-3 text-center text-sm font-medium text-white/50 cursor-pointer hover:text-white" className="hidden sm:table-cell px-4 py-3 text-center text-sm font-medium text-muted-foreground cursor-pointer hover:text-foreground"
onClick={() => handleSort('version')} onClick={() => handleSort('version')}
> >
<div className="flex items-center justify-center gap-1"> <div className="flex items-center justify-center gap-1">
@@ -108,7 +108,7 @@ export function TreeTableView({
</div> </div>
</th> </th>
<th <th
className="hidden sm:table-cell px-4 py-3 text-center text-sm font-medium text-white/50 cursor-pointer hover:text-white" className="hidden sm:table-cell px-4 py-3 text-center text-sm font-medium text-muted-foreground cursor-pointer hover:text-foreground"
onClick={() => handleSort('usage')} onClick={() => handleSort('usage')}
> >
<div className="flex items-center justify-center gap-1"> <div className="flex items-center justify-center gap-1">
@@ -117,7 +117,7 @@ export function TreeTableView({
</div> </div>
</th> </th>
<th <th
className="hidden md:table-cell px-4 py-3 text-left text-sm font-medium text-white/50 cursor-pointer hover:text-white" className="hidden md:table-cell px-4 py-3 text-left text-sm font-medium text-muted-foreground cursor-pointer hover:text-foreground"
onClick={() => handleSort('updated')} onClick={() => handleSort('updated')}
> >
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
@@ -125,17 +125,17 @@ export function TreeTableView({
{getSortIcon('updated')} {getSortIcon('updated')}
</div> </div>
</th> </th>
<th className="px-4 py-3 text-right text-sm font-medium text-white/50"> <th className="px-4 py-3 text-right text-sm font-medium text-muted-foreground">
Actions Actions
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody className="bg-transparent"> <tbody className="bg-transparent">
{trees.map((tree) => ( {trees.map((tree) => (
<tr key={tree.id} className="border-b border-white/[0.06] last:border-0 hover:bg-white/[0.04]"> <tr key={tree.id} className="border-b border-border last:border-0 hover:bg-accent/50">
<td className="px-4 py-3"> <td className="px-4 py-3">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="font-medium text-white truncate max-w-[200px]"> <span className="font-medium text-foreground truncate max-w-[200px]">
{tree.name} {tree.name}
</span> </span>
{tree.status === 'draft' && ( {tree.status === 'draft' && (
@@ -146,23 +146,23 @@ export function TreeTableView({
)} )}
{tree.is_public ? ( {tree.is_public ? (
<span title="Public tree"> <span title="Public tree">
<Globe className="h-3.5 w-3.5 text-white/40 flex-shrink-0" /> <Globe className="h-3.5 w-3.5 text-muted-foreground flex-shrink-0" />
</span> </span>
) : ( ) : (
<span title="Private tree"> <span title="Private tree">
<Lock className="h-3.5 w-3.5 text-white/40 flex-shrink-0" /> <Lock className="h-3.5 w-3.5 text-muted-foreground flex-shrink-0" />
</span> </span>
)} )}
</div> </div>
</td> </td>
<td className="hidden md:table-cell px-4 py-3 text-sm text-white/70"> <td className="hidden md:table-cell px-4 py-3 text-sm text-muted-foreground">
<span className="truncate block max-w-[250px]"> <span className="truncate block max-w-[250px]">
{tree.description || 'No description'} {tree.description || 'No description'}
</span> </span>
</td> </td>
<td className="hidden lg:table-cell px-4 py-3"> <td className="hidden lg:table-cell px-4 py-3">
{tree.category_info && ( {tree.category_info && (
<span className="inline-block rounded-full bg-white/10 px-2 py-0.5 text-xs text-white/70"> <span className="inline-block rounded-full bg-accent px-2 py-0.5 text-xs text-muted-foreground">
{tree.category_info.name} {tree.category_info.name}
</span> </span>
)} )}
@@ -172,13 +172,13 @@ export function TreeTableView({
<TagBadges tags={tree.tags} maxVisible={2} onTagClick={onTagClick} /> <TagBadges tags={tree.tags} maxVisible={2} onTagClick={onTagClick} />
)} )}
</td> </td>
<td className="hidden sm:table-cell px-4 py-3 text-center text-sm text-white/70"> <td className="hidden sm:table-cell px-4 py-3 text-center text-sm text-muted-foreground">
v{tree.version} v{tree.version}
</td> </td>
<td className="hidden sm:table-cell px-4 py-3 text-center text-sm text-white/70"> <td className="hidden sm:table-cell px-4 py-3 text-center text-sm text-muted-foreground">
{tree.usage_count} {tree.usage_count}
</td> </td>
<td className="hidden md:table-cell px-4 py-3 text-sm text-white/70"> <td className="hidden md:table-cell px-4 py-3 text-sm text-muted-foreground">
{formatDate(tree.updated_at)} {formatDate(tree.updated_at)}
</td> </td>
<td className="px-4 py-3"> <td className="px-4 py-3">
@@ -189,8 +189,8 @@ export function TreeTableView({
type="button" type="button"
onClick={() => onForkTree(tree.id)} onClick={() => onForkTree(tree.id)}
className={cn( className={cn(
'rounded-md border border-white/10 p-1.5 text-white/60', 'rounded-md border border-border p-1.5 text-muted-foreground',
'hover:bg-white/10 hover:text-white' 'hover:bg-accent hover:text-foreground'
)} )}
title="Fork tree" title="Fork tree"
aria-label="Fork tree" aria-label="Fork tree"
@@ -203,8 +203,8 @@ export function TreeTableView({
<Link <Link
to={`/trees/${tree.id}/edit`} to={`/trees/${tree.id}/edit`}
className={cn( className={cn(
'rounded-md border border-white/10 p-1.5 text-white/60', 'rounded-md border border-border p-1.5 text-muted-foreground',
'hover:bg-white/10 hover:text-white' 'hover:bg-accent hover:text-foreground'
)} )}
title="Edit tree" title="Edit tree"
aria-label="Edit tree" aria-label="Edit tree"
@@ -215,7 +215,7 @@ export function TreeTableView({
type="button" type="button"
onClick={() => onDeleteTree(tree)} onClick={() => onDeleteTree(tree)}
className={cn( className={cn(
'rounded-md border border-white/10 p-1.5 text-white/60', 'rounded-md border border-border p-1.5 text-muted-foreground',
'hover:bg-red-500/20 hover:text-red-400' 'hover:bg-red-500/20 hover:text-red-400'
)} )}
title="Delete tree" title="Delete tree"
@@ -229,8 +229,8 @@ export function TreeTableView({
type="button" type="button"
onClick={() => onStartSession(tree.id, tree.tree_type)} onClick={() => onStartSession(tree.id, tree.tree_type)}
className={cn( className={cn(
'rounded-md bg-white px-3 py-1.5 text-xs font-medium text-black', 'rounded-md bg-gradient-brand px-3 py-1.5 text-xs font-medium text-white shadow-lg shadow-primary/20',
'hover:bg-white/90 whitespace-nowrap' 'hover:opacity-90 whitespace-nowrap'
)} )}
> >
Start Start

View File

@@ -11,15 +11,15 @@ interface ViewToggleProps {
export function ViewToggle({ view, onChange, className }: ViewToggleProps) { export function ViewToggle({ view, onChange, className }: ViewToggleProps) {
return ( return (
<div className={cn('flex items-center gap-1 rounded-md border border-white/10 p-1', className)}> <div className={cn('flex items-center gap-1 rounded-md border border-border p-1', className)}>
<button <button
type="button" type="button"
onClick={() => onChange('grid')} onClick={() => onChange('grid')}
className={cn( className={cn(
'rounded p-1.5 transition-colors', 'rounded p-1.5 transition-colors',
view === 'grid' view === 'grid'
? 'bg-white/10 text-white border-white/20' ? 'bg-accent text-foreground border-border'
: 'text-white/50 hover:bg-white/[0.06] hover:text-white' : 'text-muted-foreground hover:bg-accent hover:text-foreground'
)} )}
title="Grid view" title="Grid view"
aria-label="Grid view" aria-label="Grid view"
@@ -32,8 +32,8 @@ export function ViewToggle({ view, onChange, className }: ViewToggleProps) {
className={cn( className={cn(
'rounded p-1.5 transition-colors', 'rounded p-1.5 transition-colors',
view === 'list' view === 'list'
? 'bg-white/10 text-white border-white/20' ? 'bg-accent text-foreground border-border'
: 'text-white/50 hover:bg-white/[0.06] hover:text-white' : 'text-muted-foreground hover:bg-accent hover:text-foreground'
)} )}
title="List view" title="List view"
aria-label="List view" aria-label="List view"
@@ -46,8 +46,8 @@ export function ViewToggle({ view, onChange, className }: ViewToggleProps) {
className={cn( className={cn(
'rounded p-1.5 transition-colors', 'rounded p-1.5 transition-colors',
view === 'table' view === 'table'
? 'bg-white/10 text-white border-white/20' ? 'bg-accent text-foreground border-border'
: 'text-white/50 hover:bg-white/[0.06] hover:text-white' : 'text-muted-foreground hover:bg-accent hover:text-foreground'
)} )}
title="Table view" title="Table view"
aria-label="Table view" aria-label="Table view"

View File

@@ -60,7 +60,7 @@ export function StepList() {
return ( return (
<div <div
key={step.id} key={step.id}
className="flex items-center gap-2 rounded-lg border border-dashed border-border bg-white/[0.02] px-3 py-2" className="flex items-center gap-2 rounded-lg border border-dashed border-border bg-accent/50 px-3 py-2"
> >
<CheckCircle2 className="h-4 w-4 text-emerald-400/50" /> <CheckCircle2 className="h-4 w-4 text-emerald-400/50" />
<input <input
@@ -142,7 +142,7 @@ export function StepList() {
<div <div
className={cn( className={cn(
'group flex items-center gap-2 rounded-xl border border-border px-3 py-2.5 transition-colors', 'group flex items-center gap-2 rounded-xl border border-border px-3 py-2.5 transition-colors',
'hover:border-primary/30 hover:bg-white/[0.03]' 'hover:border-primary/30 hover:bg-accent/50'
)} )}
> >
<GripVertical className="h-4 w-4 shrink-0 cursor-grab text-muted-foreground group-hover:text-muted-foreground" /> <GripVertical className="h-4 w-4 shrink-0 cursor-grab text-muted-foreground group-hover:text-muted-foreground" />

View File

@@ -20,24 +20,24 @@ export function ProgressBar({ currentStep, totalSteps, elapsedMinutes, estimated
return ( return (
<div className="space-y-1.5"> <div className="space-y-1.5">
<div className="flex items-center justify-between text-xs"> <div className="flex items-center justify-between text-xs">
<span className="text-white/60"> <span className="text-muted-foreground">
Step {currentStep} of {totalSteps} Step {currentStep} of {totalSteps}
</span> </span>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
{elapsedMinutes !== undefined && ( {elapsedMinutes !== undefined && (
<span className="text-white/50"> <span className="text-muted-foreground">
{formatTime(elapsed)} {formatTime(elapsed)}
{estimatedTotalMinutes ? ( {estimatedTotalMinutes ? (
<span className="text-white/25"> / est. {formatTime(estimatedTotalMinutes)}</span> <span className="text-muted-foreground"> / est. {formatTime(estimatedTotalMinutes)}</span>
) : null} ) : null}
</span> </span>
)} )}
<span className="font-medium text-white/70">{percentage}%</span> <span className="font-medium text-muted-foreground">{percentage}%</span>
</div> </div>
</div> </div>
<div className="h-1.5 overflow-hidden rounded-full bg-white/10"> <div className="h-1.5 overflow-hidden rounded-full bg-accent">
<div <div
className="h-full rounded-full bg-white transition-all duration-300" className="h-full rounded-full bg-gradient-brand transition-all duration-300"
style={{ width: `${percentage}%` }} style={{ width: `${percentage}%` }}
/> />
</div> </div>

View File

@@ -45,7 +45,7 @@ export function ContinuationModal({
{/* Descendant Selection */} {/* Descendant Selection */}
{hasDescendants && ( {hasDescendants && (
<div> <div>
<p className="mb-4 text-sm text-white/70"> <p className="mb-4 text-sm text-muted-foreground">
Select the next step in your troubleshooting path: Select the next step in your troubleshooting path:
</p> </p>
@@ -56,20 +56,20 @@ export function ContinuationModal({
onClick={() => onSelectNode(node.id)} onClick={() => onSelectNode(node.id)}
title={`From: ${node.parentOptionLabel}`} title={`From: ${node.parentOptionLabel}`}
className={cn( className={cn(
'flex w-full items-center gap-3 rounded-lg border border-white/[0.06] p-3 text-left transition-colors', 'flex w-full items-center gap-3 rounded-lg border border-border p-3 text-left transition-colors',
'hover:border-white/20 hover:bg-white/10' 'hover:border-border hover:bg-accent'
)} )}
> >
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-white/10"> <div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-accent">
{nodeTypeIcons[node.type]} {nodeTypeIcons[node.type]}
</div> </div>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<p className="truncate font-medium text-white">{node.label}</p> <p className="truncate font-medium text-foreground">{node.label}</p>
<p className="text-xs text-white/40"> <p className="text-xs text-muted-foreground">
{nodeTypeLabels[node.type]} {nodeTypeLabels[node.type]}
</p> </p>
</div> </div>
<ArrowRight className="h-4 w-4 flex-shrink-0 text-white/40" /> <ArrowRight className="h-4 w-4 flex-shrink-0 text-muted-foreground" />
</button> </button>
))} ))}
</div> </div>
@@ -79,11 +79,11 @@ export function ContinuationModal({
{/* Divider */} {/* Divider */}
{hasDescendants && ( {hasDescendants && (
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="h-px flex-1 bg-white/[0.06]" /> <div className="h-px flex-1 bg-border" />
<span className="text-xs font-medium uppercase tracking-wide text-white/40"> <span className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
Or Or
</span> </span>
<div className="h-px flex-1 bg-white/[0.06]" /> <div className="h-px flex-1 bg-border" />
</div> </div>
)} )}
@@ -100,8 +100,8 @@ export function ContinuationModal({
<GitBranch className="h-5 w-5 text-amber-500" /> <GitBranch className="h-5 w-5 text-amber-500" />
</div> </div>
<div className="flex-1"> <div className="flex-1">
<p className="font-medium text-white">Build Custom Branch</p> <p className="font-medium text-foreground">Build Custom Branch</p>
<p className="text-sm text-white/70"> <p className="text-sm text-muted-foreground">
Create your own troubleshooting path with custom steps Create your own troubleshooting path with custom steps
</p> </p>
</div> </div>

View File

@@ -69,9 +69,9 @@ export function ExportPreviewModal({
<Modal isOpen={isOpen} onClose={handleClose} title="Export Preview" size="xl"> <Modal isOpen={isOpen} onClose={handleClose} title="Export Preview" size="xl">
{/* Filename, format info, and controls */} {/* Filename, format info, and controls */}
<div className="mb-3 flex flex-wrap items-center justify-between gap-2"> <div className="mb-3 flex flex-wrap items-center justify-between gap-2">
<p className="text-sm text-white/70"> <p className="text-sm text-muted-foreground">
Filename: <span className="font-mono text-white">{filename}</span> Filename: <span className="font-mono text-foreground">{filename}</span>
<span className="ml-3 rounded bg-white/10 px-2 py-0.5 text-xs text-white/70"> <span className="ml-3 rounded bg-accent px-2 py-0.5 text-xs text-muted-foreground">
{format === 'markdown' ? 'Markdown' : format === 'html' ? 'HTML' : format === 'psa' ? 'PSA' : 'Plain Text'} {format === 'markdown' ? 'Markdown' : format === 'html' ? 'HTML' : format === 'psa' ? 'PSA' : 'Plain Text'}
</span> </span>
{isModified && ( {isModified && (
@@ -81,23 +81,23 @@ export function ExportPreviewModal({
<div className="flex flex-col items-end gap-1"> <div className="flex flex-col items-end gap-1">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
{onToggleSummary && ( {onToggleSummary && (
<label className="flex items-center gap-2 text-sm text-white/60 cursor-pointer"> <label className="flex items-center gap-2 text-sm text-muted-foreground cursor-pointer">
<input <input
type="checkbox" type="checkbox"
checked={includeSummary} checked={includeSummary}
onChange={(e) => onToggleSummary(e.target.checked)} onChange={(e) => onToggleSummary(e.target.checked)}
className="h-4 w-4 rounded border-white/20 bg-black/50" className="h-4 w-4 rounded border-border bg-card"
/> />
Include Summary Include Summary
</label> </label>
)} )}
{onToggleRedaction && ( {onToggleRedaction && (
<label className="flex items-center gap-2 text-sm text-white/60 cursor-pointer"> <label className="flex items-center gap-2 text-sm text-muted-foreground cursor-pointer">
<input <input
type="checkbox" type="checkbox"
checked={redactionEnabled} checked={redactionEnabled}
onChange={(e) => onToggleRedaction(e.target.checked)} onChange={(e) => onToggleRedaction(e.target.checked)}
className="h-4 w-4 rounded border-white/20 bg-black/50" className="h-4 w-4 rounded border-border bg-card"
/> />
Mask Sensitive Data Mask Sensitive Data
</label> </label>
@@ -114,13 +114,13 @@ export function ExportPreviewModal({
</p> </p>
)} )}
{redactionEnabled && redactionSummary && redactionSummary.total === 0 && ( {redactionEnabled && redactionSummary && redactionSummary.total === 0 && (
<p className="text-xs text-white/40">No sensitive data detected</p> <p className="text-xs text-muted-foreground">No sensitive data detected</p>
)} )}
{isModified && ( {isModified && (
<button <button
type="button" type="button"
onClick={handleReset} onClick={handleReset}
className="flex items-center gap-1 text-xs text-white/40 hover:text-white" className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground"
title="Reset to original" title="Reset to original"
> >
<RotateCcw className="h-3 w-3" /> <RotateCcw className="h-3 w-3" />
@@ -139,9 +139,9 @@ export function ExportPreviewModal({
value={editedContent} value={editedContent}
onChange={(e) => setEditedContent(e.target.value)} onChange={(e) => setEditedContent(e.target.value)}
className={cn( className={cn(
'h-96 w-full resize-y rounded-md border border-white/10 bg-black/50 p-4', 'h-96 w-full resize-y rounded-md border border-border bg-card p-4',
'font-mono text-sm text-white', 'font-mono text-sm text-foreground',
'focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20' 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20'
)} )}
/> />
@@ -151,9 +151,9 @@ export function ExportPreviewModal({
type="button" type="button"
onClick={handleCopy} onClick={handleCopy}
className={cn( className={cn(
'flex items-center gap-2 rounded-md border border-white/10 px-3 py-2 text-sm font-medium', 'flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium',
'text-white/60 hover:bg-white/10 hover:text-white', 'text-muted-foreground hover:bg-accent hover:text-foreground',
'focus:outline-none focus:ring-2 focus:ring-white/20' 'focus:outline-none focus:ring-2 focus:ring-primary/20'
)} )}
> >
{copied ? ( {copied ? (
@@ -172,8 +172,8 @@ export function ExportPreviewModal({
type="button" type="button"
onClick={handleDownload} onClick={handleDownload}
className={cn( className={cn(
'flex items-center gap-2 rounded-md bg-white px-3 py-2 text-sm font-medium text-black', 'flex items-center gap-2 rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-3 py-2 text-sm font-medium',
'hover:bg-white/90 focus:outline-none focus:ring-2 focus:ring-white/20' 'hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-primary/20'
)} )}
> >
<Download className="h-4 w-4" /> <Download className="h-4 w-4" />

View File

@@ -49,7 +49,7 @@ export function ForkTreeModal({
disabled={isSaving} disabled={isSaving}
className={cn( className={cn(
'rounded-md px-4 py-2 text-sm font-medium transition-colors', 'rounded-md px-4 py-2 text-sm font-medium transition-colors',
'text-white/60 hover:bg-white/10 hover:text-white', 'text-muted-foreground hover:bg-accent hover:text-foreground',
'disabled:cursor-not-allowed disabled:opacity-50' 'disabled:cursor-not-allowed disabled:opacity-50'
)} )}
> >
@@ -59,8 +59,8 @@ export function ForkTreeModal({
onClick={handleFork} onClick={handleFork}
disabled={isSaving || !name.trim()} disabled={isSaving || !name.trim()}
className={cn( className={cn(
'flex items-center gap-2 rounded-md bg-white px-4 py-2 text-sm font-medium text-black transition-colors', 'flex items-center gap-2 rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium transition-colors',
'hover:bg-white/90', 'hover:opacity-90',
'disabled:cursor-not-allowed disabled:opacity-50' 'disabled:cursor-not-allowed disabled:opacity-50'
)} )}
> >
@@ -82,13 +82,13 @@ export function ForkTreeModal({
return ( return (
<Modal isOpen={isOpen} onClose={onClose} title="Save Custom Tree?" footer={footer}> <Modal isOpen={isOpen} onClose={onClose} title="Save Custom Tree?" footer={footer}>
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-start gap-3 rounded-lg bg-white/5 p-4"> <div className="flex items-start gap-3 rounded-lg bg-accent/50 p-4">
<div className="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full bg-white/10"> <div className="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full bg-accent">
<GitFork className="h-5 w-5 text-white" /> <GitFork className="h-5 w-5 text-foreground" />
</div> </div>
<div> <div>
<p className="font-medium text-white">You've created a custom troubleshooting path!</p> <p className="font-medium text-foreground">You've created a custom troubleshooting path!</p>
<p className="mt-1 text-sm text-white/70"> <p className="mt-1 text-sm text-muted-foreground">
Save it as your own personal tree to reuse this troubleshooting flow in the future. Save it as your own personal tree to reuse this troubleshooting flow in the future.
</p> </p>
</div> </div>
@@ -96,7 +96,7 @@ export function ForkTreeModal({
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<label htmlFor="tree-name" className="mb-1.5 block text-sm font-medium text-white"> <label htmlFor="tree-name" className="mb-1.5 block text-sm font-medium text-foreground">
Tree Name <span className="text-red-400">*</span> Tree Name <span className="text-red-400">*</span>
</label> </label>
<input <input
@@ -106,15 +106,15 @@ export function ForkTreeModal({
onChange={(e) => setName(e.target.value)} onChange={(e) => setName(e.target.value)}
placeholder="My Custom Tree" placeholder="My Custom Tree"
className={cn( className={cn(
'w-full rounded-md border border-white/10 bg-black/50 px-3 py-2 text-sm text-white', 'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
'focus:outline-none focus:border-white/30 focus:ring-1 focus:ring-white/20' 'focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20'
)} )}
/> />
</div> </div>
<div> <div>
<label htmlFor="tree-description" className="mb-1.5 block text-sm font-medium text-white"> <label htmlFor="tree-description" className="mb-1.5 block text-sm font-medium text-foreground">
Description <span className="text-white/40">(optional)</span> Description <span className="text-muted-foreground">(optional)</span>
</label> </label>
<textarea <textarea
id="tree-description" id="tree-description"
@@ -123,8 +123,8 @@ export function ForkTreeModal({
placeholder="Describe what this tree helps troubleshoot..." placeholder="Describe what this tree helps troubleshoot..."
rows={3} rows={3}
className={cn( className={cn(
'w-full rounded-md border border-white/10 bg-black/50 px-3 py-2 text-sm text-white', 'w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground',
'focus:outline-none focus:border-white/30 focus:ring-1 focus:ring-white/20', 'focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20',
'resize-none' 'resize-none'
)} )}
/> />
@@ -135,7 +135,7 @@ export function ForkTreeModal({
<p className="text-sm text-red-400">{error}</p> <p className="text-sm text-red-400">{error}</p>
)} )}
<p className="text-xs text-white/40"> <p className="text-xs text-muted-foreground">
The new tree will include your custom steps and will be saved to your personal tree library. The new tree will include your custom steps and will be saved to your personal tree library.
</p> </p>
</div> </div>

View File

@@ -28,8 +28,8 @@ export function PostStepActionModal({
return ( return (
<Modal isOpen={isOpen} onClose={onClose} title="What would you like to do?"> <Modal isOpen={isOpen} onClose={onClose} title="What would you like to do?">
<div className="space-y-3"> <div className="space-y-3">
<p className="mb-4 text-sm text-white/70"> <p className="mb-4 text-sm text-muted-foreground">
You've created: <strong className="text-white">{step.title}</strong> You've created: <strong className="text-foreground">{step.title}</strong>
</p> </p>
{/* Save for Later - Only show if not already from library */} {/* Save for Later - Only show if not already from library */}
@@ -48,8 +48,8 @@ export function PostStepActionModal({
<Bookmark className="h-5 w-5 text-blue-500" /> <Bookmark className="h-5 w-5 text-blue-500" />
</div> </div>
<div> <div>
<p className="font-medium text-white">Save for Later</p> <p className="font-medium text-foreground">Save for Later</p>
<p className="text-sm text-white/70"> <p className="text-sm text-muted-foreground">
Add to your step library for future use Add to your step library for future use
</p> </p>
</div> </div>
@@ -62,8 +62,8 @@ export function PostStepActionModal({
onClick={onUseNow} onClick={onUseNow}
disabled={isSaving} disabled={isSaving}
className={cn( className={cn(
'w-full rounded-lg border border-white/[0.06] p-4 text-left transition-colors', 'w-full rounded-lg border border-border p-4 text-left transition-colors',
'hover:border-white/20 hover:bg-white/10', 'hover:border-border hover:bg-accent',
'disabled:cursor-not-allowed disabled:opacity-50' 'disabled:cursor-not-allowed disabled:opacity-50'
)} )}
> >
@@ -96,8 +96,8 @@ export function PostStepActionModal({
<BookmarkPlus className="h-5 w-5 text-purple-500" /> <BookmarkPlus className="h-5 w-5 text-purple-500" />
</div> </div>
<div> <div>
<p className="font-medium text-white">Do Both</p> <p className="font-medium text-foreground">Do Both</p>
<p className="text-sm text-white/70"> <p className="text-sm text-muted-foreground">
Save to library AND use in this session Save to library AND use in this session
</p> </p>
</div> </div>
@@ -106,7 +106,7 @@ export function PostStepActionModal({
)} )}
{isSaving && ( {isSaving && (
<p className="text-center text-sm text-white/40">Saving...</p> <p className="text-center text-sm text-muted-foreground">Saving...</p>
)} )}
</div> </div>
</Modal> </Modal>

View File

@@ -124,8 +124,8 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
onClick={() => setIsCollapsed(false)} onClick={() => setIsCollapsed(false)}
className={cn( className={cn(
'fixed right-2 top-1/2 z-40 -translate-y-1/2 rounded-md p-2.5', 'fixed right-2 top-1/2 z-40 -translate-y-1/2 rounded-md p-2.5',
'bg-[#0a0a0a] border border-white/[0.06] shadow-md', 'bg-card border border-border shadow-md',
'text-white/40 hover:bg-white/10 hover:text-white', 'text-muted-foreground hover:bg-accent hover:text-foreground',
'transition-opacity duration-200', 'transition-opacity duration-200',
isCollapsed ? 'opacity-100' : 'pointer-events-none opacity-0' isCollapsed ? 'opacity-100' : 'pointer-events-none opacity-0'
)} )}
@@ -153,29 +153,29 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
'fixed z-40', 'fixed z-40',
'inset-0 sm:inset-auto sm:right-2 sm:top-1/2 sm:-translate-y-1/2', 'inset-0 sm:inset-auto sm:right-2 sm:top-1/2 sm:-translate-y-1/2',
'flex w-full flex-col sm:h-[55vh] sm:w-[420px]', 'flex w-full flex-col sm:h-[55vh] sm:w-[420px]',
'border-white/[0.06] bg-[#0a0a0a]/95 backdrop-blur-md shadow-xl sm:rounded-lg sm:border', 'border-border bg-card/95 backdrop-blur-md shadow-xl sm:rounded-lg sm:border',
'transition-transform duration-200 ease-out', 'transition-transform duration-200 ease-out',
isCollapsed ? 'translate-x-full' : 'translate-x-0' isCollapsed ? 'translate-x-full' : 'translate-x-0'
)} )}
> >
{/* Header */} {/* Header */}
<div className="flex items-center justify-between border-b border-white/[0.06] px-3 py-2"> <div className="flex items-center justify-between border-b border-border px-3 py-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<StickyNote className="h-4 w-4 text-white/40" /> <StickyNote className="h-4 w-4 text-muted-foreground" />
<span className="text-sm font-medium text-white">Scratchpad</span> <span className="text-sm font-medium text-foreground">Scratchpad</span>
<span className="text-xs text-white/30">Ctrl+/</span> <span className="text-xs text-muted-foreground">Ctrl+/</span>
</div> </div>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<button <button
onClick={() => setShowPreview(!showPreview)} onClick={() => setShowPreview(!showPreview)}
className="rounded p-1 text-white/40 hover:bg-white/10 hover:text-white" className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
title={showPreview ? 'Edit' : 'Preview'} title={showPreview ? 'Edit' : 'Preview'}
> >
{showPreview ? <Pencil className="h-3.5 w-3.5" /> : <Eye className="h-3.5 w-3.5" />} {showPreview ? <Pencil className="h-3.5 w-3.5" /> : <Eye className="h-3.5 w-3.5" />}
</button> </button>
<button <button
onClick={() => setIsCollapsed(true)} onClick={() => setIsCollapsed(true)}
className="rounded p-1 text-white/40 hover:bg-white/10 hover:text-white" className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
title="Close scratchpad" title="Close scratchpad"
aria-label="Close scratchpad" aria-label="Close scratchpad"
> >
@@ -191,7 +191,7 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
{content.trim() ? ( {content.trim() ? (
<MarkdownContent content={content} className="text-sm" /> <MarkdownContent content={content} className="text-sm" />
) : ( ) : (
<p className="text-sm italic text-white/40">Nothing to preview</p> <p className="text-sm italic text-muted-foreground">Nothing to preview</p>
)} )}
</div> </div>
) : ( ) : (
@@ -202,7 +202,7 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
placeholder={"Capture IPs, error codes, server names, user info...\n\nSupports markdown formatting."} placeholder={"Capture IPs, error codes, server names, user info...\n\nSupports markdown formatting."}
className={cn( className={cn(
'h-full min-h-[200px] w-full resize-none rounded-md border-0 bg-transparent p-0 text-sm', 'h-full min-h-[200px] w-full resize-none rounded-md border-0 bg-transparent p-0 text-sm',
'text-white placeholder:text-white/40', 'text-foreground placeholder:text-muted-foreground',
'focus:outline-none focus:ring-0' 'focus:outline-none focus:ring-0'
)} )}
/> />
@@ -210,15 +210,15 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
</div> </div>
{/* Save Indicator */} {/* Save Indicator */}
<div className="border-t border-white/[0.06] px-3 py-1.5"> <div className="border-t border-border px-3 py-1.5">
<div className="flex items-center gap-1.5 text-xs"> <div className="flex items-center gap-1.5 text-xs">
{saveStatus === 'unsaved' && ( {saveStatus === 'unsaved' && (
<span className="text-white/40">Unsaved changes</span> <span className="text-muted-foreground">Unsaved changes</span>
)} )}
{saveStatus === 'saving' && ( {saveStatus === 'saving' && (
<> <>
<Loader2 className="h-3 w-3 animate-spin text-white/40" /> <Loader2 className="h-3 w-3 animate-spin text-muted-foreground" />
<span className="text-white/40">Saving...</span> <span className="text-muted-foreground">Saving...</span>
</> </>
)} )}
{saveStatus === 'saved' && ( {saveStatus === 'saved' && (
@@ -228,7 +228,7 @@ export function ScratchpadSidebar({ sessionId, initialContent, onSave, onOpenCha
<span className="text-red-400">Save failed</span> <span className="text-red-400">Save failed</span>
)} )}
{saveStatus === 'idle' && ( {saveStatus === 'idle' && (
<span className="text-white/30">Markdown supported</span> <span className="text-muted-foreground">Markdown supported</span>
)} )}
</div> </div>
</div> </div>

View File

@@ -51,8 +51,8 @@ export function SessionOutcomeModal({
onClick={onClose} onClick={onClose}
disabled={isSubmitting} disabled={isSubmitting}
className={cn( className={cn(
'rounded-md border border-white/10 px-4 py-2 text-sm font-medium text-white/60', 'rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground',
'hover:bg-white/10 hover:text-white disabled:opacity-50' 'hover:bg-accent hover:text-foreground disabled:opacity-50'
)} )}
> >
Cancel Cancel
@@ -62,8 +62,8 @@ export function SessionOutcomeModal({
onClick={handleSubmit} onClick={handleSubmit}
disabled={isSubmitting} disabled={isSubmitting}
className={cn( className={cn(
'rounded-md bg-white px-4 py-2 text-sm font-medium text-black', 'rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium',
'hover:bg-white/90 disabled:opacity-50' 'hover:opacity-90 disabled:opacity-50'
)} )}
> >
{isSubmitting ? 'Completing...' : 'Complete Session'} {isSubmitting ? 'Completing...' : 'Complete Session'}
@@ -72,7 +72,7 @@ export function SessionOutcomeModal({
)} )}
> >
<form key={String(isOpen)} ref={formRef} className="space-y-4"> <form key={String(isOpen)} ref={formRef} className="space-y-4">
<p className="text-sm text-white/70"> <p className="text-sm text-muted-foreground">
Select the session outcome before completion. Select the session outcome before completion.
</p> </p>
<div className="space-y-2"> <div className="space-y-2">
@@ -80,8 +80,8 @@ export function SessionOutcomeModal({
<label <label
key={option.value} key={option.value}
className={cn( className={cn(
'block cursor-pointer rounded-lg border border-white/10 p-3 transition-colors', 'block cursor-pointer rounded-lg border border-border p-3 transition-colors',
'hover:bg-white/[0.04]' 'hover:bg-accent/50'
)} )}
> >
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
@@ -93,8 +93,8 @@ export function SessionOutcomeModal({
className="mt-1 h-4 w-4" className="mt-1 h-4 w-4"
/> />
<div> <div>
<p className="text-sm font-medium text-white">{option.label}</p> <p className="text-sm font-medium text-foreground">{option.label}</p>
<p className="text-xs text-white/50">{option.description}</p> <p className="text-xs text-muted-foreground">{option.description}</p>
</div> </div>
</div> </div>
</label> </label>
@@ -102,31 +102,31 @@ export function SessionOutcomeModal({
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-white">Outcome Notes (optional)</label> <label className="block text-sm font-medium text-foreground">Outcome Notes (optional)</label>
<textarea <textarea
name="outcome-notes" name="outcome-notes"
defaultValue="" defaultValue=""
rows={3} rows={3}
placeholder="Add context for this outcome..." placeholder="Add context for this outcome..."
className={cn( className={cn(
'mt-1 block w-full rounded-md border border-white/10 bg-black/50 px-3 py-2', 'mt-1 block w-full rounded-md border border-border bg-card px-3 py-2',
'text-sm text-white placeholder:text-white/40', 'text-sm text-foreground placeholder:text-muted-foreground',
'focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20' 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20'
)} )}
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-white">Next Steps / Follow-Up (optional)</label> <label className="block text-sm font-medium text-foreground">Next Steps / Follow-Up (optional)</label>
<textarea <textarea
name="next-steps" name="next-steps"
defaultValue="" defaultValue=""
rows={3} rows={3}
placeholder="Actions to take after this session..." placeholder="Actions to take after this session..."
className={cn( className={cn(
'mt-1 block w-full rounded-md border border-white/10 bg-black/50 px-3 py-2', 'mt-1 block w-full rounded-md border border-border bg-card px-3 py-2',
'text-sm text-white placeholder:text-white/40', 'text-sm text-foreground placeholder:text-muted-foreground',
'focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20' 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20'
)} )}
/> />
</div> </div>

View File

@@ -65,13 +65,13 @@ export function CustomStepModal({ isOpen, onClose, onInsertStep }: CustomStepMod
return ( return (
<div className="fixed inset-0 z-50 flex items-end justify-center bg-black/80 backdrop-blur-sm sm:items-center sm:p-4"> <div className="fixed inset-0 z-50 flex items-end justify-center bg-black/80 backdrop-blur-sm sm:items-center sm:p-4">
<div className="relative flex h-[95vh] w-full max-w-full flex-col border border-white/[0.06] bg-[#0a0a0a] shadow-lg sm:h-[90vh] sm:max-w-4xl sm:rounded-2xl"> <div className="relative flex h-[95vh] w-full max-w-full flex-col border border-border bg-card shadow-lg sm:h-[90vh] sm:max-w-4xl sm:rounded-2xl">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between border-b border-white/[0.06] p-4"> <div className="flex items-center justify-between border-b border-border p-4">
<h2 className="text-lg font-semibold text-white">Add Custom Step</h2> <h2 className="text-lg font-semibold text-foreground">Add Custom Step</h2>
<button <button
onClick={onClose} onClick={onClose}
className="rounded-md p-1.5 text-white/40 hover:bg-white/10 hover:text-white" className="rounded-md p-1.5 text-muted-foreground hover:bg-accent hover:text-foreground"
aria-label="Close" aria-label="Close"
> >
<X className="h-5 w-5" /> <X className="h-5 w-5" />
@@ -79,15 +79,15 @@ export function CustomStepModal({ isOpen, onClose, onInsertStep }: CustomStepMod
</div> </div>
{/* Tabs */} {/* Tabs */}
<div className="flex border-b border-white/[0.06]"> <div className="flex border-b border-border">
{canCreateSteps && ( {canCreateSteps && (
<button <button
onClick={() => setActiveTab('create')} onClick={() => setActiveTab('create')}
className={cn( className={cn(
'flex-1 px-4 py-3 text-sm font-medium transition-colors', 'flex-1 px-4 py-3 text-sm font-medium transition-colors',
activeTab === 'create' activeTab === 'create'
? 'border-b-2 border-white bg-white/5 text-white' ? 'border-b-2 border-primary bg-primary/5 text-foreground'
: 'text-white/40 hover:bg-white/10 hover:text-white' : 'text-muted-foreground hover:bg-accent hover:text-foreground'
)} )}
> >
Type My Own Type My Own
@@ -134,8 +134,8 @@ export function CustomStepModal({ isOpen, onClose, onInsertStep }: CustomStepMod
{isSubmitting && ( {isSubmitting && (
<div className="absolute inset-0 flex items-center justify-center bg-black/80 backdrop-blur-sm"> <div className="absolute inset-0 flex items-center justify-center bg-black/80 backdrop-blur-sm">
<div className="flex flex-col items-center gap-3"> <div className="flex flex-col items-center gap-3">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-white/20 border-t-white" /> <div className="h-8 w-8 animate-spin rounded-full border-4 border-border border-t-foreground" />
<p className="text-sm text-white/40">Creating step...</p> <p className="text-sm text-muted-foreground">Creating step...</p>
</div> </div>
</div> </div>
)} )}

View File

@@ -27,7 +27,7 @@ export function StepCard({ step, onPreview, onInsert }: StepCardProps) {
const remainingTags = step.tags.length - 3 const remainingTags = step.tags.length - 3
return ( return (
<div className="group rounded-lg border border-white/[0.06] bg-[#0a0a0a] p-4 transition-shadow hover:shadow-md"> <div className="group rounded-lg border border-border bg-card p-4 transition-shadow hover:shadow-md">
{/* Header */} {/* Header */}
<div className="mb-3 flex items-start justify-between gap-2"> <div className="mb-3 flex items-start justify-between gap-2">
<div className="flex-1"> <div className="flex-1">
@@ -52,12 +52,12 @@ export function StepCard({ step, onPreview, onInsert }: StepCardProps) {
</div> </div>
{/* Title */} {/* Title */}
<h3 className="font-semibold text-white line-clamp-2">{step.title}</h3> <h3 className="font-semibold text-foreground line-clamp-2">{step.title}</h3>
</div> </div>
</div> </div>
{/* Metadata */} {/* Metadata */}
<div className="mb-3 space-y-1.5 text-sm text-white/40"> <div className="mb-3 space-y-1.5 text-sm text-muted-foreground">
{/* Category */} {/* Category */}
{step.category_name && ( {step.category_name && (
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
@@ -103,7 +103,7 @@ export function StepCard({ step, onPreview, onInsert }: StepCardProps) {
{visibleTags.map(tag => ( {visibleTags.map(tag => (
<span <span
key={tag} key={tag}
className="rounded-full bg-white/10 px-2 py-0.5 text-xs text-white/70" className="rounded-full bg-accent px-2 py-0.5 text-xs text-muted-foreground"
> >
{tag} {tag}
</span> </span>
@@ -121,8 +121,8 @@ export function StepCard({ step, onPreview, onInsert }: StepCardProps) {
<button <button
onClick={() => onPreview(step)} onClick={() => onPreview(step)}
className={cn( className={cn(
'flex flex-1 items-center justify-center gap-2 rounded-md border border-white/10 px-3 py-2 text-sm font-medium text-white/60', 'flex flex-1 items-center justify-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium text-muted-foreground',
'hover:bg-white/10 hover:text-white transition-colors' 'hover:bg-accent hover:text-foreground transition-colors'
)} )}
> >
<Eye className="h-4 w-4" /> <Eye className="h-4 w-4" />
@@ -131,8 +131,8 @@ export function StepCard({ step, onPreview, onInsert }: StepCardProps) {
<button <button
onClick={() => onInsert(step)} onClick={() => onInsert(step)}
className={cn( className={cn(
'flex flex-1 items-center justify-center gap-2 rounded-md bg-white px-3 py-2 text-sm font-medium text-black', 'flex flex-1 items-center justify-center gap-2 rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-3 py-2 text-sm font-medium',
'hover:bg-white/90 transition-colors' 'hover:opacity-90 transition-colors'
)} )}
> >
<Plus className="h-4 w-4" /> <Plus className="h-4 w-4" />

View File

@@ -136,7 +136,7 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
<form onSubmit={handleSubmit} className="space-y-6"> <form onSubmit={handleSubmit} className="space-y-6">
{/* Step Type */} {/* Step Type */}
<div> <div>
<label className="mb-2 block text-sm font-medium text-white"> <label className="mb-2 block text-sm font-medium text-foreground">
Step Type <span className="text-red-400">*</span> Step Type <span className="text-red-400">*</span>
</label> </label>
<div className="grid grid-cols-3 gap-2"> <div className="grid grid-cols-3 gap-2">
@@ -150,15 +150,15 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
className={cn( className={cn(
'rounded-lg border p-3 text-left transition-colors', 'rounded-lg border p-3 text-left transition-colors',
stepType === option.value stepType === option.value
? 'border-white/20 bg-white/10 ring-2 ring-white/20' ? 'border-border bg-accent ring-2 ring-primary/20'
: 'border-white/[0.06] hover:border-white/20' : 'border-border hover:border-border'
)} )}
> >
<div className="mb-1 flex items-center gap-2"> <div className="mb-1 flex items-center gap-2">
<Icon className="h-4 w-4" /> <Icon className="h-4 w-4" />
<span className="font-medium text-sm text-white">{option.label}</span> <span className="font-medium text-sm text-foreground">{option.label}</span>
</div> </div>
<p className="text-xs text-white/40">{option.description}</p> <p className="text-xs text-muted-foreground">{option.description}</p>
</button> </button>
) )
})} })}
@@ -167,7 +167,7 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
{/* Title */} {/* Title */}
<div> <div>
<label htmlFor="title" className="mb-2 block text-sm font-medium text-white"> <label htmlFor="title" className="mb-2 block text-sm font-medium text-foreground">
Title <span className="text-red-400">*</span> Title <span className="text-red-400">*</span>
</label> </label>
<input <input
@@ -177,8 +177,8 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
onChange={(e) => setTitle(e.target.value)} onChange={(e) => setTitle(e.target.value)}
placeholder="Enter step title" placeholder="Enter step title"
className={cn( className={cn(
'w-full rounded-md border bg-black/50 px-3 py-2 text-sm text-white focus:outline-none focus:border-white/30 focus:ring-1 focus:ring-white/20', 'w-full rounded-md border bg-card px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20',
errors.title ? 'border-red-400/50' : 'border-white/10' errors.title ? 'border-red-400/50' : 'border-border'
)} )}
/> />
{errors.title && ( {errors.title && (
@@ -188,9 +188,9 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
{/* Instructions */} {/* Instructions */}
<div> <div>
<label htmlFor="instructions" className="mb-2 block text-sm font-medium text-white"> <label htmlFor="instructions" className="mb-2 block text-sm font-medium text-foreground">
Instructions <span className="text-red-400">*</span> Instructions <span className="text-red-400">*</span>
<span className="ml-2 text-xs font-normal text-white/40">(Markdown supported)</span> <span className="ml-2 text-xs font-normal text-muted-foreground">(Markdown supported)</span>
</label> </label>
<textarea <textarea
id="instructions" id="instructions"
@@ -199,8 +199,8 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
placeholder="Describe what to do in this step..." placeholder="Describe what to do in this step..."
rows={6} rows={6}
className={cn( className={cn(
'w-full rounded-md border bg-black/50 px-3 py-2 text-sm text-white focus:outline-none focus:border-white/30 focus:ring-1 focus:ring-white/20', 'w-full rounded-md border bg-card px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20',
errors.instructions ? 'border-red-400/50' : 'border-white/10' errors.instructions ? 'border-red-400/50' : 'border-border'
)} )}
/> />
{errors.instructions && ( {errors.instructions && (
@@ -210,8 +210,8 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
{/* Help Text */} {/* Help Text */}
<div> <div>
<label htmlFor="helpText" className="mb-2 block text-sm font-medium text-white"> <label htmlFor="helpText" className="mb-2 block text-sm font-medium text-foreground">
Help Text <span className="text-xs font-normal text-white/40">(Optional)</span> Help Text <span className="text-xs font-normal text-muted-foreground">(Optional)</span>
</label> </label>
<textarea <textarea
id="helpText" id="helpText"
@@ -219,20 +219,20 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
onChange={(e) => setHelpText(e.target.value)} onChange={(e) => setHelpText(e.target.value)}
placeholder="Additional context or tips..." placeholder="Additional context or tips..."
rows={3} rows={3}
className="w-full rounded-md border border-white/10 bg-black/50 px-3 py-2 text-sm text-white focus:outline-none focus:border-white/30 focus:ring-1 focus:ring-white/20" className="w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20"
/> />
</div> </div>
{/* Commands */} {/* Commands */}
<div> <div>
<div className="mb-2 flex items-center justify-between"> <div className="mb-2 flex items-center justify-between">
<label className="text-sm font-medium text-white"> <label className="text-sm font-medium text-foreground">
Commands <span className="text-xs font-normal text-white/40">(Optional)</span> Commands <span className="text-xs font-normal text-muted-foreground">(Optional)</span>
</label> </label>
<button <button
type="button" type="button"
onClick={addCommand} onClick={addCommand}
className="flex items-center gap-1 rounded-md bg-white/10 px-2 py-1 text-xs font-medium text-white/70 hover:bg-white/20 hover:text-white" className="flex items-center gap-1 rounded-md bg-accent px-2 py-1 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<Plus className="h-3 w-3" /> <Plus className="h-3 w-3" />
Add Command Add Command
@@ -241,13 +241,13 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
{commands.length > 0 && ( {commands.length > 0 && (
<div className="space-y-3"> <div className="space-y-3">
{commands.map((cmd, index) => ( {commands.map((cmd, index) => (
<div key={index} className="rounded-lg border border-white/[0.06] bg-white/5 p-3"> <div key={index} className="rounded-lg border border-border bg-accent/50 p-3">
<div className="mb-2 flex items-center justify-between"> <div className="mb-2 flex items-center justify-between">
<span className="text-xs font-medium text-white/40">Command {index + 1}</span> <span className="text-xs font-medium text-muted-foreground">Command {index + 1}</span>
<button <button
type="button" type="button"
onClick={() => removeCommand(index)} onClick={() => removeCommand(index)}
className="rounded p-1 text-white/40 hover:bg-red-400/10 hover:text-red-400" className="rounded p-1 text-muted-foreground hover:bg-red-400/10 hover:text-red-400"
> >
<X className="h-3 w-3" /> <X className="h-3 w-3" />
</button> </button>
@@ -259,8 +259,8 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
onChange={(e) => updateCommand(index, 'label', e.target.value)} onChange={(e) => updateCommand(index, 'label', e.target.value)}
placeholder="Command label (e.g., 'Restart service')" placeholder="Command label (e.g., 'Restart service')"
className={cn( className={cn(
'w-full rounded-md border bg-black/50 px-3 py-1.5 text-sm text-white', 'w-full rounded-md border bg-card px-3 py-1.5 text-sm text-foreground',
errors[`command_${index}_label`] ? 'border-red-400/50' : 'border-white/10' errors[`command_${index}_label`] ? 'border-red-400/50' : 'border-border'
)} )}
/> />
<input <input
@@ -269,8 +269,8 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
onChange={(e) => updateCommand(index, 'command', e.target.value)} onChange={(e) => updateCommand(index, 'command', e.target.value)}
placeholder="Command (e.g., 'systemctl restart nginx')" placeholder="Command (e.g., 'systemctl restart nginx')"
className={cn( className={cn(
'w-full rounded-md border bg-black/50 px-3 py-1.5 font-mono text-sm text-white', 'w-full rounded-md border bg-card px-3 py-1.5 font-mono text-sm text-foreground',
errors[`command_${index}_command`] ? 'border-red-400/50' : 'border-white/10' errors[`command_${index}_command`] ? 'border-red-400/50' : 'border-border'
)} )}
/> />
{(errors[`command_${index}_label`] || errors[`command_${index}_command`]) && ( {(errors[`command_${index}_label`] || errors[`command_${index}_command`]) && (
@@ -287,14 +287,14 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
{/* Category */} {/* Category */}
<div> <div>
<label htmlFor="category" className="mb-2 block text-sm font-medium text-white"> <label htmlFor="category" className="mb-2 block text-sm font-medium text-foreground">
Category <span className="text-xs font-normal text-white/40">(Optional)</span> Category <span className="text-xs font-normal text-muted-foreground">(Optional)</span>
</label> </label>
<select <select
id="category" id="category"
value={categoryId} value={categoryId}
onChange={(e) => setCategoryId(e.target.value)} onChange={(e) => setCategoryId(e.target.value)}
className="w-full rounded-md border border-white/10 bg-black/50 px-3 py-2 text-sm text-white focus:outline-none focus:border-white/30 focus:ring-1 focus:ring-white/20" className="w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20"
> >
<option value="">None</option> <option value="">None</option>
{categories.map(cat => ( {categories.map(cat => (
@@ -305,8 +305,8 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
{/* Tags */} {/* Tags */}
<div> <div>
<label htmlFor="tagInput" className="mb-2 block text-sm font-medium text-white"> <label htmlFor="tagInput" className="mb-2 block text-sm font-medium text-foreground">
Tags <span className="text-xs font-normal text-white/40">(Optional)</span> Tags <span className="text-xs font-normal text-muted-foreground">(Optional)</span>
</label> </label>
<div className="flex gap-2"> <div className="flex gap-2">
<input <input
@@ -316,12 +316,12 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
onChange={(e) => setTagInput(e.target.value)} onChange={(e) => setTagInput(e.target.value)}
onKeyDown={handleTagInputKeyDown} onKeyDown={handleTagInputKeyDown}
placeholder="Type tag and press Enter" placeholder="Type tag and press Enter"
className="flex-1 rounded-md border border-white/10 bg-black/50 px-3 py-2 text-sm text-white focus:outline-none focus:border-white/30 focus:ring-1 focus:ring-white/20" className="flex-1 rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20"
/> />
<button <button
type="button" type="button"
onClick={addTag} onClick={addTag}
className="rounded-md bg-white/10 px-4 py-2 text-sm font-medium text-white/70 hover:bg-white/20 hover:text-white" className="rounded-md bg-accent px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground"
> >
Add Add
</button> </button>
@@ -331,13 +331,13 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
{tags.map(tag => ( {tags.map(tag => (
<span <span
key={tag} key={tag}
className="flex items-center gap-1 rounded-full bg-white/10 px-2.5 py-1 text-xs text-white/70" className="flex items-center gap-1 rounded-full bg-accent px-2.5 py-1 text-xs text-muted-foreground"
> >
{tag} {tag}
<button <button
type="button" type="button"
onClick={() => removeTag(tag)} onClick={() => removeTag(tag)}
className="rounded-full hover:bg-white/20" className="rounded-full hover:bg-accent"
aria-label={`Remove tag ${tag}`} aria-label={`Remove tag ${tag}`}
> >
<X className="h-3 w-3" /> <X className="h-3 w-3" />
@@ -350,14 +350,14 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
{/* Visibility */} {/* Visibility */}
<div> <div>
<label htmlFor="visibility" className="mb-2 block text-sm font-medium text-white"> <label htmlFor="visibility" className="mb-2 block text-sm font-medium text-foreground">
Visibility Visibility
</label> </label>
<select <select
id="visibility" id="visibility"
value={visibility} value={visibility}
onChange={(e) => setVisibility(e.target.value as 'private' | 'team' | 'public')} onChange={(e) => setVisibility(e.target.value as 'private' | 'team' | 'public')}
className="w-full rounded-md border border-white/10 bg-black/50 px-3 py-2 text-sm text-white focus:outline-none focus:border-white/30 focus:ring-1 focus:ring-white/20" className="w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/20"
> >
<option value="private">Private (only me)</option> <option value="private">Private (only me)</option>
<option value="team">Team (my team members)</option> <option value="team">Team (my team members)</option>
@@ -370,13 +370,13 @@ export function StepForm({ onSubmit, onCancel, initialData }: StepFormProps) {
<button <button
type="button" type="button"
onClick={onCancel} onClick={onCancel}
className="flex-1 rounded-md border border-white/10 px-4 py-2 text-sm font-medium text-white/60 hover:bg-white/10 hover:text-white" className="flex-1 rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground"
> >
Cancel Cancel
</button> </button>
<button <button
type="submit" type="submit"
className="flex-1 rounded-md bg-white px-4 py-2 text-sm font-medium text-black hover:bg-white/90" className="flex-1 rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90"
> >
Insert Step Insert Step
</button> </button>

View File

@@ -51,7 +51,7 @@ export function DynamicArrayField<T>({
type="button" type="button"
onClick={() => handleMoveUp(index)} onClick={() => handleMoveUp(index)}
disabled={index === 0} disabled={index === 0}
className="rounded p-0.5 text-white/50 hover:bg-white/[0.06] hover:text-white disabled:opacity-30" className="rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-30"
title="Move up" title="Move up"
aria-label="Move up" aria-label="Move up"
> >
@@ -61,7 +61,7 @@ export function DynamicArrayField<T>({
type="button" type="button"
onClick={() => handleMoveDown(index)} onClick={() => handleMoveDown(index)}
disabled={index === items.length - 1} disabled={index === items.length - 1}
className="rounded p-0.5 text-white/50 hover:bg-white/[0.06] hover:text-white disabled:opacity-30" className="rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-30"
title="Move down" title="Move down"
aria-label="Move down" aria-label="Move down"
> >
@@ -78,7 +78,7 @@ export function DynamicArrayField<T>({
<button <button
type="button" type="button"
onClick={() => onRemove(index)} onClick={() => onRemove(index)}
className="mt-1 rounded p-1 text-white/50 hover:bg-red-400/20 hover:text-red-400" className="mt-1 rounded p-1 text-muted-foreground hover:bg-red-400/20 hover:text-red-400"
title="Remove" title="Remove"
aria-label="Remove" aria-label="Remove"
> >
@@ -94,9 +94,9 @@ export function DynamicArrayField<T>({
type="button" type="button"
onClick={onAdd} onClick={onAdd}
className={cn( className={cn(
'flex w-full items-center justify-center gap-1 rounded-md border border-dashed border-white/10', 'flex w-full items-center justify-center gap-1 rounded-md border border-dashed border-border',
'px-3 py-2 text-sm text-white/50', 'px-3 py-2 text-sm text-muted-foreground',
'hover:border-white/30 hover:text-white' 'hover:border-border hover:text-foreground'
)} )}
> >
<Plus className="h-4 w-4" /> <Plus className="h-4 w-4" />
@@ -106,7 +106,7 @@ export function DynamicArrayField<T>({
{/* Empty state */} {/* Empty state */}
{items.length === 0 && !canAdd && ( {items.length === 0 && !canAdd && (
<p className="text-center text-sm text-white/40">No items</p> <p className="text-center text-sm text-muted-foreground">No items</p>
)} )}
</div> </div>
) )

View File

@@ -68,14 +68,14 @@ export function NodeEditorModal({ node, onClose, isNewNode = false }: NodeEditor
<button <button
type="button" type="button"
onClick={handleCancel} onClick={handleCancel}
className="rounded-md border border-white/10 px-4 py-2 text-sm font-medium text-white/60 hover:bg-white/10 hover:text-white" className="rounded-md border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground"
> >
Cancel Cancel
</button> </button>
<button <button
type="button" type="button"
onClick={handleSave} onClick={handleSave}
className="rounded-md bg-white px-4 py-2 text-sm font-medium text-black hover:bg-white/90" className="rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-4 py-2 text-sm font-medium hover:opacity-90"
> >
Done Done
</button> </button>
@@ -85,8 +85,8 @@ export function NodeEditorModal({ node, onClose, isNewNode = false }: NodeEditor
return ( return (
<Modal isOpen={true} onClose={onClose} title={getTitle()} size="lg" footer={footerContent}> <Modal isOpen={true} onClose={onClose} title={getTitle()} size="lg" footer={footerContent}>
{/* Node ID display */} {/* Node ID display */}
<div className="mb-4 text-xs text-white/40"> <div className="mb-4 text-xs text-muted-foreground">
Node ID: <code className="rounded bg-white/10 px-1 py-0.5">{node.id}</code> Node ID: <code className="rounded bg-accent px-1 py-0.5">{node.id}</code>
</div> </div>
{/* Validation errors */} {/* Validation errors */}

View File

@@ -52,7 +52,7 @@ export function NodeFormAction({ node, onUpdate }: NodeFormActionProps) {
<div className="space-y-4"> <div className="space-y-4">
{/* Title */} {/* Title */}
<div> <div>
<label className="block text-sm font-medium text-white"> <label className="block text-sm font-medium text-foreground">
Title <span className="text-red-400">*</span> Title <span className="text-red-400">*</span>
</label> </label>
<input <input
@@ -62,9 +62,9 @@ export function NodeFormAction({ node, onUpdate }: NodeFormActionProps) {
placeholder="e.g., Restart the Service" placeholder="e.g., Restart the Service"
className={cn( className={cn(
'mt-1 block w-full rounded-md border px-3 py-2 text-sm', 'mt-1 block w-full rounded-md border px-3 py-2 text-sm',
'bg-black/50 text-white placeholder:text-white/40', 'bg-card text-foreground placeholder:text-muted-foreground',
'focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20', 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20',
titleError ? 'border-red-400' : 'border-white/10' titleError ? 'border-red-400' : 'border-border'
)} )}
/> />
{titleError && ( {titleError && (
@@ -75,24 +75,24 @@ export function NodeFormAction({ node, onUpdate }: NodeFormActionProps) {
{/* Description */} {/* Description */}
<div> <div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<label className="block text-sm font-medium text-white"> <label className="block text-sm font-medium text-foreground">
Description Description
</label> </label>
{node.description && ( {node.description && (
<button <button
type="button" type="button"
onClick={() => setShowPreview(!showPreview)} onClick={() => setShowPreview(!showPreview)}
className="text-xs text-white/50 hover:text-white hover:underline" className="text-xs text-muted-foreground hover:text-foreground hover:underline"
> >
{showPreview ? 'Edit' : 'Preview'} {showPreview ? 'Edit' : 'Preview'}
</button> </button>
)} )}
</div> </div>
<p className="mb-1 text-xs text-white/40"> <p className="mb-1 text-xs text-muted-foreground">
Supports markdown: **bold**, *italic*, - lists, 1. numbered lists, `code` Supports markdown: **bold**, *italic*, - lists, 1. numbered lists, `code`
</p> </p>
{showPreview && node.description ? ( {showPreview && node.description ? (
<div className="mt-1 rounded-md border border-white/10 bg-white/[0.04] p-3 text-sm"> <div className="mt-1 rounded-md border border-border bg-accent/50 p-3 text-sm">
<MarkdownContent content={node.description} /> <MarkdownContent content={node.description} />
</div> </div>
) : ( ) : (
@@ -108,7 +108,7 @@ export function NodeFormAction({ node, onUpdate }: NodeFormActionProps) {
**Note:** Important information here" **Note:** Important information here"
rows={5} rows={5}
className={cn( className={cn(
'mt-1 block w-full rounded-md border border-white/10 px-3 py-2 text-sm', 'mt-1 block w-full rounded-md border border-border px-3 py-2 text-sm',
'bg-background text-foreground placeholder:text-muted-foreground', 'bg-background text-foreground placeholder:text-muted-foreground',
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary' 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary'
)} )}
@@ -118,10 +118,10 @@ export function NodeFormAction({ node, onUpdate }: NodeFormActionProps) {
{/* Commands */} {/* Commands */}
<div> <div>
<label className="block text-sm font-medium text-white"> <label className="block text-sm font-medium text-foreground">
Commands Commands
</label> </label>
<p className="mb-2 text-xs text-white/40"> <p className="mb-2 text-xs text-muted-foreground">
PowerShell or CLI commands to execute PowerShell or CLI commands to execute
</p> </p>
<DynamicArrayField <DynamicArrayField
@@ -137,7 +137,7 @@ export function NodeFormAction({ node, onUpdate }: NodeFormActionProps) {
onChange={(e) => handleUpdateCommand(index, e.target.value)} onChange={(e) => handleUpdateCommand(index, e.target.value)}
placeholder="e.g., Get-Service BrokerAgent" placeholder="e.g., Get-Service BrokerAgent"
className={cn( className={cn(
'block w-full rounded-md border border-white/10 px-3 py-2 font-mono text-sm', 'block w-full rounded-md border border-border px-3 py-2 font-mono text-sm',
'bg-background text-foreground placeholder:text-muted-foreground', 'bg-background text-foreground placeholder:text-muted-foreground',
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary' 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary'
)} )}
@@ -148,7 +148,7 @@ export function NodeFormAction({ node, onUpdate }: NodeFormActionProps) {
{/* Expected Outcome */} {/* Expected Outcome */}
<div> <div>
<label className="block text-sm font-medium text-white"> <label className="block text-sm font-medium text-foreground">
Expected Outcome Expected Outcome
</label> </label>
<input <input
@@ -157,7 +157,7 @@ export function NodeFormAction({ node, onUpdate }: NodeFormActionProps) {
onChange={(e) => onUpdate({ expected_outcome: e.target.value })} onChange={(e) => onUpdate({ expected_outcome: e.target.value })}
placeholder="e.g., Service should show as Running" placeholder="e.g., Service should show as Running"
className={cn( className={cn(
'mt-1 block w-full rounded-md border border-white/10 px-3 py-2 text-sm', 'mt-1 block w-full rounded-md border border-border px-3 py-2 text-sm',
'bg-background text-foreground placeholder:text-muted-foreground', 'bg-background text-foreground placeholder:text-muted-foreground',
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary' 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary'
)} )}

View File

@@ -67,7 +67,7 @@ export function NodeFormDecision({ node, onUpdate }: NodeFormDecisionProps) {
<h3 className="font-semibold text-blue-400"> <h3 className="font-semibold text-blue-400">
Starting Question Starting Question
</h3> </h3>
<p className="mt-1 text-sm text-white/40"> <p className="mt-1 text-sm text-muted-foreground">
This is the first question users will see when they start this troubleshooting tree. This is the first question users will see when they start this troubleshooting tree.
Each option below creates a different troubleshooting path. Each option below creates a different troubleshooting path.
</p> </p>
@@ -78,11 +78,11 @@ export function NodeFormDecision({ node, onUpdate }: NodeFormDecisionProps) {
{/* Question */} {/* Question */}
<div> <div>
<label className="block text-sm font-medium text-white"> <label className="block text-sm font-medium text-foreground">
{isRootNode ? 'Starting Question' : 'Question'} <span className="text-red-400">*</span> {isRootNode ? 'Starting Question' : 'Question'} <span className="text-red-400">*</span>
</label> </label>
{isRootNode && ( {isRootNode && (
<p className="mt-0.5 text-xs text-white/40"> <p className="mt-0.5 text-xs text-muted-foreground">
What's the main question to diagnose the issue? What's the main question to diagnose the issue?
</p> </p>
)} )}
@@ -95,9 +95,9 @@ export function NodeFormDecision({ node, onUpdate }: NodeFormDecisionProps) {
: "e.g., Can you ping the server?"} : "e.g., Can you ping the server?"}
className={cn( className={cn(
'mt-1 block w-full rounded-md border px-3 py-2 text-sm', 'mt-1 block w-full rounded-md border px-3 py-2 text-sm',
'bg-black/50 text-white placeholder:text-white/40', 'bg-card text-foreground placeholder:text-muted-foreground',
'focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20', 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20',
questionError ? 'border-red-400' : 'border-white/10' questionError ? 'border-red-400' : 'border-border'
)} )}
/> />
{questionError && ( {questionError && (
@@ -107,7 +107,7 @@ export function NodeFormDecision({ node, onUpdate }: NodeFormDecisionProps) {
{/* Help Text */} {/* Help Text */}
<div> <div>
<label className="block text-sm font-medium text-white"> <label className="block text-sm font-medium text-foreground">
Help Text Help Text
</label> </label>
<textarea <textarea
@@ -116,7 +116,7 @@ export function NodeFormDecision({ node, onUpdate }: NodeFormDecisionProps) {
placeholder="Additional context or instructions for this decision..." placeholder="Additional context or instructions for this decision..."
rows={2} rows={2}
className={cn( className={cn(
'mt-1 block w-full rounded-md border border-white/10 px-3 py-2 text-sm', 'mt-1 block w-full rounded-md border border-border px-3 py-2 text-sm',
'bg-background text-foreground placeholder:text-muted-foreground', 'bg-background text-foreground placeholder:text-muted-foreground',
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary' 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary'
)} )}
@@ -125,15 +125,15 @@ export function NodeFormDecision({ node, onUpdate }: NodeFormDecisionProps) {
{/* Options */} {/* Options */}
<div> <div>
<label className="block text-sm font-medium text-white"> <label className="block text-sm font-medium text-foreground">
{isRootNode ? 'Answer Options (Branches)' : 'Options'} <span className="text-red-400">*</span> {isRootNode ? 'Answer Options (Branches)' : 'Options'} <span className="text-red-400">*</span>
</label> </label>
{isRootNode ? ( {isRootNode ? (
<p className="mt-0.5 text-xs text-white/40"> <p className="mt-0.5 text-xs text-muted-foreground">
Add as many options as needed (A, B, C, D...). Each option leads to a completely different troubleshooting path. Add as many options as needed (A, B, C, D...). Each option leads to a completely different troubleshooting path.
</p> </p>
) : ( ) : (
<p className="mt-0.5 text-xs text-white/40"> <p className="mt-0.5 text-xs text-muted-foreground">
Each option can branch to a different next step. Each option can branch to a different next step.
</p> </p>
)} )}
@@ -158,14 +158,14 @@ export function NodeFormDecision({ node, onUpdate }: NodeFormDecisionProps) {
const letter = indexToLetter(index) const letter = indexToLetter(index)
return ( return (
<div className="rounded-md border border-white/10 bg-white/[0.04] p-3"> <div className="rounded-md border border-border bg-accent/50 p-3">
<div className="mb-2 flex items-center gap-2"> <div className="mb-2 flex items-center gap-2">
{/* Letter badge */} {/* Letter badge */}
<span className={cn( <span className={cn(
'flex h-6 w-6 items-center justify-center rounded-full text-xs font-bold', 'flex h-6 w-6 items-center justify-center rounded-full text-xs font-bold',
isRootNode isRootNode
? 'bg-blue-500/20 text-blue-400' ? 'bg-blue-500/20 text-blue-400'
: 'bg-white/10 text-white/50' : 'bg-accent text-muted-foreground'
)}> )}>
{letter} {letter}
</span> </span>
@@ -180,7 +180,7 @@ export function NodeFormDecision({ node, onUpdate }: NodeFormDecisionProps) {
'block flex-1 rounded-md border px-3 py-2 text-sm', 'block flex-1 rounded-md border px-3 py-2 text-sm',
'bg-background text-foreground placeholder:text-muted-foreground', 'bg-background text-foreground placeholder:text-muted-foreground',
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary', 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary',
optionLabelError ? 'border-red-400' : 'border-white/10' optionLabelError ? 'border-red-400' : 'border-border'
)} )}
/> />
</div> </div>
@@ -207,7 +207,7 @@ export function NodeFormDecision({ node, onUpdate }: NodeFormDecisionProps) {
{/* Example hint for root node */} {/* Example hint for root node */}
{isRootNode && (node.options?.length || 0) < 2 && ( {isRootNode && (node.options?.length || 0) < 2 && (
<div className="mt-3 rounded-md border border-dashed border-white/10 bg-white/[0.02] p-3 text-xs text-white/40"> <div className="mt-3 rounded-md border border-dashed border-border bg-accent/50 p-3 text-xs text-muted-foreground">
<strong>Tip:</strong> Most troubleshooting trees start with 2-5 main branches. <strong>Tip:</strong> Most troubleshooting trees start with 2-5 main branches.
For example: "Connection Issues", "Performance Problems", "Error Messages", "Other". For example: "Connection Issues", "Performance Problems", "Error Messages", "Other".
</div> </div>

View File

@@ -47,7 +47,7 @@ export function NodeFormResolution({ node, onUpdate }: NodeFormResolutionProps)
<div className="space-y-4"> <div className="space-y-4">
{/* Title */} {/* Title */}
<div> <div>
<label className="block text-sm font-medium text-white"> <label className="block text-sm font-medium text-foreground">
Title <span className="text-red-400">*</span> Title <span className="text-red-400">*</span>
</label> </label>
<input <input
@@ -57,9 +57,9 @@ export function NodeFormResolution({ node, onUpdate }: NodeFormResolutionProps)
placeholder="e.g., VDA Successfully Registered" placeholder="e.g., VDA Successfully Registered"
className={cn( className={cn(
'mt-1 block w-full rounded-md border px-3 py-2 text-sm', 'mt-1 block w-full rounded-md border px-3 py-2 text-sm',
'bg-black/50 text-white placeholder:text-white/40', 'bg-card text-foreground placeholder:text-muted-foreground',
'focus:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20', 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20',
titleError ? 'border-red-400' : 'border-white/10' titleError ? 'border-red-400' : 'border-border'
)} )}
/> />
{titleError && ( {titleError && (
@@ -70,24 +70,24 @@ export function NodeFormResolution({ node, onUpdate }: NodeFormResolutionProps)
{/* Description */} {/* Description */}
<div> <div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<label className="block text-sm font-medium text-white"> <label className="block text-sm font-medium text-foreground">
Description Description
</label> </label>
{node.description && ( {node.description && (
<button <button
type="button" type="button"
onClick={() => setShowPreview(!showPreview)} onClick={() => setShowPreview(!showPreview)}
className="text-xs text-white/50 hover:text-white hover:underline" className="text-xs text-muted-foreground hover:text-foreground hover:underline"
> >
{showPreview ? 'Edit' : 'Preview'} {showPreview ? 'Edit' : 'Preview'}
</button> </button>
)} )}
</div> </div>
<p className="mb-1 text-xs text-white/40"> <p className="mb-1 text-xs text-muted-foreground">
Supports markdown: **bold**, *italic*, - lists, 1. numbered lists, `code` Supports markdown: **bold**, *italic*, - lists, 1. numbered lists, `code`
</p> </p>
{showPreview && node.description ? ( {showPreview && node.description ? (
<div className="mt-1 rounded-md border border-white/10 bg-white/[0.04] p-3 text-sm"> <div className="mt-1 rounded-md border border-border bg-accent/50 p-3 text-sm">
<MarkdownContent content={node.description} /> <MarkdownContent content={node.description} />
</div> </div>
) : ( ) : (
@@ -102,7 +102,7 @@ Document what was done and the outcome.
**Close ticket as:** Resolved" **Close ticket as:** Resolved"
rows={5} rows={5}
className={cn( className={cn(
'mt-1 block w-full rounded-md border border-white/10 px-3 py-2 text-sm', 'mt-1 block w-full rounded-md border border-border px-3 py-2 text-sm',
'bg-background text-foreground placeholder:text-muted-foreground', 'bg-background text-foreground placeholder:text-muted-foreground',
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary' 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary'
)} )}
@@ -112,10 +112,10 @@ Document what was done and the outcome.
{/* Resolution Steps */} {/* Resolution Steps */}
<div> <div>
<label className="block text-sm font-medium text-white"> <label className="block text-sm font-medium text-foreground">
Resolution Steps Resolution Steps
</label> </label>
<p className="mb-2 text-xs text-white/40"> <p className="mb-2 text-xs text-muted-foreground">
Step-by-step instructions for resolving the issue Step-by-step instructions for resolving the issue
</p> </p>
<DynamicArrayField <DynamicArrayField
@@ -135,7 +135,7 @@ Document what was done and the outcome.
onChange={(e) => handleUpdateStep(index, e.target.value)} onChange={(e) => handleUpdateStep(index, e.target.value)}
placeholder={`Step ${index + 1}`} placeholder={`Step ${index + 1}`}
className={cn( className={cn(
'block w-full rounded-md border border-white/10 px-3 py-2 text-sm', 'block w-full rounded-md border border-border px-3 py-2 text-sm',
'bg-background text-foreground placeholder:text-muted-foreground', 'bg-background text-foreground placeholder:text-muted-foreground',
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary' 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary'
)} )}

View File

@@ -95,9 +95,9 @@ function NodeListItem({
} }
const nodeTypeColors: Record<NodeType, string> = { const nodeTypeColors: Record<NodeType, string> = {
decision: 'bg-blue-500/20 text-blue-600 dark:text-blue-400', decision: 'bg-blue-500/20 text-blue-400',
action: 'bg-yellow-500/20 text-yellow-600 dark:text-yellow-400', action: 'bg-yellow-500/20 text-yellow-400',
solution: 'bg-green-500/20 text-green-600 dark:text-green-400' solution: 'bg-green-500/20 text-green-400'
} }
const getNodeLabel = () => { const getNodeLabel = () => {
@@ -223,7 +223,7 @@ function NodeListItem({
{/* Node type icon - special treatment for root */} {/* Node type icon - special treatment for root */}
{isRootNode ? ( {isRootNode ? (
<span className="flex items-center gap-1 rounded px-1.5 py-0.5 text-xs bg-blue-500/30 text-blue-600 dark:text-blue-400 font-semibold"> <span className="flex items-center gap-1 rounded px-1.5 py-0.5 text-xs bg-blue-500/30 text-blue-400 font-semibold">
<Play className="h-4 w-4" /> <Play className="h-4 w-4" />
<span className="hidden sm:inline">START</span> <span className="hidden sm:inline">START</span>
</span> </span>
@@ -254,7 +254,7 @@ function NodeListItem({
'flex items-center gap-1 rounded px-1.5 py-0.5 text-xs', 'flex items-center gap-1 rounded px-1.5 py-0.5 text-xs',
hasError hasError
? 'bg-destructive/20 text-destructive' ? 'bg-destructive/20 text-destructive'
: 'bg-yellow-500/20 text-yellow-600 dark:text-yellow-500' : 'bg-yellow-500/20 text-yellow-500'
)} )}
> >
{hasError ? ( {hasError ? (

View File

@@ -28,12 +28,12 @@ export function TreeEditorLayout({ isMobile = false }: TreeEditorLayoutProps) {
<> <>
{/* Code Mode: Monaco editor (60%) + Preview (40%) */} {/* Code Mode: Monaco editor (60%) + Preview (40%) */}
<div className={cn( <div className={cn(
'flex flex-col overflow-hidden border-white/[0.06]', 'flex flex-col overflow-hidden border-border',
isMobile ? 'h-full w-full border-b' : 'w-3/5 border-r' isMobile ? 'h-full w-full border-b' : 'w-3/5 border-r'
)}> )}>
<Suspense fallback={ <Suspense fallback={
<div className="flex h-full items-center justify-center bg-[#0a0a0a]"> <div className="flex h-full items-center justify-center bg-card">
<div className="h-6 w-6 animate-spin rounded-full border-2 border-white/20 border-t-white" /> <div className="h-6 w-6 animate-spin rounded-full border-2 border-border border-t-foreground" />
</div> </div>
}> }>
<CodeModeEditor /> <CodeModeEditor />
@@ -42,7 +42,7 @@ export function TreeEditorLayout({ isMobile = false }: TreeEditorLayoutProps) {
{/* Right Panel - Preview */} {/* Right Panel - Preview */}
<div className={cn( <div className={cn(
'flex-1 overflow-hidden bg-white/[0.02]', 'flex-1 overflow-hidden bg-accent/50',
isMobile ? 'hidden' : 'block' isMobile ? 'hidden' : 'block'
)}> )}>
<TreePreviewPanel /> <TreePreviewPanel />
@@ -52,7 +52,7 @@ export function TreeEditorLayout({ isMobile = false }: TreeEditorLayoutProps) {
<> <>
{/* Flow Mode: Form editor (60%) + Preview (40%) */} {/* Flow Mode: Form editor (60%) + Preview (40%) */}
<div className={cn( <div className={cn(
'flex flex-col overflow-y-auto border-white/[0.06]', 'flex flex-col overflow-y-auto border-border',
isMobile ? 'h-full w-full border-b' : 'w-3/5 border-r' isMobile ? 'h-full w-full border-b' : 'w-3/5 border-r'
)}> )}>
<div className="space-y-4 p-4"> <div className="space-y-4 p-4">
@@ -63,7 +63,7 @@ export function TreeEditorLayout({ isMobile = false }: TreeEditorLayoutProps) {
{/* Right Panel - Preview */} {/* Right Panel - Preview */}
<div className={cn( <div className={cn(
'flex-1 overflow-hidden bg-white/[0.02]', 'flex-1 overflow-hidden bg-accent/50',
isMobile ? 'hidden' : 'block' isMobile ? 'hidden' : 'block'
)}> )}>
<TreePreviewPanel /> <TreePreviewPanel />

View File

@@ -35,7 +35,7 @@ export function ValidationSummary({ errors, onSelectNode }: ValidationSummaryPro
<button <button
onClick={() => setIsExpanded(!isExpanded)} onClick={() => setIsExpanded(!isExpanded)}
className={cn( className={cn(
'flex w-full items-center justify-between p-3 text-left transition-colors hover:bg-white/5', 'flex w-full items-center justify-between p-3 text-left transition-colors hover:bg-accent',
errorItems.length > 0 ? 'text-red-400' : 'text-yellow-400' errorItems.length > 0 ? 'text-red-400' : 'text-yellow-400'
)} )}
> >
@@ -81,7 +81,7 @@ export function ValidationSummary({ errors, onSelectNode }: ValidationSummaryPro
<div className="flex-1"> <div className="flex-1">
<p className="text-red-400">{error.message}</p> <p className="text-red-400">{error.message}</p>
{error.nodeId && ( {error.nodeId && (
<p className="mt-0.5 text-xs text-white/40"> <p className="mt-0.5 text-xs text-muted-foreground">
Click to select node: {error.nodeId} Click to select node: {error.nodeId}
</p> </p>
)} )}
@@ -105,7 +105,7 @@ export function ValidationSummary({ errors, onSelectNode }: ValidationSummaryPro
<div className="flex-1"> <div className="flex-1">
<p className="text-yellow-400">{warning.message}</p> <p className="text-yellow-400">{warning.message}</p>
{warning.nodeId && ( {warning.nodeId && (
<p className="mt-0.5 text-xs text-white/40"> <p className="mt-0.5 text-xs text-muted-foreground">
Click to select node: {warning.nodeId} Click to select node: {warning.nodeId}
</p> </p>
)} )}

View File

@@ -166,8 +166,8 @@ export function CodeModeEditor() {
beforeMount={handleEditorWillMount} beforeMount={handleEditorWillMount}
onMount={handleEditorDidMount} onMount={handleEditorDidMount}
loading={ loading={
<div className="flex h-full items-center justify-center bg-[#0a0a0a]"> <div className="flex h-full items-center justify-center bg-card">
<div className="h-6 w-6 animate-spin rounded-full border-2 border-white/20 border-t-white" /> <div className="h-6 w-6 animate-spin rounded-full border-2 border-border border-t-foreground" />
</div> </div>
} }
options={{ options={{

View File

@@ -91,15 +91,15 @@ export function CodeModeToolbar({
}, []) }, [])
return ( return (
<div className="flex items-center justify-between border-b border-white/[0.06] bg-black/50 px-3 py-1.5"> <div className="flex items-center justify-between border-b border-border bg-card px-3 py-1.5">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{/* Insert Node dropdown */} {/* Insert Node dropdown */}
<div className="relative" ref={dropdownRef}> <div className="relative" ref={dropdownRef}>
<button <button
onClick={() => setInsertOpen(!insertOpen)} onClick={() => setInsertOpen(!insertOpen)}
className={cn( className={cn(
'flex items-center gap-1 rounded-md border border-white/10 px-2.5 py-1 text-xs font-medium text-white/60', 'flex items-center gap-1 rounded-md border border-border px-2.5 py-1 text-xs font-medium text-muted-foreground',
'hover:bg-white/10 hover:text-white' 'hover:bg-accent hover:text-foreground'
)} )}
> >
<Plus className="h-3 w-3" /> <Plus className="h-3 w-3" />
@@ -107,24 +107,24 @@ export function CodeModeToolbar({
<ChevronDown className="h-3 w-3" /> <ChevronDown className="h-3 w-3" />
</button> </button>
{insertOpen && ( {insertOpen && (
<div className="absolute left-0 top-full z-50 mt-1 w-44 rounded-lg border border-white/10 bg-[#111] py-1 shadow-xl"> <div className="absolute left-0 top-full z-50 mt-1 w-44 rounded-lg border border-border bg-card py-1 shadow-xl">
<button <button
onClick={() => { onInsertTemplate(NODE_TEMPLATES.decision); setInsertOpen(false) }} onClick={() => { onInsertTemplate(NODE_TEMPLATES.decision); setInsertOpen(false) }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-xs text-white/70 hover:bg-white/10" className="flex w-full items-center gap-2 px-3 py-1.5 text-xs text-muted-foreground hover:bg-accent"
> >
<span className="h-2 w-2 rounded-full bg-blue-400" /> <span className="h-2 w-2 rounded-full bg-blue-400" />
Decision Decision
</button> </button>
<button <button
onClick={() => { onInsertTemplate(NODE_TEMPLATES.action); setInsertOpen(false) }} onClick={() => { onInsertTemplate(NODE_TEMPLATES.action); setInsertOpen(false) }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-xs text-white/70 hover:bg-white/10" className="flex w-full items-center gap-2 px-3 py-1.5 text-xs text-muted-foreground hover:bg-accent"
> >
<span className="h-2 w-2 rounded-full bg-amber-400" /> <span className="h-2 w-2 rounded-full bg-amber-400" />
Action Action
</button> </button>
<button <button
onClick={() => { onInsertTemplate(NODE_TEMPLATES.solution); setInsertOpen(false) }} onClick={() => { onInsertTemplate(NODE_TEMPLATES.solution); setInsertOpen(false) }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-xs text-white/70 hover:bg-white/10" className="flex w-full items-center gap-2 px-3 py-1.5 text-xs text-muted-foreground hover:bg-accent"
> >
<span className="h-2 w-2 rounded-full bg-emerald-400" /> <span className="h-2 w-2 rounded-full bg-emerald-400" />
Solution Solution
@@ -139,8 +139,8 @@ export function CodeModeToolbar({
<div className="flex items-center gap-1.5 text-xs"> <div className="flex items-center gap-1.5 text-xs">
{isValidating ? ( {isValidating ? (
<> <>
<Loader2 className="h-3 w-3 animate-spin text-white/40" /> <Loader2 className="h-3 w-3 animate-spin text-muted-foreground" />
<span className="text-white/40">Validating...</span> <span className="text-muted-foreground">Validating...</span>
</> </>
) : isValid ? ( ) : isValid ? (
<> <>
@@ -173,8 +173,8 @@ export function CodeModeToolbar({
className={cn( className={cn(
'flex items-center gap-1 rounded-md px-2 py-1 text-xs', 'flex items-center gap-1 rounded-md px-2 py-1 text-xs',
syntaxHelpOpen syntaxHelpOpen
? 'bg-white/10 text-white' ? 'bg-accent text-foreground'
: 'text-white/40 hover:bg-white/[0.06] hover:text-white/60' : 'text-muted-foreground hover:bg-accent hover:text-muted-foreground'
)} )}
> >
<HelpCircle className="h-3 w-3" /> <HelpCircle className="h-3 w-3" />

View File

@@ -10,17 +10,17 @@ export function SyntaxHelpPanel({ open, onClose }: SyntaxHelpPanelProps) {
if (!open) return null if (!open) return null
return ( return (
<div className="flex h-full flex-col border-l border-white/[0.06] bg-[#0a0a0a]"> <div className="flex h-full flex-col border-l border-border bg-card">
<div className="flex items-center justify-between border-b border-white/[0.06] px-3 py-2"> <div className="flex items-center justify-between border-b border-border px-3 py-2">
<span className="text-xs font-medium text-white/60">Syntax Reference</span> <span className="text-xs font-medium text-muted-foreground">Syntax Reference</span>
<button <button
onClick={onClose} onClick={onClose}
className="rounded p-0.5 text-white/30 hover:bg-white/10 hover:text-white/60" className="rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-muted-foreground"
> >
<X className="h-3.5 w-3.5" /> <X className="h-3.5 w-3.5" />
</button> </button>
</div> </div>
<div className="flex-1 overflow-y-auto px-3 py-3 text-[11px] leading-relaxed text-white/50"> <div className="flex-1 overflow-y-auto px-3 py-3 text-[11px] leading-relaxed text-muted-foreground">
<Section title="Node Structure"> <Section title="Node Structure">
<Code>{`--- <Code>{`---
id: node_id id: node_id
@@ -82,7 +82,7 @@ Description paragraph.
function Section({ title, children }: { title: string; children: React.ReactNode }) { function Section({ title, children }: { title: string; children: React.ReactNode }) {
return ( return (
<div className="mb-4"> <div className="mb-4">
<h4 className="mb-1.5 text-[11px] font-semibold uppercase tracking-wider text-white/30">{title}</h4> <h4 className="mb-1.5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">{title}</h4>
{children} {children}
</div> </div>
) )
@@ -91,8 +91,8 @@ function Section({ title, children }: { title: string; children: React.ReactNode
function Code({ children }: { children: string }) { function Code({ children }: { children: string }) {
return ( return (
<pre className={cn( <pre className={cn(
'mb-2 overflow-x-auto rounded-md border border-white/[0.06] bg-black/50 px-2 py-1.5', 'mb-2 overflow-x-auto rounded-md border border-border bg-card px-2 py-1.5',
'text-[10px] leading-relaxed text-white/50 whitespace-pre' 'text-[10px] leading-relaxed text-muted-foreground whitespace-pre'
)}> )}>
{children} {children}
</pre> </pre>
@@ -102,8 +102,8 @@ function Code({ children }: { children: string }) {
function Row({ label, code }: { label: string; code: string }) { function Row({ label, code }: { label: string; code: string }) {
return ( return (
<div className="flex items-center justify-between py-0.5"> <div className="flex items-center justify-between py-0.5">
<span className="text-white/40">{label}</span> <span className="text-muted-foreground">{label}</span>
<code className="rounded bg-white/[0.06] px-1 py-0.5 text-[10px] text-white/50">{code}</code> <code className="rounded bg-accent px-1 py-0.5 text-[10px] text-muted-foreground">{code}</code>
</div> </div>
) )
} }

View File

@@ -154,8 +154,8 @@ export function TreePreviewNode({
<div className="relative"> <div className="relative">
{/* From option label */} {/* From option label */}
{fromOption && ( {fromOption && (
<div className="mb-1 text-xs font-medium text-white/40"> <div className="mb-1 text-xs font-medium text-muted-foreground">
<span className="rounded bg-white/10 px-1.5 py-0.5">{fromOption}</span> <span className="rounded bg-accent px-1.5 py-0.5">{fromOption}</span>
</div> </div>
)} )}
@@ -185,7 +185,7 @@ export function TreePreviewNode({
className="absolute -top-1.5 -right-1.5 flex items-center justify-center rounded-full bg-green-500/90 p-0.5 shadow-sm" className="absolute -top-1.5 -right-1.5 flex items-center justify-center rounded-full bg-green-500/90 p-0.5 shadow-sm"
title="This branch leads to a solution" title="This branch leads to a solution"
> >
<CheckCircle className="h-3 w-3 text-white" /> <CheckCircle className="h-3 w-3 text-foreground" />
</div> </div>
)} )}
{/* Root node START header */} {/* Root node START header */}
@@ -206,12 +206,12 @@ export function TreePreviewNode({
<button <button
type="button" type="button"
onClick={toggleCollapse} onClick={toggleCollapse}
className="mt-0.5 rounded p-0.5 hover:bg-white/10" className="mt-0.5 rounded p-0.5 hover:bg-accent"
> >
{isCollapsed ? ( {isCollapsed ? (
<ChevronRight className="h-4 w-4 text-white/50" /> <ChevronRight className="h-4 w-4 text-muted-foreground" />
) : ( ) : (
<ChevronDown className="h-4 w-4 text-white/50" /> <ChevronDown className="h-4 w-4 text-muted-foreground" />
)} )}
</button> </button>
) : ( ) : (
@@ -222,14 +222,14 @@ export function TreePreviewNode({
{isRootNode && <HelpCircle className="h-4 w-4 text-blue-500" />} {isRootNode && <HelpCircle className="h-4 w-4 text-blue-500" />}
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<p className="text-sm font-medium text-white leading-tight"> <p className="text-sm font-medium text-foreground leading-tight">
{getNodeLabel()} {getNodeLabel()}
</p> </p>
{/* Node ID with copy button */} {/* Node ID with copy button */}
<div className="flex items-center gap-1 mt-1"> <div className="flex items-center gap-1 mt-1">
<span <span
className="text-xs text-white/40 cursor-help" className="text-xs text-muted-foreground cursor-help"
title={`Full ID: ${node.id}`} title={`Full ID: ${node.id}`}
> >
{node.id === 'root' ? 'root' : node.id.slice(0, 8) + '...'} {node.id === 'root' ? 'root' : node.id.slice(0, 8) + '...'}
@@ -237,7 +237,7 @@ export function TreePreviewNode({
<button <button
type="button" type="button"
onClick={handleCopyId} onClick={handleCopyId}
className="rounded p-0.5 text-white/40 hover:bg-white/10 hover:text-white" className="rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-foreground"
title="Copy full ID" title="Copy full ID"
> >
{copiedId ? ( {copiedId ? (
@@ -252,8 +252,8 @@ export function TreePreviewNode({
{/* Show options for decision nodes */} {/* Show options for decision nodes */}
{node.type === 'decision' && node.options && node.options.length > 0 && ( {node.type === 'decision' && node.options && node.options.length > 0 && (
<div className="mt-2 space-y-1 border-t border-white/[0.06] pt-2"> <div className="mt-2 space-y-1 border-t border-border pt-2">
<p className="text-[10px] uppercase tracking-wide text-white/40">Options:</p> <p className="text-[10px] uppercase tracking-wide text-muted-foreground">Options:</p>
{node.options.map((opt, i) => { {node.options.map((opt, i) => {
const leadsToSolution = nodeLeadsToSolution(opt.next_node_id) const leadsToSolution = nodeLeadsToSolution(opt.next_node_id)
return ( return (
@@ -261,15 +261,15 @@ export function TreePreviewNode({
key={opt.id} key={opt.id}
className={cn( className={cn(
'flex items-center gap-1 text-xs rounded px-1 py-0.5 -mx-1', 'flex items-center gap-1 text-xs rounded px-1 py-0.5 -mx-1',
opt.next_node_id && 'hover:bg-white/[0.06] cursor-pointer' opt.next_node_id && 'hover:bg-accent cursor-pointer'
)} )}
onMouseEnter={() => opt.next_node_id && onHoverNodeId?.(opt.next_node_id)} onMouseEnter={() => opt.next_node_id && onHoverNodeId?.(opt.next_node_id)}
onMouseLeave={() => onHoverNodeId?.(null)} onMouseLeave={() => onHoverNodeId?.(null)}
> >
<span className="inline-flex h-4 w-4 items-center justify-center rounded bg-white/10 text-[10px] font-medium text-white/50"> <span className="inline-flex h-4 w-4 items-center justify-center rounded bg-accent text-[10px] font-medium text-muted-foreground">
{i + 1} {i + 1}
</span> </span>
<span className="truncate text-white/70">{opt.label || 'Untitled'}</span> <span className="truncate text-muted-foreground">{opt.label || 'Untitled'}</span>
<span className="ml-auto flex items-center gap-1"> <span className="ml-auto flex items-center gap-1">
{leadsToSolution && ( {leadsToSolution && (
<span title="Leads to solution"> <span title="Leads to solution">
@@ -279,7 +279,7 @@ export function TreePreviewNode({
{opt.next_node_id ? ( {opt.next_node_id ? (
<span className="text-blue-500"></span> <span className="text-blue-500"></span>
) : ( ) : (
<span className="text-white/30 text-[10px]">(no link)</span> <span className="text-muted-foreground text-[10px]">(no link)</span>
)} )}
</span> </span>
</div> </div>
@@ -308,12 +308,12 @@ export function TreePreviewNode({
return ( return (
<div <div
className="mt-2 text-xs border-t border-white/[0.06] pt-2 hover:bg-white/[0.04] cursor-pointer rounded px-1 -mx-1" className="mt-2 text-xs border-t border-border pt-2 hover:bg-accent/50 cursor-pointer rounded px-1 -mx-1"
onMouseEnter={() => onHoverNodeId?.(node.next_node_id!)} onMouseEnter={() => onHoverNodeId?.(node.next_node_id!)}
onMouseLeave={() => onHoverNodeId?.(null)} onMouseLeave={() => onHoverNodeId?.(null)}
> >
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<span className="text-white/40">Next:</span> <span className="text-muted-foreground">Next:</span>
{isSharedTarget && ( {isSharedTarget && (
<span title={sharedTooltip} className="flex items-center"> <span title={sharedTooltip} className="flex items-center">
<Users className="h-3 w-3 text-purple-500" /> <Users className="h-3 w-3 text-purple-500" />
@@ -321,7 +321,7 @@ export function TreePreviewNode({
)} )}
<span className={cn( <span className={cn(
'truncate', 'truncate',
nextNode?.type === 'solution' ? 'text-green-500 font-medium' : 'text-white/70' nextNode?.type === 'solution' ? 'text-green-500 font-medium' : 'text-muted-foreground'
)}> )}>
{nextNodeLabel.slice(0, 30)}{nextNodeLabel.length > 30 ? '...' : ''} {nextNodeLabel.slice(0, 30)}{nextNodeLabel.length > 30 ? '...' : ''}
</span> </span>
@@ -347,7 +347,7 @@ export function TreePreviewNode({
{/* Children - show as branches */} {/* Children - show as branches */}
{hasChildren && !isCollapsed && ( {hasChildren && !isCollapsed && (
<div className="relative mt-3 ml-6 pl-6 border-l-2 border-white/[0.06]"> <div className="relative mt-3 ml-6 pl-6 border-l-2 border-border">
<div className="space-y-4"> <div className="space-y-4">
{node.children!.map((child) => { {node.children!.map((child) => {
const optionLabel = getOptionLabelForChild(child.id) const optionLabel = getOptionLabelForChild(child.id)
@@ -355,7 +355,7 @@ export function TreePreviewNode({
return ( return (
<div key={child.id} className="relative"> <div key={child.id} className="relative">
{/* Horizontal connector line */} {/* Horizontal connector line */}
<div className="absolute -left-6 top-6 h-0.5 w-6 bg-white/[0.06]" /> <div className="absolute -left-6 top-6 h-0.5 w-6 bg-border" />
<TreePreviewNode <TreePreviewNode
node={child} node={child}
@@ -377,8 +377,8 @@ export function TreePreviewNode({
{/* Show collapsed indicator */} {/* Show collapsed indicator */}
{hasChildren && isCollapsed && ( {hasChildren && isCollapsed && (
<div className="mt-2 ml-6 text-xs text-white/40"> <div className="mt-2 ml-6 text-xs text-muted-foreground">
<span className="rounded bg-white/10 px-2 py-1"> <span className="rounded bg-accent px-2 py-1">
{node.children!.length} child node{node.children!.length !== 1 ? 's' : ''} hidden {node.children!.length} child node{node.children!.length !== 1 ? 's' : ''} hidden
</span> </span>
</div> </div>

View File

@@ -56,7 +56,7 @@ export function TreePreviewPanel() {
if (!treeStructure) { if (!treeStructure) {
return ( return (
<div className="flex h-full items-center justify-center p-4 text-sm text-white/40"> <div className="flex h-full items-center justify-center p-4 text-sm text-muted-foreground">
No tree structure to preview No tree structure to preview
</div> </div>
) )
@@ -65,11 +65,11 @@ export function TreePreviewPanel() {
return ( return (
<div className="flex h-full flex-col"> <div className="flex h-full flex-col">
{/* Header */} {/* Header */}
<div className="border-b border-white/[0.06] px-4 py-2"> <div className="border-b border-border px-4 py-2">
<h3 className="text-sm font-semibold text-white"> <h3 className="text-sm font-semibold text-foreground">
Preview: {name || 'Untitled Tree'} Preview: {name || 'Untitled Tree'}
</h3> </h3>
<p className="text-xs text-white/40"> <p className="text-xs text-muted-foreground">
Click a node to select Hover options to highlight targets Click a node to select Hover options to highlight targets
</p> </p>
</div> </div>
@@ -91,8 +91,8 @@ export function TreePreviewPanel() {
</div> </div>
{/* Legend */} {/* Legend */}
<div className="border-t border-white/[0.06] px-4 py-2"> <div className="border-t border-border px-4 py-2">
<div className="flex flex-wrap gap-4 text-xs text-white/40"> <div className="flex flex-wrap gap-4 text-xs text-muted-foreground">
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<div className="h-3 w-3 rounded bg-blue-500/50" /> <div className="h-3 w-3 rounded bg-blue-500/50" />
<span>Decision</span> <span>Decision</span>

View File

@@ -12,7 +12,7 @@ interface MarkdownContentProps {
*/ */
export function MarkdownContent({ content, className }: MarkdownContentProps) { export function MarkdownContent({ content, className }: MarkdownContentProps) {
return ( return (
<div className={cn('prose prose-sm dark:prose-invert max-w-none', className)}> <div className={cn('prose prose-sm prose-invert max-w-none', className)}>
<ReactMarkdown <ReactMarkdown
components={{ components={{
// Style paragraphs // Style paragraphs
@@ -21,7 +21,7 @@ export function MarkdownContent({ content, className }: MarkdownContentProps) {
), ),
// Style bold text // Style bold text
strong: ({ children }) => ( strong: ({ children }) => (
<strong className="font-semibold text-white">{children}</strong> <strong className="font-semibold text-foreground">{children}</strong>
), ),
// Style ordered lists // Style ordered lists
ol: ({ children }) => ( ol: ({ children }) => (
@@ -33,7 +33,7 @@ export function MarkdownContent({ content, className }: MarkdownContentProps) {
), ),
// Style list items // Style list items
li: ({ children }) => ( li: ({ children }) => (
<li className="text-white/60">{children}</li> <li className="text-muted-foreground">{children}</li>
), ),
// Style inline code // Style inline code
code: ({ className, children, ...props }) => { code: ({ className, children, ...props }) => {
@@ -43,7 +43,7 @@ export function MarkdownContent({ content, className }: MarkdownContentProps) {
return ( return (
<code <code
className={cn( className={cn(
'block rounded bg-white/10 p-3 font-mono text-sm overflow-x-auto', 'block rounded bg-accent p-3 font-mono text-sm overflow-x-auto',
className className
)} )}
{...props} {...props}
@@ -54,7 +54,7 @@ export function MarkdownContent({ content, className }: MarkdownContentProps) {
} }
return ( return (
<code <code
className="rounded bg-white/10 px-1.5 py-0.5 font-mono text-sm" className="rounded bg-accent px-1.5 py-0.5 font-mono text-sm"
{...props} {...props}
> >
{children} {children}
@@ -63,25 +63,25 @@ export function MarkdownContent({ content, className }: MarkdownContentProps) {
}, },
// Style code blocks (pre) // Style code blocks (pre)
pre: ({ children }) => ( pre: ({ children }) => (
<pre className="mb-3 overflow-x-auto rounded bg-white/10 p-0 last:mb-0"> <pre className="mb-3 overflow-x-auto rounded bg-accent p-0 last:mb-0">
{children} {children}
</pre> </pre>
), ),
// Style headers // Style headers
h1: ({ children }) => ( h1: ({ children }) => (
<h1 className="mb-3 text-lg font-bold text-white">{children}</h1> <h1 className="mb-3 text-lg font-bold text-foreground">{children}</h1>
), ),
h2: ({ children }) => ( h2: ({ children }) => (
<h2 className="mb-2 text-base font-bold text-white">{children}</h2> <h2 className="mb-2 text-base font-bold text-foreground">{children}</h2>
), ),
h3: ({ children }) => ( h3: ({ children }) => (
<h3 className="mb-2 text-sm font-bold text-white">{children}</h3> <h3 className="mb-2 text-sm font-bold text-foreground">{children}</h3>
), ),
// Style horizontal rules // Style horizontal rules
hr: () => <hr className="my-4 border-white/[0.06]" />, hr: () => <hr className="my-4 border-border" />,
// Style blockquotes // Style blockquotes
blockquote: ({ children }) => ( blockquote: ({ children }) => (
<blockquote className="mb-3 border-l-4 border-white/20 pl-4 italic text-white/50 last:mb-0"> <blockquote className="mb-3 border-l-4 border-border pl-4 italic text-muted-foreground last:mb-0">
{children} {children}
</blockquote> </blockquote>
), ),