Stijnus commited on
Commit
23d253e
·
1 Parent(s): 07435fc

fixes as fequestd

Browse files
app/components/@settings/core/AvatarDropdown.tsx CHANGED
@@ -5,6 +5,12 @@ import { classNames } from '~/utils/classNames';
5
  import { profileStore } from '~/lib/stores/profile';
6
  import type { TabType, Profile } from './types';
7
 
 
 
 
 
 
 
8
  interface AvatarDropdownProps {
9
  onSelectTab: (tab: TabType) => void;
10
  }
@@ -15,55 +21,52 @@ export const AvatarDropdown = ({ onSelectTab }: AvatarDropdownProps) => {
15
  return (
16
  <DropdownMenu.Root>
17
  <DropdownMenu.Trigger asChild>
18
- <motion.button
19
- className="group flex items-center justify-center"
20
- whileHover={{ scale: 1.02 }}
21
- whileTap={{ scale: 0.98 }}
22
- >
23
- <div
24
- className={classNames(
25
- 'w-10 h-10',
26
- 'rounded-full overflow-hidden',
27
- 'bg-gray-100/50 dark:bg-gray-800/50',
28
- 'flex items-center justify-center',
29
- 'ring-1 ring-gray-200/50 dark:ring-gray-700/50',
30
- 'group-hover:ring-purple-500/50 dark:group-hover:ring-purple-500/50',
31
- 'group-hover:bg-purple-500/10 dark:group-hover:bg-purple-500/10',
32
- 'transition-all duration-200',
33
- 'relative',
34
- )}
35
- >
36
- {profile?.avatar ? (
37
- <div className="w-full h-full">
38
- <img
39
- src={profile.avatar}
40
- alt={profile?.username || 'Profile'}
41
- className={classNames(
42
- 'w-full h-full',
43
- 'object-cover',
44
- 'transform-gpu',
45
- 'image-rendering-crisp',
46
- 'group-hover:brightness-110',
47
- 'group-hover:scale-105',
48
- 'transition-all duration-200',
49
- )}
50
- loading="eager"
51
- decoding="sync"
52
- />
53
- <div
54
- className={classNames(
55
- 'absolute inset-0',
56
- 'ring-1 ring-inset ring-black/5 dark:ring-white/5',
57
- 'group-hover:ring-purple-500/20 dark:group-hover:ring-purple-500/20',
58
- 'group-hover:bg-purple-500/5 dark:group-hover:bg-purple-500/5',
59
- 'transition-colors duration-200',
60
- )}
61
- />
62
- </div>
63
- ) : (
64
- <div className="i-ph:robot-fill w-6 h-6 text-gray-400 dark:text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
65
- )}
66
- </div>
67
  </motion.button>
68
  </DropdownMenu.Trigger>
69
 
@@ -86,7 +89,7 @@ export const AvatarDropdown = ({ onSelectTab }: AvatarDropdownProps) => {
86
  'border-b border-gray-200/50 dark:border-gray-800/50',
87
  )}
88
  >
89
- <div className="w-10 h-10 rounded-full overflow-hidden bg-gray-100/50 dark:bg-gray-800/50 flex-shrink-0">
90
  {profile?.avatar ? (
91
  <img
92
  src={profile.avatar}
@@ -96,8 +99,8 @@ export const AvatarDropdown = ({ onSelectTab }: AvatarDropdownProps) => {
96
  decoding="sync"
97
  />
98
  ) : (
99
- <div className="w-full h-full flex items-center justify-center">
100
- <div className="i-ph:robot-fill w-6 h-6 text-gray-400 dark:text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
101
  </div>
102
  )}
103
  </div>
@@ -121,7 +124,7 @@ export const AvatarDropdown = ({ onSelectTab }: AvatarDropdownProps) => {
121
  )}
122
  onClick={() => onSelectTab('profile')}
123
  >
124
- <div className="i-ph:robot-fill w-4 h-4 text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
125
  Edit Profile
126
  </DropdownMenu.Item>
127
 
@@ -137,7 +140,7 @@ export const AvatarDropdown = ({ onSelectTab }: AvatarDropdownProps) => {
137
  )}
138
  onClick={() => onSelectTab('settings')}
139
  >
140
- <div className="i-ph:gear-six-fill w-4 h-4 text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
141
  Settings
