Skip to content

Commit 8e230cd

Browse files
Update connection select UI (#1740)
<!-- Ensure the title clearly reflects what was changed. Provide a clear and concise description of the changes made. The PR should only contain the changes related to the issue, and no other unrelated changes. --> Fixes OPS-3164. <img width="815" height="270" alt="image" src="https://github.com/user-attachments/assets/480b6977-28d7-4e82-8d21-d131d72d7b65" /> <img width="446" height="99" alt="image" src="https://github.com/user-attachments/assets/73695f57-92e4-4854-b139-a18cf4f44715" /> <img width="454" height="104" alt="image" src="https://github.com/user-attachments/assets/024e9ed2-4c6a-44f9-95a3-fdd130f4893d" /> <img width="447" height="111" alt="image" src="https://github.com/user-attachments/assets/72a5cb02-8e77-459c-b7da-572b49ec6198" /> It's on UX <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Edit and Clear action buttons to the connection selector interface for improved management and flexibility when working with connections. * **UI & Style Improvements** * Enhanced the connection selector layout with better visual presentation and refined icon styling for trigger controls. * Updated the connection creation action label text to "Create new connection" for improved clarity and consistency. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 220ad69 commit 8e230cd

File tree

2 files changed

+87
-36
lines changed

2 files changed

+87
-36
lines changed

packages/react-ui/src/app/features/builder/step-settings/block-settings/connection-select.tsx

Lines changed: 82 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import {
1818
removeConnectionBrackets,
1919
} from '@openops/shared';
2020
import { t } from 'i18next';
21-
import { Plus } from 'lucide-react';
21+
import { PencilLine, Plus, X } from 'lucide-react';
22+
import type React from 'react';
2223
import { memo, useCallback, useState } from 'react';
2324
import { ControllerRenderProps, useFormContext } from 'react-hook-form';
2425

@@ -38,6 +39,7 @@ type ConnectionSelectProps = {
3839
allowDynamicValues: boolean;
3940
providerKey: string;
4041
name: string;
42+
displayName?: string;
4143
};
4244

4345
const ConnectionSelect = memo((params: ConnectionSelectProps) => {
@@ -68,9 +70,9 @@ const ConnectionSelect = memo((params: ConnectionSelectProps) => {
6870
);
6971

7072
const handleReconnectClick = useCallback(
71-
(e: React.MouseEvent<HTMLButtonElement>) => {
72-
e.preventDefault();
73-
e.stopPropagation();
73+
(e?: React.SyntheticEvent<HTMLElement>) => {
74+
e?.preventDefault?.();
75+
e?.stopPropagation?.();
7476
const currentValue = form.getValues(params.name);
7577
const connectionName = removeConnectionBrackets(currentValue ?? '');
7678

@@ -85,6 +87,26 @@ const ConnectionSelect = memo((params: ConnectionSelectProps) => {
8587
[connectionsPage?.data, form, params.name],
8688
);
8789

90+
const suppressPointerOrMouseDown = useCallback(
91+
(e: React.PointerEvent<HTMLElement> | React.MouseEvent<HTMLElement>) => {
92+
e.stopPropagation();
93+
e.preventDefault();
94+
},
95+
[],
96+
);
97+
98+
const makeActivationKeysHandler = (
99+
action: (e: React.KeyboardEvent<HTMLElement>) => void,
100+
) => {
101+
return (e: React.KeyboardEvent<HTMLElement>) => {
102+
if (e.key === ' ' || e.key === 'Enter') {
103+
e.stopPropagation();
104+
e.preventDefault();
105+
action(e);
106+
}
107+
};
108+
};
109+
88110
return (
89111
<FormField
90112
control={form.control}
@@ -100,7 +122,11 @@ const ConnectionSelect = memo((params: ConnectionSelectProps) => {
100122
)}
101123
{!isLoading && (
102124
<AutoFormFieldWrapper
103-
property={params.block.auth!}
125+
property={{
126+
...params.block.auth!,
127+
displayName:
128+
params.displayName ?? params.block.auth?.displayName ?? '',
129+
}}
104130
propertyName="auth"
105131
field={field as unknown as ControllerRenderProps}
106132
disabled={params.disabled}
@@ -138,45 +164,68 @@ const ConnectionSelect = memo((params: ConnectionSelectProps) => {
138164
}}
139165
disabled={params.disabled}
140166
>
141-
<div className="relative">
142-
{field.value && !field.disabled && (
143-
<Button
144-
type="button"
145-
variant="ghost"
146-
size="xs"
147-
className="z-50 absolute right-8 top-2 "
148-
onClick={handleReconnectClick}
149-
>
150-
{t('Reconnect')}
151-
</Button>
152-
)}
153-
154-
<SelectTrigger className="flex gap-2 items-center">
167+
<SelectTrigger
168+
className="h-14 flex items-center gap-2"
169+
iconClassName="size-5"
170+
>
171+
<div className="flex-1 min-w-0 overflow-hidden">
155172
<SelectValue
156-
className="truncate flex-grow flex-shrink"
157-
placeholder={t('Select a connection')}
173+
placeholder={
174+
<span className="text-start block">
175+
{t('Select a connection')}
176+
</span>
177+
}
158178
>
159179
{!!field.value && (
160-
<div className="truncate flex-grow flex-shrink">
180+
<span className="text-start block truncate text-primary-700 text-base font-medium">
161181
{removeConnectionBrackets(field.value)}
162-
</div>
182+
</span>
163183
)}
164184
</SelectValue>
165-
<div className="grow"></div>
166-
{/* Hidden Button to take same space as shown button */}
167-
{field.value && (
185+
</div>
186+
187+
{field.value && !field.disabled && !params.disabled && (
188+
<div className="shrink-0 flex items-center gap-1">
189+
{selectConnectionOpen && (
190+
<Button
191+
type="button"
192+
variant="ghost"
193+
size="xs"
194+
className="text-primary-700 text-base font-medium"
195+
onPointerDown={suppressPointerOrMouseDown}
196+
onMouseDown={suppressPointerOrMouseDown}
197+
onKeyDown={makeActivationKeysHandler((e) =>
198+
handleReconnectClick(e),
199+
)}
200+
onClick={(e) => {
201+
handleReconnectClick(e);
202+
}}
203+
>
204+
<PencilLine size={16} />
205+
{t('Edit')}
206+
</Button>
207+
)}
208+
168209
<Button
169210
type="button"
170211
variant="ghost"
171212
size="xs"
172-
className="z-50 opacity-0 pointer-events-none"
213+
className="text-primary-700 text-base font-medium"
214+
onPointerDown={suppressPointerOrMouseDown}
215+
onMouseDown={suppressPointerOrMouseDown}
216+
onKeyDown={makeActivationKeysHandler(() => {
217+
field.onChange('');
218+
})}
219+
onClick={() => {
220+
field.onChange('');
221+
}}
173222
>
174-
{t('Reconnect')}
223+
<X size={16} />
224+
{t('Clear')}
175225
</Button>
176-
)}
177-
</SelectTrigger>
178-
</div>
179-
226+
</div>
227+
)}
228+
</SelectTrigger>
180229
<SelectContent>
181230
<SelectAction
182231
onClick={() => {
@@ -187,7 +236,7 @@ const ConnectionSelect = memo((params: ConnectionSelectProps) => {
187236
>
188237
<span className="flex items-center gap-1 text-primary w-full">
189238
<Plus size={16} />
190-
{t('Create Connection')}
239+
{t('Create new connection')}
191240
</span>
192241
</SelectAction>
193242

packages/ui-components/src/ui/select.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ const SelectValue = SelectPrimitive.Value;
2121

2222
const SelectTrigger = React.forwardRef<
2323
React.ElementRef<typeof SelectPrimitive.Trigger>,
24-
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
25-
>(({ className, children, ...props }, ref) => (
24+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> & {
25+
iconClassName?: string;
26+
}
27+
>(({ className, iconClassName, children, ...props }, ref) => (
2628
<SelectPrimitive.Trigger
2729
ref={ref}
2830
className={cn(
@@ -33,7 +35,7 @@ const SelectTrigger = React.forwardRef<
3335
>
3436
{children}
3537
<SelectPrimitive.Icon asChild>
36-
<CaretSortIcon className="size-4 opacity-50" />
38+
<CaretSortIcon className={cn('size-4 opacity-50', iconClassName)} />
3739
</SelectPrimitive.Icon>
3840
</SelectPrimitive.Trigger>
3941
));

0 commit comments

Comments
 (0)