diff --git a/frontend/components/forms/fields/DropdownWrapper/DropdownWrapper.tsx b/frontend/components/forms/fields/DropdownWrapper/DropdownWrapper.tsx index 51c5c3cd69..789d17679c 100644 --- a/frontend/components/forms/fields/DropdownWrapper/DropdownWrapper.tsx +++ b/frontend/components/forms/fields/DropdownWrapper/DropdownWrapper.tsx @@ -54,7 +54,8 @@ export interface IDropdownWrapper { isSearchable?: boolean; isDisabled?: boolean; placeholder?: string; - menuPortalTarget?: HTMLElement | null; + /** E.g. scroll to view dropdown menu in a scrollable parent container */ + onMenuOpen?: () => void; } const baseClass = "dropdown-wrapper"; @@ -72,7 +73,7 @@ const DropdownWrapper = ({ isSearchable, isDisabled = false, placeholder, - menuPortalTarget, + onMenuOpen, }: IDropdownWrapper) => { const wrapperClassNames = classnames(baseClass, className); @@ -326,12 +327,10 @@ const DropdownWrapper = ({ value={getCurrentValue()} onChange={handleChange} isDisabled={isDisabled} - menuPortalTarget={ - menuPortalTarget === undefined ? document.body : menuPortalTarget - } noOptionsMessage={() => "No results found"} tabIndex={isDisabled ? -1 : 0} // Ensures disabled dropdown has no keyboard accessibility placeholder={placeholder} + onMenuOpen={onMenuOpen} /> ); diff --git a/frontend/pages/admin/UserManagementPage/components/SelectRoleForm/SelectRoleForm.tsx b/frontend/pages/admin/UserManagementPage/components/SelectRoleForm/SelectRoleForm.tsx index 26c6e37f27..0ab3012f9f 100644 --- a/frontend/pages/admin/UserManagementPage/components/SelectRoleForm/SelectRoleForm.tsx +++ b/frontend/pages/admin/UserManagementPage/components/SelectRoleForm/SelectRoleForm.tsx @@ -13,6 +13,7 @@ interface ISelectRoleFormProps { teams: ITeam[]; onFormChange: (teams: ITeam[]) => void; isApiOnly?: boolean; + onMenuOpen?: () => void; } const generateSelectedTeamData = ( @@ -33,6 +34,7 @@ const SelectRoleForm = ({ teams, onFormChange, isApiOnly, + onMenuOpen, }: ISelectRoleFormProps): JSX.Element => { const { isPremiumTier } = useContext(AppContext); @@ -60,6 +62,7 @@ const SelectRoleForm = ({ value={selectedRole} onChange={updateSelectedRole} isSearchable={false} + onMenuOpen={onMenuOpen} /> ); }; diff --git a/frontend/pages/admin/UserManagementPage/components/SelectedTeamsForm/SelectedTeamsForm.tsx b/frontend/pages/admin/UserManagementPage/components/SelectedTeamsForm/SelectedTeamsForm.tsx index 4f8635f995..9953515054 100644 --- a/frontend/pages/admin/UserManagementPage/components/SelectedTeamsForm/SelectedTeamsForm.tsx +++ b/frontend/pages/admin/UserManagementPage/components/SelectedTeamsForm/SelectedTeamsForm.tsx @@ -17,6 +17,7 @@ interface ISelectedTeamsFormProps { usersCurrentTeams: ITeam[]; onFormChange: (teams: ITeam[]) => void; isApiOnly?: boolean; + onMenuOpen?: () => void; } const baseClass = "selected-teams-form"; @@ -106,6 +107,7 @@ const SelectedTeamsForm = ({ usersCurrentTeams, onFormChange, isApiOnly, + onMenuOpen, }: ISelectedTeamsFormProps): JSX.Element => { const [teamsFormList, updateSelectedTeams] = useSelectedTeamState( availableTeams, @@ -137,6 +139,7 @@ const SelectedTeamsForm = ({ onChange={(newValue: SingleValue) => updateSelectedTeams(teamItem.id, newValue as CustomOptionType) } + onMenuOpen={onMenuOpen} /> ); diff --git a/frontend/pages/admin/UserManagementPage/components/UserForm/UserForm.tsx b/frontend/pages/admin/UserManagementPage/components/UserForm/UserForm.tsx index f599c585ec..4f7db7bfa9 100644 --- a/frontend/pages/admin/UserManagementPage/components/UserForm/UserForm.tsx +++ b/frontend/pages/admin/UserManagementPage/components/UserForm/UserForm.tsx @@ -166,6 +166,19 @@ const UserForm = ({ }; }; + // Used to show entire dropdown when a dropdown menu is open in scrollable component of a modal + // menuPortalTarget solution not used as scrolling is weird + const scrollToFitDropdownMenu = () => { + if (topDivRef?.current) { + setTimeout(() => { + if (topDivRef.current) { + topDivRef.current.scrollTop = + topDivRef.current.scrollHeight - topDivRef.current.clientHeight; + } + }, 50); // Delay needed for scrollHeight to update first + } + }; + const onCheckboxChange = (formField: string): ((evt: string) => void) => { return (evt: string) => { return onInputChange(formField)(evt); @@ -318,6 +331,7 @@ const UserForm = ({ } }} isSearchable={false} + onMenuOpen={scrollToFitDropdownMenu} /> ); @@ -366,6 +380,7 @@ const UserForm = ({ usersCurrentTeams={formData.teams} onFormChange={onSelectedTeamChange} isApiOnly={isApiOnly} + onMenuOpen={scrollToFitDropdownMenu} /> ) : ( @@ -375,6 +390,7 @@ const UserForm = ({ defaultTeamRole={defaultTeamRole || "Observer"} onFormChange={onTeamRoleChange} isApiOnly={isApiOnly} + onMenuOpen={scrollToFitDropdownMenu} /> ))} {!availableTeams.length && renderNoTeamsMessage()}