mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-11 12:17:45 +02:00
[aidan] ux/workflows: animate sidebar title on auto-rename
Wrap the calendar hub's sidebar row title in the same Typewriter the workflow card uses, so a title that auto-renames retypes letter-by-letter in the sidebar too. Extract the placeholder/isRealTitle guard into the shared workflowVisuals so the card and sidebar stay in sync.
This commit is contained in:
@@ -43,7 +43,7 @@ import InlineEditableTitle from '@/app/components/InlineEditableTitle';
|
||||
import { Typewriter } from '@/app/components/feedback/Animated';
|
||||
import StopRounded from '@mui/icons-material/StopRounded';
|
||||
import PauseRounded from '@mui/icons-material/PauseRounded';
|
||||
import { StatusDot, RunSparkline, LastFiredHint, isStaleSinceLastRun } from './workflowVisuals';
|
||||
import { StatusDot, RunSparkline, LastFiredHint, isStaleSinceLastRun, isRealTitle } from './workflowVisuals';
|
||||
import { store } from '@/shared/state/store';
|
||||
import { getAgentWorkTime, fmtSeconds } from '@/shared/agentWorkTime';
|
||||
|
||||
@@ -75,14 +75,6 @@ const HANDLE_DEFS: { dir: ResizeDir; sx: Record<string, any> }[] = [
|
||||
{ dir: 'se', sx: { bottom: -EDGE_THICKNESS / 2, right: -EDGE_THICKNESS / 2, width: CORNER_SIZE, height: CORNER_SIZE } },
|
||||
];
|
||||
|
||||
// Placeholder titles the backend uses before auto-naming kicks in. The title
|
||||
// Typewriter only animates once the title is a real (generated/user) name, so
|
||||
// the card doesn't animate on mount or while still showing a placeholder.
|
||||
const PLACEHOLDER_TITLES = new Set(['', 'New workflow', 'Untitled workflow', 'Scheduled workflow']);
|
||||
function isRealTitle(title?: string | null): boolean {
|
||||
return !!title && !PLACEHOLDER_TITLES.has(title.trim());
|
||||
}
|
||||
|
||||
interface Props {
|
||||
workflowId: string;
|
||||
cardX: number;
|
||||
|
||||
@@ -29,6 +29,8 @@ import { useEffect } from 'react';
|
||||
import ScheduleCalendar from './ScheduleCalendar';
|
||||
import AddToSchedulePopover from './AddToSchedulePopover';
|
||||
import { WEEKDAY_LABEL, addDays, sameDay, startOfMonthGrid, isWorkflowSchedulable } from './scheduleUtils';
|
||||
import { isRealTitle } from './workflowVisuals';
|
||||
import { Typewriter } from '@/app/components/feedback/Animated';
|
||||
|
||||
type ResizeDir = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw';
|
||||
|
||||
@@ -680,7 +682,14 @@ function SidebarSection({ title, items, onPick, scheduled, onContext, onSchedule
|
||||
</Box>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Typography sx={{ flex: 1, fontSize: '0.82rem', color: c.text.primary, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', opacity: scheduled && !w.schedule.enabled ? 0.7 : 1 }}>{w.title}</Typography>
|
||||
{/* Retype the title letter-by-letter when it auto-renames, matching
|
||||
the workflow card. Gated on a real (non-placeholder) title so it
|
||||
never animates on first appearance or for already-named rows. */}
|
||||
<Typewriter value={w.title} enabled={isRealTitle(w.title)}>
|
||||
{(t) => (
|
||||
<Typography sx={{ flex: 1, fontSize: '0.82rem', color: c.text.primary, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', opacity: scheduled && !w.schedule.enabled ? 0.7 : 1 }}>{t}</Typography>
|
||||
)}
|
||||
</Typewriter>
|
||||
{scheduled && !w.schedule.enabled && (
|
||||
<Box sx={{ flexShrink: 0, px: 0.6, py: 0.1, borderRadius: '3px', bgcolor: c.bg.elevated, color: c.text.muted, fontSize: '0.62rem', fontWeight: 600, lineHeight: 1.5, letterSpacing: '0.02em' }}>Paused</Box>
|
||||
)}
|
||||
|
||||
@@ -31,6 +31,16 @@ import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import type { Workflow, WorkflowRun, ScheduleConfig, PermissionTier } from '@/shared/state/workflowsSlice';
|
||||
import { formatTime, WEEKDAY_LABEL, isScheduleConfigured } from './scheduleUtils';
|
||||
|
||||
// ---------- Title placeholders ----------
|
||||
|
||||
// Placeholder titles the backend uses before auto-naming kicks in. The title
|
||||
// Typewriter only animates once the title is a real (generated/user) name, so
|
||||
// the UI doesn't animate on mount or while still showing a placeholder.
|
||||
const PLACEHOLDER_TITLES = new Set(['', 'New workflow', 'Untitled workflow', 'Scheduled workflow']);
|
||||
export function isRealTitle(title?: string | null): boolean {
|
||||
return !!title && !PLACEHOLDER_TITLES.has(title.trim());
|
||||
}
|
||||
|
||||
// ---------- Status colors ----------
|
||||
|
||||
export type LastRunStatus = NonNullable<Workflow['last_run_status']>;
|
||||
|
||||
Reference in New Issue
Block a user