Skip to content

Commit a0e62b6

Browse files
committed
fix(selector-dropdown): add dynamic positioning to the dropdown overlay
1 parent 0933062 commit a0e62b6

7 files changed

Lines changed: 27 additions & 32 deletions

File tree

‎src/components/pill-selector-dropdown/PillSelector.js‎

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,20 @@ function stopDefaultEvent(event) {
1818
}
1919

2020
type Props = {
21-
allowInvalidPills: boolean,
21+
allowInvalidPills?: boolean,
2222
className?: string,
2323
disabled?: boolean,
2424
error?: React.Node,
2525
/** Called on pill render to get a specific class name to use for a particular option. Note: Only has effect when showRoundedPills is true. */
2626
getPillClassName?: (option: Option) => string,
2727
/** Function to retrieve the image URL associated with a pill */
2828
getPillImageUrl?: (data: { id: string | number, [key: string]: any }) => string,
29-
inputProps: Object,
29+
innerRef?: React.Ref<any>,
30+
inputProps?: Object,
3031
onInput: Function,
3132
onRemove: Function,
3233
onSuggestedPillAdd?: Function,
33-
placeholder: string,
34+
placeholder?: string,
3435
selectedOptions: Array<Object> | List<Object>,
3536
/** Whether to show avatars in pills (if rounded style is enabled) */
3637
showAvatars?: boolean,
@@ -39,7 +40,7 @@ type Props = {
3940
suggestedPillsData?: Array<Object>,
4041
suggestedPillsFilter?: SuggestedPillsFilter,
4142
suggestedPillsTitle?: string,
42-
validator: (option: Option | OptionValue) => boolean,
43+
validator?: (option: Option | OptionValue) => boolean,
4344
};
4445

4546
type State = {
@@ -54,6 +55,7 @@ class PillSelector extends React.Component<Props, State> {
5455
error: '',
5556
inputProps: {},
5657
placeholder: '',
58+
// $FlowFixMe
5759
selectedOptions: [],
5860
validator: () => true,
5961
};
@@ -179,6 +181,7 @@ class PillSelector extends React.Component<Props, State> {
179181
onRemove,
180182
onSuggestedPillAdd,
181183
placeholder,
184+
innerRef,
182185
selectedOptions,
183186
showAvatars,
184187
showRoundedPills,
@@ -213,13 +216,15 @@ class PillSelector extends React.Component<Props, State> {
213216
onClick={this.handleClick}
214217
onFocus={this.handleFocus}
215218
onKeyDown={this.handleKeyDown}
219+
ref={innerRef}
216220
>
217221
{showRoundedPills
218222
? selectedOptions.map((option: RoundOption, index: number) => {
219223
return (
220224
<RoundPill
221225
className={getPillClassName ? getPillClassName(option) : undefined}
222226
getPillImageUrl={getPillImageUrl}
227+
// $FlowFixMe
223228
isValid={allowInvalidPills ? validator(option) : true}
224229
isDisabled={disabled}
225230
isSelected={index === selectedIndex}
@@ -238,6 +243,7 @@ class PillSelector extends React.Component<Props, State> {
238243
// TODO: This and associated types will be removed once all views are updates with round pills.
239244
return (
240245
<Pill
246+
// $FlowFixMe
241247
isValid={allowInvalidPills ? validator(option) : true}
242248
isDisabled={disabled}
243249
isSelected={index === selectedIndex}
@@ -289,4 +295,10 @@ class PillSelector extends React.Component<Props, State> {
289295
}
290296
}
291297

292-
export default PillSelector;
298+
export { PillSelector as PillSelectorBase };
299+
const PillSelectorContainer = React.forwardRef<Props, React.Ref<any>>((props: Props, ref: React.Ref<any>) => (
300+
<PillSelector {...props} innerRef={ref} />
301+
));
302+
PillSelectorContainer.displayName = 'PillSelector';
303+
304+
export default PillSelectorContainer;

‎src/components/pill-selector-dropdown/__tests__/PillSelector.test.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { mount, shallow } from 'enzyme';
33
import { List, Record } from 'immutable';
44
import sinon from 'sinon';
55

6-
import PillSelector from '../PillSelector';
6+
import { PillSelectorBase as PillSelector } from '../PillSelector';
77

88
const sandbox = sinon.sandbox.create();
99

‎src/components/pill-selector-dropdown/__tests__/PillSelectorDropdown.test.js‎

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,6 @@ describe('components/pill-selector-dropdown/PillSelectorDropdown', () => {
4545
expect(selectorDropdown.contains(children)).toBe(true);
4646
});
4747

48-
test('should render pill selector', () => {
49-
const inputProps = { 'aria-label': 'test' };
50-
const wrapper = getWrapper({ inputProps });
51-
wrapper.setState({ inputValue: 'value' });
52-
const pillSelector = shallow(wrapper.find('SelectorDropdown').prop('selector'));
53-
const instance = pillSelector.instance();
54-
expect(pillSelector.prop('onInput')).toEqual(instance.handleInput);
55-
expect(pillSelector.prop('onPaste')).toEqual(instance.handlePaste);
56-
expect(pillSelector.instance().props.value).toEqual('value');
57-
});
58-
5948
test('should render disabled pill selector', () => {
6049
const wrapper = getWrapper({ disabled: true });
6150

‎src/components/pill-selector-dropdown/__tests__/__snapshots__/PillSelectorDropdown.test.js.snap‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ exports[`components/pill-selector-dropdown/PillSelectorDropdown render() should
66
onEnter={[Function]}
77
onSelect={[Function]}
88
selector={
9-
<PillSelector
9+
<ForwardRef
1010
allowInvalidPills={false}
1111
aria-label="test"
1212
disabled={true}
1313
error=""
14-
inputProps={Object {}}
1514
onBlur={[Function]}
1615
onChange={[Function]}
1716
onCompositionEnd={[Function]}

‎src/components/selector-dropdown/SelectorDropdown.js‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import classNames from 'classnames';
44
import uniqueId from 'lodash/uniqueId';
55

66
import { scrollIntoView } from '../../utils/dom';
7+
import PopperComponent from '../popper';
8+
import { PLACEMENT_BOTTOM_START } from '../popper/constants';
79
import ScrollWrapper from '../scroll-wrapper';
8-
import { OVERLAY_WRAPPER_CLASS } from '../../constants';
910

1011
import './SelectorDropdown.scss';
1112

@@ -311,13 +312,13 @@ class SelectorDropdown extends React.Component<Props, State> {
311312
onPaste={this.handleInput}
312313
ref={this.selectorDropdownRef}
313314
>
314-
{React.cloneElement(selector, { inputProps })}
315-
{isOpen && (
316-
<div className={`${OVERLAY_WRAPPER_CLASS} is-visible`}>
315+
<PopperComponent placement={PLACEMENT_BOTTOM_START} isOpen={isOpen}>
316+
{React.cloneElement(selector, { inputProps })}
317+
<div className="SelectorDropdown-overlay-wrapper">
317318
{title}
318319
{shouldScroll ? <ScrollWrapper>{list}</ScrollWrapper> : list}
319320
</div>
320-
)}
321+
</PopperComponent>
321322
</div>
322323
);
323324
}

‎src/components/selector-dropdown/SelectorDropdown.scss‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
@include bdl-Overlay-container;
1414
}
1515

16-
.overlay-wrapper,
16+
.SelectorDropdown-overlay-wrapper,
1717
.overlay {
1818
display: block;
1919
width: 100%;

‎src/elements/content-sidebar/skills/keywords/__tests__/__snapshots__/EditableKeywords.test.js.snap‎

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,14 @@ exports[`elements/content-sidebar/Skills/Keywords/EditableKeywords should correc
44
<span
55
className="bdl-EditableKeywords"
66
>
7-
<PillSelector
8-
allowInvalidPills={false}
9-
disabled={false}
10-
error=""
11-
inputProps={Object {}}
7+
<ForwardRef
128
onBlur={[Function]}
139
onCompositionEnd={[Function]}
1410
onCompositionStart={[Function]}
1511
onInput={[Function]}
1612
onKeyDown={[Function]}
1713
onPaste={[Function]}
1814
onRemove={[Function]}
19-
placeholder=""
2015
selectedOptions={
2116
Array [
2217
Object {
@@ -29,7 +24,6 @@ exports[`elements/content-sidebar/Skills/Keywords/EditableKeywords should correc
2924
},
3025
]
3126
}
32-
validator={[Function]}
3327
value=""
3428
/>
3529
<div

0 commit comments

Comments
 (0)