Skip to content

Conversation

amnambiar
Copy link
Collaborator

Pull request template

Description

Details of this Dropdown component and its behaviour is as per this document

Task

Checklist

  • Commit messages broadly make sense and follow the Conventional Commits format.
  • PR targets master/develop
  • New tests are added for the changes (if not, mention it in the PR description). These may include:
    • Unit tests,
    • Integration tests,
    • Property-Based testing,
    • End-to-end tests.
  • The new version builds and passes all tests. If not, please mention it in the PR description.
  • Self review of the code has been done.
  • Reviewer has been requested.

@amnambiar amnambiar requested a review from KJES4 September 10, 2025 14:25
@amnambiar amnambiar marked this pull request as ready for review September 10, 2025 14:25
Copy link
Collaborator

@KJES4 KJES4 left a comment

Choose a reason for hiding this comment

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

I've left some comments requesting changes to a few files.

open,
onOpenChange: setOpen, // Floating UI will control open state
whileElementsMounted: autoUpdate, // auto reposition on resize/scroll
strategy: "fixed"
Copy link
Collaborator

Choose a reason for hiding this comment

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

This line of code is canceling out the position absolute styles you applied to the div that is also receiving the floatingStyles from the style prop. This strategy: "fixed" line of code can be removed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good catch! 'absolute' is unnecessary when using floating-ui.

But, I would like to decide if we want to proceed floating-ui before i correct these areas.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Couldn't find the popovers to be aligned properly without this style for floating. I'd suggest we retain the floating-ui in Dropdown for the moment, and rework on it (remove or handle the popup aligning manually) after the main components are ready. I will not use the floating-ui in the Selectbox

Copy link
Collaborator

Choose a reason for hiding this comment

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

If that is the case there is something incorrect with the styles in the file you are working on and we need to have a call to figure out what the issue is. There is no reason to keep this package when the problem stated for why it is needed can be solved by adding a single tailwind class name.


return (
<div className={cn(dropdownVariants({ size }))}>
<span ref={refs.setReference}>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since the div doesn't have any margin or padding and the button doesn't have a margin, you can remove the element and attach the ref to the root container div element.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

While using floating-ui, ref has to be attached to the element respective to which the floating popover should be placed. hence here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Comment resolved, floating-ui was removed.

}
};

const dropdownRef = useRef<HTMLDivElement>(null);
Copy link
Collaborator

Choose a reason for hiding this comment

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

dropdownRef isn't being assigned to any element so it isn't actually being used for anything.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That was a miss.

Should have been

