Skip to content

Commit

Permalink
Make MenuPlacer component customizable and switchable.
Browse files Browse the repository at this point in the history
  • Loading branch information
kkamik committed Apr 27, 2022
1 parent fe7dab3 commit 3de79ec
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 4 deletions.
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

0 comments on commit 3de79ec

Please sign in to comment.