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

feat(plasma-new-hope): Added prop 'portal' into Dropdown component #1260

Merged
merged 1 commit into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 23 additions & 28 deletions packages/plasma-new-hope/src/components/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { useHashMaps } from './hooks/useHashMaps';
/**
* Выпадающий список.
*/
export const dropdownRoot = (Root: RootProps<HTMLDivElement, DropdownProps>) =>
export const dropdownRoot = (Root: RootProps<HTMLDivElement, Omit<DropdownProps, 'items'>>) =>
forwardRef<HTMLDivElement, DropdownProps>(
(
{
Expand All @@ -42,6 +42,7 @@ export const dropdownRoot = (Root: RootProps<HTMLDivElement, DropdownProps>) =>
trigger = 'click',
variant = 'normal',
hasArrow = true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а почему проп просто portal ? почему не hasPortal или там usePortal ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hasPortal - boolean, не то
usePortal - так хук называется
frame - непонятно че за фрейм
portalRef - неплохо, но Popover принимает еще и строку

поэтому я решил оставить просто portal, не вижу в этом проблем

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А господи я решил что это hasPortal,
типа это свойство на случай если ты хочешь конкретно куда указать, а по умолчанию портал есть ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Что значит по-умолчанию? Если не прокидывать portal - то его и не будет, если прокинуть - то будет.

portal,
...rest
},
ref,
Expand Down Expand Up @@ -85,32 +86,26 @@ export const dropdownRoot = (Root: RootProps<HTMLDivElement, DropdownProps>) =>
};

return (
<Root
className={cx(className, classes.dropdownRoot)}
ref={ref}
view={view}
size={size}
items={items}
{...rest}
<StyledPopover
isOpen={isCurrentListOpen}
onToggle={handleGlobalToggle}
offset={offset}
placement={getPlacements(placement)}
trigger={trigger}
closeOnOverlayClick={closeOnOverlayClick}
isFocusTrapped={false}
target={childrenWithProps(children, {
role: 'combobox',
'aria-controls': 'tree_level_1',
'aria-expanded': isCurrentListOpen,
'aria-activedescendant': getActiveDescendant(),
onKeyDown,
})}
preventOverflow={false}
usePortal={Boolean(portal)}
frame={portal}
>
<StyledPopover
isOpen={isCurrentListOpen}
usePortal={false}
onToggle={handleGlobalToggle}
offset={offset}
placement={getPlacements(placement)}
trigger={trigger}
closeOnOverlayClick={closeOnOverlayClick}
isFocusTrapped={false}
target={childrenWithProps(children, {
role: 'combobox',
'aria-controls': 'tree_level_1',
'aria-expanded': isCurrentListOpen,
'aria-activedescendant': getActiveDescendant(),
onKeyDown,
})}
preventOverflow={false}
>
<Root className={cx(className, classes.dropdownRoot)} ref={ref} view={view} size={size} {...rest}>
<Ul
listHeight={listHeight}
listOverflow={listOverflow}
Expand Down Expand Up @@ -142,8 +137,8 @@ export const dropdownRoot = (Root: RootProps<HTMLDivElement, DropdownProps>) =>
/>
))}
</Ul>
</StyledPopover>
</Root>
</Root>
</StyledPopover>
);
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ export interface DropdownProps extends HTMLAttributes<HTMLDivElement> {
* @default normal
*/
variant?: 'normal' | 'tight';
/**
* Портал для выпадающего списка. Принимает id контейнера или ref.
*/
portal?: string | React.RefObject<HTMLElement>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а в итоге на тэг нельзя ссылаться? portal='body' не сработает?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не, только document


/**
* Обработчик клика по item.
* @deprecated использовать onItemSelect.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@ export const popoverRoot = (Root: RootProps<HTMLDivElement, PopoverProps>) =>
if (isOpen && closeOnOverlayClick && onToggle) {
const targetIsRoot = event.target === rootRef.current;
const rootHasTarget = rootRef.current?.contains(event.target as Element);
const popoverRootHasTarget = popoverRef.current?.contains(event.target as Element);

if (!targetIsRoot && !rootHasTarget) {
if (!targetIsRoot && !rootHasTarget && !popoverRootHasTarget) {
onToggle(false, event);
}
}
Expand Down
54 changes: 53 additions & 1 deletion website/plasma-web-docs/docs/components/Dropdown.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,6 @@ type Items = Array<{
},
];


return (
<div style={{ height:"300px" }}>
<Dropdown
Expand All @@ -320,6 +319,59 @@ type Items = Array<{
}
```
</TabItem>

<TabItem value="portal" label="Portal">
Иногда возникает необходимость вынесения выпадающего списка на уровни выше в DOM. К примеру, когда у родительского блока имеется скролл, и список будет обрезаться, чего хотелось бы избежать.\
Для такой реализации имеется пропс `portal`, который принимает либо `ref` либо `id` html-тега.

```tsx live
import React, { useRef } from 'react';
import { Select } from '@salutejs/plasma-web';

export function App() {
const items = [
{
value: 'north_america',
label: 'Северная Америка',
},
{
value: 'south_america',
label: 'Южная Америка',
items: [
{
value: 'brazil',
label: 'Бразилия',
items: [
{
value: 'rio_de_janeiro',
label: 'Рио-де-Жанейро',
},
{
value: 'sao_paulo',
label: 'Сан-Паулу',
},
],
},
{
value: 'argentina',
label: 'Аргентина',
},
],
},
];

const ref = useRef(null)

return (
<div style={{ height: '300px' }} ref={ref}>
<Dropdown items={items} portal={ref}>
<Button text="Список стран" />
</Dropdown>
</div>
);
}
```
</TabItem>
</Tabs>

## Клавиатурная навигация
Expand Down
53 changes: 53 additions & 0 deletions website/sdds-serv-docs/docs/components/Dropdown.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,59 @@ type Items = Array<{
}
```
</TabItem>

<TabItem value="portal" label="Portal">
Иногда возникает необходимость вынесения выпадающего списка на уровни выше в DOM. К примеру, когда у родительского блока имеется скролл, и список будет обрезаться, чего хотелось бы избежать.\
Для такой реализации имеется пропс `portal`, который принимает либо `ref` либо `id` html-тега.

```tsx live
import React, { useRef } from 'react';
import { Select } from '@salutejs/sdds-serv';

export function App() {
const items = [
{
value: 'north_america',
label: 'Северная Америка',
},
{
value: 'south_america',
label: 'Южная Америка',
items: [
{
value: 'brazil',
label: 'Бразилия',
items: [
{
value: 'rio_de_janeiro',
label: 'Рио-де-Жанейро',
},
{
value: 'sao_paulo',
label: 'Сан-Паулу',
},
],
},
{
value: 'argentina',
label: 'Аргентина',
},
],
},
];

const ref = useRef(null)

return (
<div style={{ height: '300px' }} ref={ref}>
<Dropdown items={items} portal={ref}>
<Button text="Список стран" />
</Dropdown>
</div>
);
}
```
</TabItem>
</Tabs>

## Клавиатурная навигация
Expand Down
Loading