mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
feat: place all styles in global vars (#1923)
* feat: place all styles in global vars * feat: prevented on workspace
This commit is contained in:
@@ -428,7 +428,7 @@ setSidebarWidth: (width) => {
|
||||
### Tailwind Classes
|
||||
|
||||
1. **No Inline Styles**: Use Tailwind utility classes exclusively
|
||||
2. **Dark Mode**: Always include dark mode variants (`dark:bg-[#1E1E1E]`)
|
||||
2. **Dark Mode**: Always include dark mode variants (`dark:bg-[var(--surface-1)]`)
|
||||
3. **Exact Values**: Use exact values from design system (`text-[14px]`, `h-[25px]`)
|
||||
4. **clsx for Conditionals**: Use clsx() for conditional classes
|
||||
5. **Consistent Spacing**: Use spacing tokens (`gap-[8px]`, `px-[14px]`)
|
||||
@@ -441,7 +441,7 @@ setSidebarWidth: (width) => {
|
||||
'base-classes that-always-apply',
|
||||
isActive && 'active-state-classes',
|
||||
disabled ? 'cursor-not-allowed opacity-60' : 'cursor-pointer hover:bg-accent',
|
||||
'dark:bg-[#1E1E1E] dark:border-[#2C2C2C]' // Dark mode variants
|
||||
'dark:bg-[var(--surface-1)] dark:border-[var(--border)]' // Dark mode variants
|
||||
)}
|
||||
>
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Eye, EyeOff } from 'lucide-react'
|
||||
import { ArrowRight, ChevronRight, Eye, EyeOff } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { useRouter, useSearchParams } from 'next/navigation'
|
||||
import { Button } from '@/components/ui/button'
|
||||
@@ -106,6 +106,7 @@ export default function LoginPage({
|
||||
const [passwordErrors, setPasswordErrors] = useState<string[]>([])
|
||||
const [showValidationError, setShowValidationError] = useState(false)
|
||||
const [buttonClass, setButtonClass] = useState('auth-button-gradient')
|
||||
const [isButtonHovered, setIsButtonHovered] = useState(false)
|
||||
|
||||
const [callbackUrl, setCallbackUrl] = useState('/workspace')
|
||||
const [isInviteFlow, setIsInviteFlow] = useState(false)
|
||||
@@ -113,6 +114,7 @@ export default function LoginPage({
|
||||
const [forgotPasswordOpen, setForgotPasswordOpen] = useState(false)
|
||||
const [forgotPasswordEmail, setForgotPasswordEmail] = useState('')
|
||||
const [isSubmittingReset, setIsSubmittingReset] = useState(false)
|
||||
const [isResetButtonHovered, setIsResetButtonHovered] = useState(false)
|
||||
const [resetStatus, setResetStatus] = useState<{
|
||||
type: 'success' | 'error' | null
|
||||
message: string
|
||||
@@ -482,10 +484,21 @@ export default function LoginPage({
|
||||
|
||||
<Button
|
||||
type='submit'
|
||||
className={`${buttonClass} flex w-full items-center justify-center gap-2 rounded-[10px] border font-medium text-[15px] text-white transition-all duration-200`}
|
||||
onMouseEnter={() => setIsButtonHovered(true)}
|
||||
onMouseLeave={() => setIsButtonHovered(false)}
|
||||
className='group inline-flex w-full items-center justify-center gap-2 rounded-[10px] border border-[#6F3DFA] bg-gradient-to-b from-[#8357FF] to-[#6F3DFA] py-[6px] pr-[10px] pl-[12px] text-[15px] text-white shadow-[inset_0_2px_4px_0_#9B77FF] transition-all'
|
||||
disabled={isLoading}
|
||||
>
|
||||
{isLoading ? 'Signing in...' : 'Sign in'}
|
||||
<span className='flex items-center gap-1'>
|
||||
{isLoading ? 'Signing in...' : 'Sign in'}
|
||||
<span className='inline-flex transition-transform duration-200 group-hover:translate-x-0.5'>
|
||||
{isButtonHovered ? (
|
||||
<ArrowRight className='h-4 w-4' aria-hidden='true' />
|
||||
) : (
|
||||
<ChevronRight className='h-4 w-4' aria-hidden='true' />
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
</Button>
|
||||
</form>
|
||||
)}
|
||||
@@ -600,10 +613,21 @@ export default function LoginPage({
|
||||
<Button
|
||||
type='button'
|
||||
onClick={handleForgotPassword}
|
||||
className={`${buttonClass} w-full rounded-[10px] border font-medium text-[15px] text-white transition-all duration-200`}
|
||||
onMouseEnter={() => setIsResetButtonHovered(true)}
|
||||
onMouseLeave={() => setIsResetButtonHovered(false)}
|
||||
className='group inline-flex w-full items-center justify-center gap-2 rounded-[10px] border border-[#6F3DFA] bg-gradient-to-b from-[#8357FF] to-[#6F3DFA] py-[6px] pr-[10px] pl-[12px] text-[15px] text-white shadow-[inset_0_2px_4px_0_#9B77FF] transition-all'
|
||||
disabled={isSubmittingReset}
|
||||
>
|
||||
{isSubmittingReset ? 'Sending...' : 'Send Reset Link'}
|
||||
<span className='flex items-center gap-1'>
|
||||
{isSubmittingReset ? 'Sending...' : 'Send Reset Link'}
|
||||
<span className='inline-flex transition-transform duration-200 group-hover:translate-x-0.5'>
|
||||
{isResetButtonHovered ? (
|
||||
<ArrowRight className='h-4 w-4' aria-hidden='true' />
|
||||
) : (
|
||||
<ChevronRight className='h-4 w-4' aria-hidden='true' />
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
</DialogContent>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Eye, EyeOff } from 'lucide-react'
|
||||
import { ArrowRight, ChevronRight, Eye, EyeOff } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
@@ -28,6 +28,7 @@ export function RequestResetForm({
|
||||
className,
|
||||
}: RequestResetFormProps) {
|
||||
const [buttonClass, setButtonClass] = useState('auth-button-gradient')
|
||||
const [isButtonHovered, setIsButtonHovered] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const checkCustomBrand = () => {
|
||||
@@ -96,9 +97,20 @@ export function RequestResetForm({
|
||||
<Button
|
||||
type='submit'
|
||||
disabled={isSubmitting}
|
||||
className={`${buttonClass} flex w-full items-center justify-center gap-2 rounded-[10px] border font-medium text-[15px] text-white transition-all duration-200`}
|
||||
onMouseEnter={() => setIsButtonHovered(true)}
|
||||
onMouseLeave={() => setIsButtonHovered(false)}
|
||||
className='group inline-flex w-full items-center justify-center gap-2 rounded-[10px] border border-[#6F3DFA] bg-gradient-to-b from-[#8357FF] to-[#6F3DFA] py-[6px] pr-[10px] pl-[12px] text-[15px] text-white shadow-[inset_0_2px_4px_0_#9B77FF] transition-all'
|
||||
>
|
||||
{isSubmitting ? 'Sending...' : 'Send Reset Link'}
|
||||
<span className='flex items-center gap-1'>
|
||||
{isSubmitting ? 'Sending...' : 'Send Reset Link'}
|
||||
<span className='inline-flex transition-transform duration-200 group-hover:translate-x-0.5'>
|
||||
{isButtonHovered ? (
|
||||
<ArrowRight className='h-4 w-4' aria-hidden='true' />
|
||||
) : (
|
||||
<ChevronRight className='h-4 w-4' aria-hidden='true' />
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
</Button>
|
||||
</form>
|
||||
)
|
||||
@@ -127,6 +139,7 @@ export function SetNewPasswordForm({
|
||||
const [showPassword, setShowPassword] = useState(false)
|
||||
const [showConfirmPassword, setShowConfirmPassword] = useState(false)
|
||||
const [buttonClass, setButtonClass] = useState('auth-button-gradient')
|
||||
const [isButtonHovered, setIsButtonHovered] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const checkCustomBrand = () => {
|
||||
@@ -286,9 +299,20 @@ export function SetNewPasswordForm({
|
||||
<Button
|
||||
disabled={isSubmitting || !token}
|
||||
type='submit'
|
||||
className={`${buttonClass} flex w-full items-center justify-center gap-2 rounded-[10px] border font-medium text-[15px] text-white transition-all duration-200`}
|
||||
onMouseEnter={() => setIsButtonHovered(true)}
|
||||
onMouseLeave={() => setIsButtonHovered(false)}
|
||||
className='group inline-flex w-full items-center justify-center gap-2 rounded-[10px] border border-[#6F3DFA] bg-gradient-to-b from-[#8357FF] to-[#6F3DFA] py-[6px] pr-[10px] pl-[12px] text-[15px] text-white shadow-[inset_0_2px_4px_0_#9B77FF] transition-all'
|
||||
>
|
||||
{isSubmitting ? 'Resetting...' : 'Reset Password'}
|
||||
<span className='flex items-center gap-1'>
|
||||
{isSubmitting ? 'Resetting...' : 'Reset Password'}
|
||||
<span className='inline-flex transition-transform duration-200 group-hover:translate-x-0.5'>
|
||||
{isButtonHovered ? (
|
||||
<ArrowRight className='h-4 w-4' aria-hidden='true' />
|
||||
) : (
|
||||
<ChevronRight className='h-4 w-4' aria-hidden='true' />
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
</Button>
|
||||
</form>
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { Suspense, useEffect, useState } from 'react'
|
||||
import { Eye, EyeOff } from 'lucide-react'
|
||||
import { ArrowRight, ChevronRight, Eye, EyeOff } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { useRouter, useSearchParams } from 'next/navigation'
|
||||
import { Button } from '@/components/ui/button'
|
||||
@@ -96,6 +96,7 @@ function SignupFormContent({
|
||||
const [redirectUrl, setRedirectUrl] = useState('')
|
||||
const [isInviteFlow, setIsInviteFlow] = useState(false)
|
||||
const [buttonClass, setButtonClass] = useState('auth-button-gradient')
|
||||
const [isButtonHovered, setIsButtonHovered] = useState(false)
|
||||
|
||||
const [name, setName] = useState('')
|
||||
const [nameErrors, setNameErrors] = useState<string[]>([])
|
||||
@@ -506,10 +507,21 @@ function SignupFormContent({
|
||||
|
||||
<Button
|
||||
type='submit'
|
||||
className={`${buttonClass} flex w-full items-center justify-center gap-2 rounded-[10px] border font-medium text-[15px] text-white transition-all duration-200`}
|
||||
onMouseEnter={() => setIsButtonHovered(true)}
|
||||
onMouseLeave={() => setIsButtonHovered(false)}
|
||||
className='group inline-flex w-full items-center justify-center gap-2 rounded-[10px] border border-[#6F3DFA] bg-gradient-to-b from-[#8357FF] to-[#6F3DFA] py-[6px] pr-[10px] pl-[12px] text-[15px] text-white shadow-[inset_0_2px_4px_0_#9B77FF] transition-all'
|
||||
disabled={isLoading}
|
||||
>
|
||||
{isLoading ? 'Creating account...' : 'Create account'}
|
||||
<span className='flex items-center gap-1'>
|
||||
{isLoading ? 'Creating account...' : 'Create account'}
|
||||
<span className='inline-flex transition-transform duration-200 group-hover:translate-x-0.5'>
|
||||
{isButtonHovered ? (
|
||||
<ArrowRight className='h-4 w-4' aria-hidden='true' />
|
||||
) : (
|
||||
<ChevronRight className='h-4 w-4' aria-hidden='true' />
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
</Button>
|
||||
</form>
|
||||
)}
|
||||
|
||||
+372
-117
@@ -52,13 +52,13 @@
|
||||
.workflow-container,
|
||||
.workflow-container .react-flow__pane,
|
||||
.workflow-container .react-flow__renderer {
|
||||
background-color: #e4e4e4 !important;
|
||||
background-color: var(--bg) !important;
|
||||
}
|
||||
|
||||
.dark .workflow-container,
|
||||
.dark .workflow-container .react-flow__pane,
|
||||
.dark .workflow-container .react-flow__renderer {
|
||||
background-color: #1b1b1b !important;
|
||||
background-color: var(--bg) !important;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,90 +75,238 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme system - CSS custom properties for light and dark modes
|
||||
* Dark color tokens - single source of truth for all colors (dark-only)
|
||||
*/
|
||||
@layer base {
|
||||
:root,
|
||||
.light {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 0 0% 3.9%;
|
||||
--card: 0 0% 99.2%;
|
||||
--card-foreground: 0 0% 3.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 0 0% 3.9%;
|
||||
--primary: 0 0% 11.2%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 0 0% 96.1%;
|
||||
--secondary-foreground: 0 0% 11.2%;
|
||||
--muted: 0 0% 96.1%;
|
||||
--muted-foreground: 0 0% 46.9%;
|
||||
--accent: 0 0% 92.5%;
|
||||
--accent-foreground: 0 0% 11.2%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 89.8%;
|
||||
--input: 0 0% 89.8%;
|
||||
--input-background: 0 0% 79.22%;
|
||||
--ring: 0 0% 3.9%;
|
||||
--radius: 0.5rem;
|
||||
--scrollbar-track: 0 0% 85%;
|
||||
--scrollbar-thumb: 0 0% 65%;
|
||||
--scrollbar-thumb-hover: 0 0% 55%;
|
||||
--scrollbar-size: 8px;
|
||||
--workflow-background: 0 0% 100%;
|
||||
--card-background: 0 0% 99.2%;
|
||||
--card-border: 0 0% 89.8%;
|
||||
--card-text: 0 0% 3.9%;
|
||||
--card-hover: 0 0% 96.1%;
|
||||
--base-muted-foreground: #737373;
|
||||
--gradient-primary: 263 85% 70%;
|
||||
--gradient-secondary: 336 95% 65%;
|
||||
--brand-primary-hex: #6f3dfa;
|
||||
--brand-primary-hover-hex: #6338d9;
|
||||
--brand-accent-hex: #6f3dfa;
|
||||
--brand-accent-hover-hex: #6f3dfa;
|
||||
--brand-background-hex: #ffffff;
|
||||
--surface-elevated: #202020;
|
||||
}
|
||||
/* Neutrals (surfaces) */
|
||||
--bg: #ffffff;
|
||||
--surface-1: #ffffff;
|
||||
--surface-2: #fafafa;
|
||||
--surface-3: #f8f8f8;
|
||||
--surface-4: #f6f6f6;
|
||||
--surface-5: #f3f3f3;
|
||||
--surface-6: #f0f0f0;
|
||||
--surface-9: #eaeaea;
|
||||
--surface-11: #e6e6e6;
|
||||
--surface-12: #e0e0e0;
|
||||
--surface-13: #dcdcdc;
|
||||
--surface-14: #d6d6d6;
|
||||
--surface-15: #cfcfcf;
|
||||
--surface-elevated: #ffffff;
|
||||
--bg-strong: #f5f5f5;
|
||||
|
||||
/* Text */
|
||||
--text-primary: #1b1b1b;
|
||||
--text-secondary: #404040;
|
||||
--text-tertiary: #555555;
|
||||
--text-muted: #737373;
|
||||
--text-subtle: #8a8a8a;
|
||||
--text-inverse: #1b1b1b;
|
||||
--text-error: #ef4444;
|
||||
|
||||
/* Borders / dividers */
|
||||
--border: #dddddd;
|
||||
--border-strong: #d1d1d1;
|
||||
--divider: #e5e5e5;
|
||||
--border-muted: #eeeeee;
|
||||
|
||||
/* Brand & state */
|
||||
--brand-400: #8e4cfb;
|
||||
--brand-500: #6f3dfa;
|
||||
--brand-secondary: #33b4ff;
|
||||
--brand-tertiary: #22c55e;
|
||||
--warning: #ff6600;
|
||||
|
||||
/* Utility */
|
||||
--white: #ffffff;
|
||||
|
||||
/* RGB for opacity usage */
|
||||
--surface-4-rgb: 246 246 246;
|
||||
--surface-5-rgb: 243 243 243;
|
||||
--surface-7-rgb: 230 230 230;
|
||||
--surface-9-rgb: 234 234 234;
|
||||
--divider-rgb: 229 229 229;
|
||||
--white-rgb: 255 255 255;
|
||||
--black-rgb: 0 0 0;
|
||||
|
||||
/* Extended palette (exhaustive from code usage via -[#...]) */
|
||||
/* Neutral deep shades */
|
||||
--c-0D0D0D: #0d0d0d;
|
||||
--c-1A1A1A: #1a1a1a;
|
||||
--c-1F1F1F: #1f1f1f;
|
||||
--c-2A2A2A: #2a2a2a;
|
||||
--c-383838: #383838;
|
||||
--c-414141: #414141;
|
||||
--c-442929: #442929;
|
||||
--c-491515: #491515;
|
||||
--c-575757: #575757;
|
||||
--c-686868: #686868;
|
||||
--c-707070: #707070;
|
||||
--c-727272: #727272;
|
||||
--c-737373: #737373;
|
||||
--c-808080: #808080;
|
||||
--c-858585: #858585;
|
||||
--c-868686: #868686;
|
||||
--c-8D8D8D: #8d8d8d;
|
||||
--c-939393: #939393;
|
||||
--c-A8A8A8: #a8a8a8;
|
||||
--c-B8B8B8: #b8b8b8;
|
||||
--c-C0C0C0: #c0c0c0;
|
||||
--c-CDCDCD: #cdcdcd;
|
||||
--c-D0D0D0: #d0d0d0;
|
||||
--c-D2D2D2: #d2d2d2;
|
||||
--c-E0E0E0: #e0e0e0;
|
||||
--c-E5E5E5: #e5e5e5;
|
||||
--c-E8E8E8: #e8e8e8;
|
||||
--c-EEEEEE: #eeeeee;
|
||||
--c-F0F0F0: #f0f0f0;
|
||||
--c-F4F4F4: #f4f4f4;
|
||||
--c-F5F5F5: #f5f5f5;
|
||||
|
||||
/* Blues and cyans */
|
||||
--c-00B0B0: #00b0b0;
|
||||
--c-264F78: #264f78;
|
||||
--c-2F55FF: #2f55ff;
|
||||
--c-2FA1FF: #2fa1ff;
|
||||
--c-336699: #336699;
|
||||
--c-34B5FF: #34b5ff;
|
||||
--c-601EE0: #601ee0;
|
||||
--c-611F69: #611f69;
|
||||
--c-802FFF: #802fff;
|
||||
--c-8357FF: #8357ff;
|
||||
--c-8C10FF: #8c10ff;
|
||||
|
||||
/* Greens */
|
||||
--c-4CAF50: #4caf50;
|
||||
|
||||
/* Oranges / Ambers */
|
||||
--c-F59E0B: #f59e0b;
|
||||
--c-F97316: #f97316;
|
||||
--c-FF972F: #ff972f;
|
||||
|
||||
/* Reds */
|
||||
--c-DC2626: #dc2626;
|
||||
--c-F6D2D2: #f6d2d2;
|
||||
--c-F87171: #f87171;
|
||||
--c-FF402F: #ff402f;
|
||||
--c-B91C1C: #b91c1c;
|
||||
--c-883827: #883827;
|
||||
}
|
||||
.dark {
|
||||
--background: 0 0% 10.59%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 0 0% 9.0%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 0 0% 9.0%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 0% 11.2%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 0 0% 12.0%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 0 0% 17.5%;
|
||||
--muted-foreground: 0 0% 65.1%;
|
||||
--accent: 0 0% 17.5%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 16.1%;
|
||||
--input: 0 0% 16.1%;
|
||||
--input-background: 0 0% 20.78%;
|
||||
--ring: 0 0% 83.9%;
|
||||
--scrollbar-track: 0 0% 17.5%;
|
||||
--scrollbar-thumb: 0 0% 30%;
|
||||
--scrollbar-thumb-hover: 0 0% 40%;
|
||||
--workflow-background: 0 0% 10.59%;
|
||||
--card-background: 0 0% 9.0%;
|
||||
--card-border: 0 0% 22.7%;
|
||||
--card-text: 0 0% 98%;
|
||||
--card-hover: 0 0% 12.0%;
|
||||
--base-muted-foreground: #a3a3a3;
|
||||
--gradient-primary: 263 90% 75%;
|
||||
--gradient-secondary: 336 100% 72%;
|
||||
--brand-primary-hex: #701ffc;
|
||||
--brand-primary-hover-hex: #802fff;
|
||||
--brand-accent-hex: #9d54ff;
|
||||
--brand-accent-hover-hex: #a66fff;
|
||||
--brand-background-hex: #0c0c0c;
|
||||
/* Neutrals (surfaces) */
|
||||
--bg: #1b1b1b;
|
||||
--surface-1: #1e1e1e;
|
||||
--surface-2: #232323;
|
||||
--surface-3: #242424;
|
||||
--surface-4: #252525;
|
||||
--surface-5: #272727;
|
||||
--surface-6: #282828;
|
||||
--surface-9: #363636;
|
||||
--surface-11: #3d3d3d;
|
||||
--surface-12: #434343;
|
||||
--surface-13: #454545;
|
||||
--surface-14: #4a4a4a;
|
||||
--surface-15: #5a5a5a;
|
||||
--surface-elevated: #202020;
|
||||
--bg-strong: #0c0c0c;
|
||||
|
||||
/* Text */
|
||||
--text-primary: #e6e6e6;
|
||||
--text-secondary: #b1b1b1;
|
||||
--text-tertiary: #aeaeae;
|
||||
--text-muted: #787878;
|
||||
--text-subtle: #7d7d7d;
|
||||
--text-inverse: #1b1b1b;
|
||||
--text-error: #ef4444;
|
||||
|
||||
/* Borders / dividers */
|
||||
--border: #2c2c2c;
|
||||
--border-strong: #303030;
|
||||
--divider: #393939;
|
||||
--border-muted: #424242;
|
||||
|
||||
/* Brand & state */
|
||||
--brand-400: #8e4cfb;
|
||||
--brand-secondary: #33b4ff;
|
||||
--brand-tertiary: #22c55e;
|
||||
--warning: #ff6600;
|
||||
|
||||
/* Utility */
|
||||
--white: #ffffff;
|
||||
|
||||
/* RGB for opacity usage */
|
||||
--surface-4-rgb: 37 37 37;
|
||||
--surface-5-rgb: 39 39 39;
|
||||
--surface-7-rgb: 44 44 44;
|
||||
--surface-9-rgb: 54 54 54;
|
||||
--divider-rgb: 57 57 57;
|
||||
--white-rgb: 255 255 255;
|
||||
--black-rgb: 0 0 0;
|
||||
|
||||
/* Extended palette (exhaustive from code usage via -[#...]) */
|
||||
/* Neutral deep shades */
|
||||
--c-0D0D0D: #0d0d0d;
|
||||
--c-1A1A1A: #1a1a1a;
|
||||
--c-1F1F1F: #1f1f1f;
|
||||
--c-2A2A2A: #2a2a2a;
|
||||
--c-383838: #383838;
|
||||
--c-414141: #414141;
|
||||
--c-442929: #442929;
|
||||
--c-491515: #491515;
|
||||
--c-575757: #575757;
|
||||
--c-686868: #686868;
|
||||
--c-707070: #707070;
|
||||
--c-727272: #727272;
|
||||
--c-737373: #737373;
|
||||
--c-808080: #808080;
|
||||
--c-858585: #858585;
|
||||
--c-868686: #868686;
|
||||
--c-8D8D8D: #8d8d8d;
|
||||
--c-939393: #939393;
|
||||
--c-A8A8A8: #a8a8a8;
|
||||
--c-B8B8B8: #b8b8b8;
|
||||
--c-C0C0C0: #c0c0c0;
|
||||
--c-CDCDCD: #cdcdcd;
|
||||
--c-D0D0D0: #d0d0d0;
|
||||
--c-D2D2D2: #d2d2d2;
|
||||
--c-E0E0E0: #e0e0e0;
|
||||
--c-E5E5E5: #e5e5e5;
|
||||
--c-E8E8E8: #e8e8e8;
|
||||
--c-EEEEEE: #eeeeee;
|
||||
--c-F0F0F0: #f0f0f0;
|
||||
--c-F4F4F4: #f4f4f4;
|
||||
--c-F5F5F5: #f5f5f5;
|
||||
|
||||
/* Blues and cyans */
|
||||
--c-00B0B0: #00b0b0;
|
||||
--c-264F78: #264f78;
|
||||
--c-2F55FF: #2f55ff;
|
||||
--c-2FA1FF: #2fa1ff;
|
||||
--c-336699: #336699;
|
||||
--c-34B5FF: #34b5ff;
|
||||
--c-601EE0: #601ee0;
|
||||
--c-611F69: #611f69;
|
||||
--c-802FFF: #802fff;
|
||||
--c-8357FF: #8357ff;
|
||||
--c-8C10FF: #8c10ff;
|
||||
|
||||
/* Greens */
|
||||
--c-4CAF50: #4caf50;
|
||||
|
||||
/* Oranges / Ambers */
|
||||
--c-F59E0B: #f59e0b;
|
||||
--c-F97316: #f97316;
|
||||
--c-FF972F: #ff972f;
|
||||
|
||||
/* Reds */
|
||||
--c-DC2626: #dc2626;
|
||||
--c-F6D2D2: #f6d2d2;
|
||||
--c-F87171: #f87171;
|
||||
--c-FF402F: #ff402f;
|
||||
--c-B91C1C: #b91c1c;
|
||||
--c-883827: #883827;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +315,7 @@
|
||||
*/
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
border-color: var(--border);
|
||||
overscroll-behavior-x: none;
|
||||
}
|
||||
|
||||
@@ -176,7 +324,8 @@
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
background-color: var(--bg);
|
||||
color: var(--text-primary);
|
||||
overscroll-behavior-x: none;
|
||||
overscroll-behavior-y: none;
|
||||
min-height: 100vh;
|
||||
@@ -185,6 +334,19 @@
|
||||
letter-spacing: 0.28px;
|
||||
}
|
||||
|
||||
/* Ensure visible text caret across inputs and editors */
|
||||
input,
|
||||
textarea,
|
||||
[contenteditable="true"] {
|
||||
caret-color: var(--text-primary);
|
||||
}
|
||||
|
||||
.dark input,
|
||||
.dark textarea,
|
||||
.dark [contenteditable="true"] {
|
||||
caret-color: var(--text-primary);
|
||||
}
|
||||
|
||||
.dark body {
|
||||
@apply antialiased;
|
||||
}
|
||||
@@ -194,7 +356,7 @@
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #f5f5f5;
|
||||
background: var(--white);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
@@ -208,7 +370,7 @@
|
||||
|
||||
/* Dark Mode Global Scrollbar */
|
||||
.dark ::-webkit-scrollbar-track {
|
||||
background: #272727;
|
||||
background: var(--surface-5);
|
||||
}
|
||||
|
||||
.dark ::-webkit-scrollbar-thumb {
|
||||
@@ -221,11 +383,11 @@
|
||||
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: hsl(var(--muted-foreground) / 0.3) #f5f5f5;
|
||||
scrollbar-color: hsl(var(--muted-foreground) / 0.3) var(--white);
|
||||
}
|
||||
|
||||
.dark * {
|
||||
scrollbar-color: hsl(var(--muted-foreground) / 0.3) #272727;
|
||||
scrollbar-color: hsl(var(--muted-foreground) / 0.3) var(--surface-5);
|
||||
}
|
||||
|
||||
.copilot-scrollable {
|
||||
@@ -241,20 +403,20 @@
|
||||
}
|
||||
|
||||
.panel-tab-active {
|
||||
background-color: #f5f5f5;
|
||||
color: #1a1a1a;
|
||||
border-color: #e5e5e5;
|
||||
background-color: var(--white);
|
||||
color: var(--text-inverse);
|
||||
border-color: var(--border-muted);
|
||||
}
|
||||
|
||||
.dark .panel-tab-active {
|
||||
background-color: #1f1f1f;
|
||||
color: #ffffff;
|
||||
border-color: #424242;
|
||||
background-color: var(--surface-1);
|
||||
color: var(--white);
|
||||
border-color: var(--border-muted);
|
||||
}
|
||||
|
||||
.panel-tab-inactive:hover {
|
||||
background-color: hsl(var(--secondary));
|
||||
color: hsl(var(--card-foreground));
|
||||
background-color: var(--surface-9);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -332,24 +494,29 @@ input[type="search"]::-ms-clear {
|
||||
}
|
||||
|
||||
.auth-card {
|
||||
background-color: rgba(255, 255, 255, 0.9) !important;
|
||||
border-color: #e5e5e5 !important;
|
||||
background-color: var(--white) !important;
|
||||
border-color: var(--border-muted) !important;
|
||||
}
|
||||
|
||||
.dark .auth-card {
|
||||
background-color: var(--surface-1) !important;
|
||||
border-color: var(--border-muted) !important;
|
||||
}
|
||||
|
||||
.auth-text-primary {
|
||||
color: #1a1a1a !important;
|
||||
color: var(--text-inverse) !important;
|
||||
}
|
||||
|
||||
.auth-text-secondary {
|
||||
color: #4a4a4a !important;
|
||||
color: var(--text-secondary) !important;
|
||||
}
|
||||
|
||||
.auth-text-muted {
|
||||
color: #737373 !important;
|
||||
color: var(--text-muted) !important;
|
||||
}
|
||||
|
||||
.auth-divider {
|
||||
border-color: #e5e5e5 !important;
|
||||
border-color: var(--border-muted) !important;
|
||||
}
|
||||
|
||||
.auth-card-shadow {
|
||||
@@ -359,7 +526,7 @@ input[type="search"]::-ms-clear {
|
||||
}
|
||||
|
||||
.auth-link {
|
||||
color: #737373 !important;
|
||||
color: var(--text-muted) !important;
|
||||
}
|
||||
|
||||
.transition-ring {
|
||||
@@ -399,25 +566,25 @@ input[type="search"]::-ms-clear {
|
||||
}
|
||||
|
||||
.auth-button-gradient {
|
||||
background: linear-gradient(to bottom, #8357ff, #6f3dfa) !important;
|
||||
border-color: #6f3dfa !important;
|
||||
box-shadow: inset 0 2px 4px 0 #9b77ff !important;
|
||||
background: linear-gradient(to bottom, var(--brand-500), var(--brand-400)) !important;
|
||||
border-color: var(--brand-400) !important;
|
||||
box-shadow: inset 0 2px 4px 0 var(--brand-400) !important;
|
||||
}
|
||||
|
||||
.auth-button-gradient:hover {
|
||||
background: linear-gradient(to bottom, #8357ff, #6f3dfa) !important;
|
||||
background: linear-gradient(to bottom, var(--brand-500), var(--brand-400)) !important;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.auth-button-custom {
|
||||
background: var(--brand-accent-hex) !important;
|
||||
border-color: var(--brand-accent-hex) !important;
|
||||
background: var(--brand-500) !important;
|
||||
border-color: var(--brand-500) !important;
|
||||
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.1) !important;
|
||||
}
|
||||
|
||||
.auth-button-custom:hover {
|
||||
background: var(--brand-accent-hover-hex, var(--brand-accent-hex)) !important;
|
||||
border-color: var(--brand-accent-hover-hex, var(--brand-accent-hex)) !important;
|
||||
background: var(--brand-500) !important;
|
||||
border-color: var(--brand-500) !important;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -440,32 +607,120 @@ input[type="search"]::-ms-clear {
|
||||
}
|
||||
|
||||
html[data-panel-active-tab="copilot"] .panel-container [data-tab-button="copilot"] {
|
||||
background-color: rgb(53 53 53) !important;
|
||||
color: rgb(230 230 230) !important;
|
||||
background-color: var(--surface-11) !important;
|
||||
color: var(--text-primary) !important;
|
||||
}
|
||||
html[data-panel-active-tab="copilot"] .panel-container [data-tab-button="toolbar"],
|
||||
html[data-panel-active-tab="copilot"] .panel-container [data-tab-button="editor"] {
|
||||
background-color: transparent !important;
|
||||
color: rgb(174 174 174) !important;
|
||||
color: var(--text-tertiary) !important;
|
||||
}
|
||||
|
||||
html[data-panel-active-tab="toolbar"] .panel-container [data-tab-button="toolbar"] {
|
||||
background-color: rgb(53 53 53) !important;
|
||||
color: rgb(230 230 230) !important;
|
||||
background-color: var(--surface-11) !important;
|
||||
color: var(--text-primary) !important;
|
||||
}
|
||||
html[data-panel-active-tab="toolbar"] .panel-container [data-tab-button="copilot"],
|
||||
html[data-panel-active-tab="toolbar"] .panel-container [data-tab-button="editor"] {
|
||||
background-color: transparent !important;
|
||||
color: rgb(174 174 174) !important;
|
||||
color: var(--text-tertiary) !important;
|
||||
}
|
||||
|
||||
html[data-panel-active-tab="editor"] .panel-container [data-tab-button="editor"] {
|
||||
background-color: rgb(53 53 53) !important;
|
||||
color: rgb(230 230 230) !important;
|
||||
background-color: var(--surface-11) !important;
|
||||
color: var(--text-primary) !important;
|
||||
}
|
||||
html[data-panel-active-tab="editor"] .panel-container [data-tab-button="copilot"],
|
||||
html[data-panel-active-tab="editor"] .panel-container [data-tab-button="toolbar"] {
|
||||
background-color: transparent !important;
|
||||
color: rgb(174 174 174) !important;
|
||||
color: var(--text-tertiary) !important;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @depricated
|
||||
* Legacy globals (light/dark) kept for backward-compat with old classes.
|
||||
* Do not modify; remove after migration.
|
||||
*/
|
||||
@layer base {
|
||||
:root,
|
||||
.light {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 0 0% 3.9%;
|
||||
--card: 0 0% 99.2%;
|
||||
--card-foreground: 0 0% 3.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 0 0% 3.9%;
|
||||
--primary: 0 0% 11.2%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 0 0% 96.1%;
|
||||
--secondary-foreground: 0 0% 11.2%;
|
||||
--muted: 0 0% 96.1%;
|
||||
--muted-foreground: 0 0% 46.9%;
|
||||
--accent: 0 0% 92.5%;
|
||||
--accent-foreground: 0 0% 11.2%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--input: 0 0% 89.8%;
|
||||
--input-background: 0 0% 100%;
|
||||
--ring: 0 0% 3.9%;
|
||||
--radius: 0.5rem;
|
||||
--scrollbar-track: 0 0% 85%;
|
||||
--scrollbar-thumb: 0 0% 65%;
|
||||
--scrollbar-thumb-hover: 0 0% 55%;
|
||||
--scrollbar-size: 8px;
|
||||
--workflow-background: 0 0% 100%;
|
||||
--card-background: 0 0% 99.2%;
|
||||
--card-border: 0 0% 89.8%;
|
||||
--card-text: 0 0% 3.9%;
|
||||
--card-hover: 0 0% 96.1%;
|
||||
--base-muted-foreground: #737373;
|
||||
--gradient-primary: 263 85% 70%;
|
||||
--gradient-secondary: 336 95% 65%;
|
||||
--brand-primary-hex: #6f3dfa;
|
||||
--brand-primary-hover-hex: #6338d9;
|
||||
--brand-accent-hex: #6f3dfa;
|
||||
--brand-accent-hover-hex: #6f3dfa;
|
||||
--brand-background-hex: #ffffff;
|
||||
--surface-elevated: #202020;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 0 0% 10.59%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 0 0% 9.0%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 0 0% 9.0%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 0% 11.2%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 0 0% 12.0%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 0 0% 17.5%;
|
||||
/* --muted-foreground: 0 0% 65.1%; */
|
||||
--accent: 0 0% 17.5%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--input: 0 0% 16.1%;
|
||||
--input-background: 0 0% 20.78%;
|
||||
--ring: 0 0% 83.9%;
|
||||
--scrollbar-track: 0 0% 17.5%;
|
||||
--scrollbar-thumb: 0 0% 30%;
|
||||
--scrollbar-thumb-hover: 0 0% 40%;
|
||||
--workflow-background: 0 0% 10.59%;
|
||||
--card-background: 0 0% 9.0%;
|
||||
--card-border: 0 0% 22.7%;
|
||||
--card-text: 0 0% 98%;
|
||||
--card-hover: 0 0% 12.0%;
|
||||
--base-muted-foreground: #a3a3a3;
|
||||
--gradient-primary: 263 90% 75%;
|
||||
--gradient-secondary: 336 100% 72%;
|
||||
--brand-primary-hex: #701ffc;
|
||||
--brand-primary-hover-hex: #802fff;
|
||||
--brand-accent-hex: #9d54ff;
|
||||
--brand-accent-hover-hex: #a66fff;
|
||||
--brand-background-hex: #0c0c0c;
|
||||
--surface-elevated: #202020;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
var editorParsed = JSON.parse(editorStored);
|
||||
var editorState = editorParsed?.state;
|
||||
var connectionsHeight = editorState?.connectionsHeight;
|
||||
if (connectionsHeight !== undefined && connectionsHeight >= 30 && connectionsHeight <= 200) {
|
||||
if (connectionsHeight !== undefined && connectionsHeight >= 30 && connectionsHeight <= 300) {
|
||||
document.documentElement.style.setProperty('--editor-connections-height', connectionsHeight + 'px');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,20 +7,22 @@ import { ThemeProvider as NextThemesProvider } from 'next-themes'
|
||||
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
||||
const pathname = usePathname()
|
||||
|
||||
// Force light mode for certain pages
|
||||
const forcedTheme =
|
||||
pathname === '/' ||
|
||||
pathname.startsWith('/login') ||
|
||||
pathname.startsWith('/signup') ||
|
||||
pathname.startsWith('/sso') ||
|
||||
pathname.startsWith('/terms') ||
|
||||
pathname.startsWith('/privacy') ||
|
||||
pathname.startsWith('/invite') ||
|
||||
pathname.startsWith('/verify') ||
|
||||
pathname.startsWith('/careers') ||
|
||||
pathname.startsWith('/changelog') ||
|
||||
pathname.startsWith('/chat') ||
|
||||
pathname.startsWith('/studio')
|
||||
// Force dark mode for workspace pages
|
||||
// Force light mode for certain public pages
|
||||
const forcedTheme = pathname.startsWith('/workspace')
|
||||
? 'dark'
|
||||
: pathname === '/' ||
|
||||
pathname.startsWith('/login') ||
|
||||
pathname.startsWith('/signup') ||
|
||||
pathname.startsWith('/sso') ||
|
||||
pathname.startsWith('/terms') ||
|
||||
pathname.startsWith('/privacy') ||
|
||||
pathname.startsWith('/invite') ||
|
||||
pathname.startsWith('/verify') ||
|
||||
pathname.startsWith('/careers') ||
|
||||
pathname.startsWith('/changelog') ||
|
||||
pathname.startsWith('/chat') ||
|
||||
pathname.startsWith('/studio')
|
||||
? 'light'
|
||||
: undefined
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export const filterButtonClass =
|
||||
'w-full justify-between rounded-[10px] border-[#E5E5E5] bg-[#FFFFFF] font-normal text-sm dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
'w-full justify-between rounded-[10px] border-[#E5E5E5] bg-[var(--white)] font-normal text-sm dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
|
||||
export const dropdownContentClass =
|
||||
'w-[220px] rounded-lg border-[#E5E5E5] bg-[#FFFFFF] p-0 shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
'w-[220px] rounded-lg border-[#E5E5E5] bg-[var(--white)] p-0 shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
|
||||
export const commandListClass = 'overflow-y-auto overflow-x-hidden'
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ export function Controls({
|
||||
placeholder='Search workflows...'
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery?.(e.target.value)}
|
||||
className='h-9 w-full rounded-[11px] border-[#E5E5E5] bg-[#FFFFFF] pr-10 pl-9 dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
className='h-9 w-full rounded-[11px] border-[#E5E5E5] bg-[var(--white)] pr-10 pl-9 dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
/>
|
||||
{searchQuery && (
|
||||
<button
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function Level() {
|
||||
<Button
|
||||
variant='outline'
|
||||
size='sm'
|
||||
className='w-full justify-between rounded-[10px] border-[#E5E5E5] bg-[#FFFFFF] font-normal text-sm dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
className='w-full justify-between rounded-[10px] border-[#E5E5E5] bg-[var(--white)] font-normal text-sm dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
>
|
||||
{getDisplayLabel()}
|
||||
<ChevronDown className='ml-2 h-4 w-4 text-muted-foreground' />
|
||||
@@ -37,7 +37,7 @@ export default function Level() {
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
align='start'
|
||||
className='w-[180px] rounded-lg border-[#E5E5E5] bg-[#FFFFFF] shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
className='w-[180px] rounded-lg border-[#E5E5E5] bg-[var(--white)] shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
>
|
||||
<DropdownMenuItem
|
||||
key='all'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export const filterButtonClass =
|
||||
'w-full justify-between rounded-[10px] border-[#E5E5E5] bg-[#FFFFFF] font-normal text-sm dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
'w-full justify-between rounded-[10px] border-[#E5E5E5] bg-[var(--white)] font-normal text-sm dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
|
||||
export const dropdownContentClass =
|
||||
'w-[200px] rounded-lg border-[#E5E5E5] bg-[#FFFFFF] p-0 shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
'w-[200px] rounded-lg border-[#E5E5E5] bg-[var(--white)] p-0 shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
|
||||
export const commandListClass = 'overflow-y-auto overflow-x-hidden'
|
||||
|
||||
|
||||
@@ -569,7 +569,7 @@ export function Chat() {
|
||||
|
||||
return (
|
||||
<div
|
||||
className='fixed z-30 flex flex-col overflow-hidden rounded-[6px] bg-[#1E1E1E] px-[10px] pt-[2px] pb-[8px]'
|
||||
className='fixed z-30 flex flex-col overflow-hidden rounded-[6px] bg-[var(--surface-1)] px-[10px] pt-[2px] pb-[8px]'
|
||||
style={{
|
||||
left: `${actualPosition.x}px`,
|
||||
top: `${actualPosition.y}px`,
|
||||
@@ -583,11 +583,13 @@ export function Chat() {
|
||||
>
|
||||
{/* Header with drag handle */}
|
||||
<div
|
||||
className='flex h-[32px] flex-shrink-0 cursor-grab items-center justify-between bg-[#1E1E1E] p-0 active:cursor-grabbing'
|
||||
className='flex h-[32px] flex-shrink-0 cursor-grab items-center justify-between bg-[var(--surface-1)] p-0 active:cursor-grabbing'
|
||||
onMouseDown={handleMouseDown}
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
<span className='flex-shrink-0 font-medium text-[#E6E6E6] text-[14px]'>Chat</span>
|
||||
<span className='flex-shrink-0 font-medium text-[14px] text-[var(--text-primary)]'>
|
||||
Chat
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Output selector - centered with mx-auto */}
|
||||
@@ -683,14 +685,14 @@ export function Chat() {
|
||||
<div>
|
||||
<div className='rounded-lg border border-[#883827] bg-[#491515]'>
|
||||
<div className='flex items-start gap-2'>
|
||||
<AlertCircle className='mt-0.5 h-3 w-3 shrink-0 text-[#EF4444]' />
|
||||
<AlertCircle className='mt-0.5 h-3 w-3 shrink-0 text-[var(--text-error)]' />
|
||||
<div className='flex-1'>
|
||||
<div className='mb-1 font-medium text-[#EF4444] text-[11px]'>
|
||||
<div className='mb-1 font-medium text-[11px] text-[var(--text-error)]'>
|
||||
File upload error
|
||||
</div>
|
||||
<div className='space-y-1'>
|
||||
{uploadErrors.map((err, idx) => (
|
||||
<div key={idx} className='text-[#EF4444] text-[10px]'>
|
||||
<div key={idx} className='text-[10px] text-[var(--text-error)]'>
|
||||
{err}
|
||||
</div>
|
||||
))}
|
||||
@@ -703,10 +705,8 @@ export function Chat() {
|
||||
|
||||
{/* Combined input container */}
|
||||
<div
|
||||
className={`rounded-[4px] border bg-[#282828] py-0 pr-[6px] pl-[4px] transition-colors dark:bg-[#363636] ${
|
||||
isDragOver
|
||||
? 'border-[var(--brand-primary-hover-hex)] bg-purple-50/50 dark:border-[var(--brand-primary-hover-hex)] dark:bg-purple-950/20'
|
||||
: 'border-[#3D3D3D]'
|
||||
className={`rounded-[4px] border bg-[var(--surface-9)] py-0 pr-[6px] pl-[4px] transition-colors ${
|
||||
isDragOver ? 'border-[var(--brand-secondary)]' : 'border-[var(--surface-11)]'
|
||||
}`}
|
||||
>
|
||||
{/* File thumbnails */}
|
||||
@@ -720,7 +720,7 @@ export function Chat() {
|
||||
<div
|
||||
key={file.id}
|
||||
className={cn(
|
||||
'group relative flex-shrink-0 overflow-hidden rounded-[6px] bg-[#232323]',
|
||||
'group relative flex-shrink-0 overflow-hidden rounded-[6px] bg-[var(--surface-2)]',
|
||||
previewUrl
|
||||
? 'h-[40px] w-[40px]'
|
||||
: 'flex min-w-[80px] max-w-[120px] items-center justify-center px-[8px] py-[2px]'
|
||||
@@ -735,10 +735,10 @@ export function Chat() {
|
||||
/>
|
||||
) : (
|
||||
<div className='min-w-0 flex-1'>
|
||||
<div className='truncate font-medium text-[#FFFFFF] text-[10px]'>
|
||||
<div className='truncate font-medium text-[10px] text-[var(--white)]'>
|
||||
{file.name}
|
||||
</div>
|
||||
<div className='text-[#AEAEAE] text-[9px]'>
|
||||
<div className='text-[9px] text-[var(--text-tertiary)]'>
|
||||
{formatFileSize(file.size)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -781,7 +781,7 @@ export function Chat() {
|
||||
onClick={() => document.getElementById('floating-chat-file-input')?.click()}
|
||||
title='Attach file'
|
||||
className={cn(
|
||||
'cursor-pointer rounded-[6px] bg-transparent p-[0px] dark:bg-transparent',
|
||||
'!bg-transparent cursor-pointer rounded-[6px] p-[0px]',
|
||||
(!activeWorkflowId || isExecuting || chatFiles.length >= 15) &&
|
||||
'cursor-not-allowed opacity-50'
|
||||
)}
|
||||
@@ -799,8 +799,8 @@ export function Chat() {
|
||||
className={cn(
|
||||
'h-[22px] w-[22px] rounded-full p-0 transition-colors',
|
||||
chatMessage.trim() || chatFiles.length > 0
|
||||
? 'bg-[#C0C0C0] hover:bg-[#D0D0D0] dark:bg-[#C0C0C0] dark:hover:bg-[#D0D0D0]'
|
||||
: 'bg-[#C0C0C0] dark:bg-[#C0C0C0]'
|
||||
? '!bg-[var(--c-C0C0C0)] hover:!bg-[var(--c-D0D0D0)]'
|
||||
: '!bg-[var(--c-C0C0C0)]'
|
||||
)}
|
||||
>
|
||||
<ArrowUp className='h-3.5 w-3.5 text-black' strokeWidth={2.25} />
|
||||
|
||||
+14
-31
@@ -1,5 +1,4 @@
|
||||
import { useMemo } from 'react'
|
||||
import { File, FileText, Image as ImageIcon } from 'lucide-react'
|
||||
import { StreamingIndicator } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/copilot/components/copilot-message/components/smooth-streaming'
|
||||
|
||||
interface ChatAttachment {
|
||||
@@ -33,17 +32,6 @@ const formatFileSize = (bytes?: number): string => {
|
||||
return `${Math.round((bytes / 1024 ** i) * 10) / 10} ${sizes[i]}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns appropriate icon for file type
|
||||
*/
|
||||
const getFileIcon = (type: string) => {
|
||||
if (type.includes('pdf')) return <FileText className='h-5 w-5 text-muted-foreground' />
|
||||
if (type.startsWith('image/')) return <ImageIcon className='h-5 w-5 text-muted-foreground' />
|
||||
if (type.includes('text') || type.includes('json'))
|
||||
return <FileText className='h-5 w-5 text-muted-foreground' />
|
||||
return <File className='h-5 w-5 text-muted-foreground' />
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens image attachment in new window
|
||||
*/
|
||||
@@ -123,7 +111,7 @@ export function ChatMessage({ message }: ChatMessageProps) {
|
||||
return (
|
||||
<div className='w-full max-w-full overflow-hidden opacity-100 transition-opacity duration-200'>
|
||||
{message.attachments && message.attachments.length > 0 && (
|
||||
<div className='mb-2 flex flex-wrap gap-1.5'>
|
||||
<div className='mb-2 flex flex-wrap gap-[6px]'>
|
||||
{message.attachments.map((attachment) => {
|
||||
const isImage = attachment.type.startsWith('image/')
|
||||
const hasValidDataUrl =
|
||||
@@ -132,9 +120,9 @@ export function ChatMessage({ message }: ChatMessageProps) {
|
||||
return (
|
||||
<div
|
||||
key={attachment.id}
|
||||
className={`relative overflow-hidden rounded-md border border-border/50 bg-muted/20 ${
|
||||
className={`group relative flex-shrink-0 overflow-hidden rounded-[6px] bg-[var(--surface-2)] ${
|
||||
hasValidDataUrl ? 'cursor-pointer' : ''
|
||||
} ${isImage ? 'h-16 w-16' : 'flex h-16 min-w-[120px] max-w-[200px] items-center gap-2 px-2'}`}
|
||||
} ${isImage ? 'h-[40px] w-[40px]' : 'flex min-w-[80px] max-w-[120px] items-center justify-center px-[8px] py-[2px]'}`}
|
||||
onClick={(e) => {
|
||||
if (hasValidDataUrl) {
|
||||
e.preventDefault()
|
||||
@@ -150,21 +138,16 @@ export function ChatMessage({ message }: ChatMessageProps) {
|
||||
className='h-full w-full object-cover'
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<div className='flex h-8 w-8 flex-shrink-0 items-center justify-center rounded bg-background/50'>
|
||||
{getFileIcon(attachment.type)}
|
||||
<div className='min-w-0 flex-1'>
|
||||
<div className='truncate font-medium text-[10px] text-[var(--white)]'>
|
||||
{attachment.name}
|
||||
</div>
|
||||
<div className='min-w-0 flex-1'>
|
||||
<div className='truncate font-medium text-foreground text-xs'>
|
||||
{attachment.name}
|
||||
{attachment.size && (
|
||||
<div className='text-[9px] text-[var(--text-tertiary)]'>
|
||||
{formatFileSize(attachment.size)}
|
||||
</div>
|
||||
{attachment.size && (
|
||||
<div className='text-[10px] text-muted-foreground'>
|
||||
{formatFileSize(attachment.size)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
@@ -173,8 +156,8 @@ export function ChatMessage({ message }: ChatMessageProps) {
|
||||
)}
|
||||
|
||||
{formattedContent && !formattedContent.startsWith('Uploaded') && (
|
||||
<div className='rounded-[4px] border border-[#3D3D3D] bg-[#282828] px-[8px] py-[6px] transition-all duration-200 dark:border-[#3D3D3D] dark:bg-[#363636]'>
|
||||
<div className='whitespace-pre-wrap break-words font-medium font-sans text-[#0D0D0D] text-sm leading-[1.25rem] dark:text-gray-100'>
|
||||
<div className='rounded-[4px] border border-[var(--surface-11)] bg-[var(--surface-9)] px-[8px] py-[6px] transition-all duration-200'>
|
||||
<div className='whitespace-pre-wrap break-words font-medium font-sans text-gray-100 text-sm leading-[1.25rem]'>
|
||||
<WordWrap text={formattedContent} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -185,7 +168,7 @@ export function ChatMessage({ message }: ChatMessageProps) {
|
||||
|
||||
return (
|
||||
<div className='w-full max-w-full overflow-hidden pl-[2px] opacity-100 transition-opacity duration-200'>
|
||||
<div className='whitespace-pre-wrap break-words font-[470] font-season text-[#707070] text-sm leading-[1.25rem] dark:text-[#E8E8E8]'>
|
||||
<div className='whitespace-pre-wrap break-words font-[470] font-season text-[#E8E8E8] text-sm leading-[1.25rem]'>
|
||||
<WordWrap text={formattedContent} />
|
||||
{message.isStreaming && <StreamingIndicator />}
|
||||
</div>
|
||||
|
||||
+4
-4
@@ -82,8 +82,8 @@ export function CommandList() {
|
||||
>
|
||||
{/* Left side: Icon and Label */}
|
||||
<div className='flex items-center gap-[8px]'>
|
||||
<Icon className='h-[14px] w-[14px] text-[#AEAEAE] group-hover:text-[#E6E6E6] dark:group-hover:text-[#E6E6E6]' />
|
||||
<span className='font-medium text-[#AEAEAE] text-[14px] group-hover:text-[#E6E6E6] dark:group-hover:text-[#E6E6E6]'>
|
||||
<Icon className='h-[14px] w-[14px] text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)]' />
|
||||
<span className='font-medium text-[14px] text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)]'>
|
||||
{command.label}
|
||||
</span>
|
||||
</div>
|
||||
@@ -91,7 +91,7 @@ export function CommandList() {
|
||||
{/* Right side: Keyboard Shortcut */}
|
||||
<div className='flex items-center gap-[4px]'>
|
||||
<Button
|
||||
className='group-hover:-translate-y-0.5 w-[26px] py-[3px] text-[12px] hover:translate-y-0 hover:text-[#AEAEAE] hover:shadow-[0_2px_0_0] group-hover:text-[#E6E6E6] group-hover:shadow-[0_4px_0_0] group-hover:dark:text-[#E6E6E6] group-hover:dark:shadow-[#303030] hover:dark:text-[#AEAEAE] hover:dark:shadow-[#303030]'
|
||||
className='group-hover:-translate-y-0.5 w-[26px] py-[3px] text-[12px] hover:translate-y-0 hover:text-[var(--text-tertiary)] hover:shadow-[0_2px_0_0] group-hover:text-[var(--text-primary)] group-hover:shadow-[0_4px_0_0]'
|
||||
variant='3d'
|
||||
>
|
||||
<span>⌘</span>
|
||||
@@ -99,7 +99,7 @@ export function CommandList() {
|
||||
{shortcuts.map((key, index) => (
|
||||
<Button
|
||||
key={index}
|
||||
className='group-hover:-translate-y-0.5 w-[26px] py-[3px] text-[12px] hover:translate-y-0 hover:text-[#AEAEAE] hover:shadow-[0_2px_0_0] group-hover:text-[#E6E6E6] group-hover:shadow-[0_4px_0_0] group-hover:dark:text-[#E6E6E6] group-hover:dark:shadow-[#303030] hover:dark:text-[#AEAEAE] hover:dark:shadow-[#303030]'
|
||||
className='group-hover:-translate-y-0.5 w-[26px] py-[3px] text-[12px] hover:translate-y-0 hover:text-[var(--text-tertiary)] hover:shadow-[0_2px_0_0] group-hover:text-[var(--text-primary)] group-hover:shadow-[0_4px_0_0]'
|
||||
variant='3d'
|
||||
>
|
||||
{key}
|
||||
|
||||
@@ -76,7 +76,7 @@ const CursorsComponent = () => {
|
||||
|
||||
{/* Name tag underneath and to the right */}
|
||||
<div
|
||||
className='absolute top-[18px] left-[4px] h-[21px] w-[140px] truncate whitespace-nowrap rounded-[2px] p-[6px] font-medium text-[#1E1E1E] text-[11px]'
|
||||
className='absolute top-[18px] left-[4px] h-[21px] w-[140px] truncate whitespace-nowrap rounded-[2px] p-[6px] font-medium text-[11px] text-[var(--surface-1)]'
|
||||
style={{ backgroundColor: color }}
|
||||
>
|
||||
{name}
|
||||
|
||||
+3
-3
@@ -303,12 +303,12 @@ export const DiffControls = memo(function DiffControls() {
|
||||
|
||||
return (
|
||||
<div className='-translate-x-1/2 fixed bottom-20 left-1/2 z-30'>
|
||||
<div className='flex items-center gap-[6px] rounded-[10px] bg-[#242424] p-[6px]'>
|
||||
<div className='flex items-center gap-[6px] rounded-[10px] bg-[var(--surface-3)] p-[6px]'>
|
||||
{/* Toggle (left, icon-only) */}
|
||||
<Button
|
||||
variant='ghost'
|
||||
onClick={handleToggleDiff}
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[#363636] p-0 text-[#868686] hover:bg-[#8E4CFB] hover:text-[#E6E6E6]'
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-400)] hover:text-[var(--text-primary)]'
|
||||
title={isShowingDiff ? 'View original' : 'Preview changes'}
|
||||
>
|
||||
{isShowingDiff ? (
|
||||
@@ -322,7 +322,7 @@ export const DiffControls = memo(function DiffControls() {
|
||||
<Button
|
||||
variant='ghost'
|
||||
onClick={handleReject}
|
||||
className='h-[30px] rounded-[8px] bg-[#363636] px-3 text-[#868686] hover:bg-[#8E4CFB] hover:text-[#E6E6E6]'
|
||||
className='h-[30px] rounded-[8px] bg-[var(--surface-9)] px-3 text-[#868686] hover:bg-[var(--brand-400)] hover:text-[var(--text-primary)]'
|
||||
title='Reject changes'
|
||||
>
|
||||
Reject
|
||||
|
||||
+4
-4
@@ -57,7 +57,7 @@ const NoteMarkdown = memo(function NoteMarkdown({ content }: { content: string }
|
||||
li: ({ children }) => <li className='mb-0'>{children}</li>,
|
||||
code: ({ inline, children }: any) =>
|
||||
inline ? (
|
||||
<code className='rounded bg-[#393939] px-1 py-0.5 text-[#F59E0B] text-xs'>
|
||||
<code className='rounded bg-[var(--divider)] px-1 py-0.5 text-[#F59E0B] text-xs'>
|
||||
{children}
|
||||
</code>
|
||||
) : (
|
||||
@@ -70,7 +70,7 @@ const NoteMarkdown = memo(function NoteMarkdown({ content }: { content: string }
|
||||
href={href}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
className='text-[#33B4FF] underline-offset-2 hover:underline'
|
||||
className='text-[var(--brand-secondary)] underline-offset-2 hover:underline'
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
@@ -152,14 +152,14 @@ export const NoteBlock = memo(function NoteBlock({ id, data }: NodeProps<NoteBlo
|
||||
<div className='group relative'>
|
||||
<div
|
||||
className={cn(
|
||||
'relative z-[20] w-[250px] cursor-default select-none rounded-[8px] bg-[#232323]'
|
||||
'relative z-[20] w-[250px] cursor-default select-none rounded-[8px] bg-[var(--surface-2)]'
|
||||
)}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<ActionBar blockId={id} blockType={type} disabled={!userPermissions.canEdit} />
|
||||
|
||||
<div
|
||||
className='note-drag-handle flex cursor-grab items-center justify-between border-[#393939] border-b p-[8px] [&:active]:cursor-grabbing'
|
||||
className='note-drag-handle flex cursor-grab items-center justify-between border-[var(--divider)] border-b p-[8px] [&:active]:cursor-grabbing'
|
||||
onMouseDown={(event) => {
|
||||
event.stopPropagation()
|
||||
}}
|
||||
|
||||
+1
-1
@@ -307,7 +307,7 @@ export default function CopilotMarkdownRenderer({ content }: CopilotMarkdownRend
|
||||
if (inline) {
|
||||
return (
|
||||
<code
|
||||
className='whitespace-normal break-all rounded bg-gray-300 px-1 py-0.5 font-mono text-[#707070] text-[0.9em] dark:bg-[#3D3D3D] dark:text-[#E8E8E8]'
|
||||
className='whitespace-normal break-all rounded bg-gray-300 px-1 py-0.5 font-mono text-[#707070] text-[0.9em] dark:bg-[var(--surface-11)] dark:text-[#E8E8E8]'
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
|
||||
+2
-2
@@ -176,7 +176,7 @@ export function ThinkingBlock({
|
||||
return next
|
||||
})
|
||||
}}
|
||||
className='mb-1 inline-flex items-center gap-1 text-left font-[470] font-season text-[#B1B1B1] text-sm transition-colors hover:text-[#E6E6E6]'
|
||||
className='mb-1 inline-flex items-center gap-1 text-left font-[470] font-season text-[var(--text-secondary)] text-sm transition-colors hover:text-[var(--text-primary)]'
|
||||
type='button'
|
||||
disabled={!hasContent}
|
||||
>
|
||||
@@ -194,7 +194,7 @@ export function ThinkingBlock({
|
||||
</button>
|
||||
|
||||
{isExpanded && (
|
||||
<div className='ml-1 border-[#303030] border-l-2 pl-2'>
|
||||
<div className='ml-1 border-[var(--border-strong)] border-l-2 pl-2'>
|
||||
<pre
|
||||
className='whitespace-pre-wrap font-[470] font-season text-[12px] leading-[1.15rem]'
|
||||
style={{ color: '#B8B8B8' }}
|
||||
|
||||
+11
-9
@@ -267,8 +267,8 @@ const CopilotMessage: FC<CopilotMessageProps> = memo(
|
||||
|
||||
{/* Inline Checkpoint Discard Confirmation - shown below input in edit mode */}
|
||||
{showCheckpointDiscardModal && (
|
||||
<div className='mt-[8px] rounded-[4px] border border-[#3D3D3D] bg-[#282828] p-[10px] dark:border-[#3D3D3D] dark:bg-[#363636]'>
|
||||
<p className='mb-[8px] text-[#E6E6E6] text-sm'>
|
||||
<div className='mt-[8px] rounded-[4px] border border-[var(--surface-11)] bg-[var(--surface-6)] p-[10px] dark:border-[var(--surface-11)] dark:bg-[var(--surface-9)]'>
|
||||
<p className='mb-[8px] text-[var(--text-primary)] text-sm'>
|
||||
Continue from a previous message?
|
||||
</p>
|
||||
<div className='flex gap-[6px]'>
|
||||
@@ -278,7 +278,7 @@ const CopilotMessage: FC<CopilotMessageProps> = memo(
|
||||
className='flex flex-1 items-center justify-center gap-[6px] px-[8px] py-[4px] text-xs'
|
||||
>
|
||||
<span>Cancel</span>
|
||||
<span className='text-[#787878] text-[10px]'>(Esc)</span>
|
||||
<span className='text-[10px] text-[var(--text-muted)]'>(Esc)</span>
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleContinueAndRevert}
|
||||
@@ -314,7 +314,7 @@ const CopilotMessage: FC<CopilotMessageProps> = memo(
|
||||
onClick={handleMessageClick}
|
||||
onMouseEnter={() => setIsHoveringMessage(true)}
|
||||
onMouseLeave={() => setIsHoveringMessage(false)}
|
||||
className='group relative w-full cursor-pointer rounded-[4px] border border-[#3D3D3D] bg-[#282828] px-[6px] py-[6px] transition-all duration-200 hover:border-[#4A4A4A] hover:bg-[#363636] dark:border-[#3D3D3D] dark:bg-[#363636] dark:hover:border-[#454545] dark:hover:bg-[#3D3D3D]'
|
||||
className='group relative w-full cursor-pointer rounded-[4px] border border-[var(--surface-11)] bg-[var(--surface-6)] px-[6px] py-[6px] transition-all duration-200 hover:border-[var(--surface-14)] hover:bg-[var(--surface-9)] dark:border-[var(--surface-11)] dark:bg-[var(--surface-9)] dark:hover:border-[var(--surface-13)] dark:hover:bg-[var(--surface-11)]'
|
||||
>
|
||||
<div
|
||||
ref={messageContentRef}
|
||||
@@ -360,7 +360,7 @@ const CopilotMessage: FC<CopilotMessageProps> = memo(
|
||||
|
||||
{/* Gradient fade when truncated - applies to entire message box */}
|
||||
{!isExpanded && needsExpansion && (
|
||||
<div className='pointer-events-none absolute right-0 bottom-0 left-0 h-6 bg-gradient-to-t from-0% from-[#282828] via-40% via-[#282828]/70 to-100% to-transparent group-hover:from-[#363636] group-hover:via-[#363636]/70 dark:from-[#363636] dark:via-[#363636]/70 dark:group-hover:from-[#3D3D3D] dark:group-hover:via-[#3D3D3D]/70' />
|
||||
<div className='pointer-events-none absolute right-0 bottom-0 left-0 h-6 bg-gradient-to-t from-0% from-[var(--surface-6)] via-40% via-[var(--surface-6)]/70 to-100% to-transparent group-hover:from-[var(--surface-9)] group-hover:via-[var(--surface-9)]/70 dark:from-[var(--surface-9)] dark:via-[var(--surface-9)]/70 dark:group-hover:from-[var(--surface-11)] dark:group-hover:via-[var(--surface-11)]/70' />
|
||||
)}
|
||||
|
||||
{/* Abort button when hovering and response is generating (only on last user message) */}
|
||||
@@ -408,11 +408,13 @@ const CopilotMessage: FC<CopilotMessageProps> = memo(
|
||||
|
||||
{/* Inline Restore Checkpoint Confirmation */}
|
||||
{showRestoreConfirmation && (
|
||||
<div className='mt-[8px] rounded-[4px] border border-[#3D3D3D] bg-[#282828] p-[10px] dark:border-[#3D3D3D] dark:bg-[#363636]'>
|
||||
<p className='mb-[8px] text-[#E6E6E6] text-sm'>
|
||||
<div className='mt-[8px] rounded-[4px] border border-[var(--surface-11)] bg-[var(--surface-6)] p-[10px] dark:border-[var(--surface-11)] dark:bg-[var(--surface-9)]'>
|
||||
<p className='mb-[8px] text-[var(--text-primary)] text-sm'>
|
||||
Revert to checkpoint? This will restore your workflow to the state saved at this
|
||||
checkpoint.{' '}
|
||||
<span className='font-medium text-[#EF4444]'>This action cannot be undone.</span>
|
||||
<span className='font-medium text-[var(--text-error)]'>
|
||||
This action cannot be undone.
|
||||
</span>
|
||||
</p>
|
||||
<div className='flex gap-[6px]'>
|
||||
<Button
|
||||
@@ -421,7 +423,7 @@ const CopilotMessage: FC<CopilotMessageProps> = memo(
|
||||
className='flex flex-1 items-center justify-center gap-[6px] px-[8px] py-[4px] text-xs'
|
||||
>
|
||||
<span>Cancel</span>
|
||||
<span className='text-[#787878] text-[10px]'>(Esc)</span>
|
||||
<span className='text-[10px] text-[var(--text-muted)]'>(Esc)</span>
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleConfirmRevert}
|
||||
|
||||
+14
-11
@@ -66,7 +66,7 @@ export const TodoList = memo(function TodoList({
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'w-full rounded-t-[4px] rounded-b-none border-[#3D3D3D] border-x border-t bg-[#282828] dark:border-[#3D3D3D] dark:bg-[#363636]',
|
||||
'w-full rounded-t-[4px] rounded-b-none border-[var(--surface-11)] border-x border-t bg-[var(--surface-6)] dark:border-[var(--surface-11)] dark:bg-[var(--surface-9)]',
|
||||
className
|
||||
)}
|
||||
>
|
||||
@@ -84,17 +84,19 @@ export const TodoList = memo(function TodoList({
|
||||
<ChevronDown className='h-[14px] w-[14px]' />
|
||||
)}
|
||||
</Button>
|
||||
<span className='font-medium text-[#E6E6E6] text-xs dark:text-[#E6E6E6]'>Todo:</span>
|
||||
<span className='font-medium text-[#E6E6E6] text-xs dark:text-[#E6E6E6]'>
|
||||
<span className='font-medium text-[var(--text-primary)] text-xs dark:text-[var(--text-primary)]'>
|
||||
Todo:
|
||||
</span>
|
||||
<span className='font-medium text-[var(--text-primary)] text-xs dark:text-[var(--text-primary)]'>
|
||||
{completedCount}/{totalCount}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className='flex flex-1 items-center gap-[8px] pl-[10px]'>
|
||||
{/* Progress bar */}
|
||||
<div className='h-1.5 flex-1 overflow-hidden rounded-full bg-[#3D3D3D] dark:bg-[#3D3D3D]'>
|
||||
<div className='h-1.5 flex-1 overflow-hidden rounded-full bg-[var(--surface-11)] dark:bg-[var(--surface-11)]'>
|
||||
<div
|
||||
className='h-full bg-[#8E4CFB] transition-all duration-300 ease-out dark:bg-[#8E4CFB]'
|
||||
className='h-full bg-[var(--brand-400)] transition-all duration-300 ease-out dark:bg-[var(--brand-400)]'
|
||||
style={{ width: `${progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
@@ -119,20 +121,21 @@ export const TodoList = memo(function TodoList({
|
||||
<div
|
||||
key={todo.id}
|
||||
className={cn(
|
||||
'flex items-start gap-2 px-3 py-1.5 transition-colors hover:bg-[#363636]/50 dark:hover:bg-[#3D3D3D]/50',
|
||||
index !== todos.length - 1 && 'border-[#3D3D3D] border-b dark:border-[#3D3D3D]'
|
||||
'flex items-start gap-2 px-3 py-1.5 transition-colors hover:bg-[var(--surface-9)]/50 dark:hover:bg-[var(--surface-11)]/50',
|
||||
index !== todos.length - 1 &&
|
||||
'border-[var(--surface-11)] border-b dark:border-[var(--surface-11)]'
|
||||
)}
|
||||
>
|
||||
{todo.executing ? (
|
||||
<div className='mt-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center'>
|
||||
<Loader2 className='h-3 w-3 animate-spin text-[#E6E6E6] dark:text-[#E6E6E6]' />
|
||||
<Loader2 className='h-3 w-3 animate-spin text-[var(--text-primary)] dark:text-[var(--text-primary)]' />
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={cn(
|
||||
'mt-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center rounded border transition-all',
|
||||
todo.completed
|
||||
? 'border-[#8E4CFB] bg-[#8E4CFB] dark:border-[#8E4CFB] dark:bg-[#8E4CFB]'
|
||||
? 'border-[var(--brand-400)] bg-[var(--brand-400)] dark:border-[var(--brand-400)] dark:bg-[var(--brand-400)]'
|
||||
: 'border-[#707070] dark:border-[#707070]'
|
||||
)}
|
||||
>
|
||||
@@ -144,8 +147,8 @@ export const TodoList = memo(function TodoList({
|
||||
className={cn(
|
||||
'flex-1 font-base text-[12px] leading-relaxed',
|
||||
todo.completed
|
||||
? 'text-[#787878] line-through dark:text-[#787878]'
|
||||
: 'text-[#FFFFFF] dark:text-[#FFFFFF]'
|
||||
? 'text-[var(--text-muted)] line-through dark:text-[var(--text-muted)]'
|
||||
: 'text-[var(--white)] dark:text-[var(--white)]'
|
||||
)}
|
||||
>
|
||||
{todo.content}
|
||||
|
||||
+9
-3
@@ -583,7 +583,9 @@ export function MentionMenu({
|
||||
<span className='flex-1 truncate'>{item.label}</span>
|
||||
{item.category === 'logs' && (
|
||||
<>
|
||||
<span className='text-[#AEAEAE] text-[10px] dark:text-[#AEAEAE]'>·</span>
|
||||
<span className='text-[10px] text-[var(--text-tertiary)] dark:text-[var(--text-tertiary)]'>
|
||||
·
|
||||
</span>
|
||||
<span className='whitespace-nowrap text-[10px]'>
|
||||
{formatTimestamp(item.data.createdAt)}
|
||||
</span>
|
||||
@@ -756,11 +758,15 @@ export function MentionMenu({
|
||||
mentionData.logsList.map((log) => (
|
||||
<PopoverItem key={log.id} onClick={() => insertLogMention(log)}>
|
||||
<span className='min-w-0 flex-1 truncate'>{log.workflowName}</span>
|
||||
<span className='text-[#AEAEAE] text-[10px] dark:text-[#AEAEAE]'>·</span>
|
||||
<span className='text-[10px] text-[var(--text-tertiary)] dark:text-[var(--text-tertiary)]'>
|
||||
·
|
||||
</span>
|
||||
<span className='whitespace-nowrap text-[10px]'>
|
||||
{formatTimestamp(log.createdAt)}
|
||||
</span>
|
||||
<span className='text-[#AEAEAE] text-[10px] dark:text-[#AEAEAE]'>·</span>
|
||||
<span className='text-[10px] text-[var(--text-tertiary)] dark:text-[var(--text-tertiary)]'>
|
||||
·
|
||||
</span>
|
||||
<span className='text-[10px] capitalize'>
|
||||
{(log.trigger || 'manual').toLowerCase()}
|
||||
</span>
|
||||
|
||||
+3
-3
@@ -568,8 +568,8 @@ const UserInput = forwardRef<UserInputRef, UserInputProps>(
|
||||
<div
|
||||
ref={setInputContainerRef}
|
||||
className={cn(
|
||||
'relative w-full rounded-[4px] border border-[#3D3D3D] bg-[#282828] px-[6px] py-[6px] transition-colors dark:bg-[#363636]',
|
||||
fileAttachments.isDragging && 'ring-[#33B4FF] ring-[1.75px]'
|
||||
'relative w-full rounded-[4px] border border-[var(--surface-11)] bg-[var(--surface-6)] px-[6px] py-[6px] transition-colors dark:bg-[var(--surface-9)]',
|
||||
fileAttachments.isDragging && 'ring-[1.75px] ring-[var(--brand-secondary)]'
|
||||
)}
|
||||
onDragEnter={fileAttachments.handleDragEnter}
|
||||
onDragLeave={fileAttachments.handleDragLeave}
|
||||
@@ -635,7 +635,7 @@ const UserInput = forwardRef<UserInputRef, UserInputProps>(
|
||||
placeholder={fileAttachments.isDragging ? 'Drop files here...' : effectivePlaceholder}
|
||||
disabled={disabled}
|
||||
rows={2}
|
||||
className='relative z-[2] m-0 box-border h-auto min-h-[48px] w-full resize-none overflow-y-auto overflow-x-hidden break-words border-0 bg-transparent px-[2px] py-1 font-medium font-sans text-sm text-transparent leading-[1.25rem] caret-foreground outline-none [-ms-overflow-style:none] [scrollbar-width:none] [text-rendering:auto] focus-visible:ring-0 focus-visible:ring-offset-0 [&::-webkit-scrollbar]:hidden'
|
||||
className='relative z-[2] m-0 box-border h-auto min-h-[48px] w-full resize-none overflow-y-auto overflow-x-hidden break-words border-0 bg-transparent px-[2px] py-1 font-medium font-sans text-sm text-transparent leading-[1.25rem] caret-foreground outline-none [-ms-overflow-style:none] [scrollbar-width:none] [text-rendering:auto] placeholder:text-[var(--text-muted)] focus-visible:ring-0 focus-visible:ring-offset-0 dark:placeholder:text-[var(--text-muted)] [&::-webkit-scrollbar]:hidden'
|
||||
/>
|
||||
|
||||
{/* Mention Menu Portal */}
|
||||
|
||||
+4
-2
@@ -64,14 +64,16 @@ export function Welcome({ onQuestionClick, mode = 'ask' }: WelcomeProps) {
|
||||
>
|
||||
<div className='flex flex-col items-start'>
|
||||
<p className='font-medium'>{title}</p>
|
||||
<p className='text-[#B1B1B1] dark:text-[#B1B1B1]'>{question}</p>
|
||||
<p className='text-[var(--text-secondary)] dark:text-[var(--text-secondary)]'>
|
||||
{question}
|
||||
</p>
|
||||
</div>
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Tips */}
|
||||
<p className='pt-[12px] text-center text-[#B1B1B1] text-[13px] dark:text-[#B1B1B1]'>
|
||||
<p className='pt-[12px] text-center text-[13px] text-[var(--text-secondary)] dark:text-[var(--text-secondary)]'>
|
||||
Tip: Use <span className='font-medium'>@</span> to reference chats, workflows, knowledge,
|
||||
blocks, or templates
|
||||
</p>
|
||||
|
||||
+2
-2
@@ -334,7 +334,7 @@ export const Copilot = forwardRef<CopilotRef, CopilotProps>(({ panelWidth }, ref
|
||||
>
|
||||
{/* Header */}
|
||||
<div className='flex flex-shrink-0 items-center justify-between rounded-[4px] bg-[#2A2A2A] px-[12px] py-[8px] dark:bg-[#2A2A2A]'>
|
||||
<h2 className='font-medium text-[#FFFFFF] text-[14px] dark:text-[#FFFFFF]'>
|
||||
<h2 className='font-medium text-[14px] text-[var(--white)] dark:text-[var(--white)]'>
|
||||
{currentChat?.title || 'New Chat'}
|
||||
</h2>
|
||||
<div className='flex items-center gap-[8px]'>
|
||||
@@ -353,7 +353,7 @@ export const Copilot = forwardRef<CopilotRef, CopilotProps>(({ panelWidth }, ref
|
||||
<ChatHistorySkeleton />
|
||||
</PopoverScrollArea>
|
||||
) : groupedChats.length === 0 ? (
|
||||
<div className='px-[6px] py-[16px] text-center text-[#FFFFFF] text-[12px] dark:text-[#FFFFFF]'>
|
||||
<div className='px-[6px] py-[16px] text-center text-[12px] text-[var(--white)] dark:text-[var(--white)]'>
|
||||
No chats yet
|
||||
</div>
|
||||
) : (
|
||||
|
||||
+3
-3
@@ -91,7 +91,7 @@ export function FieldItem({
|
||||
onDragStart={handleDragStart}
|
||||
onClick={handleClick}
|
||||
className={clsx(
|
||||
'group flex h-[25px] cursor-grab items-center gap-[8px] rounded-[8px] px-[8px] text-[14px] hover:bg-[#2C2C2C] active:cursor-grabbing dark:hover:bg-[#2C2C2C]',
|
||||
'group flex h-[25px] cursor-grab items-center gap-[8px] rounded-[8px] px-[8px] text-[14px] hover:bg-[var(--border)] active:cursor-grabbing dark:hover:bg-[var(--border)]',
|
||||
hasChildren && 'cursor-pointer'
|
||||
)}
|
||||
style={{ marginLeft: `${indent}px` }}
|
||||
@@ -99,7 +99,7 @@ export function FieldItem({
|
||||
<span
|
||||
className={clsx(
|
||||
'flex-1 truncate font-medium',
|
||||
'text-[#AEAEAE] group-hover:text-[#E6E6E6] dark:text-[#AEAEAE] dark:group-hover:text-[#E6E6E6]'
|
||||
'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)] dark:text-[var(--text-tertiary)] dark:group-hover:text-[var(--text-primary)]'
|
||||
)}
|
||||
>
|
||||
{field.name}
|
||||
@@ -109,7 +109,7 @@ export function FieldItem({
|
||||
<ChevronDown
|
||||
className={clsx(
|
||||
'h-3.5 w-3.5 flex-shrink-0 transition-transform',
|
||||
'text-[#AEAEAE] group-hover:text-[#E6E6E6] dark:text-[#AEAEAE] dark:group-hover:text-[#E6E6E6]',
|
||||
'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)] dark:text-[var(--text-tertiary)] dark:group-hover:text-[var(--text-primary)]',
|
||||
isExpanded && 'rotate-180'
|
||||
)}
|
||||
/>
|
||||
|
||||
+3
-3
@@ -119,7 +119,7 @@ function ConnectionItem({
|
||||
draggable
|
||||
onDragStart={(e) => onConnectionDragStart(e, connection)}
|
||||
className={clsx(
|
||||
'group flex h-[25px] cursor-grab items-center gap-[8px] rounded-[8px] px-[5.5px] text-[14px] hover:bg-[#2C2C2C] active:cursor-grabbing dark:hover:bg-[#2C2C2C]',
|
||||
'group flex h-[25px] cursor-grab items-center gap-[8px] rounded-[8px] px-[5.5px] text-[14px] hover:bg-[var(--border)] active:cursor-grabbing dark:hover:bg-[var(--border)]',
|
||||
hasFields && 'cursor-pointer'
|
||||
)}
|
||||
onClick={() => hasFields && onToggleExpand(connection.id)}
|
||||
@@ -141,7 +141,7 @@ function ConnectionItem({
|
||||
<span
|
||||
className={clsx(
|
||||
'truncate font-medium',
|
||||
'text-[#AEAEAE] group-hover:text-[#E6E6E6] dark:text-[#AEAEAE] dark:group-hover:text-[#E6E6E6]'
|
||||
'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)] dark:text-[var(--text-tertiary)] dark:group-hover:text-[var(--text-primary)]'
|
||||
)}
|
||||
>
|
||||
{connection.name}
|
||||
@@ -150,7 +150,7 @@ function ConnectionItem({
|
||||
<ChevronDown
|
||||
className={clsx(
|
||||
'h-3.5 w-3.5 flex-shrink-0 transition-transform',
|
||||
'text-[#AEAEAE] group-hover:text-[#E6E6E6] dark:text-[#AEAEAE] dark:group-hover:text-[#E6E6E6]',
|
||||
'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)] dark:text-[var(--text-tertiary)] dark:group-hover:text-[var(--text-primary)]',
|
||||
isExpanded && 'rotate-180'
|
||||
)}
|
||||
/>
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ function CheckboxItem({ blockId, option, isPreview, subBlockValues, disabled }:
|
||||
/>
|
||||
<Label
|
||||
htmlFor={`${blockId}-${option.id}`}
|
||||
className='cursor-pointer font-medium font-sans text-[#E6E6E6] text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50'
|
||||
className='cursor-pointer font-medium font-sans text-[var(--text-primary)] text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50'
|
||||
>
|
||||
{option.label}
|
||||
</Label>
|
||||
|
||||
+6
-4
@@ -708,17 +708,19 @@ export function ConditionInput({
|
||||
{conditionalBlocks.map((block, index) => (
|
||||
<div
|
||||
key={block.id}
|
||||
className='group relative overflow-visible rounded-[4px] border border-[#303030] bg-[#1F1F1F]'
|
||||
className='group relative overflow-visible rounded-[4px] border border-[var(--border-strong)] bg-[#1F1F1F]'
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center justify-between overflow-hidden bg-transparent px-[10px] py-[5px]',
|
||||
block.title === 'else'
|
||||
? 'rounded-[4px] border-0'
|
||||
: 'rounded-t-[4px] border-[#303030] border-b'
|
||||
: 'rounded-t-[4px] border-[var(--border-strong)] border-b'
|
||||
)}
|
||||
>
|
||||
<span className='font-medium text-[#AEAEAE] text-[14px]'>{block.title}</span>
|
||||
<span className='font-medium text-[14px] text-[var(--text-tertiary)]'>
|
||||
{block.title}
|
||||
</span>
|
||||
<div className='flex items-center gap-[8px]'>
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger asChild>
|
||||
@@ -777,7 +779,7 @@ export function ConditionInput({
|
||||
variant='ghost'
|
||||
onClick={() => removeBlock(block.id)}
|
||||
disabled={isPreview || conditionalBlocks.length === 1 || disabled}
|
||||
className='h-auto p-0 text-[#EF4444] hover:text-[#EF4444]'
|
||||
className='h-auto p-0 text-[var(--text-error)] hover:text-[var(--text-error)]'
|
||||
>
|
||||
<Trash className='h-[14px] w-[14px]' />
|
||||
<span className='sr-only'>Delete Block</span>
|
||||
|
||||
+1
-1
@@ -284,7 +284,7 @@ export const EnvVarDropdown: React.FC<EnvVarDropdownProps> = ({
|
||||
onCloseAutoFocus={(e) => e.preventDefault()}
|
||||
>
|
||||
{filteredEnvVars.length === 0 ? (
|
||||
<div className='px-[6px] py-[8px] text-[#FFFFFF]/60 text-[12px]'>
|
||||
<div className='px-[6px] py-[8px] text-[12px] text-[var(--white)]/60'>
|
||||
No matching environment variables
|
||||
</div>
|
||||
) : (
|
||||
|
||||
+7
-5
@@ -130,8 +130,10 @@ export function EvalInput({
|
||||
}
|
||||
|
||||
const renderMetricHeader = (metric: EvalMetric, index: number) => (
|
||||
<div className='flex items-center justify-between overflow-hidden rounded-t-[4px] border-[#303030] border-b bg-transparent px-[10px] py-[5px]'>
|
||||
<span className='font-medium text-[#AEAEAE] text-[14px]'>Metric {index + 1}</span>
|
||||
<div className='flex items-center justify-between overflow-hidden rounded-t-[4px] border-[var(--border-strong)] border-b bg-transparent px-[10px] py-[5px]'>
|
||||
<span className='font-medium text-[14px] text-[var(--text-tertiary)]'>
|
||||
Metric {index + 1}
|
||||
</span>
|
||||
<div className='flex items-center gap-[8px]'>
|
||||
<Tooltip.Root key={`add-${metric.id}`}>
|
||||
<Tooltip.Trigger asChild>
|
||||
@@ -154,7 +156,7 @@ export function EvalInput({
|
||||
variant='ghost'
|
||||
onClick={() => removeMetric(metric.id)}
|
||||
disabled={isPreview || disabled || metrics.length === 1}
|
||||
className='h-auto p-0 text-[#EF4444] hover:text-[#EF4444]'
|
||||
className='h-auto p-0 text-[var(--text-error)] hover:text-[var(--text-error)]'
|
||||
>
|
||||
<Trash className='h-[14px] w-[14px]' />
|
||||
<span className='sr-only'>Delete Metric</span>
|
||||
@@ -172,11 +174,11 @@ export function EvalInput({
|
||||
<div
|
||||
key={metric.id}
|
||||
data-metric-id={metric.id}
|
||||
className='group relative overflow-visible rounded-[4px] border border-[#303030] bg-[#1F1F1F]'
|
||||
className='group relative overflow-visible rounded-[4px] border border-[var(--border-strong)] bg-[#1F1F1F]'
|
||||
>
|
||||
{renderMetricHeader(metric, index)}
|
||||
|
||||
<div className='flex flex-col gap-[6px] border-[#303030] px-[10px] pt-[6px] pb-[10px]'>
|
||||
<div className='flex flex-col gap-[6px] border-[var(--border-strong)] px-[10px] pt-[6px] pb-[10px]'>
|
||||
<div key={`name-${metric.id}`} className='space-y-[4px]'>
|
||||
<Label className='text-[13px]'>Name</Label>
|
||||
<Input
|
||||
|
||||
+10
-10
@@ -247,9 +247,9 @@ export function InputMapping({
|
||||
|
||||
if (!selectedWorkflowId) {
|
||||
return (
|
||||
<div className='flex flex-col items-center justify-center rounded-[4px] border border-[#303030] bg-[#1F1F1F] p-8 text-center'>
|
||||
<div className='flex flex-col items-center justify-center rounded-[4px] border border-[var(--border-strong)] bg-[#1F1F1F] p-8 text-center'>
|
||||
<svg
|
||||
className='mb-3 h-10 w-10 text-[#AEAEAE]'
|
||||
className='mb-3 h-10 w-10 text-[var(--text-tertiary)]'
|
||||
fill='none'
|
||||
viewBox='0 0 24 24'
|
||||
stroke='currentColor'
|
||||
@@ -261,8 +261,8 @@ export function InputMapping({
|
||||
d='M13 10V3L4 14h7v7l9-11h-7z'
|
||||
/>
|
||||
</svg>
|
||||
<p className='font-medium text-[#AEAEAE] text-sm'>No workflow selected</p>
|
||||
<p className='mt-1 text-[#AEAEAE]/80 text-xs'>
|
||||
<p className='font-medium text-[var(--text-tertiary)] text-sm'>No workflow selected</p>
|
||||
<p className='mt-1 text-[var(--text-tertiary)]/80 text-xs'>
|
||||
Select a workflow above to configure inputs
|
||||
</p>
|
||||
</div>
|
||||
@@ -290,7 +290,7 @@ export function InputMapping({
|
||||
}
|
||||
|
||||
if (!childInputFields || childInputFields.length === 0) {
|
||||
return <p className='text-[#787878] text-sm'>No inputs available</p>
|
||||
return <p className='text-[var(--text-muted)] text-sm'>No inputs available</p>
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -354,22 +354,22 @@ function InputMappingField({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='group relative overflow-visible rounded-[4px] border border-[#303030] bg-[#1F1F1F]'>
|
||||
<div className='group relative overflow-visible rounded-[4px] border border-[var(--border-strong)] bg-[#1F1F1F]'>
|
||||
<div className='flex items-center justify-between bg-transparent px-[10px] py-[5px]'>
|
||||
<Label className='font-medium text-[#AEAEAE] text-[14px]'>{fieldName}</Label>
|
||||
<Label className='font-medium text-[14px] text-[var(--text-tertiary)]'>{fieldName}</Label>
|
||||
{fieldType && (
|
||||
<span className='rounded-md bg-[#2A2A2A] px-1.5 py-0.5 font-mono text-[#AEAEAE] text-[10px]'>
|
||||
<span className='rounded-md bg-[#2A2A2A] px-1.5 py-0.5 font-mono text-[10px] text-[var(--text-tertiary)]'>
|
||||
{fieldType}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className='relative w-full border-[#303030] border-t bg-transparent'>
|
||||
<div className='relative w-full border-[var(--border-strong)] border-t bg-transparent'>
|
||||
<Input
|
||||
ref={(el) => {
|
||||
if (el) inputRefs.current.set(fieldId, el)
|
||||
}}
|
||||
className={cn(
|
||||
'allow-scroll !bg-transparent w-full overflow-auto rounded-none border-0 px-[10px] py-[8px] text-transparent caret-white [-ms-overflow-style:none] [scrollbar-width:none] placeholder:text-[#787878] focus-visible:ring-0 focus-visible:ring-offset-0 [&::-webkit-scrollbar]:hidden'
|
||||
'allow-scroll !bg-transparent w-full overflow-auto rounded-none border-0 px-[10px] py-[8px] text-transparent caret-white [-ms-overflow-style:none] [scrollbar-width:none] placeholder:text-[var(--text-muted)] focus-visible:ring-0 focus-visible:ring-offset-0 [&::-webkit-scrollbar]:hidden'
|
||||
)}
|
||||
type='text'
|
||||
value={value}
|
||||
|
||||
+2
-2
@@ -326,13 +326,13 @@ export function LongInput({
|
||||
{/* Custom resize handle */}
|
||||
{!wandHook.isStreaming && (
|
||||
<div
|
||||
className='absolute right-1 bottom-1 flex h-4 w-4 cursor-ns-resize items-center justify-center rounded-[4px] border border-[#3D3D3D] bg-[#282828] dark:bg-[#363636]'
|
||||
className='absolute right-1 bottom-1 flex h-4 w-4 cursor-ns-resize items-center justify-center rounded-[4px] border border-[var(--surface-11)] bg-[var(--surface-6)] dark:bg-[var(--surface-9)]'
|
||||
onMouseDown={startResize}
|
||||
onDragStart={(e) => {
|
||||
e.preventDefault()
|
||||
}}
|
||||
>
|
||||
<ChevronsUpDown className='h-3 w-3 text-[#787878]' />
|
||||
<ChevronsUpDown className='h-3 w-3 text-[var(--text-muted)]' />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
+6
-6
@@ -165,7 +165,7 @@ export function FieldFormat({
|
||||
onClick={() => toggleCollapse(field.id)}
|
||||
>
|
||||
<div className='flex min-w-0 flex-1 items-center gap-[8px]'>
|
||||
<span className='block truncate font-medium text-[#AEAEAE] text-[14px]'>
|
||||
<span className='block truncate font-medium text-[14px] text-[var(--text-tertiary)]'>
|
||||
{field.name || `${title} ${index + 1}`}
|
||||
</span>
|
||||
{field.name && showType && <Badge className='h-[20px] text-[13px]'>{field.type}</Badge>}
|
||||
@@ -179,7 +179,7 @@ export function FieldFormat({
|
||||
variant='ghost'
|
||||
onClick={() => removeField(field.id)}
|
||||
disabled={isReadOnly || fields.length === 1}
|
||||
className='h-auto p-0 text-[#EF4444] hover:text-[#EF4444]'
|
||||
className='h-auto p-0 text-[var(--text-error)] hover:text-[var(--text-error)]'
|
||||
>
|
||||
<Trash className='h-[14px] w-[14px]' />
|
||||
<span className='sr-only'>Delete Field</span>
|
||||
@@ -240,7 +240,7 @@ export function FieldFormat({
|
||||
return Array.from({ length: lineCount }, (_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className='font-medium font-mono text-[#787878] text-xs'
|
||||
className='font-medium font-mono text-[var(--text-muted)] text-xs'
|
||||
style={{ height: `${21}px`, lineHeight: `${21}px` }}
|
||||
>
|
||||
{i + 1}
|
||||
@@ -279,7 +279,7 @@ export function FieldFormat({
|
||||
return Array.from({ length: lineCount }, (_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className='font-medium font-mono text-[#787878] text-xs'
|
||||
className='font-medium font-mono text-[var(--text-muted)] text-xs'
|
||||
style={{ height: `${21}px`, lineHeight: `${21}px` }}
|
||||
>
|
||||
{i + 1}
|
||||
@@ -364,14 +364,14 @@ export function FieldFormat({
|
||||
key={field.id}
|
||||
data-field-id={field.id}
|
||||
className={cn(
|
||||
'rounded-[4px] border border-[#303030] bg-[#1F1F1F]',
|
||||
'rounded-[4px] border border-[var(--border-strong)] bg-[#1F1F1F]',
|
||||
field.collapsed ? 'overflow-hidden' : 'overflow-visible'
|
||||
)}
|
||||
>
|
||||
{renderFieldHeader(field, index)}
|
||||
|
||||
{!field.collapsed && (
|
||||
<div className='flex flex-col gap-[6px] border-[#303030] border-t px-[10px] pt-[6px] pb-[10px]'>
|
||||
<div className='flex flex-col gap-[6px] border-[var(--border-strong)] border-t px-[10px] pt-[6px] pb-[10px]'>
|
||||
<div className='flex flex-col gap-[4px]'>
|
||||
<Label className='text-[13px]'>Name</Label>
|
||||
<Input
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ export function Switch({
|
||||
/>
|
||||
<Label
|
||||
htmlFor={`${blockId}-${subBlockId}`}
|
||||
className='cursor-pointer font-medium font-sans text-[#E6E6E6] text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50'
|
||||
className='cursor-pointer font-medium font-sans text-[var(--text-primary)] text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50'
|
||||
>
|
||||
{title}
|
||||
</Label>
|
||||
|
||||
+10
-7
@@ -134,13 +134,13 @@ export function Table({
|
||||
|
||||
const renderHeader = () => (
|
||||
<thead className='bg-transparent'>
|
||||
<tr className='border-[#303030] border-b bg-transparent'>
|
||||
<tr className='border-[var(--border-strong)] border-b bg-transparent'>
|
||||
{columns.map((column, index) => (
|
||||
<th
|
||||
key={column}
|
||||
className={cn(
|
||||
'bg-transparent px-[10px] py-[5px] text-left font-medium text-[#AEAEAE] text-[14px]',
|
||||
index < columns.length - 1 && 'border-[#303030] border-r'
|
||||
'bg-transparent px-[10px] py-[5px] text-left font-medium text-[14px] text-[var(--text-tertiary)]',
|
||||
index < columns.length - 1 && 'border-[var(--border-strong)] border-r'
|
||||
)}
|
||||
>
|
||||
{column}
|
||||
@@ -187,7 +187,7 @@ export function Table({
|
||||
key={`${row.id}-${column}`}
|
||||
className={cn(
|
||||
'relative bg-transparent p-0',
|
||||
cellIndex < columns.length - 1 && 'border-[#303030] border-r'
|
||||
cellIndex < columns.length - 1 && 'border-[var(--border-strong)] border-r'
|
||||
)}
|
||||
>
|
||||
<div className='relative w-full'>
|
||||
@@ -203,7 +203,7 @@ export function Table({
|
||||
onDragOver={handlers.onDragOver}
|
||||
disabled={isPreview || disabled}
|
||||
autoComplete='off'
|
||||
className='w-full border-0 bg-transparent px-[10px] py-[8px] text-transparent caret-white placeholder:text-[#787878] focus-visible:ring-0 focus-visible:ring-offset-0'
|
||||
className='w-full border-0 bg-transparent px-[10px] py-[8px] text-transparent caret-white placeholder:text-[var(--text-muted)] focus-visible:ring-0 focus-visible:ring-offset-0'
|
||||
/>
|
||||
<div
|
||||
data-overlay={cellKey}
|
||||
@@ -270,12 +270,15 @@ export function Table({
|
||||
|
||||
return (
|
||||
<div className='relative'>
|
||||
<div className='overflow-visible rounded-[4px] border border-[#303030] bg-[#1F1F1F]'>
|
||||
<div className='overflow-visible rounded-[4px] border border-[var(--border-strong)] bg-[#1F1F1F]'>
|
||||
<table className='w-full bg-transparent'>
|
||||
{renderHeader()}
|
||||
<tbody className='bg-transparent'>
|
||||
{rows.map((row, rowIndex) => (
|
||||
<tr key={row.id} className='group relative border-[#303030] border-t bg-transparent'>
|
||||
<tr
|
||||
key={row.id}
|
||||
className='group relative border-[var(--border-strong)] border-t bg-transparent'
|
||||
>
|
||||
{columns.map((column, cellIndex) => renderCell(row, rowIndex, column, cellIndex))}
|
||||
{renderDeleteButton(rowIndex)}
|
||||
</tr>
|
||||
|
||||
+4
-4
@@ -1324,7 +1324,7 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
/>
|
||||
<PopoverScrollArea>
|
||||
{flatTagList.length === 0 ? (
|
||||
<div className='px-[6px] py-[8px] text-[#FFFFFF]/60 text-[12px]'>
|
||||
<div className='px-[6px] py-[8px] text-[12px] text-[var(--white)]/60'>
|
||||
No matching tags found
|
||||
</div>
|
||||
) : (
|
||||
@@ -1362,7 +1362,7 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
: tag}
|
||||
</span>
|
||||
{variableInfo && (
|
||||
<span className='ml-auto text-[#FFFFFF]/60 text-[10px]'>
|
||||
<span className='ml-auto text-[10px] text-[var(--white)]/60'>
|
||||
{variableInfo.type}
|
||||
</span>
|
||||
)}
|
||||
@@ -1468,7 +1468,7 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
<TagIcon icon={tagIcon} color={blockColor} />
|
||||
<span className='flex-1 truncate'>{child.display}</span>
|
||||
{childType && childType !== 'any' && (
|
||||
<span className='ml-auto text-[#FFFFFF]/60 text-[10px]'>
|
||||
<span className='ml-auto text-[10px] text-[var(--white)]/60'>
|
||||
{childType}
|
||||
</span>
|
||||
)}
|
||||
@@ -1547,7 +1547,7 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
<TagIcon icon={displayIcon} color={blockColor} />
|
||||
<span className='flex-1 truncate'>{nestedTag.display}</span>
|
||||
{tagDescription && tagDescription !== 'any' && (
|
||||
<span className='ml-auto text-[#FFFFFF]/60 text-[10px]'>
|
||||
<span className='ml-auto text-[10px] text-[var(--white)]/60'>
|
||||
{tagDescription}
|
||||
</span>
|
||||
)}
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@ export function Text({ blockId, subBlockId, content, className }: TextProps) {
|
||||
return (
|
||||
<div
|
||||
id={`${blockId}-${subBlockId}`}
|
||||
className={`rounded-md border bg-[#232323] p-4 shadow-sm ${className || ''}`}
|
||||
className={`rounded-md border bg-[var(--surface-2)] p-4 shadow-sm ${className || ''}`}
|
||||
>
|
||||
<div
|
||||
className='prose prose-sm dark:prose-invert max-w-none break-words text-sm [&_a]:text-blue-600 [&_a]:underline [&_a]:hover:text-blue-700 [&_a]:dark:text-blue-400 [&_a]:dark:hover:text-blue-300 [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_code]:text-xs [&_strong]:font-semibold [&_ul]:ml-5 [&_ul]:list-disc'
|
||||
@@ -40,7 +40,7 @@ export function Text({ blockId, subBlockId, content, className }: TextProps) {
|
||||
return (
|
||||
<div
|
||||
id={`${blockId}-${subBlockId}`}
|
||||
className={`whitespace-pre-wrap break-words rounded-md border bg-[#232323] p-4 text-muted-foreground text-sm shadow-sm ${className || ''}`}
|
||||
className={`whitespace-pre-wrap break-words rounded-md border bg-[var(--surface-2)] p-4 text-muted-foreground text-sm shadow-sm ${className || ''}`}
|
||||
>
|
||||
{content}
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -125,7 +125,7 @@ export function TimeInput({
|
||||
type='text'
|
||||
autoComplete='off'
|
||||
/>
|
||||
<span className='text-[#E6E6E6]'>:</span>
|
||||
<span className='text-[var(--text-primary)]'>:</span>
|
||||
<Input
|
||||
className='w-[4rem]'
|
||||
value={minute}
|
||||
|
||||
+3
-3
@@ -181,7 +181,7 @@ export function CommandEmpty({ children, className }: CommandEmptyProps) {
|
||||
if (filteredItems.length > 0) return null
|
||||
|
||||
return (
|
||||
<div className={cn('px-[6px] py-[8px] text-[#FFFFFF]/60 text-[12px]', className)}>
|
||||
<div className={cn('px-[6px] py-[8px] text-[12px] text-[var(--white)]/60', className)}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
@@ -213,8 +213,8 @@ export function CommandItem({
|
||||
<button
|
||||
id={value}
|
||||
className={cn(
|
||||
'flex h-[25px] w-full cursor-pointer select-none items-center gap-[8px] rounded-[6px] px-[6px] font-base text-[#E6E6E6] text-[12px] outline-none transition-colors hover:bg-[#363636] hover:text-[#E6E6E6] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 data-[disabled=true]:pointer-events-none data-[selected=true]:bg-[#363636] data-[selected=true]:text-[#E6E6E6] data-[disabled=true]:opacity-50',
|
||||
(isActive || isHovered) && 'bg-[#363636] text-[#E6E6E6]',
|
||||
'flex h-[25px] w-full cursor-pointer select-none items-center gap-[8px] rounded-[6px] px-[6px] font-base text-[12px] text-[var(--text-primary)] outline-none transition-colors hover:bg-[var(--surface-9)] hover:text-[var(--text-primary)] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 data-[disabled=true]:pointer-events-none data-[selected=true]:bg-[var(--surface-9)] data-[selected=true]:text-[var(--text-primary)] data-[disabled=true]:opacity-50',
|
||||
(isActive || isHovered) && 'bg-[var(--surface-9)] text-[var(--text-primary)]',
|
||||
className
|
||||
)}
|
||||
onClick={() => !disabled && onSelect?.()}
|
||||
|
||||
+27
-19
@@ -1095,13 +1095,13 @@ export function ToolInput({
|
||||
case 'dropdown':
|
||||
return (
|
||||
<Select value={value} onValueChange={onChange}>
|
||||
<SelectTrigger className='w-full rounded-[4px] border border-[#303030] bg-[#1F1F1F] px-[10px] py-[8px] text-left font-medium text-sm'>
|
||||
<SelectTrigger className='w-full rounded-[4px] border border-[var(--border-strong)] bg-[#1F1F1F] px-[10px] py-[8px] text-left font-medium text-sm'>
|
||||
<SelectValue
|
||||
placeholder={uiComponent.placeholder || 'Select option'}
|
||||
className='truncate'
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent className='border-[#303030] bg-[#1F1F1F]'>
|
||||
<SelectContent className='border-[var(--border-strong)] bg-[#1F1F1F]'>
|
||||
{uiComponent.options
|
||||
?.filter((option: any) => option.id !== '')
|
||||
.map((option: any) => (
|
||||
@@ -1321,8 +1321,8 @@ export function ToolInput({
|
||||
{selectedTools.length === 0 ? (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<div className='flex w-full cursor-pointer items-center justify-center rounded-[4px] border border-[#303030] bg-[#1F1F1F] px-[10px] py-[6px] font-medium text-sm transition-colors hover:bg-[#252525]'>
|
||||
<div className='flex items-center text-[#787878] text-[13px]'>
|
||||
<div className='flex w-full cursor-pointer items-center justify-center rounded-[4px] border border-[var(--border-strong)] bg-[#1F1F1F] px-[10px] py-[6px] font-medium text-sm transition-colors hover:bg-[var(--surface-4)]'>
|
||||
<div className='flex items-center text-[13px] text-[var(--text-muted)]'>
|
||||
<PlusIcon className='mr-2 h-4 w-4' />
|
||||
Add Tool
|
||||
</div>
|
||||
@@ -1540,7 +1540,7 @@ export function ToolInput({
|
||||
<div
|
||||
key={`${tool.toolId}-${toolIndex}`}
|
||||
className={cn(
|
||||
'group relative flex flex-col overflow-visible rounded-[4px] border border-[#303030] bg-[#1F1F1F] transition-all duration-200 ease-in-out',
|
||||
'group relative flex flex-col overflow-visible rounded-[4px] border border-[var(--border-strong)] bg-[#1F1F1F] transition-all duration-200 ease-in-out',
|
||||
draggedIndex === toolIndex ? 'scale-95 opacity-40' : '',
|
||||
dragOverIndex === toolIndex && draggedIndex !== toolIndex && draggedIndex !== null
|
||||
? 'translate-y-1 transform border-t-2 border-t-muted-foreground/40'
|
||||
@@ -1558,7 +1558,9 @@ export function ToolInput({
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center justify-between px-[10px] py-[8px]',
|
||||
isExpandedForDisplay && !isCustomTool && 'border-[#303030] border-b',
|
||||
isExpandedForDisplay &&
|
||||
!isCustomTool &&
|
||||
'border-[var(--border-strong)] border-b',
|
||||
'cursor-pointer'
|
||||
)}
|
||||
onClick={() => {
|
||||
@@ -1617,21 +1619,21 @@ export function ToolInput({
|
||||
aria-label='Toggle tool usage control'
|
||||
>
|
||||
<span
|
||||
className={`font-medium text-[#AEAEAE] text-xs ${
|
||||
className={`font-medium text-[var(--text-tertiary)] text-xs ${
|
||||
tool.usageControl === 'auto' ? 'block' : 'hidden'
|
||||
}`}
|
||||
>
|
||||
Auto
|
||||
</span>
|
||||
<span
|
||||
className={`font-medium text-[#AEAEAE] text-xs ${
|
||||
className={`font-medium text-[var(--text-tertiary)] text-xs ${
|
||||
tool.usageControl === 'force' ? 'block' : 'hidden'
|
||||
}`}
|
||||
>
|
||||
Force
|
||||
</span>
|
||||
<span
|
||||
className={`font-medium text-[#AEAEAE] text-xs ${
|
||||
className={`font-medium text-[var(--text-tertiary)] text-xs ${
|
||||
tool.usageControl === 'none' ? 'block' : 'hidden'
|
||||
}`}
|
||||
>
|
||||
@@ -1667,7 +1669,7 @@ export function ToolInput({
|
||||
e.stopPropagation()
|
||||
handleRemoveTool(toolIndex)
|
||||
}}
|
||||
className='text-[#AEAEAE] transition-colors hover:text-[#EEEEEE]'
|
||||
className='text-[var(--text-tertiary)] transition-colors hover:text-[#EEEEEE]'
|
||||
aria-label='Remove tool'
|
||||
>
|
||||
<XIcon className='h-[14px] w-[14px]' />
|
||||
@@ -1684,16 +1686,18 @@ export function ToolInput({
|
||||
|
||||
return hasOperations && operationOptions.length > 0 ? (
|
||||
<div className='relative min-w-0 space-y-[6px]'>
|
||||
<div className='font-medium text-[#AEAEAE] text-[13px]'>Operation</div>
|
||||
<div className='font-medium text-[13px] text-[var(--text-tertiary)]'>
|
||||
Operation
|
||||
</div>
|
||||
<div className='w-full min-w-0'>
|
||||
<Select
|
||||
value={tool.operation || operationOptions[0].id}
|
||||
onValueChange={(value) => handleOperationChange(toolIndex, value)}
|
||||
>
|
||||
<SelectTrigger className='w-full min-w-0 rounded-[4px] border border-[#303030] bg-[#1F1F1F] px-[10px] py-[8px] text-left font-medium text-sm'>
|
||||
<SelectTrigger className='w-full min-w-0 rounded-[4px] border border-[var(--border-strong)] bg-[#1F1F1F] px-[10px] py-[8px] text-left font-medium text-sm'>
|
||||
<SelectValue placeholder='Select operation' className='truncate' />
|
||||
</SelectTrigger>
|
||||
<SelectContent className='border-[#303030] bg-[#1F1F1F]'>
|
||||
<SelectContent className='border-[var(--border-strong)] bg-[#1F1F1F]'>
|
||||
{operationOptions
|
||||
.filter((option) => option.id !== '')
|
||||
.map((option) => (
|
||||
@@ -1711,7 +1715,9 @@ export function ToolInput({
|
||||
{/* OAuth credential selector if required */}
|
||||
{requiresOAuth && oauthConfig && (
|
||||
<div className='relative min-w-0 space-y-[6px]'>
|
||||
<div className='font-medium text-[#AEAEAE] text-[13px]'>Account</div>
|
||||
<div className='font-medium text-[13px] text-[var(--text-tertiary)]'>
|
||||
Account
|
||||
</div>
|
||||
<div className='w-full min-w-0'>
|
||||
<ToolCredentialSelector
|
||||
value={tool.params.credential || ''}
|
||||
@@ -1768,7 +1774,7 @@ export function ToolInput({
|
||||
key={`group-${groupTitle}`}
|
||||
className='relative min-w-0 space-y-[6px]'
|
||||
>
|
||||
<div className='flex items-center font-medium text-[#AEAEAE] text-[13px]'>
|
||||
<div className='flex items-center font-medium text-[13px] text-[var(--text-tertiary)]'>
|
||||
{groupTitle}
|
||||
</div>
|
||||
<div className='relative w-full min-w-0'>
|
||||
@@ -1802,13 +1808,15 @@ export function ToolInput({
|
||||
standaloneParams.forEach((param) => {
|
||||
renderedElements.push(
|
||||
<div key={param.id} className='relative min-w-0 space-y-[6px]'>
|
||||
<div className='flex items-center font-medium text-[#AEAEAE] text-[13px]'>
|
||||
<div className='flex items-center font-medium text-[13px] text-[var(--text-tertiary)]'>
|
||||
{param.uiComponent?.title || formatParameterLabel(param.id)}
|
||||
{param.required && param.visibility === 'user-only' && (
|
||||
<span className='ml-1 text-red-500'>*</span>
|
||||
)}
|
||||
{(!param.required || param.visibility !== 'user-only') && (
|
||||
<span className='ml-1 text-[#787878] text-xs'>(Optional)</span>
|
||||
<span className='ml-1 text-[var(--text-muted)] text-xs'>
|
||||
(Optional)
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className='relative w-full min-w-0'>
|
||||
@@ -1853,8 +1861,8 @@ export function ToolInput({
|
||||
{/* Add Tool Button */}
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<div className='flex w-full cursor-pointer items-center justify-center rounded-[4px] border border-[#303030] bg-[#1F1F1F] px-[10px] py-[6px] font-medium text-sm transition-colors hover:bg-[#252525]'>
|
||||
<div className='flex items-center text-[#787878] text-[13px]'>
|
||||
<div className='flex w-full cursor-pointer items-center justify-center rounded-[4px] border border-[var(--border-strong)] bg-[#1F1F1F] px-[10px] py-[6px] font-medium text-sm transition-colors hover:bg-[var(--surface-4)]'>
|
||||
<div className='flex items-center text-[13px] text-[var(--text-muted)]'>
|
||||
<PlusIcon className='mr-2 h-4 w-4' />
|
||||
Add Tool
|
||||
</div>
|
||||
|
||||
+4
-4
@@ -71,7 +71,7 @@ export function SubflowEditor({
|
||||
<div className='flex-1 overflow-y-auto overflow-x-hidden px-[8px] pt-[5px] pb-[8px]'>
|
||||
{/* Type Selection */}
|
||||
<div>
|
||||
<Label className='mb-[6.5px] block pl-[2px] font-medium text-[#E6E6E6] text-[13px] dark:text-[#E6E6E6]'>
|
||||
<Label className='mb-[6.5px] block pl-[2px] font-medium text-[13px] text-[var(--text-primary)] dark:text-[var(--text-primary)]'>
|
||||
{currentBlock.type === 'loop' ? 'Loop Type' : 'Parallel Type'}
|
||||
</Label>
|
||||
<Combobox
|
||||
@@ -96,7 +96,7 @@ export function SubflowEditor({
|
||||
|
||||
{/* Configuration */}
|
||||
<div>
|
||||
<Label className='mb-[6.5px] block pl-[2px] font-medium text-[#E6E6E6] text-[13px] dark:text-[#E6E6E6]'>
|
||||
<Label className='mb-[6.5px] block pl-[2px] font-medium text-[13px] text-[var(--text-primary)] dark:text-[var(--text-primary)]'>
|
||||
{isCountMode
|
||||
? `${currentBlock.type === 'loop' ? 'Loop' : 'Parallel'} Iterations`
|
||||
: isConditionMode
|
||||
@@ -165,7 +165,7 @@ export function SubflowEditor({
|
||||
{hasIncomingConnections && (
|
||||
<div
|
||||
className={
|
||||
'connections-section flex flex-shrink-0 flex-col overflow-hidden border-[#2C2C2C] border-t dark:border-[#2C2C2C]' +
|
||||
'connections-section flex flex-shrink-0 flex-col overflow-hidden border-[var(--border)] border-t dark:border-[var(--border)]' +
|
||||
(!isResizing ? ' transition-[height] duration-100 ease-out' : '')
|
||||
}
|
||||
style={{ height: `${connectionsHeight}px` }}
|
||||
@@ -198,7 +198,7 @@ export function SubflowEditor({
|
||||
(!isConnectionsAtMinHeight ? ' rotate-180' : '')
|
||||
}
|
||||
/>
|
||||
<div className='font-medium text-[#E6E6E6] text-[13px] dark:text-[#E6E6E6]'>
|
||||
<div className='font-medium text-[13px] text-[var(--text-primary)] dark:text-[var(--text-primary)]'>
|
||||
Connections
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+8
-17
@@ -1,16 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import {
|
||||
BookOpen,
|
||||
Check,
|
||||
ChevronUp,
|
||||
Crosshair,
|
||||
Pencil,
|
||||
RepeatIcon,
|
||||
Settings,
|
||||
SplitIcon,
|
||||
} from 'lucide-react'
|
||||
import { BookOpen, Check, ChevronUp, Pencil, RepeatIcon, Settings, SplitIcon } from 'lucide-react'
|
||||
import { Button, Tooltip } from '@/components/emcn'
|
||||
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
|
||||
import { getSubBlockStableKey } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/utils'
|
||||
@@ -197,7 +188,7 @@ export function Editor() {
|
||||
>
|
||||
<IconComponent
|
||||
icon={isSubflow ? subflowIcon : blockConfig?.icon}
|
||||
className='h-[12px] w-[12px] text-[#FFFFFF]'
|
||||
className='h-[12px] w-[12px] text-[var(--white)]'
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@@ -215,11 +206,11 @@ export function Editor() {
|
||||
handleCancelRename()
|
||||
}
|
||||
}}
|
||||
className='min-w-0 flex-1 truncate bg-transparent pr-[8px] font-medium text-[#FFFFFF] text-[14px] outline-none dark:text-[#FFFFFF]'
|
||||
className='min-w-0 flex-1 truncate bg-transparent pr-[8px] font-medium text-[14px] text-[var(--white)] outline-none dark:text-[var(--white)]'
|
||||
/>
|
||||
) : (
|
||||
<h2
|
||||
className='min-w-0 flex-1 truncate pr-[8px] font-medium text-[#FFFFFF] text-[14px] dark:text-[#FFFFFF]'
|
||||
className='min-w-0 flex-1 truncate pr-[8px] font-medium text-[14px] text-[var(--white)] dark:text-[var(--white)]'
|
||||
title={title}
|
||||
>
|
||||
{title}
|
||||
@@ -251,7 +242,7 @@ export function Editor() {
|
||||
</Tooltip.Root>
|
||||
)}
|
||||
{/* Focus on block button */}
|
||||
{currentBlock && (
|
||||
{/* {currentBlock && (
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger asChild>
|
||||
<Button
|
||||
@@ -267,7 +258,7 @@ export function Editor() {
|
||||
<p>Focus on block</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
)}
|
||||
)} */}
|
||||
{/* Mode toggles - Only show for regular blocks, not subflows */}
|
||||
{currentBlock && !isSubflow && hasAdvancedMode && (
|
||||
<Tooltip.Root>
|
||||
@@ -380,7 +371,7 @@ export function Editor() {
|
||||
{hasIncomingConnections && (
|
||||
<div
|
||||
className={
|
||||
'connections-section flex flex-shrink-0 flex-col overflow-hidden border-[#2C2C2C] border-t dark:border-[#2C2C2C]' +
|
||||
'connections-section flex flex-shrink-0 flex-col overflow-hidden border-[var(--border)] border-t dark:border-[var(--border)]' +
|
||||
(!isResizing ? ' transition-[height] duration-100 ease-out' : '')
|
||||
}
|
||||
style={{ height: `${connectionsHeight}px` }}
|
||||
@@ -415,7 +406,7 @@ export function Editor() {
|
||||
(!isConnectionsAtMinHeight ? ' rotate-180' : '')
|
||||
}
|
||||
/>
|
||||
<div className='font-medium text-[#E6E6E6] text-[13px] dark:text-[#E6E6E6]'>
|
||||
<div className='font-medium text-[13px] text-[var(--text-primary)] dark:text-[var(--text-primary)]'>
|
||||
Connections
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -6,9 +6,9 @@ import { usePanelEditorStore } from '@/stores/panel-new/editor/store'
|
||||
*/
|
||||
const MIN_CONNECTIONS_HEIGHT = 30
|
||||
/**
|
||||
* Maximum height for the connections section (same as default fixed height)
|
||||
* Maximum height for the connections section
|
||||
*/
|
||||
const MAX_CONNECTIONS_HEIGHT = 200
|
||||
const MAX_CONNECTIONS_HEIGHT = 300
|
||||
|
||||
/**
|
||||
* Props for the useConnectionsResize hook
|
||||
|
||||
+11
-9
@@ -299,7 +299,9 @@ export function Toolbar({ isActive = true }: ToolbarProps) {
|
||||
className='flex flex-shrink-0 cursor-pointer items-center justify-between rounded-[4px] bg-[#2A2A2A] px-[12px] py-[8px] dark:bg-[#2A2A2A]'
|
||||
onClick={handleSearchClick}
|
||||
>
|
||||
<h2 className='font-medium text-[#FFFFFF] text-[14px] dark:text-[#FFFFFF]'>Toolbar</h2>
|
||||
<h2 className='font-medium text-[14px] text-[var(--white)] dark:text-[var(--white)]'>
|
||||
Toolbar
|
||||
</h2>
|
||||
<div className='flex shrink-0 items-center gap-[8px]'>
|
||||
{!isSearchActive ? (
|
||||
<Button
|
||||
@@ -317,7 +319,7 @@ export function Toolbar({ isActive = true }: ToolbarProps) {
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
onBlur={handleSearchBlur}
|
||||
className='w-full border-none bg-transparent pr-[2px] text-right font-medium text-[#E6E6E6] text-[13px] placeholder:text-[#737373] focus:outline-none dark:text-[#E6E6E6]'
|
||||
className='w-full border-none bg-transparent pr-[2px] text-right font-medium text-[13px] text-[var(--text-primary)] placeholder:text-[#737373] focus:outline-none dark:text-[var(--text-primary)]'
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -335,7 +337,7 @@ export function Toolbar({ isActive = true }: ToolbarProps) {
|
||||
>
|
||||
<div
|
||||
ref={triggersHeaderRef}
|
||||
className='px-[10px] pt-[5px] pb-[5px] font-medium text-[#E6E6E6] text-[13px] dark:text-[#E6E6E6]'
|
||||
className='px-[10px] pt-[5px] pb-[5px] font-medium text-[13px] text-[var(--text-primary)] dark:text-[var(--text-primary)]'
|
||||
>
|
||||
Triggers
|
||||
</div>
|
||||
@@ -359,7 +361,7 @@ export function Toolbar({ isActive = true }: ToolbarProps) {
|
||||
onClick={() => handleItemClick(trigger.type, isTriggerCapable)}
|
||||
className={clsx(
|
||||
'group flex h-[25px] items-center gap-[8px] rounded-[8px] px-[5px] text-[14px]',
|
||||
'cursor-pointer hover:bg-[#2C2C2C] active:cursor-grabbing dark:hover:bg-[#2C2C2C]'
|
||||
'cursor-pointer hover:bg-[var(--border)] active:cursor-grabbing dark:hover:bg-[var(--border)]'
|
||||
)}
|
||||
>
|
||||
<div
|
||||
@@ -379,7 +381,7 @@ export function Toolbar({ isActive = true }: ToolbarProps) {
|
||||
<span
|
||||
className={clsx(
|
||||
'truncate font-medium',
|
||||
'text-[#AEAEAE] group-hover:text-[#E6E6E6] dark:text-[#AEAEAE] dark:group-hover:text-[#E6E6E6]'
|
||||
'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)] dark:text-[var(--text-tertiary)] dark:group-hover:text-[var(--text-primary)]'
|
||||
)}
|
||||
>
|
||||
{trigger.name}
|
||||
@@ -392,7 +394,7 @@ export function Toolbar({ isActive = true }: ToolbarProps) {
|
||||
</div>
|
||||
|
||||
{/* Resize Handle */}
|
||||
<div className='relative flex-shrink-0 border-[#2C2C2C] border-t dark:border-[#2C2C2C]'>
|
||||
<div className='relative flex-shrink-0 border-[var(--border)] border-t dark:border-[var(--border)]'>
|
||||
<div
|
||||
className='absolute top-[-4px] right-0 left-0 z-30 h-[8px] cursor-ns-resize'
|
||||
onMouseDown={handleMouseDown}
|
||||
@@ -404,7 +406,7 @@ export function Toolbar({ isActive = true }: ToolbarProps) {
|
||||
<div
|
||||
ref={blocksHeaderRef}
|
||||
onClick={handleBlocksHeaderClick}
|
||||
className='cursor-pointer px-[10px] pt-[5px] pb-[5px] font-medium text-[#E6E6E6] text-[13px] dark:text-[#E6E6E6]'
|
||||
className='cursor-pointer px-[10px] pt-[5px] pb-[5px] font-medium text-[13px] text-[var(--text-primary)] dark:text-[var(--text-primary)]'
|
||||
>
|
||||
Blocks
|
||||
</div>
|
||||
@@ -435,7 +437,7 @@ export function Toolbar({ isActive = true }: ToolbarProps) {
|
||||
onClick={() => handleItemClick(block.type, false)}
|
||||
className={clsx(
|
||||
'group flex h-[25px] items-center gap-[8px] rounded-[8px] px-[5.5px] text-[14px]',
|
||||
'cursor-pointer hover:bg-[#2C2C2C] active:cursor-grabbing dark:hover:bg-[#2C2C2C]'
|
||||
'cursor-pointer hover:bg-[var(--border)] active:cursor-grabbing dark:hover:bg-[var(--border)]'
|
||||
)}
|
||||
>
|
||||
<div
|
||||
@@ -455,7 +457,7 @@ export function Toolbar({ isActive = true }: ToolbarProps) {
|
||||
<span
|
||||
className={clsx(
|
||||
'truncate font-medium',
|
||||
'text-[#AEAEAE] group-hover:text-[#E6E6E6] dark:text-[#AEAEAE] dark:group-hover:text-[#E6E6E6]'
|
||||
'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)] dark:text-[var(--text-tertiary)] dark:group-hover:text-[var(--text-primary)]'
|
||||
)}
|
||||
>
|
||||
{block.name}
|
||||
|
||||
+7
-7
@@ -258,10 +258,10 @@ export function Panel() {
|
||||
<>
|
||||
<aside
|
||||
ref={panelRef}
|
||||
className='panel-container fixed inset-y-0 right-0 z-10 overflow-hidden dark:bg-[#1E1E1E]'
|
||||
className='panel-container fixed inset-y-0 right-0 z-10 overflow-hidden dark:bg-[var(--surface-1)]'
|
||||
aria-label='Workflow panel'
|
||||
>
|
||||
<div className='flex h-full flex-col border-l pt-[14px] dark:border-[#2C2C2C]'>
|
||||
<div className='flex h-full flex-col border-l pt-[14px] dark:border-[var(--border)]'>
|
||||
{/* Header */}
|
||||
<div className='flex flex-shrink-0 items-center justify-between px-[8px]'>
|
||||
{/* More and Chat */}
|
||||
@@ -352,7 +352,7 @@ export function Panel() {
|
||||
<div className='flex flex-shrink-0 items-center justify-between px-[8px] pt-[14px]'>
|
||||
<div className='flex gap-[4px]'>
|
||||
<Button
|
||||
className='h-[28px] px-[8px] py-[5px] text-[12.5px] hover:bg-[#363636] hover:text-[#E6E6E6] dark:hover:bg-[#363636] dark:hover:text-[#E6E6E6]'
|
||||
className='h-[28px] px-[8px] py-[5px] text-[12.5px] hover:bg-[var(--surface-9)] hover:text-[var(--text-primary)] dark:hover:bg-[var(--surface-9)] dark:hover:text-[var(--text-primary)]'
|
||||
variant={_hasHydrated && activeTab === 'copilot' ? 'active' : 'ghost'}
|
||||
onClick={() => handleTabClick('copilot')}
|
||||
data-tab-button='copilot'
|
||||
@@ -360,7 +360,7 @@ export function Panel() {
|
||||
Copilot
|
||||
</Button>
|
||||
<Button
|
||||
className='h-[28px] px-[8px] py-[5px] text-[12.5px] hover:bg-[#363636] hover:text-[#E6E6E6] dark:hover:bg-[#363636] dark:hover:text-[#E6E6E6]'
|
||||
className='h-[28px] px-[8px] py-[5px] text-[12.5px] hover:bg-[var(--surface-9)] hover:text-[var(--text-primary)] dark:hover:bg-[var(--surface-9)] dark:hover:text-[var(--text-primary)]'
|
||||
variant={_hasHydrated && activeTab === 'toolbar' ? 'active' : 'ghost'}
|
||||
onClick={() => handleTabClick('toolbar')}
|
||||
data-tab-button='toolbar'
|
||||
@@ -368,7 +368,7 @@ export function Panel() {
|
||||
Toolbar
|
||||
</Button>
|
||||
<Button
|
||||
className='h-[28px] px-[8px] py-[5px] text-[12.5px] hover:bg-[#363636] hover:text-[#E6E6E6] dark:hover:bg-[#363636] dark:hover:text-[#E6E6E6]'
|
||||
className='h-[28px] px-[8px] py-[5px] text-[12.5px] hover:bg-[var(--surface-9)] hover:text-[var(--text-primary)] dark:hover:bg-[var(--surface-9)] dark:hover:text-[var(--text-primary)]'
|
||||
variant={_hasHydrated && activeTab === 'editor' ? 'active' : 'ghost'}
|
||||
onClick={() => handleTabClick('editor')}
|
||||
data-tab-button='editor'
|
||||
@@ -440,7 +440,7 @@ export function Panel() {
|
||||
<ModalDescription>
|
||||
Deleting this workflow will permanently remove all associated blocks, executions, and
|
||||
configuration.{' '}
|
||||
<span className='text-[#EF4444] dark:text-[#EF4444]'>
|
||||
<span className='text-[var(--text-error)] dark:text-[var(--text-error)]'>
|
||||
This action cannot be undone.
|
||||
</span>
|
||||
</ModalDescription>
|
||||
@@ -455,7 +455,7 @@ export function Panel() {
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
className='h-[32px] bg-[#EF4444] px-[12px] text-[#FFFFFF] hover:bg-[#EF4444] hover:text-[#FFFFFF] dark:bg-[#EF4444] dark:text-[#FFFFFF] hover:dark:bg-[#EF4444] dark:hover:text-[#FFFFFF]'
|
||||
className='h-[32px] bg-[var(--text-error)] px-[12px] text-[var(--white)] hover:bg-[var(--text-error)] hover:text-[var(--white)] dark:bg-[var(--text-error)] dark:text-[var(--white)] hover:dark:bg-[var(--text-error)] dark:hover:text-[var(--white)]'
|
||||
onClick={handleDeleteWorkflow}
|
||||
disabled={isDeleting}
|
||||
>
|
||||
|
||||
+2
-2
@@ -439,7 +439,7 @@ export function ConsoleEntry({ entry, consoleWidth }: ConsoleEntryProps) {
|
||||
onClick={() => setShowInput(false)}
|
||||
className={`flex h-5 items-center rounded-lg px-2 transition-colors ${
|
||||
!showInput
|
||||
? 'border-[#e5e5e5] bg-[#f5f5f5] text-[#1a1a1a] dark:border-[#424242] dark:bg-[#1f1f1f] dark:text-[#ffffff]'
|
||||
? 'border-[#e5e5e5] bg-[#f5f5f5] text-[#1a1a1a] dark:border-[var(--border-muted)] dark:bg-[#1f1f1f] dark:text-[var(--white)]'
|
||||
: 'bg-secondary text-muted-foreground hover:bg-secondary hover:text-card-foreground'
|
||||
}`}
|
||||
>
|
||||
@@ -449,7 +449,7 @@ export function ConsoleEntry({ entry, consoleWidth }: ConsoleEntryProps) {
|
||||
onClick={() => setShowInput(true)}
|
||||
className={`flex h-5 items-center rounded-lg px-2 transition-colors ${
|
||||
showInput
|
||||
? 'border-[#e5e5e5] bg-[#f5f5f5] text-[#1a1a1a] dark:border-[#424242] dark:bg-[#1f1f1f] dark:text-[#ffffff]'
|
||||
? 'border-[#e5e5e5] bg-[#f5f5f5] text-[#1a1a1a] dark:border-[var(--border-muted)] dark:bg-[#1f1f1f] dark:text-[var(--white)]'
|
||||
: 'bg-secondary text-muted-foreground hover:bg-secondary hover:text-card-foreground'
|
||||
}`}
|
||||
>
|
||||
|
||||
+4
-4
@@ -255,7 +255,7 @@ export function Variables() {
|
||||
<div className='flex h-full items-center justify-center'>
|
||||
<Button
|
||||
onClick={handleAddVariable}
|
||||
className='h-9 rounded-lg border border-[#E5E5E5] bg-[#FFFFFF] px-3 py-1.5 font-normal text-muted-foreground text-sm shadow-xs transition-colors hover:text-muted-foreground dark:border-[#414141] dark:bg-[var(--surface-elevated)] dark:hover:text-muted-foreground'
|
||||
className='h-9 rounded-lg border border-[#E5E5E5] bg-[var(--white)] px-3 py-1.5 font-normal text-muted-foreground text-sm shadow-xs transition-colors hover:text-muted-foreground dark:border-[#414141] dark:bg-[var(--surface-elevated)] dark:hover:text-muted-foreground'
|
||||
variant='outline'
|
||||
>
|
||||
<Plus className='h-4 w-4' />
|
||||
@@ -294,7 +294,7 @@ export function Variables() {
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
align='end'
|
||||
className='min-w-32 rounded-lg border-[#E5E5E5] bg-[#FFFFFF] shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
className='min-w-32 rounded-lg border-[#E5E5E5] bg-[var(--white)] shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
>
|
||||
{VARIABLE_TYPES.map((type) => (
|
||||
<DropdownMenuItem
|
||||
@@ -324,7 +324,7 @@ export function Variables() {
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
align='end'
|
||||
className='min-w-32 rounded-lg border-[#E5E5E5] bg-[#FFFFFF] shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
className='min-w-32 rounded-lg border-[#E5E5E5] bg-[var(--white)] shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
>
|
||||
<DropdownMenuItem
|
||||
onClick={() => toggleCollapsed(variable.id)}
|
||||
@@ -429,7 +429,7 @@ export function Variables() {
|
||||
{/* Add Variable Button */}
|
||||
<Button
|
||||
onClick={handleAddVariable}
|
||||
className='mt-2 h-9 w-full rounded-lg border border-[#E5E5E5] bg-[#FFFFFF] px-3 py-1.5 font-[380] text-muted-foreground text-sm shadow-xs transition-colors hover:text-muted-foreground dark:border-[#414141] dark:bg-[var(--surface-elevated)] dark:hover:text-muted-foreground'
|
||||
className='mt-2 h-9 w-full rounded-lg border border-[#E5E5E5] bg-[var(--white)] px-3 py-1.5 font-[380] text-muted-foreground text-sm shadow-xs transition-colors hover:text-muted-foreground dark:border-[#414141] dark:bg-[var(--surface-elevated)] dark:hover:text-muted-foreground'
|
||||
variant='outline'
|
||||
>
|
||||
<Plus className='h-4 w-4' />
|
||||
|
||||
+6
-6
@@ -107,7 +107,7 @@ export const SubflowNodeComponent = memo(({ data, id }: NodeProps<SubflowNodeDat
|
||||
*/
|
||||
const getHandleClasses = (position: 'left' | 'right') => {
|
||||
const baseClasses = '!z-[10] !cursor-crosshair !border-none !transition-[colors] !duration-150'
|
||||
const colorClasses = '!bg-[#434343]'
|
||||
const colorClasses = '!bg-[var(--surface-12)]'
|
||||
|
||||
const positionClasses = {
|
||||
left: '!left-[-7px] !h-5 !w-[7px] !rounded-l-[2px] !rounded-r-none hover:!left-[-10px] hover:!w-[10px] hover:!rounded-l-full',
|
||||
@@ -130,9 +130,9 @@ export const SubflowNodeComponent = memo(({ data, id }: NodeProps<SubflowNodeDat
|
||||
const hasRing = isFocused || diffStatus === 'new' || diffStatus === 'edited'
|
||||
const ringStyles = cn(
|
||||
hasRing && 'ring-[1.75px]',
|
||||
isFocused && 'ring-[#33B4FF]',
|
||||
isFocused && 'ring-[var(--brand-secondary)]',
|
||||
diffStatus === 'new' && 'ring-[#22C55F]',
|
||||
diffStatus === 'edited' && 'ring-[#FF6600]'
|
||||
diffStatus === 'edited' && 'ring-[var(--warning)]'
|
||||
)
|
||||
|
||||
return (
|
||||
@@ -143,7 +143,7 @@ export const SubflowNodeComponent = memo(({ data, id }: NodeProps<SubflowNodeDat
|
||||
ref={blockRef}
|
||||
onClick={() => setCurrentBlockId(id)}
|
||||
className={cn(
|
||||
'relative cursor-pointer select-none rounded-[8px] border border-[#393939]',
|
||||
'relative cursor-pointer select-none rounded-[8px] border border-[var(--divider)]',
|
||||
'transition-block-bg transition-ring',
|
||||
'z-[20]'
|
||||
)}
|
||||
@@ -161,7 +161,7 @@ export const SubflowNodeComponent = memo(({ data, id }: NodeProps<SubflowNodeDat
|
||||
{/* Header Section */}
|
||||
<div
|
||||
className={cn(
|
||||
'workflow-drag-handle flex cursor-grab items-center justify-between rounded-t-[8px] border-[#393939] border-b bg-[#232323] py-[8px] pr-[12px] pl-[8px] dark:bg-[#232323] [&:active]:cursor-grabbing'
|
||||
'workflow-drag-handle flex cursor-grab items-center justify-between rounded-t-[8px] border-[var(--divider)] border-b bg-[var(--surface-2)] py-[8px] pr-[12px] pl-[8px] dark:bg-[var(--surface-2)] [&:active]:cursor-grabbing'
|
||||
)}
|
||||
onMouseDown={(e) => {
|
||||
e.stopPropagation()
|
||||
@@ -210,7 +210,7 @@ export const SubflowNodeComponent = memo(({ data, id }: NodeProps<SubflowNodeDat
|
||||
>
|
||||
{/* Subflow Start */}
|
||||
<div
|
||||
className='absolute top-[16px] left-[16px] flex items-center justify-center rounded-[8px] bg-[#232323] px-[12px] py-[6px]'
|
||||
className='absolute top-[16px] left-[16px] flex items-center justify-center rounded-[8px] bg-[var(--surface-2)] px-[12px] py-[6px]'
|
||||
style={{ pointerEvents: isPreview ? 'none' : 'auto' }}
|
||||
data-parent-id={id}
|
||||
data-node-role={`${data.kind}-start`}
|
||||
|
||||
+9
-4
@@ -87,7 +87,7 @@ function ValueRow({ name, value, level, path, expandedPaths, onToggle, wrapText
|
||||
onClick={handleClick}
|
||||
className={clsx(
|
||||
'flex items-center gap-2 rounded-md px-2 py-1',
|
||||
isExpandable && 'cursor-pointer hover:bg-[#2C2C2C]'
|
||||
isExpandable && 'cursor-pointer hover:bg-[var(--border)]'
|
||||
)}
|
||||
style={{
|
||||
paddingLeft: `${indent + 8}px`,
|
||||
@@ -105,11 +105,14 @@ function ValueRow({ name, value, level, path, expandedPaths, onToggle, wrapText
|
||||
<div className='h-3 w-3 flex-shrink-0' />
|
||||
)}
|
||||
|
||||
<span className='font-medium text-[#AEAEAE] text-[13px]'>{name}:</span>
|
||||
<span className='font-medium text-[13px] text-[var(--text-tertiary)]'>{name}:</span>
|
||||
|
||||
{!isExpandable ? (
|
||||
<span
|
||||
className={clsx('flex-1 text-[#E6E6E6] text-[13px]', !wrapText && 'truncate')}
|
||||
className={clsx(
|
||||
'flex-1 text-[13px] text-[var(--text-primary)]',
|
||||
!wrapText && 'truncate'
|
||||
)}
|
||||
style={wrapText ? { wordBreak: 'break-word' } : undefined}
|
||||
>
|
||||
{formatValue(value, type)}
|
||||
@@ -195,7 +198,9 @@ export function PrettierOutput({ output, wrapText }: PrettierOutputProps) {
|
||||
return (
|
||||
<div className='p-2'>
|
||||
<div className='flex items-center gap-2 py-1'>
|
||||
<span className='text-[#E6E6E6] text-[13px]'>{formatValue(output, type)}</span>
|
||||
<span className='text-[13px] text-[var(--text-primary)]'>
|
||||
{formatValue(output, type)}
|
||||
</span>
|
||||
<Badge className='rounded-[4px] px-2 py-0.5 font-mono text-[10px]'>{type}</Badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+19
-16
@@ -77,7 +77,8 @@ const RUN_ID_COLORS = [
|
||||
/**
|
||||
* Shared styling constants
|
||||
*/
|
||||
const HEADER_TEXT_CLASS = 'font-medium text-[#AEAEAE] text-[12px] dark:text-[#AEAEAE]'
|
||||
const HEADER_TEXT_CLASS =
|
||||
'font-medium text-[var(--text-tertiary)] text-[12px] dark:text-[var(--text-tertiary)]'
|
||||
const ROW_TEXT_CLASS = 'font-medium text-[#D2D2D2] text-[12px] dark:text-[#D2D2D2]'
|
||||
const COLUMN_BASE_CLASS = 'flex-shrink-0'
|
||||
|
||||
@@ -674,13 +675,13 @@ export function Terminal() {
|
||||
<aside
|
||||
ref={terminalRef}
|
||||
className={clsx(
|
||||
'terminal-container fixed right-[var(--panel-width)] bottom-0 left-[var(--sidebar-width)] z-10 overflow-hidden dark:bg-[#1E1E1E]',
|
||||
'terminal-container fixed right-[var(--panel-width)] bottom-0 left-[var(--sidebar-width)] z-10 overflow-hidden dark:bg-[var(--surface-1)]',
|
||||
isToggling && 'transition-[height] duration-100 ease-out'
|
||||
)}
|
||||
onTransitionEnd={handleTransitionEnd}
|
||||
aria-label='Terminal'
|
||||
>
|
||||
<div className='relative flex h-full border-t dark:border-[#2C2C2C]'>
|
||||
<div className='relative flex h-full border-t dark:border-[var(--border)]'>
|
||||
{/* Left Section - Logs Table */}
|
||||
<div
|
||||
className={clsx('flex flex-col', !selectedEntry && 'flex-1')}
|
||||
@@ -688,7 +689,7 @@ export function Terminal() {
|
||||
>
|
||||
{/* Header */}
|
||||
<div
|
||||
className='group flex h-[30px] flex-shrink-0 cursor-pointer items-center bg-[#1E1E1E] pr-[16px] pl-[24px]'
|
||||
className='group flex h-[30px] flex-shrink-0 cursor-pointer items-center bg-[var(--surface-1)] pr-[16px] pl-[24px]'
|
||||
onClick={handleHeaderClick}
|
||||
>
|
||||
{uniqueBlocks.length > 0 ? (
|
||||
@@ -706,7 +707,7 @@ export function Terminal() {
|
||||
<Filter
|
||||
className={clsx(
|
||||
'h-[11px] w-[11px]',
|
||||
filters.blockIds.size > 0 && 'text-[#33B4FF]'
|
||||
filters.blockIds.size > 0 && 'text-[var(--brand-secondary)]'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -759,7 +760,7 @@ export function Terminal() {
|
||||
<Filter
|
||||
className={clsx(
|
||||
'h-[11px] w-[11px]',
|
||||
filters.statuses.size > 0 && 'text-[#33B4FF]'
|
||||
filters.statuses.size > 0 && 'text-[var(--brand-secondary)]'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -818,7 +819,7 @@ export function Terminal() {
|
||||
<Filter
|
||||
className={clsx(
|
||||
'h-[11px] w-[11px]',
|
||||
filters.runIds.size > 0 && 'text-[#33B4FF]'
|
||||
filters.runIds.size > 0 && 'text-[var(--brand-secondary)]'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -954,8 +955,8 @@ export function Terminal() {
|
||||
<div
|
||||
key={entry.id}
|
||||
className={clsx(
|
||||
'flex h-[36px] cursor-pointer items-center px-[24px] hover:bg-[#2C2C2C]',
|
||||
isSelected && 'bg-[#2C2C2C]'
|
||||
'flex h-[36px] cursor-pointer items-center px-[24px] hover:bg-[var(--border)]',
|
||||
isSelected && 'bg-[var(--border)]'
|
||||
)}
|
||||
onClick={() => handleRowClick(entry)}
|
||||
>
|
||||
@@ -1056,7 +1057,7 @@ export function Terminal() {
|
||||
{/* Right Section - Block Output (Overlay) */}
|
||||
{selectedEntry && (
|
||||
<div
|
||||
className='absolute top-0 right-0 bottom-0 flex flex-col border-l dark:border-[#2C2C2C] dark:bg-[#1E1E1E]'
|
||||
className='absolute top-0 right-0 bottom-0 flex flex-col border-l dark:border-[var(--border)] dark:bg-[var(--surface-1)]'
|
||||
style={{ width: `${outputPanelWidth}px` }}
|
||||
>
|
||||
{/* Horizontal Resize Handle */}
|
||||
@@ -1070,7 +1071,7 @@ export function Terminal() {
|
||||
|
||||
{/* Header */}
|
||||
<div
|
||||
className='group flex h-[30px] flex-shrink-0 cursor-pointer items-center justify-between bg-[#1E1E1E] px-[16px]'
|
||||
className='group flex h-[30px] flex-shrink-0 cursor-pointer items-center justify-between bg-[var(--surface-1)] px-[16px]'
|
||||
onClick={handleHeaderClick}
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
@@ -1078,7 +1079,9 @@ export function Terminal() {
|
||||
variant='ghost'
|
||||
className={clsx(
|
||||
'px-[8px] py-[6px] text-[12px]',
|
||||
!showInput && hasInputData && '!text-[#E6E6E6] dark:!text-[#E6E6E6]'
|
||||
!showInput &&
|
||||
hasInputData &&
|
||||
'!text-[var(--text-primary)] dark:!text-[var(--text-primary)]'
|
||||
)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
@@ -1099,7 +1102,7 @@ export function Terminal() {
|
||||
variant='ghost'
|
||||
className={clsx(
|
||||
'px-[8px] py-[6px] text-[12px]',
|
||||
showInput && '!text-[#E6E6E6] dark:!text-[#E6E6E6] '
|
||||
showInput && '!text-[var(--text-primary)] dark:!text-[var(--text-primary)] '
|
||||
)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
@@ -1268,7 +1271,7 @@ export function Terminal() {
|
||||
language={
|
||||
(selectedEntry.input.language as 'javascript' | 'json') || 'javascript'
|
||||
}
|
||||
className='m-0 min-h-full rounded-none border-0 bg-[#1E1E1E]'
|
||||
className='m-0 min-h-full rounded-none border-0 bg-[var(--surface-1)]'
|
||||
paddingLeft={8}
|
||||
gutterStyle={{ backgroundColor: 'transparent' }}
|
||||
wrapText={wrapText}
|
||||
@@ -1278,7 +1281,7 @@ export function Terminal() {
|
||||
code={JSON.stringify(outputData, null, 2)}
|
||||
showGutter
|
||||
language='json'
|
||||
className='m-0 min-h-full rounded-none border-0 bg-[#1E1E1E]'
|
||||
className='m-0 min-h-full rounded-none border-0 bg-[var(--surface-1)]'
|
||||
paddingLeft={8}
|
||||
gutterStyle={{ backgroundColor: 'transparent' }}
|
||||
wrapText={wrapText}
|
||||
@@ -1289,7 +1292,7 @@ export function Terminal() {
|
||||
code={JSON.stringify(outputData, null, 2)}
|
||||
showGutter
|
||||
language='json'
|
||||
className='m-0 min-h-full rounded-none border-0 bg-[#1E1E1E]'
|
||||
className='m-0 min-h-full rounded-none border-0 bg-[var(--surface-1)]'
|
||||
paddingLeft={8}
|
||||
gutterStyle={{ backgroundColor: 'transparent' }}
|
||||
wrapText={wrapText}
|
||||
|
||||
+12
-10
@@ -274,7 +274,7 @@ export function Variables() {
|
||||
aria-controls={`variable-content-${variable.id}`}
|
||||
>
|
||||
<div className='flex min-w-0 flex-1 items-center gap-[8px]'>
|
||||
<span className='block truncate font-medium text-[#AEAEAE] text-[14px]'>
|
||||
<span className='block truncate font-medium text-[14px] text-[var(--text-tertiary)]'>
|
||||
{variable.name || `Variable ${index + 1}`}
|
||||
</span>
|
||||
{variable.name && (
|
||||
@@ -289,7 +289,7 @@ export function Variables() {
|
||||
e.stopPropagation()
|
||||
handleRemoveVariable(variable.id)
|
||||
}}
|
||||
className='h-auto p-0 text-[#EF4444] hover:text-[#EF4444]'
|
||||
className='h-auto p-0 text-[var(--text-error)] hover:text-[var(--text-error)]'
|
||||
aria-label={`Delete ${variable.name || `variable ${index + 1}`}`}
|
||||
>
|
||||
<Trash style={{ width: `${ICON_SIZE}px`, height: `${ICON_SIZE}px` }} />
|
||||
@@ -324,7 +324,7 @@ export function Variables() {
|
||||
return Array.from({ length: lineCount }, (_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className='font-medium font-mono text-[#787878] text-xs'
|
||||
className='font-medium font-mono text-[var(--text-muted)] text-xs'
|
||||
style={{ height: `${LINE_HEIGHT}px`, lineHeight: `${LINE_HEIGHT}px` }}
|
||||
>
|
||||
{i + 1}
|
||||
@@ -373,7 +373,7 @@ export function Variables() {
|
||||
|
||||
return (
|
||||
<div
|
||||
className='fixed z-30 flex flex-col overflow-hidden rounded-[6px] bg-[#1E1E1E] px-[10px] pt-[2px] pb-[8px]'
|
||||
className='fixed z-30 flex flex-col overflow-hidden rounded-[6px] bg-[var(--surface-1)] px-[10px] pt-[2px] pb-[8px]'
|
||||
style={{
|
||||
left: `${actualPosition.x}px`,
|
||||
top: `${actualPosition.y}px`,
|
||||
@@ -387,11 +387,13 @@ export function Variables() {
|
||||
>
|
||||
{/* Header (drag handle) */}
|
||||
<div
|
||||
className='flex h-[32px] flex-shrink-0 cursor-grab items-center justify-between bg-[#1E1E1E] p-0 active:cursor-grabbing'
|
||||
className='flex h-[32px] flex-shrink-0 cursor-grab items-center justify-between bg-[var(--surface-1)] p-0 active:cursor-grabbing'
|
||||
onMouseDown={handleMouseDown}
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
<span className='flex-shrink-0 font-medium text-[#E6E6E6] text-[14px]'>Variables</span>
|
||||
<span className='flex-shrink-0 font-medium text-[14px] text-[var(--text-primary)]'>
|
||||
Variables
|
||||
</span>
|
||||
</div>
|
||||
<div className='flex items-center gap-[8px]'>
|
||||
<Button
|
||||
@@ -419,7 +421,7 @@ export function Variables() {
|
||||
{/* Content */}
|
||||
<div className='flex flex-1 flex-col overflow-hidden pt-[8px]'>
|
||||
{workflowVariables.length === 0 ? (
|
||||
<div className='flex flex-1 items-center justify-center text-[#8D8D8D] text-[13px]'>
|
||||
<div className='flex flex-1 items-center justify-center text-[13px] text-[var(--text-tertiary)]'>
|
||||
{STRINGS.emptyState}
|
||||
</div>
|
||||
) : (
|
||||
@@ -429,7 +431,7 @@ export function Variables() {
|
||||
<div
|
||||
key={variable.id}
|
||||
className={cn(
|
||||
'rounded-[4px] border border-[#303030] bg-[#1F1F1F]',
|
||||
'rounded-[4px] border border-[var(--border-strong)] bg-[var(--surface-1)]',
|
||||
(collapsedById[variable.id] ?? false) ? 'overflow-hidden' : 'overflow-visible'
|
||||
)}
|
||||
>
|
||||
@@ -438,7 +440,7 @@ export function Variables() {
|
||||
{!(collapsedById[variable.id] ?? false) && (
|
||||
<div
|
||||
id={`variable-content-${variable.id}`}
|
||||
className='flex flex-col gap-[6px] border-[#303030] border-t px-[10px] pt-[6px] pb-[10px]'
|
||||
className='flex flex-col gap-[6px] border-[var(--border-strong)] border-t px-[10px] pt-[6px] pb-[10px]'
|
||||
>
|
||||
<div className='flex flex-col gap-[4px]'>
|
||||
<Label className='text-[13px]'>{STRINGS.labels.name}</Label>
|
||||
@@ -452,7 +454,7 @@ export function Variables() {
|
||||
placeholder={STRINGS.placeholders.name}
|
||||
/>
|
||||
{nameErrors[variable.id] && (
|
||||
<p className='text-[#EF4444] text-xs' role='alert'>
|
||||
<p className='text-[var(--text-error)] text-xs' role='alert'>
|
||||
{nameErrors[variable.id]}
|
||||
</p>
|
||||
)}
|
||||
|
||||
+6
-6
@@ -77,7 +77,7 @@ export const ActionBar = memo(
|
||||
'-right-20 absolute top-0',
|
||||
'flex flex-col items-center',
|
||||
'opacity-0 transition-opacity duration-200 group-hover:opacity-100',
|
||||
'gap-[6px] rounded-[10px] bg-[#242424] p-[6px]'
|
||||
'gap-[6px] rounded-[10px] bg-[var(--surface-3)] p-[6px]'
|
||||
)}
|
||||
>
|
||||
<Tooltip.Root>
|
||||
@@ -90,7 +90,7 @@ export const ActionBar = memo(
|
||||
collaborativeToggleBlockEnabled(blockId)
|
||||
}
|
||||
}}
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[#363636] p-0 text-[#868686] hover:bg-[#33B4FF] hover:text-[#1B1B1B] dark:text-[#868686] dark:hover:bg-[#33B4FF] dark:hover:text-[#1B1B1B]'
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)]'
|
||||
disabled={disabled}
|
||||
>
|
||||
{isEnabled ? (
|
||||
@@ -116,7 +116,7 @@ export const ActionBar = memo(
|
||||
collaborativeDuplicateBlock(blockId)
|
||||
}
|
||||
}}
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[#363636] p-0 text-[#868686] hover:bg-[#33B4FF] hover:text-[#1B1B1B] dark:text-[#868686] dark:hover:bg-[#33B4FF] dark:hover:text-[#1B1B1B]'
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)]'
|
||||
disabled={disabled}
|
||||
>
|
||||
<Duplicate className='h-[14px] w-[14px]' />
|
||||
@@ -139,7 +139,7 @@ export const ActionBar = memo(
|
||||
)
|
||||
}
|
||||
}}
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[#363636] p-0 text-[#868686] hover:bg-[#33B4FF] hover:text-[#1B1B1B] dark:text-[#868686] dark:hover:bg-[#33B4FF] dark:hover:text-[#1B1B1B]'
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)]'
|
||||
disabled={disabled || !userPermissions.canEdit}
|
||||
>
|
||||
<LogOut className='h-[14px] w-[14px]' />
|
||||
@@ -161,7 +161,7 @@ export const ActionBar = memo(
|
||||
collaborativeToggleBlockHandles(blockId)
|
||||
}
|
||||
}}
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[#363636] p-0 text-[#868686] hover:bg-[#33B4FF] hover:text-[#1B1B1B] dark:text-[#868686] dark:hover:bg-[#33B4FF] dark:hover:text-[#1B1B1B]'
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)]'
|
||||
disabled={disabled}
|
||||
>
|
||||
{horizontalHandles ? (
|
||||
@@ -186,7 +186,7 @@ export const ActionBar = memo(
|
||||
collaborativeRemoveBlock(blockId)
|
||||
}
|
||||
}}
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[#363636] p-0 text-[#868686] hover:bg-[#33B4FF] hover:text-[#1B1B1B] dark:text-[#868686] dark:hover:bg-[#33B4FF] dark:hover:text-[#1B1B1B]'
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)] '
|
||||
disabled={disabled}
|
||||
>
|
||||
<Trash2 className='h-[14px] w-[14px]' />
|
||||
|
||||
+11
-5
@@ -53,16 +53,22 @@ export function Connections({ blockId, horizontalHandles }: ConnectionsProps) {
|
||||
{visibleConnections.map((connection: ConnectedBlock) => {
|
||||
const Icon = getConnectionIcon(connection)
|
||||
if (!Icon) return null
|
||||
return <Icon key={connection.id} className='h-[14px] w-[14px] text-[#AEAEAE]' />
|
||||
return (
|
||||
<Icon key={connection.id} className='h-[14px] w-[14px] text-[var(--text-tertiary)]' />
|
||||
)
|
||||
})}
|
||||
{remainingCount > 0 && <span className='text-[#AEAEAE] text-[14px]'>+{remainingCount}</span>}
|
||||
{remainingCount > 0 && (
|
||||
<span className='text-[14px] text-[var(--text-tertiary)]'>+{remainingCount}</span>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
if (!horizontalHandles) {
|
||||
return (
|
||||
<div className='-translate-x-full -translate-y-1/2 pointer-events-none absolute top-1/2 left-0 flex flex-col items-end gap-[8px] pr-[8px] opacity-0 transition-opacity group-hover:opacity-100'>
|
||||
<span className='text-[#AEAEAE] text-[14px] leading-[14px]'>{connectionText}</span>
|
||||
<span className='text-[14px] text-[var(--text-tertiary)] leading-[14px]'>
|
||||
{connectionText}
|
||||
</span>
|
||||
<div className='flex items-center justify-end gap-[4px]'>{connectionIcons}</div>
|
||||
</div>
|
||||
)
|
||||
@@ -70,8 +76,8 @@ export function Connections({ blockId, horizontalHandles }: ConnectionsProps) {
|
||||
|
||||
return (
|
||||
<div className='pointer-events-none absolute bottom-full left-0 ml-[8px] flex items-center gap-[8px] pb-[8px] opacity-0 transition-opacity group-hover:opacity-100'>
|
||||
<span className='text-[#AEAEAE] text-[14px]'>{connectionText}</span>
|
||||
<div className='h-[14px] w-[1px] bg-[#AEAEAE]' />
|
||||
<span className='text-[14px] text-[var(--text-tertiary)]'>{connectionText}</span>
|
||||
<div className='h-[14px] w-[1px] bg-[var(--text-tertiary)]' />
|
||||
<div className='flex items-center gap-[4px]'>{connectionIcons}</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
+10
-7
@@ -305,12 +305,12 @@ const SubBlockRow = ({
|
||||
|
||||
return (
|
||||
<div className='flex items-center gap-[8px]'>
|
||||
<span className='min-w-0 truncate text-[#AEAEAE] text-[14px]' title={title}>
|
||||
<span className='min-w-0 truncate text-[14px] text-[var(--text-tertiary)]' title={title}>
|
||||
{title}
|
||||
</span>
|
||||
{displayValue !== undefined && (
|
||||
<span
|
||||
className='flex-1 truncate text-right text-[#FFFFFF] text-[14px]'
|
||||
className='flex-1 truncate text-right text-[14px] text-[var(--white)]'
|
||||
title={displayValue}
|
||||
>
|
||||
{displayValue}
|
||||
@@ -590,7 +590,7 @@ export const WorkflowBlock = memo(function WorkflowBlock({
|
||||
*/
|
||||
const getHandleClasses = (position: 'left' | 'right' | 'top' | 'bottom', isError = false) => {
|
||||
const baseClasses = '!z-[10] !cursor-crosshair !border-none !transition-[colors] !duration-150'
|
||||
const colorClasses = isError ? '!bg-red-400 dark:!bg-red-500' : '!bg-[#434343]'
|
||||
const colorClasses = isError ? '!bg-red-400 dark:!bg-red-500' : '!bg-[var(--surface-12)]'
|
||||
|
||||
const positionClasses = {
|
||||
left: '!left-[-7px] !h-5 !w-[7px] !rounded-l-[2px] !rounded-r-none hover:!left-[-10px] hover:!w-[10px] hover:!rounded-l-full',
|
||||
@@ -701,7 +701,7 @@ export const WorkflowBlock = memo(function WorkflowBlock({
|
||||
ref={contentRef}
|
||||
onClick={handleClick}
|
||||
className={cn(
|
||||
'relative z-[20] w-[250px] cursor-default select-none rounded-[8px] bg-[#232323]'
|
||||
'relative z-[20] w-[250px] cursor-default select-none rounded-[8px] bg-[var(--surface-2)]'
|
||||
)}
|
||||
>
|
||||
{isPending && (
|
||||
@@ -734,7 +734,7 @@ export const WorkflowBlock = memo(function WorkflowBlock({
|
||||
<div
|
||||
className={cn(
|
||||
'workflow-drag-handle flex cursor-grab items-center justify-between p-[8px] [&:active]:cursor-grabbing',
|
||||
hasContentBelowHeader && 'border-[#393939] border-b'
|
||||
hasContentBelowHeader && 'border-[var(--divider)] border-b'
|
||||
)}
|
||||
onMouseDown={(e) => {
|
||||
e.stopPropagation()
|
||||
@@ -855,10 +855,13 @@ export const WorkflowBlock = memo(function WorkflowBlock({
|
||||
{showWebhookIndicator && (
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger asChild>
|
||||
<Badge variant='outline' className='bg-[#22C55E] text-[#22C55E]'>
|
||||
<Badge
|
||||
variant='outline'
|
||||
className='bg-[var(--brand-tertiary)] text-[var(--brand-tertiary)]'
|
||||
>
|
||||
<div className='relative flex items-center justify-center'>
|
||||
<div className='197, 94, 0.2)] absolute h-3 w-3 rounded-full bg-[rgba(34,' />
|
||||
<div className='relative h-2 w-2 rounded-full bg-[#22C55E]' />
|
||||
<div className='relative h-2 w-2 rounded-full bg-[var(--brand-tertiary)]' />
|
||||
</div>
|
||||
Webhook
|
||||
</Badge>
|
||||
|
||||
+5
-5
@@ -79,10 +79,10 @@ export const WorkflowEdge = ({
|
||||
const isErrorEdge = (sourceHandle ?? dataSourceHandle) === 'error'
|
||||
|
||||
const getEdgeColor = () => {
|
||||
if (edgeDiffStatus === 'deleted') return '#ef4444' // Red for deleted edges
|
||||
if (isErrorEdge) return '#EF4444' // Red for error paths (matches error handle)
|
||||
if (edgeDiffStatus === 'new') return '#22C55E' // Green for new edges
|
||||
return '#434343' // Matches workflow-block handle color
|
||||
if (edgeDiffStatus === 'deleted') return 'var(--text-error)'
|
||||
if (isErrorEdge) return 'var(--text-error)'
|
||||
if (edgeDiffStatus === 'new') return 'var(--brand-tertiary)'
|
||||
return 'var(--surface-12)'
|
||||
}
|
||||
|
||||
const edgeStyle = {
|
||||
@@ -133,7 +133,7 @@ export const WorkflowEdge = ({
|
||||
}
|
||||
}}
|
||||
>
|
||||
<X className='h-4 w-4 text-[#EF4444] transition-colors group-hover:text-[#EF4444]/80 dark:text-[#EF4444] dark:group-hover:text-[#EF4444]/80' />
|
||||
<X className='h-4 w-4 text-[var(--text-error)] transition-colors group-hover:text-[var(--text-error)]/80 dark:text-[var(--text-error)] dark:group-hover:text-[var(--text-error)]/80' />
|
||||
</div>
|
||||
</EdgeLabelRenderer>
|
||||
)}
|
||||
|
||||
@@ -50,11 +50,11 @@ export function useBlockCore({ blockId, data, isPending = false }: UseBlockCoreO
|
||||
const ringStyles = cn(
|
||||
hasRing && 'ring-[1.75px]',
|
||||
isActive && 'ring-[#8C10FF] animate-pulse-ring',
|
||||
isPending && 'ring-[#FF6600]',
|
||||
isFocused && 'ring-[#33B4FF]',
|
||||
isPending && 'ring-[var(--warning)]',
|
||||
isFocused && 'ring-[var(--brand-secondary)]',
|
||||
diffStatus === 'new' && 'ring-[#22C55F]',
|
||||
diffStatus === 'edited' && 'ring-[#FF6600]',
|
||||
isDeletedBlock && 'ring-[#EF4444]'
|
||||
diffStatus === 'edited' && 'ring-[var(--warning)]',
|
||||
isDeletedBlock && 'ring-[var(--text-error)]'
|
||||
)
|
||||
|
||||
return { hasRing, ringStyles }
|
||||
|
||||
+8
-6
@@ -79,28 +79,30 @@ export function FooterNavigation() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='flex flex-shrink-0 flex-col gap-[2px] border-t px-[7.75px] pt-[8px] pb-[8px] dark:border-[#2C2C2C]'>
|
||||
<div className='flex flex-shrink-0 flex-col gap-[2px] border-t px-[7.75px] pt-[8px] pb-[8px] dark:border-[var(--border)]'>
|
||||
{navigationItems.map((item) => {
|
||||
const Icon = item.icon
|
||||
const active = item.href ? isActive(item.href) : false
|
||||
|
||||
const itemClasses = clsx(
|
||||
'group flex h-[24px] items-center gap-[8px] rounded-[8px] px-[7px] text-[14px]',
|
||||
active ? 'bg-[#2C2C2C] dark:bg-[#2C2C2C]' : 'hover:bg-[#2C2C2C] dark:hover:bg-[#2C2C2C]'
|
||||
active
|
||||
? 'bg-[var(--border)] dark:bg-[var(--border)]'
|
||||
: 'hover:bg-[var(--border)] dark:hover:bg-[var(--border)]'
|
||||
)
|
||||
|
||||
const iconClasses = clsx(
|
||||
'h-[14px] w-[14px] flex-shrink-0',
|
||||
active
|
||||
? 'text-[#E6E6E6] dark:text-[#E6E6E6]'
|
||||
: 'text-[#AEAEAE] group-hover:text-[#E6E6E6] dark:text-[#AEAEAE] dark:group-hover:text-[#E6E6E6]'
|
||||
? 'text-[var(--text-primary)] dark:text-[var(--text-primary)]'
|
||||
: 'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)] dark:text-[var(--text-tertiary)] dark:group-hover:text-[var(--text-primary)]'
|
||||
)
|
||||
|
||||
const labelClasses = clsx(
|
||||
'truncate font-base text-[13px]',
|
||||
active
|
||||
? 'text-[#E6E6E6] dark:text-[#E6E6E6]'
|
||||
: 'text-[#AEAEAE] group-hover:text-[#E6E6E6] dark:text-[#AEAEAE] dark:group-hover:text-[#E6E6E6]'
|
||||
? 'text-[var(--text-primary)] dark:text-[var(--text-primary)]'
|
||||
: 'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)] dark:text-[var(--text-tertiary)] dark:group-hover:text-[var(--text-primary)]'
|
||||
)
|
||||
|
||||
const content = (
|
||||
|
||||
+13
-13
@@ -478,14 +478,14 @@ export function SearchModal({
|
||||
</VisuallyHidden.Root>
|
||||
|
||||
{/* Search input container */}
|
||||
<div className='flex items-center gap-[6px] rounded-[10px] border border-[#2C2C2C] bg-[#272727] px-[10px] py-[8px] shadow-sm dark:border-[#2C2C2C] dark:bg-[#272727]'>
|
||||
<Search className='h-[16px] w-[16px] flex-shrink-0 text-[#7D7D7D] dark:text-[#7D7D7D]' />
|
||||
<div className='flex items-center gap-[6px] rounded-[10px] border border-[var(--border)] bg-[var(--surface-5)] px-[10px] py-[8px] shadow-sm dark:border-[var(--border)] dark:bg-[var(--surface-5)]'>
|
||||
<Search className='h-[16px] w-[16px] flex-shrink-0 text-[var(--text-subtle)] dark:text-[var(--text-subtle)]' />
|
||||
<input
|
||||
type='text'
|
||||
placeholder='Search anything...'
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
className='w-full border-0 bg-transparent font-base text-[#E6E6E6] text-[16px] placeholder:text-[#B1B1B1] focus:outline-none dark:text-[#E6E6E6] dark:placeholder:text-[#B1B1B1]'
|
||||
className='w-full border-0 bg-transparent font-base text-[16px] text-[var(--text-primary)] placeholder:text-[var(--text-secondary)] focus:outline-none dark:text-[var(--text-primary)] dark:placeholder:text-[var(--text-secondary)]'
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
@@ -499,7 +499,7 @@ export function SearchModal({
|
||||
return (
|
||||
<div key={type} className='mb-[10px] last:mb-0'>
|
||||
{/* Section header */}
|
||||
<div className='pt-[2px] pb-[4px] font-medium text-[#7D7D7D] text-[11px] uppercase tracking-wide dark:text-[#7D7D7D]'>
|
||||
<div className='pt-[2px] pb-[4px] font-medium text-[11px] text-[var(--text-subtle)] uppercase tracking-wide dark:text-[var(--text-subtle)]'>
|
||||
{sectionTitles[type]}
|
||||
</div>
|
||||
|
||||
@@ -520,10 +520,10 @@ export function SearchModal({
|
||||
data-search-item-index={globalIndex}
|
||||
onClick={() => handleItemClick(item)}
|
||||
className={cn(
|
||||
'group flex h-[28px] w-full items-center gap-[8px] rounded-[6px] bg-[#252525]/60 px-[8px] text-left text-[13px] transition-all focus:outline-none dark:bg-[#252525]/60',
|
||||
'group flex h-[28px] w-full items-center gap-[8px] rounded-[6px] bg-[var(--surface-4)]/60 px-[8px] text-left text-[13px] transition-all focus:outline-none dark:bg-[var(--surface-4)]/60',
|
||||
isSelected
|
||||
? 'bg-[#2C2C2C] shadow-sm dark:bg-[#2C2C2C]'
|
||||
: 'hover:bg-[#2C2C2C] dark:hover:bg-[#2C2C2C]'
|
||||
? 'bg-[var(--border)] shadow-sm dark:bg-[var(--border)]'
|
||||
: 'hover:bg-[var(--border)] dark:hover:bg-[var(--border)]'
|
||||
)}
|
||||
>
|
||||
{/* Icon - different rendering for workflows vs others */}
|
||||
@@ -549,7 +549,7 @@ export function SearchModal({
|
||||
'transition-transform duration-100 group-hover:scale-110',
|
||||
showColoredIcon
|
||||
? '!h-[10px] !w-[10px] text-white'
|
||||
: 'h-[14px] w-[14px] text-[#AEAEAE] group-hover:text-[#E6E6E6] dark:text-[#AEAEAE] dark:group-hover:text-[#E6E6E6]'
|
||||
: 'h-[14px] w-[14px] text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)] dark:text-[var(--text-tertiary)] dark:group-hover:text-[var(--text-primary)]'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
@@ -563,8 +563,8 @@ export function SearchModal({
|
||||
className={cn(
|
||||
'truncate font-medium',
|
||||
isSelected
|
||||
? 'text-[#E6E6E6] dark:text-[#E6E6E6]'
|
||||
: 'text-[#AEAEAE] group-hover:text-[#E6E6E6] dark:text-[#AEAEAE] dark:group-hover:text-[#E6E6E6]'
|
||||
? 'text-[var(--text-primary)] dark:text-[var(--text-primary)]'
|
||||
: 'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)] dark:text-[var(--text-tertiary)] dark:group-hover:text-[var(--text-primary)]'
|
||||
)}
|
||||
>
|
||||
{item.name}
|
||||
@@ -573,7 +573,7 @@ export function SearchModal({
|
||||
|
||||
{/* Shortcut */}
|
||||
{item.shortcut && (
|
||||
<span className='ml-auto flex-shrink-0 font-medium text-[#7D7D7D] text-[11px] dark:text-[#7D7D7D]'>
|
||||
<span className='ml-auto flex-shrink-0 font-medium text-[11px] text-[var(--text-subtle)] dark:text-[var(--text-subtle)]'>
|
||||
{item.shortcut}
|
||||
</span>
|
||||
)}
|
||||
@@ -586,8 +586,8 @@ export function SearchModal({
|
||||
})}
|
||||
</div>
|
||||
) : searchQuery ? (
|
||||
<div className='flex items-center justify-center rounded-[10px] bg-[#272727] px-[16px] py-[24px] shadow-sm dark:bg-[#272727]'>
|
||||
<p className='text-[#7D7D7D] text-[13px] dark:text-[#7D7D7D]'>
|
||||
<div className='flex items-center justify-center rounded-[10px] bg-[var(--surface-5)] px-[16px] py-[24px] shadow-sm dark:bg-[var(--surface-5)]'>
|
||||
<p className='text-[13px] text-[var(--text-subtle)] dark:text-[var(--text-subtle)]'>
|
||||
No results found for "{searchQuery}"
|
||||
</p>
|
||||
</div>
|
||||
|
||||
+24
-20
@@ -3,13 +3,14 @@ import { Info } from 'lucide-react'
|
||||
import { Tooltip } from '@/components/emcn'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select'
|
||||
// COMMENTED OUT: Theme switching disabled - dark mode is forced for workspace
|
||||
// import {
|
||||
// Select,
|
||||
// SelectContent,
|
||||
// SelectItem,
|
||||
// SelectTrigger,
|
||||
// SelectValue,
|
||||
// } from '@/components/ui/select'
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { useSession } from '@/lib/auth-client'
|
||||
@@ -95,14 +96,15 @@ export function General() {
|
||||
}
|
||||
}
|
||||
|
||||
// Sync theme from store to next-themes when theme changes
|
||||
useEffect(() => {
|
||||
if (!isLoading && theme) {
|
||||
// Ensure next-themes is in sync with our store
|
||||
const { syncThemeToNextThemes } = require('@/lib/theme-sync')
|
||||
syncThemeToNextThemes(theme)
|
||||
}
|
||||
}, [theme, isLoading])
|
||||
// COMMENTED OUT: Theme switching disabled - dark mode is forced for workspace
|
||||
// // Sync theme from store to next-themes when theme changes
|
||||
// useEffect(() => {
|
||||
// if (!isLoading && theme) {
|
||||
// // Ensure next-themes is in sync with our store
|
||||
// const { syncThemeToNextThemes } = require('@/lib/theme-sync')
|
||||
// syncThemeToNextThemes(theme)
|
||||
// }
|
||||
// }, [theme, isLoading])
|
||||
|
||||
const handleThemeChange = async (value: 'system' | 'light' | 'dark') => {
|
||||
await setTheme(value)
|
||||
@@ -143,15 +145,16 @@ export function General() {
|
||||
<div className='flex flex-col gap-4'>
|
||||
{isLoading ? (
|
||||
<>
|
||||
{/* COMMENTED OUT: Theme switching disabled - dark mode is forced for workspace */}
|
||||
{/* Theme setting with skeleton value */}
|
||||
<div className='flex items-center justify-between'>
|
||||
{/* <div className='flex items-center justify-between'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Label htmlFor='theme-select' className='font-normal'>
|
||||
Theme
|
||||
</Label>
|
||||
</div>
|
||||
<Skeleton className='h-9 w-[180px]' />
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
{/* Auto-connect setting with skeleton value */}
|
||||
<div className='flex items-center justify-between'>
|
||||
@@ -207,7 +210,8 @@ export function General() {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div className='flex items-center justify-between'>
|
||||
{/* COMMENTED OUT: Theme switching disabled - dark mode is forced for workspace */}
|
||||
{/* <div className='flex items-center justify-between'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Label htmlFor='theme-select' className='font-normal'>
|
||||
Theme
|
||||
@@ -221,7 +225,7 @@ export function General() {
|
||||
<SelectTrigger id='theme-select' className='h-9 w-[180px]'>
|
||||
<SelectValue placeholder='Select theme' />
|
||||
</SelectTrigger>
|
||||
<SelectContent className='min-w-32 rounded-[10px] border-[#E5E5E5] bg-[#FFFFFF] shadow-xs dark:border-[#414141] dark:bg-[#202020]'>
|
||||
<SelectContent className='min-w-32 rounded-[10px] border-[#E5E5E5] bg-[var(--white)] shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'>
|
||||
<SelectItem
|
||||
value='system'
|
||||
className='rounded-[8px] text-card-foreground text-sm hover:bg-muted focus:bg-muted'
|
||||
@@ -242,7 +246,7 @@ export function General() {
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Label htmlFor='auto-connect' className='font-normal'>
|
||||
|
||||
+2
-2
@@ -97,7 +97,7 @@ export function DeleteModal({
|
||||
<ModalTitle>{title}</ModalTitle>
|
||||
<ModalDescription>
|
||||
{description}{' '}
|
||||
<span className='text-[#EF4444] dark:text-[#EF4444]'>
|
||||
<span className='text-[var(--text-error)] dark:text-[var(--text-error)]'>
|
||||
This action cannot be undone.
|
||||
</span>
|
||||
</ModalDescription>
|
||||
@@ -112,7 +112,7 @@ export function DeleteModal({
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
className='h-[32px] bg-[#EF4444] px-[12px] text-[#FFFFFF] hover:bg-[#EF4444] hover:text-[#FFFFFF] dark:bg-[#EF4444] dark:text-[#FFFFFF] hover:dark:bg-[#EF4444] dark:hover:text-[#FFFFFF]'
|
||||
className='h-[32px] bg-[var(--text-error)] px-[12px] text-[var(--white)] hover:bg-[var(--text-error)] hover:text-[var(--white)] dark:bg-[var(--text-error)] dark:text-[var(--white)] hover:dark:bg-[var(--text-error)] dark:hover:text-[var(--white)]'
|
||||
onClick={onConfirm}
|
||||
disabled={isDeleting}
|
||||
>
|
||||
|
||||
+5
-5
@@ -197,19 +197,19 @@ export function FolderItem({ folder, level, hoverHandlers }: FolderItemProps) {
|
||||
>
|
||||
<ChevronRight
|
||||
className={clsx(
|
||||
'mr-[8px] h-[10px] w-[10px] flex-shrink-0 text-[#787878] transition-all dark:text-[#787878]',
|
||||
'mr-[8px] h-[10px] w-[10px] flex-shrink-0 text-[var(--text-muted)] transition-all dark:text-[var(--text-muted)]',
|
||||
isExpanded ? 'rotate-90' : ''
|
||||
)}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
{isExpanded ? (
|
||||
<FolderOpen
|
||||
className='mr-[10px] h-[16px] w-[16px] flex-shrink-0 text-[#787878] dark:text-[#787878]'
|
||||
className='mr-[10px] h-[16px] w-[16px] flex-shrink-0 text-[var(--text-muted)] dark:text-[var(--text-muted)]'
|
||||
aria-hidden='true'
|
||||
/>
|
||||
) : (
|
||||
<Folder
|
||||
className='mr-[10px] h-[16px] w-[16px] flex-shrink-0 text-[#787878] dark:text-[#787878]'
|
||||
className='mr-[10px] h-[16px] w-[16px] flex-shrink-0 text-[var(--text-muted)] dark:text-[var(--text-muted)]'
|
||||
aria-hidden='true'
|
||||
/>
|
||||
)}
|
||||
@@ -221,7 +221,7 @@ export function FolderItem({ folder, level, hoverHandlers }: FolderItemProps) {
|
||||
onKeyDown={handleRenameKeyDown}
|
||||
onBlur={handleInputBlur}
|
||||
className={clsx(
|
||||
'min-w-0 flex-1 border-0 bg-transparent p-0 font-medium text-[#AEAEAE] text-[14px] outline-none focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 dark:text-[#AEAEAE]'
|
||||
'min-w-0 flex-1 border-0 bg-transparent p-0 font-medium text-[14px] text-[var(--text-tertiary)] outline-none focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 dark:text-[var(--text-tertiary)]'
|
||||
)}
|
||||
maxLength={50}
|
||||
disabled={isRenaming}
|
||||
@@ -236,7 +236,7 @@ export function FolderItem({ folder, level, hoverHandlers }: FolderItemProps) {
|
||||
/>
|
||||
) : (
|
||||
<span
|
||||
className='truncate font-medium text-[#AEAEAE] dark:text-[#AEAEAE]'
|
||||
className='truncate font-medium text-[var(--text-tertiary)] dark:text-[var(--text-tertiary)]'
|
||||
onDoubleClick={handleDoubleClick}
|
||||
>
|
||||
{folder.name}
|
||||
|
||||
+8
-6
@@ -234,9 +234,11 @@ export function WorkflowItem({ workflow, active, level, onWorkflowClick }: Workf
|
||||
data-item-id={workflow.id}
|
||||
className={clsx(
|
||||
'group flex h-[25px] items-center gap-[8px] rounded-[8px] px-[5.5px] text-[14px]',
|
||||
active ? 'bg-[#2C2C2C] dark:bg-[#2C2C2C]' : 'hover:bg-[#2C2C2C] dark:hover:bg-[#2C2C2C]',
|
||||
active
|
||||
? 'bg-[var(--border)] dark:bg-[var(--border)]'
|
||||
: 'hover:bg-[var(--border)] dark:hover:bg-[var(--border)]',
|
||||
isSelected && selectedWorkflows.size > 1 && !active
|
||||
? 'bg-[#2C2C2C] dark:bg-[#2C2C2C]'
|
||||
? 'bg-[var(--border)] dark:bg-[var(--border)]'
|
||||
: '',
|
||||
isDragging ? 'opacity-50' : ''
|
||||
)}
|
||||
@@ -261,8 +263,8 @@ export function WorkflowItem({ workflow, active, level, onWorkflowClick }: Workf
|
||||
className={clsx(
|
||||
'w-full border-0 bg-transparent p-0 font-medium text-[14px] outline-none focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0',
|
||||
active
|
||||
? 'text-[#E6E6E6] dark:text-[#E6E6E6]'
|
||||
: 'text-[#AEAEAE] group-hover:text-[#E6E6E6] dark:text-[#AEAEAE] dark:group-hover:text-[#E6E6E6]'
|
||||
? 'text-[var(--text-primary)] dark:text-[var(--text-primary)]'
|
||||
: 'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)]'
|
||||
)}
|
||||
maxLength={100}
|
||||
disabled={isRenaming}
|
||||
@@ -280,8 +282,8 @@ export function WorkflowItem({ workflow, active, level, onWorkflowClick }: Workf
|
||||
className={clsx(
|
||||
'truncate font-medium',
|
||||
active
|
||||
? 'text-[#E6E6E6] dark:text-[#E6E6E6]'
|
||||
: 'text-[#AEAEAE] group-hover:text-[#E6E6E6] dark:text-[#AEAEAE] dark:group-hover:text-[#E6E6E6]'
|
||||
? 'text-[var(--text-primary)] dark:text-[var(--text-primary)]'
|
||||
: 'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)] dark:text-[var(--text-tertiary)] dark:group-hover:text-[var(--text-primary)]'
|
||||
)}
|
||||
onDoubleClick={handleDoubleClick}
|
||||
>
|
||||
|
||||
+4
-4
@@ -259,7 +259,7 @@ export function WorkspaceHeader({
|
||||
{/* Workspace Name */}
|
||||
<div className='flex min-w-0 flex-1 items-center gap-[8px]'>
|
||||
<h2
|
||||
className='max-w-full truncate font-base text-[14px] dark:text-[#FFFFFF]'
|
||||
className='max-w-full truncate font-base text-[14px] dark:text-[var(--white)]'
|
||||
title={activeWorkspace?.name || 'Loading...'}
|
||||
>
|
||||
{activeWorkspace?.name || 'Loading...'}
|
||||
@@ -278,7 +278,7 @@ export function WorkspaceHeader({
|
||||
className='group !p-[3px] -m-[3px]'
|
||||
onClick={handleRefresh}
|
||||
>
|
||||
<RefreshCw className='h-[14px] w-[14px] text-[#EF4444] dark:text-[#EF4444]' />
|
||||
<RefreshCw className='h-[14px] w-[14px] text-[var(--text-error)] dark:text-[var(--text-error)]' />
|
||||
</Button>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content>Connection lost - refresh</Tooltip.Content>
|
||||
@@ -378,7 +378,7 @@ export function WorkspaceHeader({
|
||||
{workspaces.map((workspace, index) => (
|
||||
<div key={workspace.id} className={index > 0 ? 'mt-[2px]' : ''}>
|
||||
{editingWorkspaceId === workspace.id ? (
|
||||
<div className='flex h-[25px] items-center gap-[8px] rounded-[6px] bg-[#363636] px-[6px] dark:bg-[#363636]'>
|
||||
<div className='flex h-[25px] items-center gap-[8px] rounded-[6px] bg-[var(--surface-9)] px-[6px] dark:bg-[var(--surface-9)]'>
|
||||
<input
|
||||
ref={listRenameInputRef}
|
||||
value={editingName}
|
||||
@@ -408,7 +408,7 @@ export function WorkspaceHeader({
|
||||
setIsListRenaming(false)
|
||||
}
|
||||
}}
|
||||
className='w-full border-0 bg-transparent p-0 font-base text-[#E6E6E6] text-[12px] outline-none focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 dark:text-[#E6E6E6]'
|
||||
className='w-full border-0 bg-transparent p-0 font-base text-[12px] text-[var(--text-primary)] outline-none focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 dark:text-[var(--text-primary)]'
|
||||
maxLength={100}
|
||||
autoComplete='off'
|
||||
autoCorrect='off'
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ export const KeyboardShortcut = ({ shortcut, className }: KeyboardShortcutProps)
|
||||
return (
|
||||
<kbd
|
||||
className={cn(
|
||||
'flex h-6 w-8 items-center justify-center rounded-[5px] border border-border bg-background font-mono text-[#CDCDCD] text-xs dark:text-[#454545]',
|
||||
'flex h-6 w-8 items-center justify-center rounded-[5px] border border-border bg-background font-mono text-[#CDCDCD] text-xs dark:text-[var(--surface-13)]',
|
||||
className
|
||||
)}
|
||||
>
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ export function WorkflowContextMenu({ onStartEdit }: WorkflowContextMenuProps) {
|
||||
<DropdownMenuContent
|
||||
align='end'
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className='min-w-32 rounded-lg border-[#E5E5E5] bg-[#FFFFFF] shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
className='min-w-32 rounded-lg border-[#E5E5E5] bg-[var(--white)] shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
|
||||
>
|
||||
{userPermissions.canEdit && (
|
||||
<DropdownMenuItem
|
||||
|
||||
@@ -440,7 +440,7 @@ export function SidebarNew() {
|
||||
<>
|
||||
{isCollapsed ? (
|
||||
/* Floating collapsed header */
|
||||
<div className='fixed top-[14px] left-[10px] z-10 max-w-[232px] rounded-[8px] border bg-white px-[12px] py-[8px] dark:border-[#2C2C2C] dark:bg-[#1E1E1E]'>
|
||||
<div className='fixed top-[14px] left-[10px] z-10 max-w-[232px] rounded-[8px] border border-[var(--border)] bg-[var(--surface-1)] px-[12px] py-[8px]'>
|
||||
<WorkspaceHeader
|
||||
activeWorkspace={activeWorkspace}
|
||||
workspaceId={workspaceId}
|
||||
@@ -466,11 +466,11 @@ export function SidebarNew() {
|
||||
<>
|
||||
<aside
|
||||
ref={sidebarRef}
|
||||
className='sidebar-container fixed inset-y-0 left-0 z-10 overflow-hidden dark:bg-[#1E1E1E]'
|
||||
className='sidebar-container fixed inset-y-0 left-0 z-10 overflow-hidden bg-[var(--surface-1)]'
|
||||
aria-label='Workspace sidebar'
|
||||
onClick={handleSidebarClick}
|
||||
>
|
||||
<div className='flex h-full flex-col border-r pt-[14px] dark:border-[#2C2C2C]'>
|
||||
<div className='flex h-full flex-col border-r pt-[14px] dark:border-[var(--border)]'>
|
||||
{/* Header */}
|
||||
<div className='flex-shrink-0 px-[14px]'>
|
||||
<WorkspaceHeader
|
||||
@@ -496,16 +496,18 @@ export function SidebarNew() {
|
||||
|
||||
{/* Search */}
|
||||
<div
|
||||
className='mx-[8px] mt-[12px] flex flex-shrink-0 cursor-pointer items-center justify-between rounded-[8px] bg-[#272727] px-[8px] py-[7px] dark:bg-[#272727]'
|
||||
className='mx-[8px] mt-[12px] flex flex-shrink-0 cursor-pointer items-center justify-between rounded-[8px] bg-[var(--surface-5)] px-[8px] py-[7px]'
|
||||
onClick={() => setIsSearchModalOpen(true)}
|
||||
>
|
||||
<div className='flex items-center gap-[6px]'>
|
||||
<Search className='h-[14px] w-[14px] text-[#7D7D7D] dark:text-[#7D7D7D]' />
|
||||
<p className='translate-y-[0.25px] font-medium text-[#B1B1B1] text-small dark:text-[#B1B1B1]'>
|
||||
<Search className='h-[14px] w-[14px] text-[var(--text-subtle)] dark:text-[var(--text-subtle)]' />
|
||||
<p className='translate-y-[0.25px] font-medium text-[var(--text-secondary)] text-small dark:text-[var(--text-secondary)]'>
|
||||
Search
|
||||
</p>
|
||||
</div>
|
||||
<p className='font-medium text-[#7D7D7D] text-small dark:text-[#7D7D7D]'>⌘K</p>
|
||||
<p className='font-medium text-[var(--text-subtle)] text-small dark:text-[var(--text-subtle)]'>
|
||||
⌘K
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Workflows */}
|
||||
@@ -513,7 +515,7 @@ export function SidebarNew() {
|
||||
{/* Header - Always visible */}
|
||||
<div className='flex flex-shrink-0 flex-col space-y-[4px] px-[14px]'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className='font-medium text-[#AEAEAE] text-small dark:text-[#AEAEAE]'>
|
||||
<div className='font-medium text-[var(--text-tertiary)] text-small dark:text-[var(--text-tertiary)]'>
|
||||
Workflows
|
||||
</div>
|
||||
<div className='flex items-center justify-center gap-[10px]'>
|
||||
|
||||
@@ -8,9 +8,9 @@ const badgeVariants = cva(
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
'bg-[#272727] text-[#B1B1B1] dark:bg-[#272727] dark:text-[#B1B1B1] hover:text-[#E6E6E6] dark:hover:text-[#E6E6E6]',
|
||||
'bg-[var(--surface-5)] text-[var(--text-secondary)] dark:bg-[var(--surface-5)] dark:text-[var(--text-secondary)] hover:text-[var(--text-primary)] dark:hover:text-[var(--text-primary)]',
|
||||
outline:
|
||||
'border border-[#575757] bg-transparent text-[#B1B1B1] dark:border-[#575757] dark:bg-transparent dark:text-[#B1B1B1] hover:text-[#E6E6E6] dark:hover:text-[#E6E6E6]',
|
||||
'border border-[#575757] bg-transparent text-[var(--text-secondary)] dark:border-[#575757] dark:bg-transparent dark:text-[var(--text-secondary)] hover:text-[var(--text-primary)] dark:hover:text-[var(--text-primary)]',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
||||
@@ -3,19 +3,21 @@ import { cva, type VariantProps } from 'class-variance-authority'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const buttonVariants = cva(
|
||||
'inline-flex items-center text-[#B1B1B1] hover:text-[#E6E6E6] dark:hover:text-[#E6E6E6] dark:text-[#B1B1B1] justify-center font-medium transition-colors disabled:pointer-events-none disabled:opacity-50 outline-none focus:outline-none focus-visible:outline-none rounded-[4px] px-[8px] py-[6px] text-[12px]',
|
||||
'inline-flex items-center text-[var(--text-secondary)] hover:text-[var(--text-primary)] dark:hover:text-[var(--text-primary)] dark:text-[var(--text-secondary)] justify-center font-medium transition-colors disabled:pointer-events-none disabled:opacity-50 outline-none focus:outline-none focus-visible:outline-none rounded-[4px] px-[8px] py-[6px] text-[12px]',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'bg-[#272727] dark:bg-[#272727] hover:bg-[#363636] dark:hover:bg-[#363636]',
|
||||
active: 'bg-[#363636] dark:bg-[#363636] dark:text-[#E6E6E6] text-[#E6E6E6]',
|
||||
'3d': 'dark:text-[#AEAEAE] border-t border-l border-r dark:border-[#303030] shadow-[0_2px_0_0] dark:shadow-[#303030] hover:shadow-[0_4px_0_0] transition-all hover:-translate-y-0.5 hover:dark:text-[#E6E6E6]',
|
||||
default:
|
||||
'bg-[var(--surface-5)] dark:bg-[var(--surface-5)] hover:bg-[var(--surface-9)] dark:hover:bg-[var(--surface-9)]',
|
||||
active:
|
||||
'bg-[var(--surface-9)] dark:bg-[var(--surface-9)] dark:text-[var(--text-primary)] text-[var(--text-primary)]',
|
||||
'3d': 'dark:text-[var(--text-tertiary)] border-t border-l border-r dark:border-[var(--border-strong)] shadow-[0_2px_0_0] dark:shadow-[var(--border-strong)] hover:shadow-[0_4px_0_0] transition-all hover:-translate-y-0.5 hover:dark:text-[var(--text-primary)]',
|
||||
outline:
|
||||
'border border-[#727272] bg-[#303030] hover:bg-[#3D3D3D] dark:border-[#727272] dark:bg-[#303030] dark:hover:bg-[#3D3D3D]',
|
||||
'border border-[#727272] bg-[var(--border-strong)] hover:bg-[var(--surface-11)] dark:border-[#727272] dark:bg-[var(--border-strong)] dark:hover:bg-[var(--surface-11)]',
|
||||
primary:
|
||||
'bg-[#8E4CFB] dark:bg-[#8E4CFB] dark:text-[#E6E6E6] text-[#E6E6E6] hover:bg-[#8E4CFB] hover:dark:bg-[#8E4CFB] hover:text-[#E6E6E6] hover:dark:text-[#E6E6E6]',
|
||||
'bg-[var(--brand-400)] dark:bg-[var(--brand-400)] dark:text-[var(--text-primary)] text-[var(--text-primary)] hover:bg-[var(--brand-400)] hover:dark:bg-[var(--brand-400)] hover:text-[var(--text-primary)] hover:dark:text-[var(--text-primary)]',
|
||||
ghost: '',
|
||||
'ghost-secondary': 'text-[#787878] dark:text-[#787878]',
|
||||
'ghost-secondary': 'text-[var(--text-muted)] dark:text-[var(--text-muted)]',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
||||
@@ -77,9 +77,9 @@ function Container({
|
||||
<div
|
||||
className={cn(
|
||||
// Base container styling
|
||||
'group relative min-h-[100px] rounded-[4px] border border-[#303030]',
|
||||
'group relative min-h-[100px] rounded-[4px] border border-[var(--border-strong)]',
|
||||
'bg-[#1F1F1F] font-medium font-mono text-sm transition-colors',
|
||||
'dark:border-[#303030]',
|
||||
'dark:border-[var(--border-strong)]',
|
||||
// Streaming state
|
||||
isStreaming && 'streaming-effect',
|
||||
className
|
||||
|
||||
@@ -17,7 +17,7 @@ import { Input } from '../input/input'
|
||||
import { Popover, PopoverAnchor, PopoverContent, PopoverScrollArea } from '../popover/popover'
|
||||
|
||||
const comboboxVariants = cva(
|
||||
'flex w-full rounded-[4px] border border-[#3D3D3D] bg-[#282828] dark:bg-[#363636] px-[8px] py-[6px] font-sans font-medium text-sm text-[#E6E6E6] placeholder:text-[#787878] dark:placeholder:text-[#787878] outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 hover:border-[#4A4A4A] hover:bg-[#363636] dark:hover:border-[#454545] dark:hover:bg-[#3D3D3D]',
|
||||
'flex w-full rounded-[4px] border border-[var(--surface-11)] bg-[var(--surface-6)] dark:bg-[var(--surface-9)] px-[8px] py-[6px] font-sans font-medium text-sm text-[var(--text-primary)] placeholder:text-[var(--text-muted)] dark:placeholder:text-[var(--text-muted)] outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 hover:border-[var(--surface-14)] hover:bg-[var(--surface-9)] dark:hover:border-[var(--surface-13)] dark:hover:bg-[var(--surface-11)]',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
@@ -338,7 +338,7 @@ const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(
|
||||
<Input
|
||||
ref={inputRef}
|
||||
className={cn(
|
||||
'w-full pr-[40px] font-medium transition-colors hover:border-[#4A4A4A] hover:bg-[#363636] dark:hover:border-[#454545] dark:hover:bg-[#3D3D3D]',
|
||||
'w-full pr-[40px] font-medium transition-colors hover:border-[var(--surface-14)] hover:bg-[var(--surface-9)] dark:hover:border-[var(--surface-13)] dark:hover:bg-[var(--surface-11)]',
|
||||
(overlayContent || SelectedIcon) && 'text-transparent caret-foreground',
|
||||
SelectedIcon && !overlayContent && 'pl-[28px]',
|
||||
className
|
||||
@@ -361,7 +361,9 @@ const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(
|
||||
{SelectedIcon && (
|
||||
<SelectedIcon className='mr-[8px] h-3 w-3 flex-shrink-0 opacity-60' />
|
||||
)}
|
||||
<span className='truncate text-[#E6E6E6]'>{selectedOption?.label}</span>
|
||||
<span className='truncate text-[var(--text-primary)]'>
|
||||
{selectedOption?.label}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
@@ -397,7 +399,7 @@ const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(
|
||||
<span
|
||||
className={cn(
|
||||
'flex-1 truncate',
|
||||
!selectedOption && 'text-[#787878]',
|
||||
!selectedOption && 'text-[var(--text-muted)]',
|
||||
overlayContent && 'text-transparent'
|
||||
)}
|
||||
>
|
||||
@@ -441,8 +443,8 @@ const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(
|
||||
<div ref={dropdownRef} role='listbox'>
|
||||
{isLoading ? (
|
||||
<div className='flex items-center justify-center py-[14px]'>
|
||||
<Loader2 className='h-[16px] w-[16px] animate-spin text-[#787878]' />
|
||||
<span className='ml-[8px] font-medium font-sans text-[#787878] text-sm'>
|
||||
<Loader2 className='h-[16px] w-[16px] animate-spin text-[var(--text-muted)]' />
|
||||
<span className='ml-[8px] font-medium font-sans text-[var(--text-muted)] text-sm'>
|
||||
Loading options...
|
||||
</span>
|
||||
</div>
|
||||
@@ -451,7 +453,7 @@ const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(
|
||||
{error}
|
||||
</div>
|
||||
) : filteredOptions.length === 0 ? (
|
||||
<div className='py-[14px] text-center font-medium font-sans text-[#787878] text-sm'>
|
||||
<div className='py-[14px] text-center font-medium font-sans text-[var(--text-muted)] text-sm'>
|
||||
{editable && value ? 'No matching options found' : 'No options available'}
|
||||
</div>
|
||||
) : (
|
||||
@@ -476,12 +478,14 @@ const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(
|
||||
onMouseEnter={() => setHighlightedIndex(index)}
|
||||
className={cn(
|
||||
'relative flex cursor-pointer select-none items-center rounded-[4px] px-[8px] py-[6px] font-medium font-sans text-sm',
|
||||
isHighlighted && 'bg-[#3D3D3D]',
|
||||
!isHighlighted && 'hover:bg-[#3D3D3D]'
|
||||
isHighlighted && 'bg-[var(--surface-11)]',
|
||||
!isHighlighted && 'hover:bg-[var(--surface-11)]'
|
||||
)}
|
||||
>
|
||||
{OptionIcon && <OptionIcon className='mr-[8px] h-3 w-3 opacity-60' />}
|
||||
<span className='flex-1 truncate text-[#E6E6E6]'>{option.label}</span>
|
||||
<span className='flex-1 truncate text-[var(--text-primary)]'>
|
||||
{option.label}
|
||||
</span>
|
||||
{isSelected && <Check className='ml-[8px] h-4 w-4 flex-shrink-0' />}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@ import { cva, type VariantProps } from 'class-variance-authority'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const inputVariants = cva(
|
||||
'flex w-full rounded-[4px] border border-[#3D3D3D] bg-[#282828] dark:bg-[#363636] px-[8px] py-[6px] font-medium font-sans text-sm text-foreground transition-colors placeholder:text-[#787878] dark:placeholder:text-[#787878] outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
'flex w-full rounded-[4px] border border-[var(--surface-11)] bg-[var(--surface-6)] dark:bg-[var(--surface-9)] px-[8px] py-[6px] font-medium font-sans text-sm text-foreground transition-colors placeholder:text-[var(--text-muted)] dark:placeholder:text-[var(--text-muted)] outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
|
||||
@@ -18,7 +18,7 @@ function Label({ className, ...props }: LabelProps) {
|
||||
return (
|
||||
<LabelPrimitive.Root
|
||||
className={cn(
|
||||
'inline-flex items-center font-medium text-[#E6E6E6] text-[13px] leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50 dark:text-[#E6E6E6]',
|
||||
'inline-flex items-center font-medium text-[13px] text-[var(--text-primary)] leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50 dark:text-[var(--text-primary)]',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -69,10 +69,10 @@ const MODAL_SPACING = {
|
||||
*/
|
||||
const MODAL_COLORS = {
|
||||
OVERLAY_BG: 'bg-black/80',
|
||||
CONTENT_BG: 'bg-[#242424] dark:bg-[#242424]',
|
||||
TITLE_TEXT: 'text-[#E6E6E6] dark:text-[#E6E6E6]',
|
||||
DESCRIPTION_TEXT: 'text-[#AEAEAE] dark:text-[#AEAEAE]',
|
||||
CLOSE_BUTTON_TEXT: 'text-[#B1B1B1] dark:text-[#B1B1B1]',
|
||||
CONTENT_BG: 'bg-[var(--surface-3)] dark:bg-[var(--surface-3)]',
|
||||
TITLE_TEXT: 'text-[var(--text-primary)] dark:text-[var(--text-primary)]',
|
||||
DESCRIPTION_TEXT: 'text-[var(--text-tertiary)] dark:text-[var(--text-tertiary)]',
|
||||
CLOSE_BUTTON_TEXT: 'text-[var(--text-secondary)] dark:text-[var(--text-secondary)]',
|
||||
} as const
|
||||
|
||||
/**
|
||||
|
||||
@@ -59,16 +59,16 @@ import { cn } from '@/lib/utils'
|
||||
* Ensures consistent height and styling across items, folders, and back button.
|
||||
*/
|
||||
const POPOVER_ITEM_BASE_CLASSES =
|
||||
'flex h-[25px] min-w-0 cursor-pointer items-center gap-[8px] rounded-[6px] px-[6px] font-base text-[#E6E6E6] text-[12px] transition-colors dark:text-[#E6E6E6] [&_svg]:transition-colors disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed'
|
||||
'flex h-[25px] min-w-0 cursor-pointer items-center gap-[8px] rounded-[6px] px-[6px] font-base text-[var(--text-primary)] text-[12px] transition-colors dark:text-[var(--text-primary)] [&_svg]:transition-colors disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed'
|
||||
|
||||
/**
|
||||
* Variant-specific active state styles for popover items.
|
||||
*/
|
||||
const POPOVER_ITEM_ACTIVE_CLASSES = {
|
||||
primary:
|
||||
'bg-[#33B4FF] text-[#1B1B1B] dark:bg-[#33B4FF] dark:text-[#1B1B1B] [&_svg]:text-[#1B1B1B] dark:[&_svg]:text-[#1B1B1B]',
|
||||
'bg-[var(--brand-secondary)] text-[var(--bg)] dark:bg-[var(--brand-secondary)] dark:text-[var(--bg)] [&_svg]:text-[var(--bg)] dark:[&_svg]:text-[var(--bg)]',
|
||||
default:
|
||||
'bg-[#363636] text-[#E6E6E6] dark:bg-[#363636] dark:text-[#E6E6E6] [&_svg]:text-[#E6E6E6] dark:[&_svg]:text-[#E6E6E6]',
|
||||
'bg-[var(--surface-9)] text-[var(--text-primary)] dark:bg-[var(--surface-9)] dark:text-[var(--text-primary)] [&_svg]:text-[var(--text-primary)] dark:[&_svg]:text-[var(--text-primary)]',
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,9 +76,9 @@ const POPOVER_ITEM_ACTIVE_CLASSES = {
|
||||
*/
|
||||
const POPOVER_ITEM_HOVER_CLASSES = {
|
||||
primary:
|
||||
'hover:bg-[#33B4FF] hover:text-[#1B1B1B] dark:hover:bg-[#33B4FF] dark:hover:text-[#1B1B1B] hover:[&_svg]:text-[#1B1B1B] dark:hover:[&_svg]:text-[#1B1B1B]',
|
||||
'hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)] hover:[&_svg]:text-[var(--bg)] dark:hover:[&_svg]:text-[var(--bg)]',
|
||||
default:
|
||||
'hover:bg-[#363636] hover:text-[#E6E6E6] dark:hover:bg-[#363636] dark:hover:text-[#E6E6E6] hover:[&_svg]:text-[#E6E6E6] dark:hover:[&_svg]:text-[#E6E6E6]',
|
||||
'hover:bg-[var(--surface-9)] hover:text-[var(--text-primary)] dark:hover:bg-[var(--surface-9)] dark:hover:text-[var(--text-primary)] hover:[&_svg]:text-[var(--text-primary)] dark:hover:[&_svg]:text-[var(--text-primary)]',
|
||||
}
|
||||
|
||||
type PopoverVariant = 'default' | 'primary'
|
||||
@@ -260,6 +260,12 @@ const PopoverContent = React.forwardRef<
|
||||
// Smart default offset: larger offset when rendering above to avoid covering cursor
|
||||
const effectiveSideOffset = sideOffset ?? (side === 'top' ? 20 : 14)
|
||||
|
||||
// Detect explicit width constraints provided by the consumer.
|
||||
// When present, we enable default text truncation behavior for inner flexible items,
|
||||
// so callers don't need to manually pass 'truncate' to every label.
|
||||
const hasUserWidthConstraint =
|
||||
style?.minWidth !== undefined || style?.maxWidth !== undefined || style?.width !== undefined
|
||||
|
||||
return (
|
||||
<PopoverPrimitive.Portal>
|
||||
<PopoverPrimitive.Content
|
||||
@@ -272,7 +278,9 @@ const PopoverContent = React.forwardRef<
|
||||
sticky='partial'
|
||||
{...restProps}
|
||||
className={cn(
|
||||
'z-[9999999] flex flex-col overflow-hidden rounded-[8px] bg-[#242424] px-[5.5px] py-[5px] text-foreground outline-none dark:bg-[#242424]',
|
||||
'z-[9999999] flex flex-col overflow-hidden rounded-[8px] bg-[var(--surface-3)] px-[5.5px] py-[5px] text-foreground outline-none dark:bg-[var(--surface-3)]',
|
||||
// If width is constrained by the caller, ensure inner flexible text truncates by default.
|
||||
hasUserWidthConstraint && '[&_.flex-1]:truncate',
|
||||
className
|
||||
)}
|
||||
style={{
|
||||
@@ -407,7 +415,7 @@ const PopoverSection = React.forwardRef<HTMLDivElement, PopoverSectionProps>(
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'px-[6px] py-[4px] font-base text-[#AEAEAE] text-[12px] dark:text-[#AEAEAE]',
|
||||
'px-[6px] py-[4px] font-base text-[12px] text-[var(--text-tertiary)] dark:text-[var(--text-tertiary)]',
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
@@ -576,7 +584,7 @@ const PopoverBackButton = React.forwardRef<HTMLDivElement, PopoverBackButtonProp
|
||||
</div>
|
||||
)}
|
||||
{folderTitle && !onFolderSelect && (
|
||||
<div className='px-[6px] py-[4px] font-base text-[#AEAEAE] text-[12px] dark:text-[#AEAEAE]'>
|
||||
<div className='px-[6px] py-[4px] font-base text-[12px] text-[var(--text-tertiary)] dark:text-[var(--text-tertiary)]'>
|
||||
{folderTitle}
|
||||
</div>
|
||||
)}
|
||||
@@ -631,10 +639,10 @@ const PopoverSearch = React.forwardRef<HTMLDivElement, PopoverSearchProps>(
|
||||
|
||||
return (
|
||||
<div ref={ref} className={cn('flex items-center px-[8px] py-[6px]', className)} {...props}>
|
||||
<Search className='mr-2 h-[12px] w-[12px] shrink-0 text-[#787878]' />
|
||||
<Search className='mr-2 h-[12px] w-[12px] shrink-0 text-[var(--text-muted)]' />
|
||||
<input
|
||||
ref={inputRef}
|
||||
className='w-full bg-transparent font-base text-[#E6E6E6] text-[12px] placeholder:text-[#787878] focus:outline-none'
|
||||
className='w-full bg-transparent font-base text-[12px] text-[var(--text-primary)] placeholder:text-[var(--text-muted)] focus:outline-none'
|
||||
placeholder={placeholder}
|
||||
value={searchQuery}
|
||||
onChange={handleChange}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { cva, type VariantProps } from 'class-variance-authority'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const textareaVariants = cva(
|
||||
'flex w-full rounded-[4px] border border-[#3D3D3D] bg-[#282828] dark:bg-[#363636] px-[8px] py-[8px] font-medium font-sans text-sm text-foreground transition-colors placeholder:text-[#787878] dark:placeholder:text-[#787878] outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 resize overflow-auto disabled:cursor-not-allowed disabled:opacity-50',
|
||||
'flex w-full rounded-[4px] border border-[var(--surface-11)] bg-[var(--surface-6)] dark:bg-[var(--surface-9)] px-[8px] py-[8px] font-medium font-sans text-sm text-[var(--text-primary)] transition-colors placeholder:text-[var(--text-muted)] dark:placeholder:text-[var(--text-muted)] outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 resize overflow-auto disabled:cursor-not-allowed disabled:opacity-50',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
|
||||
@@ -87,7 +87,7 @@ const AlertDialogContent = React.forwardRef<
|
||||
<AlertDialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-[8px] border border-border bg-background px-6 py-5 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in',
|
||||
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-[8px] border border-[var(--border-muted)] bg-[var(--surface-3)] px-6 py-5 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in dark:bg-[var(--surface-3)]',
|
||||
className
|
||||
)}
|
||||
onPointerDown={(e) => {
|
||||
|
||||
@@ -12,7 +12,7 @@ const Checkbox = React.forwardRef<
|
||||
<CheckboxPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'peer h-4 w-4 shrink-0 rounded-sm border border-[#3D3D3D] bg-[#272727] ring-offset-background transition-colors hover:border-[#4A4A4A] hover:bg-[#282828] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-[#4A4A4A] data-[state=checked]:bg-[#3D3D3D] data-[state=checked]:text-[#E6E6E6] dark:border-[#3D3D3D] dark:bg-[#363636] dark:data-[state=checked]:border-[#5A5A5A] dark:data-[state=checked]:bg-[#454545] dark:hover:border-[#454545] dark:hover:bg-[#3D3D3D]',
|
||||
'peer h-4 w-4 shrink-0 rounded-sm border border-[var(--surface-11)] bg-[var(--surface-5)] ring-offset-background transition-colors hover:border-[var(--surface-14)] hover:bg-[var(--surface-6)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-[var(--surface-14)] data-[state=checked]:bg-[var(--surface-11)] data-[state=checked]:text-[var(--text-primary)] dark:border-[var(--surface-11)] dark:bg-[var(--surface-9)] dark:data-[state=checked]:border-[var(--surface-15)] dark:data-[state=checked]:bg-[var(--surface-13)] dark:hover:border-[var(--surface-13)] dark:hover:bg-[var(--surface-11)]',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -70,7 +70,7 @@ const DialogContent = React.forwardRef<
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-[8px] border border-border bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in',
|
||||
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-[8px] border border-[var(--border-muted)] bg-[var(--surface-3)] p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in dark:bg-[var(--surface-3)]',
|
||||
className
|
||||
)}
|
||||
onInteractOutside={(e) => {
|
||||
|
||||
@@ -10,7 +10,7 @@ const Switch = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SwitchPrimitives.Root
|
||||
className={cn(
|
||||
'peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent bg-[#272727] transition-colors hover:bg-[#282828] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-[#3D3D3D] data-[state=unchecked]:bg-[#272727] dark:bg-[#272727] dark:data-[state=checked]:bg-[#454545] dark:data-[state=unchecked]:bg-[#363636] dark:hover:bg-[#282828]',
|
||||
'peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent bg-[var(--surface-5)] transition-colors hover:bg-[var(--surface-6)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-[var(--surface-11)] data-[state=unchecked]:bg-[var(--surface-5)] dark:bg-[var(--surface-5)] dark:data-[state=checked]:bg-[var(--surface-13)] dark:data-[state=unchecked]:bg-[var(--surface-9)] dark:hover:bg-[var(--surface-6)]',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -18,7 +18,7 @@ const Switch = React.forwardRef<
|
||||
>
|
||||
<SwitchPrimitives.Thumb
|
||||
className={cn(
|
||||
'pointer-events-none block h-4 w-4 rounded-full bg-[#E6E6E6] shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0'
|
||||
'pointer-events-none block h-4 w-4 rounded-full bg-[var(--text-primary)] shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0'
|
||||
)}
|
||||
/>
|
||||
</SwitchPrimitives.Root>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Environment utility functions for consistent environment detection across the application
|
||||
*/
|
||||
import { env, isTruthy } from './env'
|
||||
import { env, getEnv, isTruthy } from './env'
|
||||
|
||||
/**
|
||||
* Is the application running in production mode
|
||||
@@ -21,7 +21,9 @@ export const isTest = env.NODE_ENV === 'test'
|
||||
/**
|
||||
* Is this the hosted version of the application
|
||||
*/
|
||||
export const isHosted = true
|
||||
export const isHosted =
|
||||
getEnv('NEXT_PUBLIC_APP_URL') === 'https://www.sim.ai' ||
|
||||
getEnv('NEXT_PUBLIC_APP_URL') === 'https://www.staging.sim.ai'
|
||||
|
||||
/**
|
||||
* Is billing enforcement enabled
|
||||
|
||||
+23
-20
@@ -5,33 +5,36 @@
|
||||
/**
|
||||
* Updates the theme in next-themes by dispatching a storage event
|
||||
* This works by updating localStorage and notifying next-themes of the change
|
||||
*
|
||||
* COMMENTED OUT: Theme switching disabled - dark mode is forced for workspace
|
||||
*/
|
||||
export function syncThemeToNextThemes(theme: 'system' | 'light' | 'dark') {
|
||||
if (typeof window === 'undefined') return
|
||||
|
||||
// Update localStorage
|
||||
localStorage.setItem('sim-theme', theme)
|
||||
// COMMENTED OUT: Dark mode is forced for workspace pages
|
||||
// // Update localStorage
|
||||
// localStorage.setItem('sim-theme', theme)
|
||||
|
||||
// Dispatch storage event to notify next-themes
|
||||
window.dispatchEvent(
|
||||
new StorageEvent('storage', {
|
||||
key: 'sim-theme',
|
||||
newValue: theme,
|
||||
oldValue: localStorage.getItem('sim-theme'),
|
||||
storageArea: localStorage,
|
||||
url: window.location.href,
|
||||
})
|
||||
)
|
||||
// // Dispatch storage event to notify next-themes
|
||||
// window.dispatchEvent(
|
||||
// new StorageEvent('storage', {
|
||||
// key: 'sim-theme',
|
||||
// newValue: theme,
|
||||
// oldValue: localStorage.getItem('sim-theme'),
|
||||
// storageArea: localStorage,
|
||||
// url: window.location.href,
|
||||
// })
|
||||
// )
|
||||
|
||||
// Also update the HTML class immediately for instant feedback
|
||||
const root = document.documentElement
|
||||
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||
const actualTheme = theme === 'system' ? systemTheme : theme
|
||||
// // Also update the HTML class immediately for instant feedback
|
||||
// const root = document.documentElement
|
||||
// const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||
// const actualTheme = theme === 'system' ? systemTheme : theme
|
||||
|
||||
// Remove existing theme classes
|
||||
root.classList.remove('light', 'dark')
|
||||
// Add new theme class
|
||||
root.classList.add(actualTheme)
|
||||
// // Remove existing theme classes
|
||||
// root.classList.remove('light', 'dark')
|
||||
// // Add new theme class
|
||||
// root.classList.add(actualTheme)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,7 +9,7 @@ import { usePanelStore } from '../store'
|
||||
*/
|
||||
const DEFAULT_CONNECTIONS_HEIGHT = 115
|
||||
const MIN_CONNECTIONS_HEIGHT = 30
|
||||
const MAX_CONNECTIONS_HEIGHT = 200
|
||||
const MAX_CONNECTIONS_HEIGHT = 300
|
||||
|
||||
/**
|
||||
* State for the Editor panel.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { create } from 'zustand'
|
||||
import { devtools, persist } from 'zustand/middleware'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { syncThemeToNextThemes } from '@/lib/theme-sync'
|
||||
// COMMENTED OUT: Theme switching disabled - dark mode is forced for workspace
|
||||
// import { syncThemeToNextThemes } from '@/lib/theme-sync'
|
||||
import { withOptimisticUpdate } from '@/lib/utils'
|
||||
import type { General, GeneralStore, UserSettings } from '@/stores/settings/general/types'
|
||||
|
||||
@@ -130,25 +131,27 @@ export const useGeneralStore = create<GeneralStore>()(
|
||||
)
|
||||
},
|
||||
|
||||
// COMMENTED OUT: Theme switching disabled - dark mode is forced for workspace
|
||||
setTheme: async (theme) => {
|
||||
if (get().isThemeLoading) return
|
||||
|
||||
await withOptimisticUpdate({
|
||||
getCurrentState: () => get().theme,
|
||||
optimisticUpdate: () => {
|
||||
set({ theme, isThemeLoading: true })
|
||||
syncThemeToNextThemes(theme)
|
||||
},
|
||||
apiCall: async () => {
|
||||
await get().updateSetting('theme', theme)
|
||||
},
|
||||
rollback: (originalTheme) => {
|
||||
set({ theme: originalTheme })
|
||||
syncThemeToNextThemes(originalTheme)
|
||||
},
|
||||
onComplete: () => set({ isThemeLoading: false }),
|
||||
errorMessage: 'Failed to sync theme to database',
|
||||
})
|
||||
// COMMENTED OUT: Dark mode is forced for workspace pages
|
||||
// await withOptimisticUpdate({
|
||||
// getCurrentState: () => get().theme,
|
||||
// optimisticUpdate: () => {
|
||||
// set({ theme, isThemeLoading: true })
|
||||
// syncThemeToNextThemes(theme)
|
||||
// },
|
||||
// apiCall: async () => {
|
||||
// await get().updateSetting('theme', theme)
|
||||
// },
|
||||
// rollback: (originalTheme) => {
|
||||
// set({ theme: originalTheme })
|
||||
// syncThemeToNextThemes(originalTheme)
|
||||
// },
|
||||
// onComplete: () => set({ isThemeLoading: false }),
|
||||
// errorMessage: 'Failed to sync theme to database',
|
||||
// })
|
||||
},
|
||||
|
||||
setTelemetryEnabled: async (enabled) => {
|
||||
@@ -231,13 +234,14 @@ export const useGeneralStore = create<GeneralStore>()(
|
||||
isLoading: false,
|
||||
})
|
||||
|
||||
// Sync theme to next-themes if it's different
|
||||
if (data.theme && typeof window !== 'undefined') {
|
||||
const currentTheme = localStorage.getItem('sim-theme')
|
||||
if (currentTheme !== data.theme) {
|
||||
syncThemeToNextThemes(data.theme)
|
||||
}
|
||||
}
|
||||
// COMMENTED OUT: Theme switching disabled - dark mode is forced for workspace
|
||||
// // Sync theme to next-themes if it's different
|
||||
// if (data.theme && typeof window !== 'undefined') {
|
||||
// const currentTheme = localStorage.getItem('sim-theme')
|
||||
// if (currentTheme !== data.theme) {
|
||||
// syncThemeToNextThemes(data.theme)
|
||||
// }
|
||||
// }
|
||||
|
||||
lastLoadTime = now
|
||||
errorRetryCount = 0
|
||||
|
||||
Reference in New Issue
Block a user