From 287ec869b5c2037b9ce2d217ec99709b7cb3b7b7 Mon Sep 17 00:00:00 2001 From: Uyarn Date: Tue, 25 Jul 2023 20:26:40 +0800 Subject: [PATCH] feat(dropdown): support panel top and bottom content --- src/dropdown/DropdownMenu.tsx | 29 ++++++++++++++++---- src/dropdown/_example/{icon.tsx => icon.jsx} | 0 src/dropdown/dropdown.en-US.md | 10 ++++--- src/dropdown/dropdown.md | 4 ++- src/dropdown/type.ts | 10 ++++++- 5 files changed, 41 insertions(+), 12 deletions(-) rename src/dropdown/_example/{icon.tsx => icon.jsx} (100%) diff --git a/src/dropdown/DropdownMenu.tsx b/src/dropdown/DropdownMenu.tsx index 5d4e0996d..f4bc18950 100644 --- a/src/dropdown/DropdownMenu.tsx +++ b/src/dropdown/DropdownMenu.tsx @@ -10,12 +10,20 @@ import { DropdownOption } from './type'; import useGlobalIcon from '../hooks/useGlobalIcon'; const DropdownMenu: React.FC = (props) => { - const { options = [], maxHeight = 300, minColumnWidth = 10, maxColumnWidth = 160, direction } = props; + const { + options = [], + maxHeight = 300, + minColumnWidth = 10, + maxColumnWidth = 160, + direction, + panelTopContent, + panelBottomContent, + } = props; const { classPrefix } = useConfig(); const dropdownClass = `${classPrefix}-dropdown`; const dropdownMenuClass = `${dropdownClass}__menu`; - + const [panelTopContentHeight, setPanelTopContentHeight] = useState(null); const { ChevronRightIcon, ChevronLeftIcon } = useGlobalIcon({ ChevronRightIcon: TdIconChevronRight, ChevronLeftIcon: TdIconChevronLeft, @@ -28,10 +36,16 @@ const DropdownMenu: React.FC = (props) => { useEffect(() => { if (menuRef.current) { const menuHeight = menuRef.current.childNodes?.length * 30; - + setTimeout(() => { + if (panelTopContent) { + const panelTopHeight = + parseInt(getComputedStyle(menuRef.current.childNodes?.[0] as HTMLElement)?.height, 10) || 0; + setPanelTopContentHeight(panelTopHeight); + } + }); if (menuHeight >= maxHeight) setIsOverMaxHeight(true); } - }, [maxHeight]); + }, [maxHeight, panelTopContent]); const handleItemClick = (options: { data: DropdownOption; @@ -56,7 +70,8 @@ const DropdownMenu: React.FC = (props) => { data.forEach?.((menu, idx) => { const optionItem = { ...(menu as DropdownOption) }; const onViewIdx = Math.ceil(calcScrollTopMap[deep] / 30); - const itemIdx = idx >= onViewIdx ? idx - onViewIdx : idx; + const isOverflow = idx >= onViewIdx; + const itemIdx = isOverflow ? idx - onViewIdx : idx; if (optionItem.children) { optionItem.children = renderOptions(optionItem.children, deep + 1); renderContent = ( @@ -92,7 +107,7 @@ const DropdownMenu: React.FC = (props) => { })} style={{ position: 'absolute', - top: `${itemIdx * 30}px`, + top: `${itemIdx * 30 + (isOverflow ? 0 : panelTopContentHeight)}px`, }} >
= (props) => { ref={menuRef} onScroll={throttleUpdate} > + {panelTopContent ?
{panelTopContent}
: null} {renderOptions(options, 0)} + {panelBottomContent ?
{panelBottomContent}
: null}
); }; diff --git a/src/dropdown/_example/icon.tsx b/src/dropdown/_example/icon.jsx similarity index 100% rename from src/dropdown/_example/icon.tsx rename to src/dropdown/_example/icon.jsx diff --git a/src/dropdown/dropdown.en-US.md b/src/dropdown/dropdown.en-US.md index 9dfe2b4b0..121b17d41 100644 --- a/src/dropdown/dropdown.en-US.md +++ b/src/dropdown/dropdown.en-US.md @@ -7,16 +7,18 @@ name | type | default | description | required -- | -- | -- | -- | -- className | String | - | 类名 | N style | Object | - | 样式,Typescript:`React.CSSProperties` | N -direction | String | right | options:left/right | N +direction | String | right | options: left/right | N disabled | Boolean | false | \- | N hideAfterItemClick | Boolean | true | \- | N maxColumnWidth | String / Number | 100 | \- | N maxHeight | Number | 300 | \- | N minColumnWidth | String / Number | 10 | \- | N options | Array | [] | Typescript:`Array` `type DropdownOption = { children?: Array } & TdDropdownItemProps & Record`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/dropdown/type.ts) | N -placement | String | bottom-left | options:top/left/right/bottom/top-left/top-right/bottom-left/bottom-right/left-top/left-bottom/right-top/right-bottom | N +panelBottomContent | TNode | - | bottom content of the dropdown panel。Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N +panelTopContent | TNode | - | top content of the dropdown panel。Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N +placement | String | bottom-left | options: top/left/right/bottom/top-left/top-right/bottom-left/bottom-right/left-top/left-bottom/right-top/right-bottom | N popupProps | Object | - | Typescript:`PopupProps`,[Popup API Documents](./popup?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/dropdown/type.ts) | N -trigger | String | hover | options:hover/click/focus/context-menu | N +trigger | String | hover | options: hover/click/focus/context-menu | N onClick | Function | | Typescript:`(dropdownItem: DropdownOption, context: { e: MouseEvent }) => void`
| N ### DropdownItem Props @@ -30,6 +32,6 @@ content | TNode | '' | Typescript:`string \| TNode`。[see more ts definition] disabled | Boolean | false | \- | N divider | Boolean | false | \- | N prefixIcon | TElement | - | Typescript:`TNode`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N -theme | String | default | options:default/success/warning/error。Typescript:`DropdownItemTheme` `type DropdownItemTheme = 'default' \| 'success' \| 'warning' \| 'error'`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/dropdown/type.ts) | N +theme | String | default | options: default/success/warning/error。Typescript:`DropdownItemTheme` `type DropdownItemTheme = 'default' \| 'success' \| 'warning' \| 'error'`。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/dropdown-menu/type.ts) | N value | String / Number / Object | - | Typescript:`string \| number \| { [key: string]: any }` | N onClick | Function | | Typescript:`(dropdownItem: DropdownOption, context: { e: MouseEvent }) => void`
| N diff --git a/src/dropdown/dropdown.md b/src/dropdown/dropdown.md index 16e15e7eb..6d44f63f7 100644 --- a/src/dropdown/dropdown.md +++ b/src/dropdown/dropdown.md @@ -20,6 +20,8 @@ maxColumnWidth | String / Number | 100 | 选项最大宽度,内容超出时, maxHeight | Number | 300 | 弹窗最大高度,单位:px 。统一控制每一列的高度 | N minColumnWidth | String / Number | 10 | 选项最小宽度。值为字符串时,值就是最小宽度;值为数字时,单位:px | N options | Array | [] | 下拉操作项。TS 类型:`Array` `type DropdownOption = { children?: Array } & TdDropdownItemProps & Record`。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/dropdown/type.ts) | N +panelBottomContent | TNode | - | 面板内的底部内容。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N +panelTopContent | TNode | - | 面板内的顶部内容。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N placement | String | bottom-left | 弹窗定位方式,可选值同 Popup 组件。可选项:top/left/right/bottom/top-left/top-right/bottom-left/bottom-right/left-top/left-bottom/right-top/right-bottom | N popupProps | Object | - | 透传 Popup 组件属性,方便更加自由地控制。比如使用 popupProps.overlayStyle 设置浮层样式。TS 类型:`PopupProps`,[Popup API Documents](./popup?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/dropdown/type.ts) | N trigger | String | hover | 触发下拉显示的方式。可选项:hover/click/focus/context-menu | N @@ -36,6 +38,6 @@ content | TNode | '' | 下拉操作项内容。TS 类型:`string \| TNode`。[ disabled | Boolean | false | 是否禁用操作项 | N divider | Boolean | false | 是否显示操作项之间的分隔线(分隔线默认在下方) | N prefixIcon | TElement | - | 组件前置图标。TS 类型:`TNode`。[通用类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N -theme | String | default | 下拉菜单选项主题。可选项:default/success/warning/error。TS 类型:`DropdownItemTheme` `type DropdownItemTheme = 'default' \| 'success' \| 'warning' \| 'error'`。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/dropdown/type.ts) | N +theme | String | default | 下拉菜单选项主题。可选项:default/success/warning/error。TS 类型:`DropdownItemTheme` `type DropdownItemTheme = 'default' \| 'success' \| 'warning' \| 'error'`。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/dropdown-menu/type.ts) | N value | String / Number / Object | - | 下拉操作项唯一标识。TS 类型:`string \| number \| { [key: string]: any }` | N onClick | Function | | TS 类型:`(dropdownItem: DropdownOption, context: { e: MouseEvent }) => void`
点击时触发 | N diff --git a/src/dropdown/type.ts b/src/dropdown/type.ts index 5a1edfbff..370dbb2db 100644 --- a/src/dropdown/type.ts +++ b/src/dropdown/type.ts @@ -44,6 +44,14 @@ export interface TdDropdownProps { * @default [] */ options?: Array; + /** + * 面板内的底部内容 + */ + panelBottomContent?: TNode; + /** + * 面板内的顶部内容 + */ + panelTopContent?: TNode; /** * 弹窗定位方式,可选值同 Popup 组件 * @default bottom-left @@ -100,7 +108,7 @@ export interface TdDropdownItemProps { /** * 组件前置图标 */ - prefixIcon?: TNode; + prefixIcon?: TElement; /** * 下拉菜单选项主题 * @default default