return (
    <div className="relative" ref={dropdownRef}>
      <span ref={refs.setReference}>

But, that is unnecessary when using floating-ui as it itself handles close-on-click-outside, so we wouldn't need to attach a separate 'click' event listener to close the popup when clicked outside of target area.

Let me know what your ideas are on keeping the floating-ui package intact. And, i can do this correction.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Commit error. Supposed to be attached here-

return (
    <div className="relative" ref={dropdownRef}>
      <span ref={refs.setReference}>
        <Button

Copy link
Collaborator

Choose a reason for hiding this comment

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

Comment resolved, floating-ui was removed.

@@ -0,0 +1,196 @@
'use client';
import React, { useEffect, useRef, useState } from 'react';
import { useFloating, offset, flip, shift, autoUpdate, useDismiss, useInteractions } from "@floating-ui/react";
Copy link
Collaborator

Choose a reason for hiding this comment

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

On my local instance I removed all of the floatingUI code and I added the ref to the root parent div and all the functionality seems to be working as expected. Remind me again, what was the rational for add this third party library?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Consider the scenario of our Sort, Filter buttons above the Counterexample Trace table. They are aligned to the far left of the container. In that scenario, we need to determine dynamically how our dropdown list popup should be opened so that it is positioned correctly. When no particular styles applied, it will be placed like in below screengrab -
image

Even with just flex-direction: row-reverse for a container that holds the buttons, and position:absolute for the popover div, we still will need to dynamically determine within the DropdownComponent if there is enough viewport space for the dropdown contents to be visible, then set right:0 / left:0 respectively.
image

We would have to deal this entirely with our set of calculations, but with floating-ui it is handled in much cleaner/easier with minimal effort from our end.
floating-ui.webm

let me know if we do not want to seek support from any third-party packages big/small, and I can edit to handle this vanilla.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Keep all the style changes I told you to make, don't change anything else, but add right-0 to the popup div element that has the absolute position and let me know how that works for you. This worked for me.
image

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We shall discuss this in person.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Discussed - Use a position prop left/right for now and style with class accordingly.

} else {
setSelected([value]);
onChange?.(value);
setOpen(false);
Copy link
Collaborator

Choose a reason for hiding this comment

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

There could be a case where a user opens the select menu options, choses an option to see what it does and then wants to click on a different option. If the setOpen to false is here that would mean the user has to re-open the menu each time they want to select a new radio button option. I think the menu button close event should work the same regardless of the content shown inside of it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Agree, done 👍

if (!dropdownRef.current || dropdownRef.current.contains(event.target as Node)) {
return;
}
setOpen(false)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since you are trying to setState from inside of a useEffect hook this state is considered a reactive value. The problem with an empty dependency array is that you will end up with a state value for the open state. You could include 'open' in the dependency array but then this would cause the eventListener to be torn down and setup each time the value for open changes, which isn't ideal. You can update the code as follows that way you can ensure you aren't falsely calling the setOpen(false) statement.

const openRef = useRef(open);

  useEffect(() => {
    openRef.current = open;
  }, [open]);

  useEffect(() => {
    const listener = (event: MouseEvent) => {
        if (!openRef.current || dropdownRef.current?.contains(event.target as Node)) {
        return;
        }
        setOpen(false);
    };

    document.addEventListener("click", listener, true);
    return () => {
       document.removeEventListener("click", listener, true);
    };
  }, []); 

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will look into this after deciding upon whether or not to keep floating-ui.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

[] in useEffect, attaches a single global listener and is ideal for as long the useEffect does not reply on a stale state open (in this case which isn't)

The suggestion to check openRef.current if dropdown popover is currently open, is 💯 right, and thus added that in.

I'm commiting my change for this bit .

Copy link
Collaborator

Choose a reason for hiding this comment

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

There are two useEffects above, which one are you talking about in your first sentence?

Copy link
Collaborator Author

@amnambiar amnambiar Sep 26, 2025

Choose a reason for hiding this comment

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

The second one which binds listener to setOpen(false) when clicked anywhere outside the dropdown targets.

Note: floating-ui offers useDismiss to handle this scenario. Then we would not have to bind additional events to listen the same, given we are continuing with the package.

We shall discuss this as well in a call

Copy link
Collaborator

Choose a reason for hiding this comment

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

Comment resolved, floating-ui was removed.

options: Option[];
multi?: boolean;
radio?: boolean;
label: string;
Copy link
Collaborator

Choose a reason for hiding this comment

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

There are two label props defined in this component, let's made the code easier to read by identifying that the labels correspond to. You can call this label btnLabel and the one on the options interface itemLabel.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

btnLabel is updated. Retained label within options , as if it is changed to itemLabel would have to change value to itemValue for naming consistency. Hence,

open,
onOpenChange: setOpen, // Floating UI will control open state
whileElementsMounted: autoUpdate, // auto reposition on resize/scroll
strategy: "fixed"
Copy link
Collaborator

Choose a reason for hiding this comment

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

If that is the case there is something incorrect with the styles in the file you are working on and we need to have a call to figure out what the issue is. There is no reason to keep this package when the problem stated for why it is needed can be solved by adding a single tailwind class name.

@amnambiar
Copy link
Collaborator Author

@KJES4 ,

I've pulled your latest changes. But I've updated the way defaultChecked option was passed into the Dropdown component. Do have a look. And I suggest, removing the file DropdownMenu.tsx

"lint": "next lint"
},
"dependencies": {
"@floating-ui/react": "^0.27.16",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since floating-ui is no longer being used please make sure it is uninstalled and removed from the package.json file.

@KJES4
Copy link
Collaborator

KJES4 commented Oct 14, 2025

@KJES4 ,

I've pulled your latest changes. But I've updated the way defaultChecked option was passed into the Dropdown component. Do have a look. And I suggest, removing the file DropdownMenu.tsx

@amnambiar are you saying on your end there are two files Dropdown.tsx and DropdownMenu.tsx and that we should remove the latter one? If so that is fine. We can keep the shorter name and keep the first file.

<Checkbox label='Checkbox Label Small' size='small' defaultChecked={true} />
<Checkbox label='Checkbox Label Medium' size='medium'/>
<Checkbox label='Checkbox Label Disabled' disabled />

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you move the Dropdown components into the third column so they don't break the layout on this page and cause a scroll bar to appear?

const [settingsMenuValue, setSettingsMenuValue] = useState<string | null>(null);


const handleFilterChange = useCallback((val: string | string[] | null) => setFilterValues(val as string[]), [])
Copy link
Collaborator

Choose a reason for hiding this comment

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

What is the rational for using useCallback here?

suffixText?: string;
}

export interface DropdownProps {
Copy link
Collaborator

Choose a reason for hiding this comment

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

In the dropdownMenu component I added a size property. Can you take a look at how I implemented that and add that prop to this file? This will help allow the component to be more condensed when used inside of a table.

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.

2 participants