Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make "MenuPlacer" component customizable and switchable. #5167

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/curly-pants-turn.md
@@ -0,0 +1,6 @@
---
'react-select': patch
'@react-select/docs': patch
---

Make "MenuPlacer" component customizable and switchable.
44 changes: 44 additions & 0 deletions docs/examples/CustomMenuPlacer.tsx
@@ -0,0 +1,44 @@
import React, { RefCallback } from 'react';
import Select, { MenuPlacerProps, PlacerProps } from 'react-select';
import {
ColourOption,
colourOptions,
FlavourOption,
GroupedOption,
groupedOptions,
} from '../data';

const MenuPlacer = (
props: MenuPlacerProps<ColourOption | FlavourOption, false, GroupedOption>
) => {
const { children } = props;

const getCustomPlacement: RefCallback<HTMLDivElement> = (ref) => {
if (!ref) return;
// custom implementation of getPlacement
};

const getUpdatedProps: () => PlacerProps = () => {
return {
placement: 'top',
maxHeight: 200,
};
};

return (
<>
{children({
ref: getCustomPlacement,
placerProps: getUpdatedProps(),
})}
</>
);
};

export default () => (
<Select<ColourOption | FlavourOption, false, GroupedOption>
defaultValue={colourOptions[1]}
options={groupedOptions}
components={{ MenuPlacer }}
/>
);
1 change: 1 addition & 0 deletions docs/examples/index.tsx
Expand Up @@ -37,6 +37,7 @@ export { default as CustomSingleValue } from './CustomSingleValue';
export { default as CustomValueContainer } from './CustomValueContainer';
export { default as CustomGetOptionLabel } from './CustomGetOptionLabel';
export { default as CustomGetOptionValue } from './CustomGetOptionValue';
export { default as CustomMenuPlacer } from './CustomMenuPlacer';
export { default as CustomFilterOptions } from './CustomFilterOptions';
export { default as CustomIsOptionDisabled } from './CustomIsOptionDisabled';
export { default as DefaultOptions } from './DefaultOptions';
Expand Down
20 changes: 19 additions & 1 deletion docs/pages/components/index.tsx
Expand Up @@ -26,6 +26,7 @@ import {
CustomSingleValue,
CustomGroupHeading,
CustomValueContainer,
CustomMenuPlacer,
} from '../../examples';

export default function Components() {
Expand All @@ -44,7 +45,7 @@ export default function Components() {
The main feature of this library is providing consumers with the
building blocks necessary to create _their_ component.

The following components are customisable and switchable:
The following components are customizable and switchable:
* ClearIndicator
* Control
* DropdownIndicator
Expand All @@ -58,6 +59,7 @@ export default function Components() {
* LoadingIndicator
* Menu
* MenuList
* MenuPlacer
* MenuPortal
* LoadingMessage
* NoOptionsMessage
Expand Down Expand Up @@ -389,6 +391,22 @@ export default function Components() {
<CustomMenuList />
</ExampleWrapper>
)}

### MenuPlacer

The wrapper of the Menu. It allows to make custom logic to find the optimal placement of the Menu.

See [props docs](/props#menuPlacer) for more details

${(
<ExampleWrapper
label="Custom MenuPlacer Example"
urlPath="docs/examples/CustomMenuPlacer.tsx"
raw={require('!!raw-loader!../../examples/CustomMenuPlacer.tsx')}
>
<CustomMenuPlacer />
</ExampleWrapper>
)}

### LoadingMessage

Expand Down
4 changes: 4 additions & 0 deletions docs/pages/props/index.tsx
Expand Up @@ -202,6 +202,10 @@ export default function Api() {

${(<ShowTypes getNode={getNode} type={selectTypes?.MenuListProps} />)}

### MenuPlacer

${(<ShowTypes getNode={getNode} type={selectTypes?.MenuPlacerProps} />)}

### LoadingMessage

${(<ShowTypes getNode={getNode} type={selectTypes?.NoticeProps} />)}
Expand Down
2 changes: 1 addition & 1 deletion packages/react-select/src/Select.tsx
Expand Up @@ -10,7 +10,6 @@ import {
RefCallback,
TouchEventHandler,
} from 'react';
import { MenuPlacer } from './components/Menu';
import LiveRegion from './components/LiveRegion';

import { createFilter, FilterOptionOption } from './filters';
Expand Down Expand Up @@ -1791,6 +1790,7 @@ export default class Select<
Group,
GroupHeading,
Menu,
MenuPlacer,
MenuList,
MenuPortal,
LoadingMessage,
Expand Down
2 changes: 1 addition & 1 deletion packages/react-select/src/components/Menu.tsx
Expand Up @@ -238,7 +238,7 @@ export interface MenuProps<
children: ReactNode;
}

interface PlacerProps {
export interface PlacerProps {
placement: CoercedMenuPlacement;
maxHeight: number;
}
Expand Down
4 changes: 4 additions & 0 deletions packages/react-select/src/components/index.ts
Expand Up @@ -34,6 +34,8 @@ import Menu, {
MenuProps,
NoOptionsMessage,
NoticeProps,
MenuPlacer,
MenuPlacerProps,
} from './Menu';
import MultiValue, {
MultiValueContainer,
Expand Down Expand Up @@ -73,6 +75,7 @@ export interface SelectComponents<
LoadingIndicatorProps<Option, IsMulti, Group>
>;
Menu: ComponentType<MenuProps<Option, IsMulti, Group>>;
MenuPlacer: ComponentType<MenuPlacerProps<Option, IsMulti, Group>>;
MenuList: ComponentType<MenuListProps<Option, IsMulti, Group>>;
MenuPortal: ComponentType<MenuPortalProps<Option, IsMulti, Group>>;
LoadingMessage: ComponentType<NoticeProps<Option, IsMulti, Group>>;
Expand Down Expand Up @@ -113,6 +116,7 @@ export const components = {
Input: Input,
LoadingIndicator: LoadingIndicator,
Menu: Menu,
MenuPlacer: MenuPlacer,
MenuList: MenuList,
MenuPortal: MenuPortal,
LoadingMessage: LoadingMessage,
Expand Down
9 changes: 8 additions & 1 deletion packages/react-select/src/index.ts
Expand Up @@ -31,7 +31,14 @@ export type {
LoadingIndicatorProps,
} from './components/indicators';
export type { InputProps } from './components/Input';
export type { MenuListProps, MenuProps, NoticeProps } from './components/Menu';
export type {
MenuListProps,
MenuProps,
NoticeProps,
MenuPlacerProps,
PlacerProps,
} from './components/Menu';

export type {
MultiValueGenericProps,
MultiValueProps,
Expand Down