feat: add UI/UX improvements on InputListComponent (#5644)

* [LFOSS-74]: input list UI improvements

* [autofix.ci] apply automated fixes

* Refactor dropdown menu icon size class

* Refactor button input list component to improve code structure and remove unnecessary div element ensuring the plus icon has the same size as ... icon

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* revert changes to keep the plus icon bigger than ... but with right positioning

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: anovazzi1 <otavio2204@gmail.com>
This commit is contained in:
Cristhian Zanforlin Lousa 2025-01-13 13:11:59 -03:00 • committed by GitHub
commit 40925e89a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 95 additions and 85 deletions

View file

@ -1,4 +1,5 @@
import IconComponent from "@/components/common/genericIconComponent";
import ShadTooltip from "@/components/common/shadTooltipComponent";
import { Button } from "@/components/ui/button";
import { ICON_STROKE_WIDTH } from "@/constants/constants";
import { cn } from "@/utils/utils";
@ -11,45 +12,49 @@ export const ButtonInputList = ({
disabled,
editNode,
componentName,
listAddLabel,
}: {
index: number;
addNewInput: (e) => void;
disabled: boolean;
editNode: boolean;
componentName: string;
listAddLabel: string;
}) => {
return (
<>
<div
onClick={addNewInput}
className={cn(
"hit-area-icon group absolute flex -translate-y-8 translate-x-[15.5rem] items-center justify-center bg-background text-center hover:bg-muted",
disabled
? "pointer-events-none bg-background hover:bg-background"
: "",
)}
>
<Button
unstyled
size="icon"
<ShadTooltip content={listAddLabel} side="top" align="center">
<div
onClick={addNewInput}
className={cn(
"hit-area-icon flex items-center justify-center",
getButtonClassName(disabled),
"hit-area-icon group absolute flex -translate-y-8 translate-x-[15.36rem] items-center justify-center bg-background text-center hover:bg-muted",
disabled
? "pointer-events-none bg-background hover:bg-background"
: "",
)}
data-testid={getTestId("plus", index, editNode, componentName)}
disabled={disabled}
>
<IconComponent
name="Plus"
<Button
unstyled
size="icon"
className={cn(
"icon-size justify-self-center text-muted-foreground",
!disabled && "hover:cursor-pointer hover:text-foreground",
"group-hover:text-foreground",
"hit-area-icon flex items-center justify-center",
getButtonClassName(disabled),
)}
strokeWidth={ICON_STROKE_WIDTH}
/>
</Button>
</div>
data-testid={getTestId("plus", index, editNode, componentName)}
disabled={disabled}
>
<IconComponent
name="Plus"
className={cn(
"icon-size justify-self-center text-muted-foreground",
!disabled && "hover:cursor-pointer hover:text-foreground",
"group-hover:text-foreground",
)}
strokeWidth={ICON_STROKE_WIDTH}
/>
</Button>
</div>
</ShadTooltip>
</>
);
};

View file

@ -19,6 +19,7 @@ export const DropdownMenuInputList = ({
editNode,
handleDuplicateInput,
removeInput,
canDelete,
}: {
index: number;
dropdownOpen: number | null;
@ -32,6 +33,7 @@ export const DropdownMenuInputList = ({
index: number,
e: React.MouseEvent<HTMLDivElement> | KeyboardEvent,
) => void;
canDelete: boolean;
}) => {
const shortcuts = useShortcutsStore((state) => state.shortcuts);
@ -45,7 +47,7 @@ export const DropdownMenuInputList = ({
(shortcutName: string, event: KeyboardEvent) => {
if (shortcutName === "duplicate") {
handleDuplicateInput(index, event);
} else if (shortcutName === "delete") {
} else if (shortcutName === "delete" && canDelete) {
removeInput(index, event);
}
setDropdownOpen(-1);
@ -70,23 +72,26 @@ export const DropdownMenuInputList = ({
<DropdownMenuTrigger
asChild
tabIndex={index}
className="absolute translate-x-60 bg-background transition-opacity peer-focus:opacity-0"
className={cn(
"absolute bg-background transition-opacity peer-focus:opacity-0",
editNode ? "translate-x-[14rem]" : "translate-x-60",
)}
>
<Button
variant="ghost"
data-testid={`input-list-dropdown-menu-${index}-${editNode ? "edit" : "view"}`}
size={editNode ? "iconSm" : "iconMd"}
className={cn("group", editNode ? "ml-4" : "")}
className={cn("group")}
autoFocus={false}
>
<ForwardedIconComponent
name="Ellipsis"
aria-hidden="true"
className="h-5 w-5 text-muted-foreground group-hover:text-foreground"
className="icon-size text-muted-foreground group-hover:text-foreground"
/>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-[185px] translate-x-20" side="bottom">
<DropdownMenuContent className="w-[185px]" side="bottom" align="start">
<DropdownMenuItem
onClick={(e) => {
handleDuplicateInput(index, e);
@ -114,32 +119,34 @@ export const DropdownMenuInputList = ({
</span>
</div>
</DropdownMenuItem>
<DropdownMenuItem
onClick={(e) => {
removeInput(index, e);
e.stopPropagation();
}}
className="cursor-pointer text-destructive"
data-testid={`input-list-dropdown-menu-${index}-delete`}
>
<ForwardedIconComponent
name="Trash2"
aria-hidden="true"
className="mr-2 h-4 w-4"
/>
<span>Delete</span>
{canDelete && (
<DropdownMenuItem
onClick={(e) => {
removeInput(index, e);
e.stopPropagation();
}}
className="cursor-pointer text-destructive"
data-testid={`input-list-dropdown-menu-${index}-delete`}
>
<ForwardedIconComponent
name="Trash2"
aria-hidden="true"
className="mr-2 h-4 w-4"
/>
<span>Delete</span>
<div className="flex grow content-end justify-end self-center text-[12px]">
<span
className={`flex content-end items-center rounded-sm px-1.5 py-[0.1em] text-muted-foreground`}
>
<ForwardedIconComponent
name="Delete"
className="h-4 w-4 stroke-2 text-red-400"
/>
</span>
</div>
</DropdownMenuItem>
<div className="flex grow content-end justify-end self-center text-[12px]">
<span
className={`flex content-end items-center rounded-sm px-1.5 py-[0.1em] text-muted-foreground`}
>
<ForwardedIconComponent
name="Delete"
className="h-4 w-4 stroke-2 text-red-400"
/>
</span>
</div>
</DropdownMenuItem>
)}
</DropdownMenuContent>
</DropdownMenu>
</>

View file

@ -86,6 +86,7 @@ export default function InputListComponent({
disabled={disabled}
editNode={editNode}
componentName={componentName || ""}
listAddLabel={listAddLabel || "Add More"}
/>
)}
@ -99,11 +100,9 @@ export default function InputListComponent({
type="text"
value={singleValue}
className={cn(
"w-full text-primary",
editNode ? "input-edit-node pr-6" : "pr-10",
disabled ? "disabled-state" : "",
focusedIndex === index
? "text-primary"
: "text-muted-foreground",
)}
placeholder={getPlaceholder(disabled, placeholder)}
onChange={(event) =>
@ -118,7 +117,7 @@ export default function InputListComponent({
<div
className={cn(
"absolute h-6 w-16",
editNode ? "translate-x-[12rem]" : "translate-x-[11.1rem]",
editNode ? "translate-x-[11rem]" : "translate-x-[11.1rem]",
)}
style={{
pointerEvents: "none",
@ -136,23 +135,23 @@ export default function InputListComponent({
editNode={editNode}
handleDuplicateInput={handleDuplicateInput}
removeInput={removeInput}
canDelete={value.length > 1}
/>
)}
</div>
</div>
))}
{editNode && !disabled && (
<Button
unstyled
onClick={addNewInput}
className="btn-add-input-list"
data-testid={`input-list-add-more-${editNode ? "edit" : "view"}`}
>
<span className="mr-2 text-lg">+</span> {listAddLabel || "Add More"}
</Button>
)}
</div>
{!disabled && (
<Button
unstyled
onClick={addNewInput}
className="btn-add-input-list"
data-testid={`input-list-add-more-${editNode ? "edit" : "view"}`}
>
<span className="mr-2 text-lg">+</span> {listAddLabel ?? "Add More"}
</Button>
)}
</div>
);
}

View file

@ -1278,7 +1278,7 @@
}
.btn-add-input-list {
@apply mt-3 flex h-8 w-full items-center justify-center rounded-md p-2 text-sm hover:bg-muted;
@apply flex h-8 w-full items-center justify-center rounded-md p-2 text-sm hover:bg-muted;
}
}

View file

@ -72,9 +72,9 @@ test(
await page.getByText("Close").last().click();
await page.getByTestId("input-list-add-more-view").click();
await page.getByTestId("input-list-add-more-view").click();
await page.getByTestId("input-list-add-more-view").click();
await page.getByTestId("input-list-plus-btn_urls-0").click();
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(),