Hooks to build things like tooltips, dropdown menu's and popovers in React
This release is a small update and adds React >= 18 to the list of peer-dependencies.
This release contains a couple of small fixes:
document.scrollingElement
)requestAnimationFrame
. With RAF, sometimes style-glitches could occur which should be fixed with this release.Thanks @simonlindholm , @btravel and @jhnns !!
This release contains a couple of small fixes:
Transition
componentResizeObserver
polyfill warninguseHover
)react
and react-dom
are set more strict: ^16.0.0 || ^17.0.0
instead of >=16
overflowContainer
was set to false
and no scroll-container was found🎉 Finally... after more than a year after the initial release, I'm proud to preset to you v2.0.0! 🎉
The past months I've been really busy with a complete rewrite of this project. The result is cleaner and better documented code 👨🏼💻, better performance 🚀, and the most important part: everything is a hook!
⚠️ Note: This is a major release with a lot of breaking stuff. Be sure to read the migration instructions below before upgrading your project from v1.x.x to v2.0.0.
The thing that definitely will have to most impact is <ToggleLayer />
(and useToggleLayer()
in some sense). However, I'm optimistic in the amount of work it will take to migrate.
Let's do a comparison of the before and after:
// old
import { ToggleLayer } from "react-laag";
function Old() {
return (
<ToggleLayer
renderLayer={({ isOpen, layerProps }) =>
isOpen && <div {...layerProps}>Layer</div>
}
>
{({ triggerRef, toggle }) => (
<button ref={triggerRef} onClick={toggle}>
Trigger
</button>
)}
</ToggleLayer>
);
}
// new
import { useLayer } from "react-laag";
function New() {
const [isOpen, setOpen] = React.useState(false);
const { layerProps, triggerProps, renderLayer } = useLayer({ isOpen });
return (
<>
<button {...triggerProps} onClick={() => setOpen(!isOpen)}>Trigger</button>
{isOpen && renderLayer(<div {...layerProps}>Layer</div>)}
</>
);
}
As you can see a lot of concepts still remain the same. One of the big differences is that the rendering of the layer now happens in a different place -> under the trigger element and wrapped inside a renderLayer()
function.
This reads a lot nicer, because mentally the layer will follow after the trigger. Also this pattern opens the door for better composition.
The previously known 'anchors' have been renamed to the 'placement' prop. Possible placements are now: top-start, top-center, top-end, right-start, right-center, ...etc
So, before it was "BOTTOM_LEFT"
, now it is "bottom-start"
.
The new option-object has been flattened and some properties have been renamed. Here's a map from old to new:
old | new | notes |
---|---|---|
isOpen | isOpen | now controlled by default |
fixed | overflowContainer | now true by default |
placement.anchor | placement | |
placement.possibleAnchors | possiblePlacements | |
placement.autoAdjust | auto | |
placement.snapToAnchor | snap | |
placement.preferX | preferX | |
placement.preferY | preferY | |
placement.triggerOffset | triggerOffset | |
placement.scrollOffset | containerOffset | this option has been renamed |
placement.arrowOffset | arrowOffset | |
placement.layerDimensions | layerDimensions | |
onDisappear | onDisappear | |
onOutsideClick | onOutsideClick | |
closeOnDisappear | x | this option has been removed |
closeOnOutsideClick | x | this option has been removed |
ResizeObserver | ResizeObserver | |
container | container | |
environment | environment |
This hook has been removed. Fortunately is pretty easy to replace this hook with useLayer()
and useHover
:
// before
import { useTooltip } from "react-laag";
function Before() {
const [element, triggerProps] = useTooltip(
({ isOpen, layerProps }) =>
isOpen && <div {...layerProps}>I'm a tooltip!</div>,
{
delayEnter: 100,
delayLeave: 100
}
);
return (
<>
{element}
<div {...triggerProps}>Hover me</div>
</>
);
}
// after
import { useLayer, useHover } from "react-laag";
function After() {
const [isOpen, hoverProps] = useHover({ delayEnter: 100, delayLeave: 100 });
const { renderLayer, triggerProps, layerProps } = useLayer({ isOpen });
return (
<>
<div {...triggerProps} {...hoverProps}>
Hover me...
</div>
{isOpen && renderLayer(<div {...layerProps}>I'm a tooltip!</div>)}
</>
);
}
This small utility component has been marked as deprecated and will be removed somewhere in de upcoming releases. I recommend to look for alternatives like framer-motion, react-spring or react-transition-group.