142
  </DropdownMenu.Item>
143
 
@@ -155,8 +158,9 @@ export const AvatarDropdown = ({ onSelectTab }: AvatarDropdownProps) => {
155
  )}
156
  onClick={() => onSelectTab('task-manager')}
157
  >
158
- <div className="i-ph:activity-fill w-4 h-4 text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
159
  Task Manager
 
160
  </DropdownMenu.Item>
161
 
162
  <DropdownMenu.Item
@@ -171,8 +175,9 @@ export const AvatarDropdown = ({ onSelectTab }: AvatarDropdownProps) => {
171
  )}
172
  onClick={() => onSelectTab('service-status')}
173
  >
174
- <div className="i-ph:heartbeat-fill w-4 h-4 text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
175
  Service Status
 
176
  </DropdownMenu.Item>
177
  </DropdownMenu.Content>
178
  </DropdownMenu.Portal>
 
5
  import { profileStore } from '~/lib/stores/profile';
6
  import type { TabType, Profile } from './types';
7
 
8
+ const BetaLabel = () => (
9
+ <span className="px-1.5 py-0.5 rounded-full bg-purple-500/10 dark:bg-purple-500/20 text-[10px] font-medium text-purple-600 dark:text-purple-400 ml-2">
10
+ BETA
11
+ </span>
12
+ );
13
+
14
  interface AvatarDropdownProps {
15
  onSelectTab: (tab: TabType) => void;
16
  }
 
21
  return (
22
  <DropdownMenu.Root>
23
  <DropdownMenu.Trigger asChild>
24
+ <motion.button className="group outline-none relative" whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }}>
25
+ {profile?.avatar ? (
26
+ <div
27
+ className={classNames(
28
+ 'w-10 h-10',
29
+ 'rounded-full overflow-hidden',
30
+ 'bg-white dark:bg-gray-800',
31
+ 'transition-all duration-200',
32
+ 'relative',
33
+ 'shadow-sm',
34
+ )}
35
+ >
36
+ <img
37
+ src={profile.avatar}
38
+ alt={profile?.username || 'Profile'}
39
+ className={classNames(
40
+ 'w-full h-full',
41
+ 'object-cover',
42
+ 'transform-gpu',
43
+ 'image-rendering-crisp',
44
+ 'group-hover:brightness-110',
45
+ 'group-hover:scale-105',
46
+ 'transition-all duration-200',
47
+ )}
48
+ loading="eager"
49
+ decoding="sync"
50
+ />
51
+ </div>
52
+ ) : (
53
+ <div
54
+ className={classNames(
55
+ 'w-10 h-10',
56
+ 'rounded-full',
57
+ 'flex items-center justify-center',
58
+ 'bg-white dark:bg-gray-800',
59
+ 'text-gray-400 dark:text-gray-500',
60
+ 'group-hover:text-purple-500 dark:group-hover:text-purple-400',
61
+ 'transition-all duration-200',
62
+ 'shadow-sm',
63
+ )}
64
+ >
65
+ <div className="i-ph:question w-6 h-6" />
66
+ </div>
67
+ )}
68
+ {/* Add subtle circular highlight effect */}
69
+ <div className="absolute inset-0 rounded-full bg-gradient-to-b from-white/10 to-transparent opacity-0 group-hover:opacity-100 transition-opacity" />
 
 
 
70
  </motion.button>
71
  </DropdownMenu.Trigger>
72
 
 
89
  'border-b border-gray-200/50 dark:border-gray-800/50',
90
  )}
91
  >
92
+ <div className="w-10 h-10 rounded-full overflow-hidden flex-shrink-0 bg-white dark:bg-gray-800 shadow-sm">
93
  {profile?.avatar ? (
94
  <img
95
  src={profile.avatar}
 
99
  decoding="sync"
100
  />
101
  ) : (
102
+ <div className="w-full h-full flex items-center justify-center text-gray-400 dark:text-gray-500 font-medium text-lg">
103
+ <span className="relative -top-0.5">?</span>
104
  </div>
105
  )}
106
  </div>
 
124
  )}
125
  onClick={() => onSelectTab('profile')}
126
  >
127
+ <div className="i-ph:user-circle w-4 h-4 text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
128
  Edit Profile
129
  </DropdownMenu.Item>
130
 
 
140
  )}
