diff --git a/demo/index.js b/demo/index.js index aa629fc..f8dbb3c 100644 --- a/demo/index.js +++ b/demo/index.js @@ -117,14 +117,21 @@ class ComponentChild extends React.Component { class App extends React.Component { state = { arrow: false, + customClass: '' } toggleArrow = () => { this.setState(state => ({ - arrow: !state.arrow, + arrow: !state.arrow })) } + updateCustomClass = (e) => { + this.setState({ + customClass: e.target.value + }) + } + render() { return (
@@ -165,6 +172,12 @@ class App extends React.Component { + +

Other

+ + + +
) } diff --git a/index.d.ts b/index.d.ts index c9ad244..0358537 100644 --- a/index.d.ts +++ b/index.d.ts @@ -9,6 +9,7 @@ export interface TippyProps extends Omit { onCreate?: (tip: Instance) => void isVisible?: boolean isEnabled?: boolean + className?: string } declare const Tippy: React.ForwardRefExoticComponent diff --git a/src/Tippy.js b/src/Tippy.js index 8ae580d..41c88f2 100644 --- a/src/Tippy.js +++ b/src/Tippy.js @@ -4,6 +4,7 @@ import React, { useState, useRef, useEffect, + useLayoutEffect, } from 'react' import { createPortal } from 'react-dom' import PropTypes from 'prop-types' @@ -13,6 +14,7 @@ import { hasOwnProperty, ssrSafeCreateDiv, preserveRef, + updateClassName, } from './utils' function Tippy(props) { @@ -33,12 +35,17 @@ function Tippy(props) { useEffect(() => { instanceRef.current = tippy(targetRef.current, options) - const { onCreate, isEnabled, isVisible } = props + const { onCreate, isEnabled, isVisible, className } = props if (onCreate) { onCreate(instanceRef.current) } + if (className) { + const { tooltip } = instanceRef.current.popperChildren + updateClassName(tooltip, 'add', props.className) + } + if (isEnabled === false) { instanceRef.current.disable() } @@ -55,7 +62,7 @@ function Tippy(props) { } }, []) - useEffect(() => { + useLayoutEffect(() => { if (!isMounted) { return } @@ -70,7 +77,6 @@ function Tippy(props) { if (isEnabled === false) { instanceRef.current.disable() } - if (isVisible === true) { instanceRef.current.show() } @@ -79,6 +85,19 @@ function Tippy(props) { } }) + useLayoutEffect(() => { + if (!isMounted) { + return + } + + const { tooltip } = instanceRef.current.popperChildren + updateClassName(tooltip, 'add', props.className) + + return () => { + updateClassName(tooltip, 'remove', props.className) + } + }, [props.className]) + return ( <> {cloneElement(props.children, { @@ -99,6 +118,7 @@ Tippy.propTypes = { onCreate: PropTypes.func, isVisible: PropTypes.bool, isEnabled: PropTypes.bool, + className: PropTypes.string, } Tippy.defaultProps = { diff --git a/src/utils.js b/src/utils.js index 2f531db..22d8818 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,6 +1,6 @@ export function getNativeTippyProps(props) { // eslint-disable-next-line no-unused-vars - const { children, onCreate, isVisible, isEnabled, ...nativeProps } = props + const { children, onCreate, isVisible, isEnabled, className, ...nativeProps } = props return nativeProps } @@ -22,3 +22,11 @@ export function preserveRef(ref, node) { export function ssrSafeCreateDiv() { return typeof document !== 'undefined' && document.createElement('div') } + +export function updateClassName(tooltip, action, classNames) { + classNames.split(/\s+/).forEach(name => { + if (name) { + tooltip.classList[action](name) + } + }) +} diff --git a/test/Tippy.test.js b/test/Tippy.test.js index 8d276f1..70b12f2 100644 --- a/test/Tippy.test.js +++ b/test/Tippy.test.js @@ -53,6 +53,29 @@ describe('', () => { expect(tip.popper.querySelector('strong')).not.toBeNull() }) + test('custom class name get added to DOM', () => { + const className = 'hello' + const { container } = render( + +