diff --git a/frontend/src/components/shared/confirmation-dialog.tsx b/frontend/src/components/shared/confirmation-dialog.tsx
index da12862a..1ec2bacb 100644
--- a/frontend/src/components/shared/confirmation-dialog.tsx
+++ b/frontend/src/components/shared/confirmation-dialog.tsx
@@ -46,13 +46,19 @@ function ConfirmationDialog({
isOpen,
itemName = 'this',
itemType = 'item',
- title = 'Confirm Action',
+ title,
}: ConfirmationDialogProps) {
const [isProcessing, setIsProcessing] = useState(false);
+ // Derive a contextual title from confirm verb + item type so callers don't
+ // see "Confirm Action" for a Delete prompt or a Save prompt. Explicit
+ // `title` always wins.
+ const verb = confirmText.trim();
+ const resolvedTitle = title ?? (verb && verb !== 'Confirm' ? `${verb} ${itemType}` : 'Confirm Action');
+
const defaultDescription = description || (
<>
- Are you sure you want to perform this action on{' '}
+ Are you sure you want to {verb.toLowerCase() || 'perform this action on'}{' '}
{itemName} {itemType}?
>
);
@@ -102,7 +108,7 @@ function ConfirmationDialog({
>
- {title}
+ {resolvedTitle}
{defaultDescription}
diff --git a/frontend/src/components/ui/sidebar.tsx b/frontend/src/components/ui/sidebar.tsx
index 335ed4e7..efe1c335 100644
--- a/frontend/src/components/ui/sidebar.tsx
+++ b/frontend/src/components/ui/sidebar.tsx
@@ -94,9 +94,15 @@ function Sidebar({
{...props}
>
{
const handleKeyDown = (event: KeyboardEvent) => {
- if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
- event.preventDefault();
- toggleSidebar();
+ if (event.key !== SIDEBAR_KEYBOARD_SHORTCUT || !(event.metaKey || event.ctrlKey)) {
+ return;
}
+
+ const target = event.target as HTMLElement | null;
+
+ if (target) {
+ const tag = target.tagName;
+
+ if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || target.isContentEditable) {
+ return;
+ }
+ }
+
+ event.preventDefault();
+ toggleSidebar();
};
window.addEventListener('keydown', handleKeyDown);
diff --git a/frontend/src/pages/settings/settings-api-tokens.tsx b/frontend/src/pages/settings/settings-api-tokens.tsx
index 30dacc84..2f9a7bbc 100644
--- a/frontend/src/pages/settings/settings-api-tokens.tsx
+++ b/frontend/src/pages/settings/settings-api-tokens.tsx
@@ -646,7 +646,11 @@ function SettingsAPITokens() {
variant="outline"
>
- {field.value ? field.value.toLocaleDateString() : Pick date}
+ {field.value ? (
+ format(field.value, 'd MMM yyyy', { locale: enUS })
+ ) : (
+ Pick date
+ )}
[
{
accessorKey: 'name',
- cell: ({ row }) => {row.getValue('name')}
,
+ cell: ({ row }) => {row.getValue('name')}
,
enableHiding: false,
header: ({ column }) => (
),
+ // Name flexes to fill remaining width — fixed `size` would push
+ // the Type column off-screen on narrow viewports (e.g. 375px).
meta: { searchable: true },
- size: 400,
},
{
accessorKey: 'type',
cell: ({ row }) => {
const providerType = row.getValue('type') as ProviderType;
const Icon = providerIcons[providerType];
+ const label = providerTypes.find((p) => p.type === providerType)?.label || providerType;
return (
-
- {Icon && }
- {providerTypes.find((p) => p.type === providerType)?.label || providerType}
+
+ {Icon && }
+ {label}
);
},
@@ -166,6 +171,7 @@ function SettingsProviders() {
/>
),
meta: { searchable: true },
+ minSize: 110,
size: 160,
},
{
diff --git a/frontend/src/pages/templates/template.tsx b/frontend/src/pages/templates/template.tsx
index ee13fecf..4b35139c 100644
--- a/frontend/src/pages/templates/template.tsx
+++ b/frontend/src/pages/templates/template.tsx
@@ -746,6 +746,7 @@ function Template() {
/>
- {isSaving ? : }
+ {isSaving ? (
+
+ ) : (
+
+ )}
diff --git a/frontend/src/providers/flow-provider.tsx b/frontend/src/providers/flow-provider.tsx
index e1e2b27f..45898aef 100644
--- a/frontend/src/providers/flow-provider.tsx
+++ b/frontend/src/providers/flow-provider.tsx
@@ -177,12 +177,18 @@ export function FlowProvider({ children }: FlowProviderProps) {
const flowStatus = useMemo(() => flowData?.flow?.status, [flowData?.flow?.status]);
- // Show toast notification when flow loading error occurs
+ // Show toast notification when flow loading error occurs.
+ // A single Postgres "no rows in result set" surfaces here every time a sibling
+ // query/subscription retries against an invalid flow id; without a stable
+ // toast id Sonner would stack 8 copies of the same message before the page
+ // redirects. Surface a friendly message and drop the raw SQL detail entirely.
useEffect(() => {
if (flowError) {
- const description = flowError.message || 'An error occurred while loading flow';
- toast.error('Failed to load flow', {
- description,
+ const raw = flowError.message ?? '';
+ const isNotFound = /no rows in result set|not found/i.test(raw);
+ toast.error(isNotFound ? 'Flow not found' : 'Failed to load flow', {
+ description: isNotFound ? undefined : raw || undefined,
+ id: 'flow-load-error',
});
Log.error('Error loading flow:', flowError);
}