Skip to content

Commit 6d2edc7

Browse files
committed
feat(CPopover, CTooltip): add the delay property to enable the delay for the hide and show animations
1 parent 0524f30 commit 6d2edc7

File tree

2 files changed

+60
-10
lines changed

2 files changed

+60
-10
lines changed

packages/coreui-react/src/components/popover/CPopover.tsx

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'tit
2929
* Offset of the popover relative to its target.
3030
*/
3131
offset?: [number, number]
32+
/**
33+
* The delay for displaying and hiding the popover (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`.
34+
*
35+
* @since 4.9.0-beta.1
36+
*/
37+
delay?: number | { show: number; hide: number }
3238
/**
3339
* Callback fired when the component requests to be hidden.
3440
*/
@@ -76,6 +82,7 @@ export const CPopover: FC<CPopoverProps> = ({
7682
animation = true,
7783
className,
7884
content,
85+
delay = 0,
7986
offset = [0, 8],
8087
onHide,
8188
onShow,
@@ -90,6 +97,8 @@ export const CPopover: FC<CPopoverProps> = ({
9097
const { initPopper, destroyPopper } = usePopper()
9198
const [_visible, setVisible] = useState(visible)
9299

100+
const _delay = typeof delay === 'number' ? { show: delay, hide: delay } : delay
101+
93102
const popperConfig = {
94103
modifiers: [
95104
{
@@ -116,20 +125,29 @@ export const CPopover: FC<CPopoverProps> = ({
116125
}
117126
}, [_visible])
118127

128+
const toggleVisible = (visible: boolean) => {
129+
if (visible) {
130+
setTimeout(() => setVisible(true), _delay.show)
131+
return
132+
}
133+
134+
setTimeout(() => setVisible(false), _delay.hide)
135+
}
136+
119137
return (
120138
<>
121139
{React.cloneElement(children as React.ReactElement<any>, {
122140
ref: togglerRef,
123141
...((trigger === 'click' || trigger.includes('click')) && {
124-
onClick: () => setVisible(!_visible),
142+
onClick: () => toggleVisible(!_visible),
125143
}),
126144
...((trigger === 'focus' || trigger.includes('focus')) && {
127-
onFocus: () => setVisible(true),
128-
onBlur: () => setVisible(false),
145+
onFocus: () => toggleVisible(true),
146+
onBlur: () => toggleVisible(false),
129147
}),
130148
...((trigger === 'hover' || trigger.includes('hover')) && {
131-
onMouseEnter: () => setVisible(true),
132-
onMouseLeave: () => setVisible(false),
149+
onMouseEnter: () => toggleVisible(true),
150+
onMouseLeave: () => toggleVisible(false),
133151
}),
134152
})}
135153
{typeof window !== 'undefined' &&
@@ -178,6 +196,13 @@ CPopover.propTypes = {
178196
children: PropTypes.node,
179197
className: PropTypes.string,
180198
content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
199+
delay: PropTypes.oneOfType([
200+
PropTypes.number,
201+
PropTypes.shape({
202+
show: PropTypes.number.isRequired,
203+
hide: PropTypes.number.isRequired,
204+
}),
205+
]),
181206
offset: PropTypes.any, // TODO: find good proptype
182207
onHide: PropTypes.func,
183208
onShow: PropTypes.func,

packages/coreui-react/src/components/tooltip/CTooltip.tsx

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'con
2525
* Content node for your component.
2626
*/
2727
content: ReactNode | string
28+
/**
29+
* The delay for displaying and hiding the tooltip (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`.
30+
*
31+
* @since 4.9.0-beta.1
32+
*/
33+
delay?: number | { show: number; hide: number }
2834
/**
2935
* Offset of the tooltip relative to its target.
3036
*/
@@ -72,6 +78,7 @@ export const CTooltip: FC<CTooltipProps> = ({
7278
animation = true,
7379
className,
7480
content,
81+
delay = 0,
7582
offset = [0, 6],
7683
onHide,
7784
onShow,
@@ -85,6 +92,8 @@ export const CTooltip: FC<CTooltipProps> = ({
8592
const { initPopper, destroyPopper } = usePopper()
8693
const [_visible, setVisible] = useState(visible)
8794

95+
const _delay = typeof delay === 'number' ? { show: delay, hide: delay } : delay
96+
8897
const popperConfig = {
8998
modifiers: [
9099
{
@@ -111,20 +120,29 @@ export const CTooltip: FC<CTooltipProps> = ({
111120
}
112121
}, [_visible])
113122

123+
const toggleVisible = (visible: boolean) => {
124+
if (visible) {
125+
setTimeout(() => setVisible(true), _delay.show)
126+
return
127+
}
128+
129+
setTimeout(() => setVisible(false), _delay.hide)
130+
}
131+
114132
return (
115133
<>
116134
{React.cloneElement(children as React.ReactElement<any>, {
117135
ref: togglerRef,
118136
...((trigger === 'click' || trigger.includes('click')) && {
119-
onClick: () => setVisible(!_visible),
137+
onClick: () => toggleVisible(!_visible),
120138
}),
121139
...((trigger === 'focus' || trigger.includes('focus')) && {
122-
onFocus: () => setVisible(true),
123-
onBlur: () => setVisible(false),
140+
onFocus: () => toggleVisible(true),
141+
onBlur: () => toggleVisible(false),
124142
}),
125143
...((trigger === 'hover' || trigger.includes('hover')) && {
126-
onMouseEnter: () => setVisible(true),
127-
onMouseLeave: () => setVisible(false),
144+
onMouseEnter: () => toggleVisible(true),
145+
onMouseLeave: () => toggleVisible(false),
128146
}),
129147
})}
130148
{typeof window !== 'undefined' &&
@@ -170,6 +188,13 @@ CTooltip.propTypes = {
170188
animation: PropTypes.bool,
171189
children: PropTypes.node,
172190
content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
191+
delay: PropTypes.oneOfType([
192+
PropTypes.number,
193+
PropTypes.shape({
194+
show: PropTypes.number.isRequired,
195+
hide: PropTypes.number.isRequired,
196+
}),
197+
]),
173198
offset: PropTypes.any, // TODO: find good proptype
174199
onHide: PropTypes.func,
175200
onShow: PropTypes.func,

0 commit comments

Comments
 (0)