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

Framework - Explicit dropdown groups + smaller fixes #861

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

Anders2303
Copy link
Collaborator

@Anders2303 Anders2303 commented Feb 3, 2025

Fixes some issues in the Dropdown framework component:

  • Replaces the "group" field on dropdown options, and introduces a new DropdownOptionGroup type to make grouping more explicit
  • Allows you to select options on arrow-key press even if the dropdown is closed
  • Adds a max-size prop to the dropdown rectangle, so it doesnt get too wide
  • Adds truncation to the dropdown list and input field to adhere to the max-width
  • Fixed an issue in the textSize util
  • Made the dropdown list use proper html tags: <ul> and <li>
  • Fixed the vertical alignment of option adornments

* Made text truncate
* Made options use <ul> and <li> tags
* Set a max-width option to avoid that the rect gets too large
Copy link
Collaborator

@jorgenherje jorgenherje left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks very good! Just some minor comments from my side.

frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
Copy link
Collaborator

@rubenthoms rubenthoms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good 👍 Some comments below.

frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
frontend/src/lib/components/Dropdown/dropdown.tsx Outdated Show resolved Hide resolved
frontend/src/lib/components/Input/input.tsx Outdated Show resolved Hide resolved
Copy link
Collaborator

@jorgenherje jorgenherje left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! 👍

Copy link
Collaborator

@rubenthoms rubenthoms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes look really good 👍 A few comments

@@ -59,74 +59,101 @@ type DropdownRect = {

type OptionItem<TValue> = {
type: "option";
parentGroup?: string;
// refference to group. Used to get the icon and adding some styling
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo

} & DropdownOption<TValue>;

type SeperatorItem<TValue> = {
type: "separator";
type GroupTitle<TValue> = {
Copy link
Collaborator

@rubenthoms rubenthoms Feb 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be consistent, consider calling this GroupTitleItem, or OptionItem just Option.

Comment on lines 124 to 133
if (itemList[adjustedIndex].type !== "option") {
if (adjustedIndex === 0) return 1;

adjustedIndex += direction;
adjustedIndex = _.clamp(adjustedIndex, 0, itemList.length - 1);
}

if (itemList[adjustedIndex].type !== "option") {
throw new Error("Expected option item to follow non-option item!");
}
Copy link
Collaborator

@rubenthoms rubenthoms Feb 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fear this could become a pitfall as two groups following each other should preferably not cause a crash. Also, the early return in line 125 is dodging the whole check - what if there are two groups in a row at the start of the dropdown in a certain case of auto-generated options where the implementation on the consumer side is lacking functionality for filtering out empty groups? You could consider using the lodash findIndex method as it has an optional fromIndex parameter - thus, you would look for the next valid option from the current index. If -1 is returned, you can start a new search from 0. With direction === -1 you could traverse a reversed array and just adjust the index afterwards (or have a utility function doing the search and just adjust the arguments and return value accordingly).


const valueWithDefault = props.value ?? null;
const [prevValue, setPrevValue] = React.useState<TValue | null>(props.value ?? null);

const [filter, setFilter] = React.useState<string | null>(null);
const [prevFilter, setPrevFilter] = React.useState<string | null>(filter);

const allOptionsWithSeperators = React.useMemo(() => makeOptionListItems(props.options), [props.options]);
const allOptionsWithSeparators = React.useMemo(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider renaming this variable as you retired the separator naming scheme.

function handleOptionsChangeEffect() {
function handleMouseDown(event: MouseEvent) {
function setupInputBlurListener() {
// ! The ref is *actually* the div wrapping the input, so normal "blur" is not available
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an inputRef prop that is referencing the input element. You can add a ref to that to gain control over blur etc. However, I double-checked and there was something messed up with the references - I created a PR to fix the issues: #865

@@ -59,74 +59,101 @@ type DropdownRect = {

type OptionItem<TValue> = {
type: "option";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using an enum as a type here as it is easier to both change/maintain the code and to explicitly find all references.


return () => {
document.removeEventListener("mousedown", handleMouseDown);
return function removeInputBlurListener() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removeInputFocusOutListener?

@@ -182,36 +217,36 @@ export function Dropdown<TValue = string>(props: DropdownProps<TValue>) {
}, []);

React.useEffect(
function handleOptionsChangeEffect() {
function handleMouseDown(event: MouseEvent) {
function setupInputBlurListener() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...focusOut...?

Comment on lines +373 to +377
// Close the dropdown
if (dropdownVisible && e.key === "Escape") {
// FIXME: the ref is a div, so blur() isn't possible
// inputRef.current?.blur();
closePopover();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make Dropdown grouping more explicit
3 participants