Skip to content

Commit 57148ff

Browse files
Auto-adjust dropdown horizontally when dropdownMatchSelectWidth is false (#461)
* Auto-adjust x when dropdownMatchSelectWidth=false * Use memoization for builtInPlacements prop Co-authored-by: Cameron Hessler <[email protected]>
1 parent ececb04 commit 57148ff

File tree

3 files changed

+179
-16
lines changed

3 files changed

+179
-16
lines changed

examples/auto-adjust-dropdown.tsx

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/* eslint-disable no-console */
2+
import React from 'react';
3+
import Select, { Option } from '../src';
4+
import '../assets/index.less';
5+
6+
class Test extends React.Component {
7+
state = {
8+
value: '3',
9+
};
10+
11+
onChange = e => {
12+
let value;
13+
if (e && e.target) {
14+
({ value } = e.target);
15+
} else {
16+
value = e;
17+
}
18+
this.setState({
19+
value,
20+
});
21+
};
22+
23+
render() {
24+
const { value } = this.state;
25+
26+
return (
27+
<div
28+
style={{
29+
display: 'flex',
30+
flexDirection: 'column',
31+
justifyContent: 'space-between',
32+
height: 'calc(100vh - 16px)',
33+
}}
34+
>
35+
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
36+
<div>
37+
<Select
38+
onChange={this.onChange}
39+
dropdownMatchSelectWidth={500}
40+
value={value}
41+
>
42+
<Option value="1">
43+
Jack Jack Jack Jack Jack Jack Jack Jack Jack Jack Jack
44+
</Option>
45+
<Option value="2">
46+
Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy
47+
</Option>
48+
<Option value="3">Jill</Option>
49+
</Select>
50+
</div>
51+
<div>
52+
<Select
53+
onChange={this.onChange}
54+
dropdownMatchSelectWidth={500}
55+
value={value}
56+
>
57+
<Option value="1">
58+
Jack Jack Jack Jack Jack Jack Jack Jack Jack Jack Jack
59+
</Option>
60+
<Option value="2">
61+
Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy
62+
</Option>{' '}
63+
<Option value="3">Jill</Option>
64+
</Select>
65+
</div>
66+
</div>
67+
<div style={{ display: 'flex', justifyContent: 'center' }}>
68+
<div>
69+
<Select
70+
onChange={this.onChange}
71+
dropdownMatchSelectWidth={500}
72+
value={value}
73+
>
74+
<Option value="1">
75+
Jack Jack Jack Jack Jack Jack Jack Jack Jack Jack Jack
76+
</Option>
77+
<Option value="2">
78+
Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy
79+
</Option>
80+
<Option value="3">Jill</Option>
81+
</Select>
82+
</div>
83+
</div>
84+
<div
85+
style={{
86+
display: 'flex',
87+
justifyContent: 'space-between',
88+
}}
89+
>
90+
<div>
91+
<Select
92+
onChange={this.onChange}
93+
dropdownMatchSelectWidth={500}
94+
value={value}
95+
>
96+
<Option value="1">
97+
Jack Jack Jack Jack Jack Jack Jack Jack Jack Jack Jack
98+
</Option>
99+
<Option value="2">
100+
Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy
101+
</Option>
102+
<Option value="3">Jill</Option>
103+
</Select>
104+
</div>
105+
<div>
106+
<Select
107+
onChange={this.onChange}
108+
dropdownMatchSelectWidth={500}
109+
value={value}
110+
>
111+
<Option value="1">
112+
Jack Jack Jack Jack Jack Jack Jack Jack Jack Jack Jack
113+
</Option>
114+
<Option value="2">
115+
Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy Lucy
116+
</Option>
117+
<Option value="3">Jill</Option>
118+
</Select>
119+
</div>
120+
</div>
121+
</div>
122+
);
123+
}
124+
}
125+
126+
export default Test;
127+
/* eslint-enable */

src/SelectTrigger.tsx

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,28 @@ import Trigger from 'rc-trigger';
33
import classNames from 'classnames';
44
import { RenderDOMFunc } from './interface';
55

6-
const BUILT_IN_PLACEMENTS = {
7-
bottomLeft: {
8-
points: ['tl', 'bl'],
9-
offset: [0, 4],
10-
overflow: {
11-
adjustX: 0,
12-
adjustY: 1,
6+
const getBuiltInPlacements = (dropdownMatchSelectWidth: number | true) => {
7+
// Enable horizontal overflow auto-adjustment when a custom dropdown width is provided
8+
const adjustX = typeof dropdownMatchSelectWidth !== 'number' ? 0 : 1;
9+
10+
return {
11+
bottomLeft: {
12+
points: ['tl', 'bl'],
13+
offset: [0, 4],
14+
overflow: {
15+
adjustX,
16+
adjustY: 1,
17+
},
1318
},
14-
},
15-
topLeft: {
16-
points: ['bl', 'tl'],
17-
offset: [0, -4],
18-
overflow: {
19-
adjustX: 0,
20-
adjustY: 1,
19+
topLeft: {
20+
points: ['bl', 'tl'],
21+
offset: [0, -4],
22+
overflow: {
23+
adjustX,
24+
adjustY: 1,
25+
},
2126
},
22-
},
27+
};
2328
};
2429

2530
export interface RefTriggerProps {
@@ -78,6 +83,11 @@ const SelectTrigger: React.RefForwardingComponent<
7883
popupNode = dropdownRender(popupElement);
7984
}
8085

86+
const builtInPlacements = React.useMemo(
87+
() => getBuiltInPlacements(dropdownMatchSelectWidth),
88+
[dropdownMatchSelectWidth],
89+
);
90+
8191
// ===================== Motion ======================
8292
const mergedTransitionName = animation
8393
? `${dropdownPrefixCls}-${animation}`
@@ -107,7 +117,7 @@ const SelectTrigger: React.RefForwardingComponent<
107117
showAction={[]}
108118
hideAction={[]}
109119
popupPlacement="bottomLeft"
110-
builtinPlacements={BUILT_IN_PLACEMENTS}
120+
builtinPlacements={builtInPlacements}
111121
prefixCls={dropdownPrefixCls}
112122
popupTransitionName={mergedTransitionName}
113123
popup={<div ref={popupRef}>{popupNode}</div>}

tests/Select.test.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,32 @@ describe('Select.Basic', () => {
12301230
});
12311231
});
12321232

1233+
it('dropdown should auto-adjust horizontally when dropdownMatchSelectWidth is false', () => {
1234+
const wrapper = mount(
1235+
<Select dropdownMatchSelectWidth={233}>
1236+
<Option value={0}>0</Option>
1237+
<Option value={1}>1</Option>
1238+
</Select>,
1239+
);
1240+
expect(
1241+
wrapper.find('Trigger').props().builtinPlacements.bottomLeft.overflow
1242+
.adjustX,
1243+
).toBe(1);
1244+
});
1245+
1246+
it('dropdown should not auto-adjust horizontally when dropdownMatchSelectWidth is true', () => {
1247+
const wrapper = mount(
1248+
<Select>
1249+
<Option value={0}>0</Option>
1250+
<Option value={1}>1</Option>
1251+
</Select>,
1252+
);
1253+
expect(
1254+
wrapper.find('Trigger').props().builtinPlacements.bottomLeft.overflow
1255+
.adjustX,
1256+
).toBe(0);
1257+
});
1258+
12331259
it('if loading, arrow should show loading icon', () => {
12341260
const wrapper = mount(
12351261
<Select style={{ width: 1000 }} loading>

0 commit comments

Comments
 (0)