141
  onClick={() => onSelectTab('settings')}
142
  >
143
+ <div className="i-ph:gear-six w-4 h-4 text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
144
  Settings
145
  </DropdownMenu.Item>
146
 
 
158
  )}
159
  onClick={() => onSelectTab('task-manager')}
160
  >
161
+ <div className="i-ph:activity w-4 h-4 text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
162
  Task Manager
163
+ <BetaLabel />
164
  </DropdownMenu.Item>
165
 
166
  <DropdownMenu.Item
 
175
  )}
176
  onClick={() => onSelectTab('service-status')}
177
  >
178
+ <div className="i-ph:heartbeat w-4 h-4 text-gray-400 group-hover:text-purple-500 dark:group-hover:text-purple-400 transition-colors" />
179
  Service Status
180
+ <BetaLabel />
181
  </DropdownMenu.Item>
182
  </DropdownMenu.Content>
183
  </DropdownMenu.Portal>
app/components/@settings/core/ControlPanel.tsx CHANGED
@@ -82,6 +82,15 @@ const TAB_DESCRIPTIONS: Record<TabType, string> = {
82
  'tab-management': 'Configure visible tabs and their order',
83
  };
84
 
 
 
 
 
 
 
 
 
 
85
  const AnimatedSwitch = ({ checked, onCheckedChange, id, label }: AnimatedSwitchProps) => {
86
  return (
87
  <div className="flex items-center gap-2">
@@ -108,11 +117,12 @@ const AnimatedSwitch = ({ checked, onCheckedChange, id, label }: AnimatedSwitchP
108
  'group-hover:shadow-md group-active:shadow-sm',
109
  'group-hover:scale-95 group-active:scale-90',
110
  )}
111
- layout
112
  transition={{
113
  type: 'spring',
114
  stiffness: 500,
115
  damping: 30,
 
116
  }}
117
  animate={{
118
  x: checked ? '1.25rem' : '0rem',
@@ -414,29 +424,13 @@ export const ControlPanel = ({ open, onClose }: ControlPanelProps) => {
414
  {/* Header */}
415
  <div className="flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700">
416
  <div className="flex items-center space-x-4">
417
- {activeTab || showTabManagement ? (
418
  <button
419
  onClick={handleBack}
420
- className="flex items-center justify-center w-8 h-8 rounded-full bg-gray-100 dark:bg-gray-800 hover:bg-purple-500/10 dark:hover:bg-purple-500/20 group transition-all duration-200"
421
  >
422
  <div className="i-ph:arrow-left w-4 h-4 text-gray-500 dark:text-gray-400 group-hover:text-purple-500 transition-colors" />
423
  </button>
424
- ) : (
425
- <motion.div
426
- className="w-7 h-7"
427
- initial={{ rotate: -5 }}
428
- animate={{ rotate: 5 }}
429
- transition={{
430
- repeat: Infinity,
431
- repeatType: 'reverse',
432
- duration: 2,
433
- ease: 'easeInOut',
434
- }}
435
- >
436
- <div className="w-full h-full flex items-center justify-center bg-gray-100/50 dark:bg-gray-800/50 rounded-full">
437
- <div className="i-ph:lightning-fill w-5 h-5 text-purple-500 dark:text-purple-400 transition-colors" />
438
- </div>
439
- </motion.div>
440
  )}
441
  <DialogTitle className="text-xl font-semibold text-gray-900 dark:text-white">
442
  {showTabManagement ? 'Tab Management' : activeTab ? TAB_LABELS[activeTab] : 'Control Panel'}
@@ -462,7 +456,7 @@ export const ControlPanel = ({ open, onClose }: ControlPanelProps) => {
462
  {/* Close Button */}
463
  <button
464
  onClick={onClose}
465
- className="flex items-center justify-center w-8 h-8 rounded-full bg-gray-100 dark:bg-gray-800 hover:bg-purple-500/10 dark:hover:bg-purple-500/20 group transition-all duration-200"
466
  >
467
  <div className="i-ph:x w-4 h-4 text-gray-500 dark:text-gray-400 group-hover:text-purple-500 transition-colors" />
468
  </button>
@@ -513,8 +507,10 @@ export const ControlPanel = ({ open, onClose }: ControlPanelProps) => {
513
  statusMessage={getStatusMessage(tab.id)}
514
  description={TAB_DESCRIPTIONS[tab.id]}
515
  isLoading={loadingTab === tab.id}
516
- className="h-full"
517
- />
 
 
518
  </motion.div>
519
  ))}
520
  </AnimatePresence>
 
82
  'tab-management': 'Configure visible tabs and their order',
83
  };
84
 
85
+ // Beta status for experimental features
86
+ const BETA_TABS = new Set<TabType>(['task-manager', 'service-status']);
87
+
88
+ const BetaLabel = () => (
89
+ <div className="absolute top-2 right-2 px-1.5 py-0.5 rounded-full bg-purple-500/10 dark:bg-purple-500/20">
90
+ <span className="text-[10px] font-medium text-purple-600 dark:text-purple-400">BETA</span>
91
+ </div>
92
+ );
93
+
94
  const AnimatedSwitch = ({ checked, onCheckedChange, id, label }: AnimatedSwitchProps) => {
95
  return (
96
  <div className="flex items-center gap-2">
 
117
  'group-hover:shadow-md group-active:shadow-sm',
118
  'group-hover:scale-95 group-active:scale-90',
119
  )}
120
+ initial={false}
121
  transition={{
122
  type: 'spring',
123
  stiffness: 500,
124
  damping: 30,
125
+ duration: 0.2,
126
  }}
127
  animate={{
128
  x: checked ? '1.25rem' : '0rem',
 
424
  {/* Header */}
425
  <div className="flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700">
426
  <div className="flex items-center space-x-4">
427
+ {(activeTab || showTabManagement) && (
428
  <button
429
  onClick={handleBack}
430
+ className="flex items-center justify-center w-8 h-8 rounded-full bg-transparent hover:bg-purple-500/10 dark:hover:bg-purple-500/20 group transition-all duration-200"
431
  >
432
  <div className="i-ph:arrow-left w-4 h-4 text-gray-500 dark:text-gray-400 group-hover:text-purple-500 transition-colors" />
433
  </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
  )}
435
  <DialogTitle className="text-xl font-semibold text-gray-900 dark:text-white">
436
  {showTabManagement ? 'Tab Management' : activeTab ? TAB_LABELS[activeTab] : 'Control Panel'}
 
456
  {/* Close Button */}
457
  <button
458
  onClick={onClose}
459
+ className="flex items-center justify-center w-8 h-8 rounded-full bg-transparent hover:bg-purple-500/10 dark:hover:bg-purple-500/20 group transition-all duration-200"
460
  >
461
  <div className="i-ph:x w-4 h-4 text-gray-500 dark:text-gray-400 group-hover:text-purple-500 transition-colors" />
462
  </button>
 
507
  statusMessage={getStatusMessage(tab.id)}
508
  description={TAB_DESCRIPTIONS[tab.id]}
509
  isLoading={loadingTab === tab.id}
510
+ className="h-full relative"
511
+ >
512
+ {BETA_TABS.has(tab.id) && <BetaLabel />}
513
+ </TabTile>
514
  </motion.div>
515
  ))}
516
  </AnimatePresence>
app/components/@settings/shared/components/TabTile.tsx CHANGED
@@ -13,9 +13,10 @@ interface TabTileProps {
13
  description?: string;
14
  isLoading?: boolean;
15
  className?: string;
 
16
  }
17
 
18
- export const TabTile = ({
19
  tab,
20
  onClick,
21
  isActive,
@@ -24,6 +25,7 @@ export const TabTile = ({
24
  description,
25
  isLoading,
26
  className,
 
27
  }: TabTileProps) => {
28
  return (
29
  <Tooltip.Provider delayDuration={200}>
@@ -100,62 +102,33 @@ export const TabTile = ({
100
  </div>
101
  </div>
102
 
103
- {/* Status Indicator */}
104
  {hasUpdate && (
105
- <motion.div
106
- className={classNames(
107
- 'absolute top-3 right-3',
108
- 'w-2.5 h-2.5 rounded-full',
109
- 'bg-purple-500',
110
- 'ring-4 ring-purple-500',
111
- )}
112
- initial={{ scale: 0 }}
113
- animate={{ scale: 1 }}
114
- transition={{ type: 'spring', bounce: 0.5 }}
115
- />
 
 
 
 
 
 
 
 
116
  )}
117
 
118
- {/* Loading Overlay */}
119
- {isLoading && (
120
- <motion.div
121
- className={classNames(
122
- 'absolute inset-0 rounded-xl z-10',
123
- 'bg-white dark:bg-black',
124
- 'flex items-center justify-center',
125
- )}
126
- initial={{ opacity: 0 }}
127
- animate={{ opacity: 1 }}
128
- transition={{ duration: 0.2 }}
129
- >
130
- <motion.div
131
- className={classNames('w-8 h-8 rounded-full', 'border-2 border-purple-500', 'border-t-purple-500')}
132
- animate={{ rotate: 360 }}
133
- transition={{
134
- duration: 1,
135
- repeat: Infinity,
136
- ease: 'linear',
137
- }}
138
- />
139
- </motion.div>
140
- )}
141
  </motion.div>
142
  </Tooltip.Trigger>
143
- <Tooltip.Portal>
144
- <Tooltip.Content
145
- className={classNames(
146
- 'px-3 py-1.5 rounded-lg',
147
- 'bg-[#18181B] text-white',
148
- 'text-sm font-medium',
149
- 'select-none',
150
- 'z-[100]',
151
- )}
152
- side="top"
153
- sideOffset={5}
154
- >
155
- {statusMessage || TAB_LABELS[tab.id]}
156
- <Tooltip.Arrow className="fill-[#18181B]" />
157
- </Tooltip.Content>
158
- </Tooltip.Portal>
159
  </Tooltip.Root>
160
  </Tooltip.Provider>
161
  );
 
13
  description?: string;
14
  isLoading?: boolean;
15
  className?: string;
16
+ children?: React.ReactNode;
17
  }
18
 
19
+ export const TabTile: React.FC<TabTileProps> = ({
20
  tab,
21
  onClick,
22
  isActive,
 
25
  description,
26
  isLoading,
27
  className,
28
+ children,
29
  }: TabTileProps) => {
30
  return (
31
  <Tooltip.Provider delayDuration={200}>
 
102
  </div>
103
  </div>
104
 
105
+ {/* Update Indicator with Tooltip */}
106
  {hasUpdate && (
107
+ <>
108
+ <div className="absolute top-4 right-4 w-2 h-2 rounded-full bg-purple-500 dark:bg-purple-400 animate-pulse" />
109
+ <Tooltip.Portal>
110
+ <Tooltip.Content
111
+ className={classNames(
112
+ 'px-3 py-1.5 rounded-lg',
113
+ 'bg-[#18181B] text-white',
114
+ 'text-sm font-medium',
115
+ 'select-none',
116
+ 'z-[100]',
117
+ )}
118
+ side="top"
119
+ sideOffset={5}
120
+ >
121
+ {statusMessage}
122
+ <Tooltip.Arrow className="fill-[#18181B]" />
123
+ </Tooltip.Content>
124
+ </Tooltip.Portal>
125
+ </>
126
  )}
127
 
128
+ {/* Children (e.g. Beta Label) */}
129
+ {children}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  </motion.div>
131
  </Tooltip.Trigger>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  </Tooltip.Root>
133
  </Tooltip.Provider>
134
  );
app/components/@settings/tabs/features/FeaturesTab.tsx CHANGED
@@ -121,19 +121,13 @@ export default function FeaturesTab() {
121
 
122
  // Enable features by default on first load
123
  React.useEffect(() => {
124
- // Only enable if they haven't been explicitly set before
125
- if (isLatestBranch === undefined) {
126
- enableLatestBranch(true);
127
- }
128
-
129
- if (contextOptimizationEnabled === undefined) {
130
- enableContextOptimization(true);
131
- }
132
-
133
- if (autoSelectTemplate === undefined) {
134
- setAutoSelectTemplate(true);
135
- }
136
 
 
137
  if (eventLogs === undefined) {
138
  setEventLogs(true);
139
  }
 
121
 
122
  // Enable features by default on first load
123
  React.useEffect(() => {
124
+ // Force enable these features by default
125
+ enableLatestBranch(true);
126
+ enableContextOptimization(true);
127
+ setAutoSelectTemplate(true);
128
+ setPromptId('optimized');
 
 
 
 
 
 
 
129
 
130
+ // Only enable event logs if not explicitly set before
131
  if (eventLogs === undefined) {
132
  setEventLogs(true);
133
  }