@rescui/select 0.17.2 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
1
  import React from 'react';
2
2
  import type { MultiselectProps } from './types';
3
- export declare function Multiselect({ options, value, onChange, error, label, note, size, mode, theme: themeFromProps, placement, isSingleLine, boldLabel, reserveErrorLine, maxVisibleItems, isClearable, isLoading, isDisabled, name, noOptionsMessage, className, id, style, placeholder, ...rest }: MultiselectProps): React.JSX.Element;
3
+ export declare function Multiselect({ options, value, onChange, error, label, note, size, mode, theme: themeFromProps, placement, renderInTrigger, disableFlip, isSingleLine, boldLabel, reserveErrorLine, maxVisibleItems, isClearable, isLoading, isDisabled, name, noOptionsMessage, className, id, style, placeholder, ...rest }: MultiselectProps): React.JSX.Element;
@@ -69,6 +69,8 @@ function Multiselect(_ref) {
69
69
  mode = 'classic',
70
70
  theme: themeFromProps,
71
71
  placement = 'bottom',
72
+ renderInTrigger = false,
73
+ disableFlip = false,
72
74
  isSingleLine = false,
73
75
  boldLabel = true,
74
76
  reserveErrorLine = false,
@@ -261,6 +263,8 @@ function Multiselect(_ref) {
261
263
  dropdownRef: dropdownRef,
262
264
  triggerRef: triggerRef,
263
265
  placement: placement,
266
+ renderInTrigger: renderInTrigger,
267
+ disableFlip: disableFlip,
264
268
  isOpen: isOpen,
265
269
  listBoxState: listBoxState,
266
270
  maxVisibleItems: maxVisibleItems,
@@ -14,7 +14,9 @@ export type PopupContentProps = {
14
14
  emptyListMessage: string;
15
15
  maxVisibleItems?: number;
16
16
  trigger?: DropdownProps['trigger'];
17
+ renderInTrigger?: boolean;
18
+ disableFlip?: boolean;
17
19
  isOpen?: boolean;
18
20
  dropdownUpdateDeps?: unknown[];
19
21
  };
20
- export declare const PopupContent: ({ theme, listBoxState, triggerRef, dropdownRef, listBoxItems, placement, size: sizeFromProps, mode, emptyListMessage, maxVisibleItems, trigger, isOpen, dropdownUpdateDeps }: PopupContentProps) => React.JSX.Element;
22
+ export declare const PopupContent: ({ theme, listBoxState, triggerRef, dropdownRef, listBoxItems, placement, size: sizeFromProps, mode, emptyListMessage, maxVisibleItems, trigger, renderInTrigger, disableFlip, isOpen, dropdownUpdateDeps }: PopupContentProps) => React.JSX.Element;
@@ -18,6 +18,8 @@ const PopupContent = _ref => {
18
18
  emptyListMessage,
19
19
  maxVisibleItems,
20
20
  trigger,
21
+ renderInTrigger,
22
+ disableFlip,
21
23
  isOpen,
22
24
  dropdownUpdateDeps = []
23
25
  } = _ref;
@@ -53,6 +55,8 @@ const PopupContent = _ref => {
53
55
  isOpen: isOpen,
54
56
  cancelCloseAnimation: true,
55
57
  disableFocusLock: true,
58
+ renderInTrigger: renderInTrigger,
59
+ disableFlip: disableFlip,
56
60
  trigger: trigger
57
61
  }, /*#__PURE__*/React.createElement(ListBox, {
58
62
  state: listBoxState,
@@ -1,3 +1,3 @@
1
1
  import React from 'react';
2
2
  import type { InnerSingleComponentProps } from './types';
3
- export declare function SelectBasic({ options, value: selectedItem, onChange, error, label, note, size, mode, theme, placement, boldLabel, reserveErrorLine, maxVisibleItems, isClearable, isLoading, isDisabled, name, noOptionsMessage, className, id, style, placeholder, ...rest }: InnerSingleComponentProps): React.JSX.Element;
3
+ export declare function SelectBasic({ options, value: selectedItem, onChange, error, label, note, size, mode, theme, placement, renderInTrigger, disableFlip, boldLabel, reserveErrorLine, maxVisibleItems, isClearable, isLoading, isDisabled, name, noOptionsMessage, className, id, style, placeholder, ...rest }: InnerSingleComponentProps): React.JSX.Element;
@@ -28,6 +28,8 @@ function SelectBasic(_ref) {
28
28
  mode,
29
29
  theme,
30
30
  placement,
31
+ renderInTrigger,
32
+ disableFlip,
31
33
  boldLabel,
32
34
  reserveErrorLine,
33
35
  maxVisibleItems,
@@ -167,6 +169,8 @@ function SelectBasic(_ref) {
167
169
  maxVisibleItems: maxVisibleItems,
168
170
  emptyListMessage: emptyListMessage,
169
171
  listBoxItems: listBoxItems,
172
+ renderInTrigger: renderInTrigger,
173
+ disableFlip: disableFlip,
170
174
  trigger: _ref3 => {
171
175
  let {
172
176
  ref: triggerRefForDropdown
@@ -1,3 +1,3 @@
1
1
  import React from 'react';
2
2
  import { InnerSingleComponentProps } from './types';
3
- export declare function SelectSearchable({ options, value: selectedItem, onChange, error, label, note, size, mode, theme, placement, boldLabel, reserveErrorLine, maxVisibleItems, isClearable, isLoading, isDisabled, name, noOptionsMessage, className, id, style, placeholder, ...rest }: InnerSingleComponentProps): React.JSX.Element;
3
+ export declare function SelectSearchable({ options, value: selectedItem, onChange, error, label, note, size, mode, theme, placement, renderInTrigger, disableFlip, boldLabel, reserveErrorLine, maxVisibleItems, isClearable, isLoading, isDisabled, name, noOptionsMessage, className, id, style, placeholder, ...rest }: InnerSingleComponentProps): React.JSX.Element;
@@ -27,6 +27,8 @@ function SelectSearchable(_ref) {
27
27
  mode,
28
28
  theme,
29
29
  placement,
30
+ renderInTrigger,
31
+ disableFlip,
30
32
  boldLabel,
31
33
  reserveErrorLine,
32
34
  maxVisibleItems,
@@ -198,6 +200,8 @@ function SelectSearchable(_ref) {
198
200
  dropdownRef: dropdownRef,
199
201
  triggerRef: inputRef,
200
202
  placement: placement,
203
+ renderInTrigger: renderInTrigger,
204
+ disableFlip: disableFlip,
201
205
  isOpen: isOpen,
202
206
  listBoxState: listBoxState,
203
207
  maxVisibleItems: maxVisibleItems,
package/lib/select.d.ts CHANGED
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import type { SelectProps, SelectOption, SelectOptionOrGroup } from './types';
4
4
  export declare const Select: {
5
- ({ options, size, mode, theme: themeFromProps, className, style, value, onChange, placeholder, isClearable, isLoading, isDisabled, isSearchable, noOptionsMessage, error, placement, boldLabel, reserveErrorLine, note, maxVisibleItems, id, ...restProps }: SelectProps): React.JSX.Element;
5
+ ({ options, size, mode, theme: themeFromProps, className, style, value, onChange, placeholder, isClearable, isLoading, isDisabled, isSearchable, noOptionsMessage, error, placement, renderInTrigger, disableFlip, boldLabel, reserveErrorLine, note, maxVisibleItems, id, ...restProps }: SelectProps): React.JSX.Element;
6
6
  propTypes: {
7
7
  className: PropTypes.Requireable<string>;
8
8
  style: PropTypes.Requireable<object>;
@@ -23,6 +23,8 @@ export declare const Select: {
23
23
  note: PropTypes.Requireable<PropTypes.ReactNodeLike>;
24
24
  noOptionsMessage: PropTypes.Validator<import("./types").NoOptionsMessage>;
25
25
  placement: PropTypes.Requireable<string>;
26
+ renderInTrigger: PropTypes.Requireable<boolean>;
27
+ disableFlip: PropTypes.Requireable<boolean>;
26
28
  name: PropTypes.Requireable<string>;
27
29
  };
28
30
  };
package/lib/select.js CHANGED
@@ -40,6 +40,8 @@ const Select = _ref => {
40
40
  noOptionsMessage,
41
41
  error,
42
42
  placement = 'bottom',
43
+ renderInTrigger = false,
44
+ disableFlip = false,
43
45
  boldLabel = true,
44
46
  reserveErrorLine = false,
45
47
  note,
@@ -71,6 +73,8 @@ const Select = _ref => {
71
73
  noOptionsMessage: noOptionsMessage,
72
74
  error: error,
73
75
  placement: placement,
76
+ renderInTrigger: renderInTrigger,
77
+ disableFlip: disableFlip,
74
78
  boldLabel: boldLabel,
75
79
  reserveErrorLine: reserveErrorLine,
76
80
  note: note,
@@ -98,6 +102,8 @@ Select.propTypes = {
98
102
  note: PropTypes.node,
99
103
  noOptionsMessage: noOptionsMessageType,
100
104
  placement: PropTypes.oneOf(['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start']),
105
+ renderInTrigger: PropTypes.bool,
106
+ disableFlip: PropTypes.bool,
101
107
  name: PropTypes.string
102
108
  };
103
109
  export { Select };
@@ -1,32 +1,32 @@
1
1
  var styles = {
2
- "themeLight": "_themeLight_f1140c_6",
3
- "themeDark": "_themeDark_f1140c_9",
4
- "sizeS": "_sizeS_f1140c_13",
5
- "sizeM": "_sizeM_f1140c_16",
6
- "sizeL": "_sizeL_f1140c_19",
7
- "classic": "_classic_f1140c_23",
8
- "rock": "_rock_f1140c_26",
9
- "root": "_root_f1140c_30",
10
- "triggerContainer": "_triggerContainer_f1140c_36",
11
- "disabled": "_disabled_f1140c_41",
12
- "trigger": "_trigger_f1140c_36",
13
- "error": "_error_f1140c_78",
14
- "enabled": "_enabled_f1140c_83",
15
- "searchable": "_searchable_f1140c_98",
16
- "canBeMultiline": "_canBeMultiline_f1140c_125",
17
- "triggerText": "_triggerText_f1140c_129",
18
- "searchInput": "_searchInput_f1140c_130",
19
- "labelNotSelected": "_labelNotSelected_f1140c_161",
20
- "multi": "_multi_f1140c_217",
21
- "tagsContainer": "_tagsContainer_f1140c_234",
22
- "tag": "_tag_f1140c_234",
23
- "filledTag": "_filledTag_f1140c_256",
24
- "iconsWrapper": "_iconsWrapper_f1140c_264",
25
- "toggle": "_toggle_f1140c_282",
26
- "icon": "_icon_f1140c_264",
27
- "clearIcon": "_clearIcon_f1140c_356",
28
- "visuallyHidden": "_visuallyHidden_f1140c_416",
29
- "select": "_select_f1140c_433",
30
- "observable": "_observable_f1140c_455"
2
+ "themeLight": "_themeLight_1ph90r1_6",
3
+ "themeDark": "_themeDark_1ph90r1_9",
4
+ "sizeS": "_sizeS_1ph90r1_13",
5
+ "sizeM": "_sizeM_1ph90r1_16",
6
+ "sizeL": "_sizeL_1ph90r1_19",
7
+ "classic": "_classic_1ph90r1_23",
8
+ "rock": "_rock_1ph90r1_26",
9
+ "root": "_root_1ph90r1_30",
10
+ "triggerContainer": "_triggerContainer_1ph90r1_36",
11
+ "disabled": "_disabled_1ph90r1_41",
12
+ "trigger": "_trigger_1ph90r1_36",
13
+ "error": "_error_1ph90r1_78",
14
+ "enabled": "_enabled_1ph90r1_83",
15
+ "searchable": "_searchable_1ph90r1_98",
16
+ "canBeMultiline": "_canBeMultiline_1ph90r1_125",
17
+ "triggerText": "_triggerText_1ph90r1_129",
18
+ "searchInput": "_searchInput_1ph90r1_130",
19
+ "labelNotSelected": "_labelNotSelected_1ph90r1_161",
20
+ "multi": "_multi_1ph90r1_217",
21
+ "tagsContainer": "_tagsContainer_1ph90r1_234",
22
+ "tag": "_tag_1ph90r1_234",
23
+ "filledTag": "_filledTag_1ph90r1_256",
24
+ "iconsWrapper": "_iconsWrapper_1ph90r1_264",
25
+ "toggle": "_toggle_1ph90r1_282",
26
+ "icon": "_icon_1ph90r1_264",
27
+ "clearIcon": "_clearIcon_1ph90r1_356",
28
+ "visuallyHidden": "_visuallyHidden_1ph90r1_416",
29
+ "select": "_select_1ph90r1_433",
30
+ "observable": "_observable_1ph90r1_455"
31
31
  };
32
32
  export { styles as default };
@@ -1,15 +1,15 @@
1
1
  var styles = {
2
- "themeLight": "_themeLight_1439i0c_6",
3
- "themeDark": "_themeDark_1439i0c_9",
4
- "sizeS": "_sizeS_1439i0c_13",
5
- "sizeM": "_sizeM_1439i0c_16",
6
- "sizeL": "_sizeL_1439i0c_19",
7
- "main": "_main_1439i0c_23",
8
- "label": "_label_1439i0c_27",
9
- "disabled": "_disabled_1439i0c_33",
10
- "footer": "_footer_1439i0c_38",
11
- "errorMessage": "_errorMessage_1439i0c_45",
12
- "error": "_error_1439i0c_45",
13
- "note": "_note_1439i0c_54"
2
+ "themeLight": "_themeLight_13ylg3x_6",
3
+ "themeDark": "_themeDark_13ylg3x_9",
4
+ "sizeS": "_sizeS_13ylg3x_13",
5
+ "sizeM": "_sizeM_13ylg3x_16",
6
+ "sizeL": "_sizeL_13ylg3x_19",
7
+ "main": "_main_13ylg3x_23",
8
+ "label": "_label_13ylg3x_27",
9
+ "disabled": "_disabled_13ylg3x_33",
10
+ "footer": "_footer_13ylg3x_38",
11
+ "errorMessage": "_errorMessage_13ylg3x_45",
12
+ "error": "_error_13ylg3x_45",
13
+ "note": "_note_13ylg3x_54"
14
14
  };
15
15
  export { styles as default };
@@ -1,16 +1,16 @@
1
1
  var styles = {
2
- "sizeS": "_sizeS_1s11z1a_6",
3
- "sizeM": "_sizeM_1s11z1a_9",
4
- "sizeL": "_sizeL_1s11z1a_12",
5
- "classic": "_classic_1s11z1a_16",
6
- "rock": "_rock_1s11z1a_19",
7
- "listBox": "_listBox_1s11z1a_23",
8
- "item": "_item_1s11z1a_39",
9
- "selected": "_selected_1s11z1a_77",
10
- "disabled": "_disabled_1s11z1a_91",
11
- "checkIcon": "_checkIcon_1s11z1a_98",
12
- "visible": "_visible_1s11z1a_105",
13
- "divider": "_divider_1s11z1a_112",
14
- "groupHeader": "_groupHeader_1s11z1a_126"
2
+ "sizeS": "_sizeS_19aocyn_6",
3
+ "sizeM": "_sizeM_19aocyn_9",
4
+ "sizeL": "_sizeL_19aocyn_12",
5
+ "classic": "_classic_19aocyn_16",
6
+ "rock": "_rock_19aocyn_19",
7
+ "listBox": "_listBox_19aocyn_23",
8
+ "item": "_item_19aocyn_39",
9
+ "selected": "_selected_19aocyn_77",
10
+ "disabled": "_disabled_19aocyn_91",
11
+ "checkIcon": "_checkIcon_19aocyn_98",
12
+ "visible": "_visible_19aocyn_105",
13
+ "divider": "_divider_19aocyn_112",
14
+ "groupHeader": "_groupHeader_19aocyn_126"
15
15
  };
16
16
  export { styles as default };
package/lib/types.d.ts CHANGED
@@ -126,6 +126,14 @@ export type SelectProps = {
126
126
  * Placement of dropdown element
127
127
  */
128
128
  placement?: Placement;
129
+ /**
130
+ * Render dropdown inside trigger function or wrapper. May be useful when the trigger placed in the fixed layout or popovers.
131
+ * */
132
+ renderInTrigger?: boolean;
133
+ /**
134
+ * Disable dropdown flip behavior. By default dropdown will flip its position if it's not fully visible.
135
+ * */
136
+ disableFlip?: boolean;
129
137
  /**
130
138
  * Note element at the bottom (use with forms)
131
139
  */
@@ -0,0 +1,282 @@
1
+ # Multiselect
2
+
3
+ Multiselect is a control that allows users to select multiple options from a list.
4
+
5
+ ## Usage
6
+
7
+ ### Features showcase
8
+
9
+ #### Example:
10
+
11
+ You can control what has been selected through `value`/`onChange` props combination. The state represents the collection of options displayed in the select box. The empty state represents by `[]`.
12
+
13
+ ```tsx
14
+ import { useState } from 'react';
15
+ import { Multiselect } from '@rescui/select';
16
+
17
+ const options = [
18
+ { label: 'St. Petersburg', value: 'spb' },
19
+ { label: 'Moscow', value: 'msk' },
20
+ { label: 'Novosibirsk', value: 'nsk' },
21
+ { label: 'Prague', value: 'prg' },
22
+ { label: 'Boston', value: 'bos' },
23
+ { label: 'Munich', value: 'muc' }
24
+ ];
25
+
26
+ const MySelect = () => {
27
+ const [selected, setSelected] = useState([options[0], options[5]]);
28
+
29
+ return (
30
+ <div>
31
+ <span>Selected cities: </span>
32
+ <code>{JSON.stringify(selected)}</code>
33
+ <div style={{ maxWidth: '380px', marginTop: '24px' }}>
34
+ <Multiselect
35
+ options={options}
36
+ value={selected}
37
+ onChange={value => {
38
+ console.log('value', value);
39
+ setSelected(value);
40
+ }}
41
+ size="m"
42
+ placeholder="Сhoose your favorite cities..."
43
+ aria-label="Сhoose your favorite cities"
44
+ />
45
+ </div>
46
+ </div>
47
+ );
48
+ };
49
+
50
+ render(<MySelect />);
51
+ ```
52
+
53
+ #### SingleLine mode:
54
+
55
+ You can use the `isSingleLine` prop to limit from grow and force it to be always single line. In this case extra tags is hidden and display the count of hidden tags instead.
56
+
57
+ ```tsx
58
+ import { useState } from 'react';
59
+ import { Multiselect } from '@rescui/select';
60
+
61
+ const options = [
62
+ { label: 'Blue', value: 'blue' },
63
+ { label: 'Black', value: 'black' },
64
+ { label: 'Red', value: 'red' },
65
+ { label: 'Orange', value: 'orange' },
66
+ { label: 'Yellow', value: 'yellow' },
67
+ { label: 'White', value: 'white' }
68
+ ];
69
+
70
+ const MySelect = () => {
71
+ const [selected, setSelected] = useState([options[1], options[5]]);
72
+
73
+ return (
74
+ <div style={{ maxWidth: '380px' }}>
75
+ <Multiselect
76
+ className="clazz"
77
+ options={options}
78
+ value={selected}
79
+ onChange={value => setSelected(value)}
80
+ isSingleLine
81
+ size="m"
82
+ placeholder="Select colors..."
83
+ aria-label="Select colors"
84
+ />
85
+ </div>
86
+ );
87
+ };
88
+
89
+ render(<MySelect />);
90
+ ```
91
+
92
+ #### Contrast primary color
93
+
94
+ If your primary color background requires dark text color, use `--rs-select-contrast-primary` CSS variable.
95
+
96
+ ```tsx
97
+ import { useState } from 'react';
98
+ import { Multiselect } from '@rescui/select';
99
+
100
+ const options = [
101
+ { label: 'St. Petersburg', value: 'spb' },
102
+ { label: 'Moscow', value: 'msk' },
103
+ { label: 'Novosibirsk', value: 'nsk' },
104
+ { label: 'Prague', value: 'prg' },
105
+ { label: 'Boston', value: 'bos' },
106
+ { label: 'Munich', value: 'muc' }
107
+ ];
108
+
109
+ const MySelect = () => {
110
+ const [selected, setSelected] = useState([options[0], options[5]]);
111
+
112
+ return (
113
+ <div>
114
+ <span>Selected cities: </span>
115
+ <code>{JSON.stringify(selected)}</code>
116
+ <div
117
+ style={{ maxWidth: '380px', marginTop: '24px' }}
118
+ className="light-green-primary"
119
+ >
120
+ <Multiselect
121
+ options={options}
122
+ value={selected}
123
+ onChange={setSelected}
124
+ size="m"
125
+ className="select-with-contrast-primary"
126
+ placeholder="Сhoose your favorite cities..."
127
+ aria-label="Сhoose your favorite cities"
128
+ />
129
+ </div>
130
+ </div>
131
+ );
132
+ };
133
+
134
+ render(<MySelect />);
135
+ ```
136
+
137
+ ```postcss attached
138
+ .select-with-contrast-primary {
139
+ --rs-select-contrast-primary: 1;
140
+ }
141
+
142
+ .light-green-primary {
143
+ --rs-color-primary-light-theme: rgb(71, 224, 84);
144
+ --rs-color-primary-t-dim-light-theme: rgba(71, 224, 84, 0.8);
145
+ --rs-color-primary-t-fog-light-theme: rgba(71, 224, 84, 0.2);
146
+
147
+ --rs-color-primary-dark-theme: rgb(71, 224, 84);
148
+ --rs-color-primary-t-dim-dark-theme: rgba(71, 224, 84, 0.8);
149
+ --rs-color-primary-t-fog-dark-theme: rgba(71, 224, 84, 0.2);
150
+ }
151
+ ```
152
+
153
+ #### In the native dialog element
154
+
155
+ Because the [popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API/Using) places the dialog element on the Top Layer, any value of `z-index` for the options list will be ignored.
156
+
157
+ To work around this, we can use the `renderInTrigger` prop to render the popover in the dialog element instead of the bottom of the `body`.
158
+
159
+ Also use `disableFlip` prop and `overflow: visible` css on the dialog if options will overflow it.
160
+
161
+ ```tsx
162
+ import { useState } from 'react';
163
+ import { Multiselect } from '@rescui/select';
164
+
165
+ const options = [
166
+ { label: 'Blue', value: 'blue' },
167
+ { label: 'Black', value: 'black' },
168
+ { label: 'Red', value: 'red' },
169
+ { label: 'Orange', value: 'orange' },
170
+ { label: 'Yellow', value: 'yellow' },
171
+ { label: 'White', value: 'white' }
172
+ ];
173
+
174
+ const MySelect = () => {
175
+ const [selected, setSelected] = useState([options[1], options[5]]);
176
+
177
+ return (
178
+ <div style={{ maxWidth: '380px' }}>
179
+ <Multiselect
180
+ className="clazz"
181
+ options={options}
182
+ value={selected}
183
+ onChange={value => setSelected(value)}
184
+ isSingleLine
185
+ size="m"
186
+ placeholder="Select colors..."
187
+ aria-label="Select colors"
188
+ renderInTrigger
189
+ disableFlip
190
+ />
191
+ </div>
192
+ );
193
+ };
194
+
195
+ render(
196
+ <>
197
+ <button command="show-modal" commandfor="my-dialog">
198
+ Open dialog
199
+ </button>
200
+
201
+ <dialog id="my-dialog" style={{ width: 500, overflow: 'visible' }}>
202
+ <div>
203
+ <button commandfor="my-dialog" command="close">
204
+ Close
205
+ </button>
206
+ </div>
207
+ <div style={{ marginTop: 12 }}>
208
+ <MySelect />
209
+ </div>
210
+ </dialog>
211
+ </>
212
+ );
213
+ ```
214
+
215
+ ## CSS Mixins API
216
+
217
+ #### `Multiselect` mixins
218
+
219
+ | Mixin name | Details |
220
+ | --- | --- |
221
+ | `rs-multiselect-size-s` | prop: `size`<br><br>value: `"s"` |
222
+ | `rs-multiselect-size-m` | prop: `size`<br><br>value: `"m"` |
223
+ | `rs-multiselect-size-l` | prop: `size`<br><br>value: `"l"` |
224
+
225
+ #### Demo
226
+
227
+ Use the controls to see the effect at different viewport widths.
228
+
229
+ ```tsx
230
+ import { useState } from 'react';
231
+ import { Multiselect } from '@rescui/select';
232
+
233
+ const options = [
234
+ { label: 'St. Petersburg', value: 'spb' },
235
+ { label: 'Moscow', value: 'msk' },
236
+ { label: 'Novosibirsk', value: 'nsk' },
237
+ { label: 'Prague', value: 'prg' },
238
+ { label: 'Boston', value: 'bos' },
239
+ { label: 'Munich', value: 'muc' }
240
+ ];
241
+
242
+ const MyMultiselect = ({ className }) => {
243
+ const [selected, setSelected] = useState([options[0], options[5]]);
244
+
245
+ return (
246
+ <div style={{ maxWidth: 380, height: 380 }}>
247
+ <Multiselect
248
+ options={options}
249
+ value={selected}
250
+ onChange={value => setSelected(value)}
251
+ size="m"
252
+ placeholder="Сhoose your favorite cities..."
253
+ aria-label="Choose your favorite cities"
254
+ className={className}
255
+ />
256
+ </div>
257
+ );
258
+ };
259
+
260
+ render(<MyMultiselect className="my-multiselect" />);
261
+ ```
262
+
263
+ ```postcss
264
+ @import '@rescui/select/lib/public-api.p.css';
265
+
266
+ .my-multiselect {
267
+ @media (max-width: 640px) {
268
+ @mixin rs-multiselect-size-l;
269
+ }
270
+ @media (max-width: 500px) {
271
+ @mixin rs-multiselect-size-s;
272
+ }
273
+ }
274
+ ```
275
+
276
+ #### `Select` CSS Vars
277
+
278
+ | Variable | Syntax | Description |
279
+ | --- | --- | --- |
280
+ | `--rs-select-contrast-primary` | `0 \| 1` | The flag whenever the current primary is contrast enough and highlighted text color should be inverted |
281
+
282
+ Check out [this example](/components/multiselect/#contrast-primary-color) for contrast primary.