From cc87607dcd7e13d041788c8b3235264b1ed53bc4 Mon Sep 17 00:00:00 2001 From: xiexiejie Date: Tue, 10 Dec 2024 17:27:33 +0800 Subject: [PATCH 1/3] feat: Add the offsetSpacing property to the Tooltip and Popover components to control the distance between the overlay and the target element. --- packages/bui-core/src/Popover/Popover.tsx | 2 + .../bui-core/src/Popover/Popover.types.ts | 4 ++ packages/bui-core/src/Popover/index.en-US.md | 46 ++++++++++++++----- packages/bui-core/src/Popover/index.zh-CN.md | 38 +++++++++++---- packages/bui-core/src/Tooltip/Tooltip.tsx | 2 + .../bui-core/src/Tooltip/Tooltip.types.ts | 4 ++ packages/bui-core/src/Tooltip/index.en-US.md | 36 +++++++++++---- packages/bui-core/src/Tooltip/index.zh-CN.md | 34 ++++++++++---- .../bui-utils/src/directionLocationUtil.ts | 22 +++++---- 9 files changed, 141 insertions(+), 47 deletions(-) diff --git a/packages/bui-core/src/Popover/Popover.tsx b/packages/bui-core/src/Popover/Popover.tsx index c18f79be..cd729225 100644 --- a/packages/bui-core/src/Popover/Popover.tsx +++ b/packages/bui-core/src/Popover/Popover.tsx @@ -20,6 +20,7 @@ const Popover = React.forwardRef((props, ref) => { title, content, defaultOpen, + offsetSpacing = 0, placement = 'top', trigger = 'click', onOpenChange, @@ -86,6 +87,7 @@ const Popover = React.forwardRef((props, ref) => { childrenRef, arrowDirection, arrowLocation, + offsetSpacing, selector: `[data-id="tt_${ttId}"]`, }); if (!result) return; diff --git a/packages/bui-core/src/Popover/Popover.types.ts b/packages/bui-core/src/Popover/Popover.types.ts index 4c6f0a7e..7f21d314 100644 --- a/packages/bui-core/src/Popover/Popover.types.ts +++ b/packages/bui-core/src/Popover/Popover.types.ts @@ -31,6 +31,10 @@ export type PopoverProps< * @default false */ hideArrow?: boolean; + /** + * 用于控制浮层和目标元素偏移量 + */ + offsetSpacing?: number; /** * 气泡框位置 * @default 'top' diff --git a/packages/bui-core/src/Popover/index.en-US.md b/packages/bui-core/src/Popover/index.en-US.md index 66ffe8e1..371af831 100644 --- a/packages/bui-core/src/Popover/index.en-US.md +++ b/packages/bui-core/src/Popover/index.en-US.md @@ -19,7 +19,11 @@ import React from 'react'; export default () => { return ( - + click显示 ); @@ -61,6 +65,23 @@ export default () => { }; ``` +### OffsetSpacing is the interval between the floating layer and the target element + +OffsetSpacing can be set to control the distance from the target element + +```tsx +import { Popover } from '@bifrostui/react'; +import React from 'react'; + +export default () => { + return ( + + offsetSpacing控制目标间隔(设置20 以便观察) + + ); +}; +``` + ### HideArrow arrow display You can set 'hideArrow' to true to hide arrows @@ -80,7 +101,7 @@ export default () => { ### Placement Bubble Box Position -Placement: Set the position of the bubble float layer. The optional values are: top, left, right, bottom, topLeft, topRight, bottomLeft, bottomRight, leftTop, leftBottom, rightTop, rightBottom +Placement: Set the position of the bubble float layer. The optional values are: top left right bottom topLeft topRight bottomLeft bottomRight leftTop leftBottom rightTop rightBottom ```tsx import { Popover, Button } from '@bifrostui/react'; @@ -232,16 +253,17 @@ export default () => { ### API -| attribute | explain | type | Default value | -| ------------ | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -| title | Title of Bubble Floating Layer Floating Layer Content | ReactNode | - | -| content | Content of Bubble Floating Layer | ReactNode | - | -| defaultOpen | Whether to hide by default | boolean | false | -| open | Used for manually controlling the appearance and concealment of bubble floating layers | boolean | - | -| hideArrow | Display arrows or not | boolean | false | -| placement | Bubble box position | String, the enumeration value is `center` `left` `leftTop` `leftBottom` `right` `rightTop` `rightBottom` `top` `topLeft` `topRight` `bottom` `bottomLeft` `bottomRight` `bottom` | 'top' | -| trigger | Trigger behavior | string \|String [], the enumeration value is' click '\|'hover' | 'click' | -| onOpenChange | The callback method for bubble floating layer manifestation and concealment | (e: React.MouseEvent,data: {open: boolean}) => void | - | +| attribute | explain | type | Default value | +| ------------- | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | +| title | Title of Bubble Floating Layer Floating Layer Content | ReactNode | - | +| content | Content of Bubble Floating Layer | ReactNode | - | +| defaultOpen | Whether to hide by default | boolean | false | +| open | Used for manually controlling the appearance and concealment of bubble floating layers | boolean | - | +| hideArrow | Display arrows or not | boolean | false | +| offsetSpacing | The offset between the floating layer and the target element | number | 0 | +| placement | Bubble box position | string, The enumeration value is `center` `left` `leftTop` `leftBottom` `right` `rightTop` `rightBottom` `top` `topLeft` `topRight` `bottom` `bottomLeft` `bottomRight` `bottom` | 'top' | +| trigger | Trigger behavior | string \|string[], The enumeration value is' click '\|'hover' | 'click' | +| onOpenChange | The callback method for bubble floating layer manifestation and concealment | (e: React.MouseEvent,data: {open: boolean}) => void | - | ### Style variables diff --git a/packages/bui-core/src/Popover/index.zh-CN.md b/packages/bui-core/src/Popover/index.zh-CN.md index db08a595..7ffa354e 100644 --- a/packages/bui-core/src/Popover/index.zh-CN.md +++ b/packages/bui-core/src/Popover/index.zh-CN.md @@ -65,6 +65,23 @@ export default () => { }; ``` +### offsetSpacing 浮层和目标元素间隔 + +可以设置offsetSpacing来控制和目标元素的距离 + +```tsx +import { Popover } from '@bifrostui/react'; +import React from 'react'; + +export default () => { + return ( + + offsetSpacing控制目标间隔(设置20 以便观察) + + ); +}; +``` + ### hideArrow 箭头展示 可以设置 `hideArrow` 为 true 隐藏箭头 @@ -236,16 +253,17 @@ export default () => { ### API -| 属性 | 说明 | 类型 | 默认值 | -| ------------ | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -| title | 气泡浮层的标题浮层内容 | ReactNode | - | -| content | 气泡浮层的内容 | ReactNode | - | -| defaultOpen | 默认是否显隐 | boolean | false | -| open | 用于手动控制气泡浮层显隐 | boolean | - | -| hideArrow | 是否展示箭头 | boolean | false | -| placement | 气泡框位置 | string,枚举值是 `center` `left` `leftTop` `leftBottom` `right` `rightTop` `rightBottom` `top` `topLeft` `topRight` `bottom` `bottomLeft` `bottomRight` `bottom` | 'top' | -| trigger | 触发行为 | string \| string[],枚举值是 'click' \| 'hover' | 'click' | -| onOpenChange | 气泡浮层显隐的回调方法 | (e: React.MouseEvent,data: {open: boolean}) => void | - | +| 属性 | 说明 | 类型 | 默认值 | +| ------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| title | 气泡浮层的标题浮层内容 | ReactNode | - | +| content | 气泡浮层的内容 | ReactNode | - | +| defaultOpen | 默认是否显隐 | boolean | false | +| open | 用于手动控制气泡浮层显隐 | boolean | - | +| hideArrow | 是否展示箭头 | boolean | false | +| offsetSpacing | 浮层与目标元素的偏移量 | number | 0 | +| placement | 气泡框位置 | string,枚举值是 `center` `left` `leftTop` `leftBottom` `right` `rightTop` `rightBottom` `top` `topLeft` `topRight` `bottom` `bottomLeft` `bottomRight` `bottom` | 'top' | +| trigger | 触发行为 | string \| string[],枚举值是 'click' \| 'hover' | 'click' | +| onOpenChange | 气泡浮层显隐的回调方法 | (e: React.MouseEvent,data: {open: boolean}) => void | - | ### 样式变量 diff --git a/packages/bui-core/src/Tooltip/Tooltip.tsx b/packages/bui-core/src/Tooltip/Tooltip.tsx index cad12bdb..c2c43bd5 100644 --- a/packages/bui-core/src/Tooltip/Tooltip.tsx +++ b/packages/bui-core/src/Tooltip/Tooltip.tsx @@ -19,6 +19,7 @@ const Tooltip = React.forwardRef((props, ref) => { children, title, defaultOpen, + offsetSpacing = 0, placement = 'top', trigger = 'click', onOpenChange, @@ -84,6 +85,7 @@ const Tooltip = React.forwardRef((props, ref) => { childrenRef, arrowDirection, arrowLocation, + offsetSpacing, selector: `[data-id="tt_${ttId}"]`, }); if (!result) return; diff --git a/packages/bui-core/src/Tooltip/Tooltip.types.ts b/packages/bui-core/src/Tooltip/Tooltip.types.ts index 1a924e2c..0e45dbfe 100644 --- a/packages/bui-core/src/Tooltip/Tooltip.types.ts +++ b/packages/bui-core/src/Tooltip/Tooltip.types.ts @@ -22,6 +22,10 @@ export type TooltipProps< * 用于手动控制气泡浮层显隐 */ open?: boolean; + /** + * 用于控制气泡浮层和目标元素偏移量 + */ + offsetSpacing?: number; /** * 气泡框位置 * @default 'top' diff --git a/packages/bui-core/src/Tooltip/index.en-US.md b/packages/bui-core/src/Tooltip/index.en-US.md index c7778344..52cf8888 100644 --- a/packages/bui-core/src/Tooltip/index.en-US.md +++ b/packages/bui-core/src/Tooltip/index.en-US.md @@ -61,6 +61,23 @@ export default () => { }; ``` +### OffsetSpacing is the interval between the floating layer and the target element + +OffsetSpacing can be set to control the distance from the target element + +```tsx +import { Tooltip } from '@bifrostui/react'; +import React from 'react'; + +export default () => { + return ( + + offsetSpacing控制目标间隔(设置20 以便观察) + + ); +}; +``` + ### Placement Bubble Box Position placement设置气泡浮层的位置,可选 top left right bottom topLeft topRight bottomLeft bottomRight leftTop leftBottom rightTop rightBottom @@ -184,7 +201,7 @@ import React from 'react'; export default () => { return ( - + hover触发方式 ); @@ -215,14 +232,15 @@ export default () => { ### API -| attribute | explain | type | Default value | -| ------------ | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -| title | Bubble floating layer content | string | - | -| defaultOpen | Whether to hide by default | boolean | false | -| open | Used for manually controlling the appearance and concealment of bubble floating layers | boolean | - | -| placement | Bubble box position | String, the enumeration value is `center` `left` `leftTop` `leftBottom` `right` `rightTop` `rightBottom` `top` `topLeft` `topRight` `bottom` `bottomLeft` `bottomRight` `bottom` | 'top' | -| trigger | Trigger behavior | string \|String [], the enumeration value is' click '\|'hover' | 'click' | -| onOpenChange | The callback method for bubble floating layer manifestation and concealment | (e: React.MouseEvent,data: {open: boolean}) => void | - | +| attribute | explain | type | Default value | +| ------------- | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | +| title | Bubble floating layer content | string | - | +| defaultOpen | Whether to hide by default | boolean | false | +| open | Used for manually controlling the appearance and concealment of bubble floating layers | boolean | - | +| offsetSpacing | The offset between the floating layer and the target element | number | 0 | +| placement | Bubble box position | string, The enumeration value is `center` `left` `leftTop` `leftBottom` `right` `rightTop` `rightBottom` `top` `topLeft` `topRight` `bottom` `bottomLeft` `bottomRight` `bottom` | 'top' | +| trigger | Trigger behavior | string \|string[], The enumeration value is' click '\|'hover' | 'click' | +| onOpenChange | The callback method for bubble floating layer manifestation and concealment | (e: React.MouseEvent,data: {open: boolean}) => void | - | ### Style variables diff --git a/packages/bui-core/src/Tooltip/index.zh-CN.md b/packages/bui-core/src/Tooltip/index.zh-CN.md index 9af87b19..d83c4f87 100644 --- a/packages/bui-core/src/Tooltip/index.zh-CN.md +++ b/packages/bui-core/src/Tooltip/index.zh-CN.md @@ -61,6 +61,23 @@ export default () => { }; ``` +### offsetSpacing 浮层和目标元素间隔 + +可以设置offsetSpacing来控制和目标元素的距离 + +```tsx +import { Tooltip } from '@bifrostui/react'; +import React from 'react'; + +export default () => { + return ( + + offsetSpacing控制目标间隔(设置20 以便观察) + + ); +}; +``` + ### placement 气泡框位置 placement设置气泡浮层的位置,可选 top left right bottom topLeft topRight bottomLeft bottomRight leftTop leftBottom rightTop rightBottom @@ -215,14 +232,15 @@ export default () => { ### API -| 属性 | 说明 | 类型 | 默认值 | -| ------------ | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -| title | 气泡浮层内容 | string | - | -| defaultOpen | 默认是否显隐 | boolean | false | -| open | 用于手动控制气泡浮层显隐 | boolean | - | -| placement | 气泡框位置 | string,枚举值是 `center` `left` `leftTop` `leftBottom` `right` `rightTop` `rightBottom` `top` `topLeft` `topRight` `bottom` `bottomLeft` `bottomRight` `bottom` | 'top' | -| trigger | 触发行为 | string \| string[],枚举值是 'click' \| 'hover' | 'click' | -| onOpenChange | 气泡浮层显隐的回调方法 | (e: React.MouseEvent,data: {open: boolean}) => void | - | +| 属性 | 说明 | 类型 | 默认值 | +| ------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| title | 气泡浮层内容 | string | - | +| defaultOpen | 默认是否显隐 | boolean | false | +| open | 用于手动控制气泡浮层显隐 | boolean | - | +| offsetSpacing | 浮层与目标元素的偏移量 | number | 0 | +| placement | 气泡框位置 | string,枚举值是 `center` `left` `leftTop` `leftBottom` `right` `rightTop` `rightBottom` `top` `topLeft` `topRight` `bottom` `bottomLeft` `bottomRight` `bottom` | 'top' | +| trigger | 触发行为 | string \| string[],枚举值是 'click' \| 'hover' | 'click' | +| onOpenChange | 气泡浮层显隐的回调方法 | (e: React.MouseEvent,data: {open: boolean}) => void | - | ### 样式变量 diff --git a/packages/bui-utils/src/directionLocationUtil.ts b/packages/bui-utils/src/directionLocationUtil.ts index 8f8eb43e..86fa62f9 100644 --- a/packages/bui-utils/src/directionLocationUtil.ts +++ b/packages/bui-utils/src/directionLocationUtil.ts @@ -13,6 +13,7 @@ export const getNewDirectionLocation = ({ arrowDirection, tipOffset, arrowLocation, + offsetSpacing, }) => { const { left: cLeft, right: cRight, top: cTop, bottom: cBottom } = rootOffset; const { width, height } = tipOffset; @@ -31,11 +32,12 @@ export const getNewDirectionLocation = ({ const isDirectionRight = arrowDirection === 'right'; if ( - (isDirectionTop && cTop - height < 0) || - (isDirectionBottom && cBottom + height > pgegHeight) || - (isDirectionLeft && cLeft - width < 0) || - (isDirectionRight && cRight + width > pgegWidth) + (isDirectionTop && cTop - height - offsetSpacing < 0) || + (isDirectionBottom && cBottom + height + offsetSpacing > pgegHeight) || + (isDirectionLeft && cLeft - width - offsetSpacing < 0) || + (isDirectionRight && cRight + width + offsetSpacing > pgegWidth) ) { + // 计算气泡超过编辑之后 到反方向去 newArrowDirection = directionCssMap[arrowDirection]; } @@ -79,6 +81,7 @@ export const getDirectionLocationStyle = ({ arrowDirection, tipOffset, arrowLocation, + offsetSpacing, }) => { const scrollTop = (window.scrollY >= 0 && window.scrollY) || @@ -99,7 +102,7 @@ export const getDirectionLocationStyle = ({ } = rootOffset; const { width, height } = tipOffset; if (arrowDirection === 'top') { - styles.top = cTop; + styles.top = cTop - offsetSpacing; styles.transform = `translateY(-100%)`; switch (arrowLocation) { case 'left': @@ -116,7 +119,7 @@ export const getDirectionLocationStyle = ({ break; } } else if (arrowDirection === 'bottom') { - styles.top = cBottom; + styles.top = cBottom + offsetSpacing; switch (arrowLocation) { case 'left': styles.left = cLeft; @@ -132,7 +135,7 @@ export const getDirectionLocationStyle = ({ break; } } else if (arrowDirection === 'left') { - styles.left = cLeft; + styles.left = cLeft - offsetSpacing; styles.transform = `translateX(-100%)`; switch (arrowLocation) { case 'top': @@ -149,7 +152,7 @@ export const getDirectionLocationStyle = ({ break; } } else if (arrowDirection === 'right') { - styles.left = cRight; + styles.left = cRight + offsetSpacing; switch (arrowLocation) { case 'top': styles.top = cTop; @@ -184,6 +187,7 @@ export const getStylesAndLocation = ({ childrenRef, arrowDirection, arrowLocation, + offsetSpacing, selector, }) => { if (!childrenRef?.current) { @@ -201,6 +205,7 @@ export const getStylesAndLocation = ({ arrowDirection, tipOffset, arrowLocation, + offsetSpacing, }); const styles = getDirectionLocationStyle({ @@ -208,6 +213,7 @@ export const getStylesAndLocation = ({ arrowDirection: newArrowDirection, tipOffset, arrowLocation: newArrowLocation, + offsetSpacing, }); styles.visibility = 'visible'; From a8526dcb25d58152819c483be54fa76429be4620 Mon Sep 17 00:00:00 2001 From: xiexiejie Date: Wed, 11 Dec 2024 14:38:46 +0800 Subject: [PATCH 2/3] feat: Optimize the height issue of the Tooltip component. --- packages/bui-utils/src/directionLocationUtil.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/bui-utils/src/directionLocationUtil.ts b/packages/bui-utils/src/directionLocationUtil.ts index 86fa62f9..9cefe354 100644 --- a/packages/bui-utils/src/directionLocationUtil.ts +++ b/packages/bui-utils/src/directionLocationUtil.ts @@ -174,9 +174,8 @@ export const getDirectionLocationStyle = ({ if (styles.left) { styles.left = `${styles.left + scrollLeft}px`; } - // 此处设置宽高是为了防止left和transform导致气泡宽高显示错误 + // 此处设置宽高是为了防止left和transform导致气泡宽度显示错误 styles.width = `${width}px`; - styles.height = `${height}px`; return styles; }; From 2208687d3444472529fc1a3240772fc9c6ef8236 Mon Sep 17 00:00:00 2001 From: xiexiejie Date: Fri, 13 Dec 2024 16:19:35 +0800 Subject: [PATCH 3/3] fix: Tooltip and Popover Fixing centering calculation issues --- .../bui-utils/src/directionLocationUtil.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/bui-utils/src/directionLocationUtil.ts b/packages/bui-utils/src/directionLocationUtil.ts index 9cefe354..8536bd1a 100644 --- a/packages/bui-utils/src/directionLocationUtil.ts +++ b/packages/bui-utils/src/directionLocationUtil.ts @@ -15,7 +15,14 @@ export const getNewDirectionLocation = ({ arrowLocation, offsetSpacing, }) => { - const { left: cLeft, right: cRight, top: cTop, bottom: cBottom } = rootOffset; + const { + left: cLeft, + right: cRight, + top: cTop, + bottom: cBottom, + width: cWidth, + height: cHeight, + } = rootOffset; const { width, height } = tipOffset; const pgegWidth = document.documentElement.clientWidth || document.body.clientWidth; @@ -54,15 +61,17 @@ export const getNewDirectionLocation = ({ const isCenter = arrowLocation === 'center'; // 箭头在中间的情况,是否超过边界 if (isCenter && (isDirectionTop || isDirectionBottom)) { - if (cLeft + width > pgegWidth) { + // cLeft + (cWidth - width) / 2 代表浮层最左侧的坐标 + if (cLeft + (cWidth - width) / 2 + width > pgegWidth) { newArrowLocation = directionCssMap.left; - } else if (cRight - width < 0) { + } else if (cLeft + (cWidth - width) / 2 < 0) { newArrowLocation = directionCssMap.right; } } else if (isCenter && (isDirectionLeft || isDirectionRight)) { - if (cTop + height > pgegHeight) { + // cTop + (cHeight - height) / 2 代表浮层最上侧的坐标 + if (cTop + (cHeight - height) / 2 + cHeight > pgegHeight) { newArrowLocation = directionCssMap.top; - } else if (cBottom - height < 0) { + } else if (cTop + (cHeight - height) / 2 < 0) { newArrowLocation = directionCssMap.bottom; } }