feat: Add fillOptions prop to dropdown (#6908)

* feat: Add fillOptions prop to dropdown
- this will make width of dropdown popup same as width the selector

* Use dropdown width for option if fillOptions true

* Use dropdown width for option if fillOptions true

* hotfix: use optionWidth when fillOptions is false

* Add 260px as default width of DropdownOptions

* fix types

* hotfix typescript issue

* fix horizontal scrollbar visible

* hotfix type issue
This commit is contained in:
Rishabh Rathod 2021-08-31 09:07:40 +05:30 committed by GitHub
parent 4938371566
commit 4a688fd11d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 9 deletions

View File

@ -37,6 +37,7 @@ export interface RenderDropdownOptionType {
isSelectedNode?: boolean;
extraProps?: any;
errorMsg?: string;
optionWidth: string;
}
type RenderOption = ({
@ -44,6 +45,7 @@ type RenderOption = ({
index,
option,
optionClickHandler,
optionWidth,
}: RenderDropdownOptionType) => ReactElement<any, any>;
export type DropdownProps = CommonComponentProps &
@ -67,6 +69,7 @@ export type DropdownProps = CommonComponentProps &
isLoading?: boolean;
errorMsg?: string; // If errorMsg is defined, we show dropDown's error state with the message.
helperText?: string;
fillOptions?: boolean;
};
export interface DefaultDropDownValueNodeProps {
selected: DropdownOption;
@ -74,6 +77,7 @@ export interface DefaultDropDownValueNodeProps {
isOpen?: boolean;
errorMsg?: string;
renderNode?: RenderOption;
optionWidth: string;
}
export interface RenderDropdownOptionType {
@ -192,6 +196,7 @@ const DropdownOptionsWrapper = styled.div<{
height: ${(props) => props.height};
max-height: ${(props) => props.maxHeight};
overflow-y: auto;
overflow-x: hidden;
`;
const OptionWrapper = styled.div<{
@ -339,6 +344,7 @@ const HelperText = styled.span`
function DefaultDropDownValueNode({
errorMsg,
optionWidth,
renderNode,
selected,
showLabelOnly,
@ -355,7 +361,12 @@ function DefaultDropDownValueNode({
return (
<SelectedDropDownHolder>
{renderNode ? (
renderNode({ isSelectedNode: true, option: selected, errorMsg })
renderNode({
isSelectedNode: true,
option: selected,
errorMsg,
optionWidth,
})
) : (
<>
{selected.icon ? (
@ -378,10 +389,11 @@ interface DropdownOptionsProps extends DropdownProps, DropdownSearchProps {
renderOption?: RenderOption;
headerLabel?: string;
selected: DropdownOption;
optionWidth: string;
}
export function RenderDropdownOptions(props: DropdownOptionsProps) {
const { onSearch, optionClickHandler, renderOption } = props;
const { onSearch, optionClickHandler, optionWidth, renderOption } = props;
const [options, setOptions] = useState<Array<DropdownOption>>(props.options);
const [searchValue, setSearchValue] = useState<string>("");
const onOptionSearch = (searchStr: string) => {
@ -398,10 +410,11 @@ export function RenderDropdownOptions(props: DropdownOptionsProps) {
setOptions(filteredOptions);
onSearch && onSearch(searchStr);
};
return options.length > 0 ? (
<DropdownWrapper
className="ads-dropdown-options-wrapper"
width={props.optionWidth || "260px"}
width={optionWidth}
>
{props.enableSearch && (
<SearchComponent
@ -422,6 +435,7 @@ export function RenderDropdownOptions(props: DropdownOptionsProps) {
option,
index,
optionClickHandler,
optionWidth,
});
}
return (
@ -512,16 +526,35 @@ export default function Dropdown(props: DropdownProps) {
}
};
const [dropdownWrapperWidth, setDropdownWrapperWidth] = useState<string>(
"100%",
);
const dropdownWrapperRef = useCallback(
(ref: HTMLDivElement) => {
if (ref) {
const { width } = ref.getBoundingClientRect();
setDropdownWrapperWidth(`${width}px`);
}
},
[setDropdownWrapperWidth],
);
const dropdownOptionWidth = props.fillOptions
? dropdownWrapperWidth
: props.optionWidth || "260px";
const dropdownTrigger = props.dropdownTriggerIcon ? (
<DropdownTriggerWrapper
disabled={props.disabled}
isOpen={isOpen}
onClick={onClickHandler}
ref={dropdownWrapperRef}
>
{props.dropdownTriggerIcon}
</DropdownTriggerWrapper>
) : (
<DropdownSelect>
<DropdownSelect ref={dropdownWrapperRef}>
<Selected
bgColor={props.bgColor}
className={props.className}
@ -534,6 +567,7 @@ export default function Dropdown(props: DropdownProps) {
>
<SelectedValueNode
errorMsg={errorMsg}
optionWidth={dropdownOptionWidth}
renderNode={renderOption}
selected={selected}
showLabelOnly={props.showLabelOnly}
@ -557,12 +591,15 @@ export default function Dropdown(props: DropdownProps) {
)}
</DropdownSelect>
);
const dropdownWidth = props.width || "260px";
return (
<DropdownContainer
className={props.containerClassName}
data-cy={props.cypressSelector}
tabIndex={0}
width={props.width || "260px"}
width={dropdownWidth}
>
<Popover
boundary="scrollParent"
@ -574,8 +611,9 @@ export default function Dropdown(props: DropdownProps) {
>
{dropdownTrigger}
<RenderDropdownOptions
optionClickHandler={optionClickHandler}
{...props}
optionClickHandler={optionClickHandler}
optionWidth={dropdownOptionWidth}
/>
</Popover>
</DropdownContainer>

View File

@ -438,7 +438,7 @@ export const CONNECT_TO_GIT_SUBTITLE = () =>
"Choose an existing empty repository to host your project and keep it in sync";
export const REMOTE_URL_VIA = () => "REMOTE URL VIA";
export const USER_PROFILE_SETTINGS_TITLE = () => "User Settings";
export const USER_PROFILE_SETTINGS_TITLE = () => "USER SETTINGS";
export const AUTHOR_NAME = () => "AUTHOR NAME";
export const AUTHOR_EMAIL = () => "AUTHOR EMAIL";

View File

@ -90,7 +90,7 @@ const DatasourceImage = styled.img`
interface DataSourceOptionType extends RenderDropdownOptionType {
cypressSelector: string;
optionWidth?: string;
optionWidth: string;
}
function DataSourceOption({

View File

@ -48,12 +48,14 @@ const TitleWrapper = styled.div`
const OptionWrapper = styled.div<{
selected: boolean;
width: string;
}>`
padding: ${(props) => props.theme.spaces[2] + 1}px
${(props) => props.theme.spaces[5]}px;
cursor: pointer;
display: flex;
align-items: center;
width: ${(props) => props.width};
background-color: ${(props) =>
props.selected ? props.theme.colors.propertyPane.dropdownSelectBg : null};
@ -75,21 +77,23 @@ function AuthConfig({ authType }: AuthConfigProps) {
<InputContainer>
<Dropdown
disabled={SSH_PROFILE_OPTION.length === 0}
fillOptions
onSelect={() => {
//
}}
// optionWidth="100%"
options={SSH_PROFILE_OPTION}
renderOption={({
isSelectedNode,
option,
optionClickHandler,
optionWidth,
}) => (
<OptionWrapper
onClick={() =>
optionClickHandler && optionClickHandler(option)
}
selected={!!isSelectedNode}
width={optionWidth || ""}
>
<Text type={TextType.P1}>{option.label}</Text>
</OptionWrapper>