Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Selection Field Component #267

Merged
merged 9 commits into from
Mar 9, 2024
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions frontend/components/input/SelectionField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { useState } from "react";
import { Check, ChevronDown } from "react-feather";

import { Text } from "@/components/Text";
import { Icon, IconName } from "@/components/graphics/Icon";

export type SelectionListItem = {
title: string;
description: string;
isSelected: boolean;
icon: IconName;
};

interface SelectionFieldProps {
/**
* Title
*/
title: string;
/**
* Selection list
*/
list: SelectionListItem[];
/**
* Additional classes
*/
className?: string;
}

/**
* UI component for displaying a SelectionField
*/
export const SelectionField = ({
title,
list,
className = "",
...props
}: SelectionFieldProps) => {
const [visible, setVisible] = useState(false);
const [selected, setSelected] = useState<SelectionListItem>(
getListSelected(list)
);
return (
<div>
Julian702 marked this conversation as resolved.
Show resolved Hide resolved
<Text className="mb-1 text-sm font-semibold text-neutral-400">
{title}
</Text>
<div
className="flex hover:cursor-pointer"
Julian702 marked this conversation as resolved.
Show resolved Hide resolved
role="button"
onKeyDown={() => {}}
Julian702 marked this conversation as resolved.
Show resolved Hide resolved
onClick={() => setVisible(!visible)}
>
<div className="w-8 align-middle">
Julian702 marked this conversation as resolved.
Show resolved Hide resolved
{selected.icon && <Icon icon={selected.icon}></Icon>}
</div>
<Text className="w-16 truncate">{selected.title}</Text>
<ChevronDown
className={`m-0 mx-2 w-8 align-middle transition ${
Julian702 marked this conversation as resolved.
Show resolved Hide resolved
Julian702 marked this conversation as resolved.
Show resolved Hide resolved
visible ? "rotate-180 " : ""
}`}
Julian702 marked this conversation as resolved.
Show resolved Hide resolved
color="gray"
Julian702 marked this conversation as resolved.
Show resolved Hide resolved
></ChevronDown>
</div>

{visible && (
<div className="absolute z-10 m-2 h-fit w-fit max-w-sm items-start space-y-2 rounded-2xl bg-black px-3 pb-3 text-sm text-white before:relative before:-top-2 before:left-[5.64rem] before:block before:h-5 before:w-5 before:rotate-45 before:bg-black">
{list?.map((selectionItem) => (
<div
key={selectionItem.title}
className={`flex hover:cursor-pointer ${
!selectionItem.isSelected
? "text-neutral-400 hover:text-neutral-300"
: ""
}`}
Julian702 marked this conversation as resolved.
Show resolved Hide resolved
role="button"
onKeyDown={() => {}}
Julian702 marked this conversation as resolved.
Show resolved Hide resolved
onClick={() => {
setSelected(selectionItem);
setVisible(false);
setListSelected(list, selectionItem);
}}
>
<Icon
className="w-10 pr-3"
icon={selectionItem.icon}
></Icon>
Julian702 marked this conversation as resolved.
Show resolved Hide resolved
<div>
<Text className="font-bold">
{selectionItem.title}
</Text>
<div className="flex">
Julian702 marked this conversation as resolved.
Show resolved Hide resolved
<Text className="w-56 font-light">
{selectionItem.description}
</Text>

<Check
className={` w-8 ${
selectionItem.isSelected
? "visible justify-end"
: "invisible"
}`}
Julian702 marked this conversation as resolved.
Show resolved Hide resolved
></Check>
</div>
</div>
</div>
))}
</div>
)}
</div>
);
};

function getListSelected(list: SelectionListItem[]) {
for (const listitem of list) {
if (listitem.isSelected) return listitem;
}
const other: SelectionListItem = {
title: "Select",
description: "",
isSelected: true,
icon: "Search",
};
return other;
}
function setListSelected(list: SelectionListItem[], item: SelectionListItem) {
for (const listitem of list) {
listitem.isSelected = false;
if (listitem === item) listitem.isSelected = true;
}
}
Loading