refactor: Enhance InputList Component UI/UX (#5726)
* [LFOSS-74]: input list UI improvements * ✨ (frontend): Add new component 'DeleteButtonInputList' to improve user experience by providing a button to delete items in a list 📝 (frontend): Comment out unused code related to duplicating input items for now, to be revisited in a future release 📝 (frontend): Add a comment to indicate that the 'DropdownMenuInputList' feature will be added back in a future release 📝 (frontend): Update CSS styling for 'hit-area-icon' class to adjust size to h-7 and w-7 for consistency 📝 (frontend): Adjust color values in CSS to improve visual appearance, changing smooth-red to a new shade * ✨ (keypairListComponent/index.tsx): simplify conditional styling logic for list items to improve readability and maintainability * 📝 (delete-button-input-list.tsx): Remove unused imports and update function parameter type for removeInput to specify React.MouseEvent 📝 (delete-button-input-list.tsx): Update button className and IconComponent className for better styling and readability 📝 (delete-button-input-list.tsx): Update ICON_STROKE_WIDTH constant value from 1.25 to 1.5 for better icon appearance 📝 (index.tsx): Update InputListComponent to render DeleteButtonInputList component conditionally based on value length 📝 (constants.ts): Update ICON_STROKE_WIDTH constant value from 1.25 to 1.5 for better icon appearance 📝 (inputListComponent.spec.ts): Update test cases to use updated test IDs for delete buttons and adjust expected input values to match changes in component behavior * [autofix.ci] apply automated fixes * 🔧 (applies.css): adjust positioning of input-slider-text to fix alignment issue and improve user experience * 🐛 (button-input-list.tsx): fix button position by adjusting translate-x value to align properly on the page * ✨ (index.tsx): add visual indicator for focused input element in the list to improve user experience --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
This commit is contained in:
parent
317c743906
commit
5c3c680c41
9 changed files with 116 additions and 80 deletions
|
|
@ -0,0 +1,45 @@
|
|||
import IconComponent from "@/components/common/genericIconComponent";
|
||||
import { ICON_STROKE_WIDTH } from "@/constants/constants";
|
||||
import { cn } from "@/utils/utils";
|
||||
import { getTestId } from "../helpers/get-test-id";
|
||||
|
||||
export const DeleteButtonInputList = ({
|
||||
index,
|
||||
removeInput,
|
||||
disabled,
|
||||
editNode,
|
||||
componentName,
|
||||
}: {
|
||||
index: number;
|
||||
removeInput: (e: React.MouseEvent) => void;
|
||||
disabled: boolean;
|
||||
editNode: boolean;
|
||||
componentName: string;
|
||||
}) => {
|
||||
return (
|
||||
<button
|
||||
disabled={disabled}
|
||||
onClick={removeInput}
|
||||
data-testid={getTestId("delete", index, editNode, componentName)}
|
||||
className={cn(
|
||||
"hit-area-icon delete-btn-group flex items-center justify-center",
|
||||
disabled
|
||||
? "pointer-events-none bg-background hover:bg-background"
|
||||
: "bg-background hover:bg-smooth-red hover:text-destructive",
|
||||
editNode && "h-4 w-4",
|
||||
)}
|
||||
>
|
||||
<IconComponent
|
||||
name="X"
|
||||
className={cn(
|
||||
"icon-size justify-self-center text-muted-foreground",
|
||||
!disabled &&
|
||||
"hover:cursor-pointer [.delete-btn-group:hover_&]:text-destructive",
|
||||
)}
|
||||
strokeWidth={ICON_STROKE_WIDTH}
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteButtonInputList;
|
||||
|
|
@ -10,6 +10,7 @@ import { GRADIENT_CLASS } from "@/constants/constants";
|
|||
import { cn } from "../../../../../utils/utils";
|
||||
import { getPlaceholder } from "../../helpers/get-placeholder-disabled";
|
||||
import { InputListComponentType, InputProps } from "../../types";
|
||||
import { DeleteButtonInputList } from "./components/delete-button-input-list";
|
||||
|
||||
export default function InputListComponent({
|
||||
value = [""],
|
||||
|
|
@ -66,16 +67,16 @@ export default function InputListComponent({
|
|||
[value, handleOnNewValue],
|
||||
);
|
||||
|
||||
const handleDuplicateInput = useCallback(
|
||||
(index: number, e: React.MouseEvent | KeyboardEvent) => {
|
||||
e.preventDefault();
|
||||
const newInputList = _.cloneDeep(value);
|
||||
newInputList.splice(index, 0, newInputList[index]);
|
||||
handleOnNewValue({ value: newInputList });
|
||||
setDropdownOpen(null);
|
||||
},
|
||||
[value, handleOnNewValue],
|
||||
);
|
||||
// const handleDuplicateInput = useCallback(
|
||||
// (index: number, e: React.MouseEvent | KeyboardEvent) => {
|
||||
// e.preventDefault();
|
||||
// const newInputList = _.cloneDeep(value);
|
||||
// newInputList.splice(index, 0, newInputList[index]);
|
||||
// handleOnNewValue({ value: newInputList });
|
||||
// setDropdownOpen(null);
|
||||
// },
|
||||
// [value, handleOnNewValue],
|
||||
// );
|
||||
|
||||
return (
|
||||
<div className={cn("w-full", editNode && "max-h-52")}>
|
||||
|
|
@ -92,16 +93,29 @@ export default function InputListComponent({
|
|||
|
||||
<div className="mt-2 flex w-full flex-col gap-3">
|
||||
{value.map((singleValue, index) => (
|
||||
<div key={index} className="relative flex w-full items-center gap-2">
|
||||
<div className="group flex flex-1 items-center rounded-md bg-background">
|
||||
<div key={index} className="flex w-full items-center">
|
||||
{focusedIndex !== index && !disabled && (
|
||||
<div
|
||||
className={cn(
|
||||
"absolute z-50 h-6 w-16",
|
||||
editNode ? "translate-x-[12rem]" : "translate-x-[11.1rem]",
|
||||
)}
|
||||
style={{
|
||||
pointerEvents: "none",
|
||||
background: GRADIENT_CLASS,
|
||||
}}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
<div className="group relative flex-1">
|
||||
<Input
|
||||
ref={index === 0 ? inputRef : null}
|
||||
disabled={disabled}
|
||||
type="text"
|
||||
value={singleValue}
|
||||
className={cn(
|
||||
"w-full text-primary",
|
||||
editNode ? "input-edit-node pr-6" : "pr-10",
|
||||
"w-full pr-10 text-primary",
|
||||
editNode ? "input-edit-node" : "",
|
||||
disabled ? "disabled-state" : "",
|
||||
)}
|
||||
placeholder={getPlaceholder(disabled, placeholder)}
|
||||
|
|
@ -113,20 +127,20 @@ export default function InputListComponent({
|
|||
onBlur={() => setFocusedIndex(null)}
|
||||
/>
|
||||
|
||||
{focusedIndex !== index && !disabled && (
|
||||
<div
|
||||
className={cn(
|
||||
"absolute h-6 w-16",
|
||||
editNode ? "translate-x-[11rem]" : "translate-x-[11.1rem]",
|
||||
)}
|
||||
style={{
|
||||
pointerEvents: "none",
|
||||
background: GRADIENT_CLASS,
|
||||
}}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{value.length > 1 && (
|
||||
<div className="absolute right-2 top-1/2 -translate-y-1/2">
|
||||
<DeleteButtonInputList
|
||||
index={index}
|
||||
removeInput={(e) => removeInput(index, e)}
|
||||
disabled={disabled}
|
||||
editNode={editNode}
|
||||
componentName={componentName || ""}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/*
|
||||
We will add this back in a future release
|
||||
{!disabled && (
|
||||
<DropdownMenuInputList
|
||||
index={index}
|
||||
|
|
@ -137,7 +151,7 @@ export default function InputListComponent({
|
|||
removeInput={removeInput}
|
||||
canDelete={value.length > 1}
|
||||
/>
|
||||
)}
|
||||
)} */}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -998,7 +998,7 @@ export const GRADIENT_CLASS =
|
|||
|
||||
export const RECEIVING_INPUT_VALUE = "Receiving input";
|
||||
|
||||
export const ICON_STROKE_WIDTH = 1.25;
|
||||
export const ICON_STROKE_WIDTH = 1.5;
|
||||
|
||||
export const DEFAULT_PLACEHOLDER = "Type something...";
|
||||
|
||||
|
|
|
|||
|
|
@ -1254,7 +1254,7 @@
|
|||
}
|
||||
|
||||
.hit-area-icon {
|
||||
@apply h-8 w-8 rounded-md;
|
||||
@apply h-7 w-7 rounded-md;
|
||||
}
|
||||
|
||||
.node-toolbar-buttons {
|
||||
|
|
@ -1274,7 +1274,7 @@
|
|||
}
|
||||
|
||||
.input-slider-text {
|
||||
@apply absolute bottom-[4.2rem] right-3 w-14 cursor-text rounded-sm px-2 py-[1px] text-center hover:ring-[1px] hover:ring-slider-input-border;
|
||||
@apply absolute right-3 w-14 -translate-y-3.5 cursor-text rounded-sm px-2 py-[1px] text-center hover:ring-[1px] hover:ring-slider-input-border;
|
||||
}
|
||||
|
||||
.btn-add-input-list {
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@
|
|||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
--placeholder: 240 5% 64.9%;
|
||||
--hard-zinc: 240 5.2% 33.9%;
|
||||
--smooth-red: 0 93.3% 94.1%;
|
||||
--smooth-red: 0 74.7% 15.5%;
|
||||
|
||||
--datatype-pink: 327.4 87.1% 81.8%;
|
||||
--datatype-pink-foreground: 333.3 71.4% 50.6%;
|
||||
|
|
|
|||
|
|
@ -54,20 +54,16 @@ test(
|
|||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
await page.getByTestId("input-list-dropdown-menu-0-edit").click();
|
||||
|
||||
await page.getByTestId("input-list-dropdown-menu-0-delete").click();
|
||||
await page.getByTestId("input-list-delete-btn-edit_urls-0").click();
|
||||
|
||||
expect(
|
||||
await page.getByTestId("input-list-dropdown-menu-2-edit").count(),
|
||||
await page.getByTestId("input-list-delete-btn-edit_urls-2").count(),
|
||||
).toBe(0);
|
||||
|
||||
await page.getByTestId("input-list-dropdown-menu-1-edit").click();
|
||||
|
||||
await page.getByTestId("input-list-dropdown-menu-1-delete").click();
|
||||
await page.getByTestId("input-list-delete-btn-edit_urls-1").click();
|
||||
|
||||
expect(
|
||||
await page.getByTestId("input-list-dropdown-menu-1-edit").count(),
|
||||
await page.getByTestId("input-list-delete-btn-edit_urls-1").count(),
|
||||
).toBe(0);
|
||||
|
||||
await page.getByText("Close").last().click();
|
||||
|
|
@ -76,35 +72,32 @@ test(
|
|||
await page.getByTestId("input-list-plus-btn_urls-0").click();
|
||||
await page.getByTestId("input-list-plus-btn_urls-0").click();
|
||||
|
||||
expect(
|
||||
await page.getByTestId("input-list-dropdown-menu-0-view").count(),
|
||||
).toBe(1);
|
||||
expect(await page.getByTestId("input-list-delete-btn_urls-0").count()).toBe(
|
||||
1,
|
||||
);
|
||||
|
||||
expect(
|
||||
await page.getByTestId("input-list-dropdown-menu-1-view").count(),
|
||||
).toBe(1);
|
||||
expect(await page.getByTestId("input-list-delete-btn_urls-1").count()).toBe(
|
||||
1,
|
||||
);
|
||||
|
||||
expect(
|
||||
await page.getByTestId("input-list-dropdown-menu-2-view").count(),
|
||||
).toBe(1);
|
||||
expect(await page.getByTestId("input-list-delete-btn_urls-2").count()).toBe(
|
||||
1,
|
||||
);
|
||||
|
||||
expect(
|
||||
await page.getByTestId("input-list-dropdown-menu-3-view").count(),
|
||||
).toBe(1);
|
||||
expect(await page.getByTestId("input-list-delete-btn_urls-3").count()).toBe(
|
||||
1,
|
||||
);
|
||||
|
||||
expect(
|
||||
await page.getByTestId("input-list-dropdown-menu-4-view").count(),
|
||||
).toBe(0);
|
||||
|
||||
await page.getByTestId("input-list-dropdown-menu-0-view").click();
|
||||
await page.getByTestId("input-list-dropdown-menu-0-duplicate").click();
|
||||
expect(await page.getByTestId("input-list-delete-btn_urls-4").count()).toBe(
|
||||
0,
|
||||
);
|
||||
|
||||
expect(await page.getByTestId("inputlist_str_urls_0").inputValue()).toBe(
|
||||
"test1 test1 test1 test1",
|
||||
);
|
||||
|
||||
expect(await page.getByTestId("inputlist_str_urls_1").inputValue()).toBe(
|
||||
"test1 test1 test1 test1",
|
||||
"",
|
||||
);
|
||||
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
|
@ -115,22 +108,6 @@ test(
|
|||
|
||||
expect(
|
||||
await page.getByTestId("inputlist_str_edit_urls_1").inputValue(),
|
||||
).toBe("test1 test1 test1 test1");
|
||||
|
||||
await page.getByTestId("input-list-dropdown-menu-1-edit").click();
|
||||
|
||||
await page.getByTestId("input-list-dropdown-menu-1-duplicate").click();
|
||||
|
||||
expect(
|
||||
await page.getByTestId("inputlist_str_edit_urls_0").inputValue(),
|
||||
).toBe("test1 test1 test1 test1");
|
||||
|
||||
expect(
|
||||
await page.getByTestId("inputlist_str_edit_urls_1").inputValue(),
|
||||
).toBe("test1 test1 test1 test1");
|
||||
|
||||
expect(
|
||||
await page.getByTestId("inputlist_str_edit_urls_2").inputValue(),
|
||||
).toBe("test1 test1 test1 test1");
|
||||
).toBe("");
|
||||
},
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue