A JavaScript library to position floating elements and create interactions for them.
MIT License
Bot releases are visible (Hide)
Published by github-actions[bot] almost 2 years ago
fix(useClick): prevent keyboard-like or undefined pointer types being considered as mouse for ignoreMouse
option (#2077)
Fix regression introduced in v0.15.0
fix(types): export interaction hook prop types (#2081)
fix(docs): add missing IntelliSense helpers/links
??
with ||
where possible to reduce bundle size transpilation cost (#2079)Published by github-actions[bot] almost 2 years ago
feat(useDismiss): allow specifying different value for outside press bubbling and escape key bubbling (#2040)
feat: useMergeRefs
hook (#2060)
feat(FloatingDelayGroup): add timeoutMs
prop (#2066)
If there's no close delay, you might still want the delays to end up grouped even if none of the tooltips are currently open within a certain period of time. Instead of relying on the close delay, you can instead rely on the timeoutMs
prop. This also helps with unmounting animations if you want to allow it to be interruptible and continue grouping even if there is a close delay, e.g. timeoutMs = closeDelayMs + animationDurationMs
feat(useListNavigation): scrollItemIntoView
option (#2061)
Any external effects that were handling .scrollIntoView()
manually can now be removed and instead use this option, which supports boolean | ScrollIntoViewOptions
. It's true
by default, using nearest
options.
feat: positionReference
callback ref (#2065)
This adds a dedicated API to separate the events reference from the positioning reference and is more reliable than the previous technique suggested in the docs.
You can call it with a real element or a virtual element:
function App() {
const {reference, positionReference} = useFloating();
return (
<>
<div ref={reference} />
<div ref={positionReference} />
</>
);
}
As a result, the generic reference type is now narrowed on refs.domReference.current
not refs.reference.current
(which is always wide).
0
(from 1000
) (#2055)fix(FloatingFocusManager): avoid returning focus to reference after unhovering (#2049)
fix(FloatingFocusManager): prevent closing on focusout
when moving from non-portalled floating element to nested portalled floating element (#2068)
fix(safePolygon): use real polygon for blockPointerEvents
option (#2069)
This prevents unwanted side effects compared to the previous "global holes" strategy.
Published by github-actions[bot] almost 2 years ago
feat: add open
option and isPositioned
property to wait for the position to be ready. (#2001)
isPositioned
allows you to call .scrollIntoView()
or .focus()
on an element in an effect without causing unwanted scrolling.
const {isPositioned} = useFloating();
This works identically to x === null
, but now has the ability to also reset if it doesn't get unmounted based on some state:
const [open, setOpen] = useState(false);
const {isPositioned} = useFloating({
// `isPositioned` is synchronized to this state/value, but
// when it changes to `true`, it will wait for the position,
// unlike when checking `open` directly.
open
});
React.useLayoutEffect(() => {
if (isPositioned) {
element.focus();
element.scrollIntoView();
}
}, [isPositioned]);
This means it will also work if the reference element moved from the first position after the floating element had been positioned for the first time, unlike x === null
, making it as reliable as the rAF
technique.
For now, null
remains as the original value of x
and y
only for SSR purposes, where the floating element is open already without a client interaction required, which can help with unmounting animations, since isPositioned
doesn't wait.
<div
style={{
position: strategy,
top: y ?? 0,
left: x ?? 0,
visibility: x === null ? 'hidden' : 'visible',
}}
/>
Published by github-actions[bot] almost 2 years ago
fix: support cross-document anchoring, where if floating element is in a higher-level window than the reference element, the positioning takes this into account (i.e. reference element is inside an iframe, but the floating element isn't) (#2043)
Bumping minor version because if you were adding external code/custom middleware to add support yourself, it will break with this update as it's no longer necessary.
refactor(getScale): handle unknowns (#2054)
fix(getDimensions): use computed width
/height
if possible (#2056)
If using box-sizing: border-box
(recommended default by most CSS resets, and this lib), then the floating rect will now always contain fractional values. When using size
to set the width of the floating element, it will no longer be truncated unexpectedly (e.g. adding ...
ellipsis overflow).
fix(isOverflowElement): check for overflow: clip
value (#2070)
Published by github-actions[bot] almost 2 years ago
fix(hide): return options
on middleware object (#2058)
React would previously not update stateful options, either via re-renders or Fast Refresh
fix(arrow): only add internal shifting under stricter conditions (#2044)
This prevents the arrow from getting stuck pointing at the center of the reference when padding
is specified in most cases, counteracting shift()
when it should take precedence, while maintaining the desired behavior for #1496.
fix(autoPlacement): preserve passed allowedPlacements
when desired (#2073)
Previously, allowed placements got filtered out if they didn't match the alignment
specified. By default this was null
, so if you passed aligned placements in the list, they got unexpectedly filtered out. Now, they are respected:
autoPlacement({
// works as expected
allowedPlacements: ['top-start', 'bottom-start']
});
autoPlacement({
alignment: null,
// only 'bottom' is actually allowed
allowedPlacements: ['top-start', 'bottom-start', 'bottom']
});
Published by github-actions[bot] almost 2 years ago
box-sizing: border-box
(#2037)Published by github-actions[bot] almost 2 years ago
box-sizing: content-box
(#2036)Published by github-actions[bot] almost 2 years ago
Published by github-actions[bot] almost 2 years ago
fix: use computed width/height when calculating scale transforms. Fractional width/height could cause slight discrepancies with the scale factors, and therefore incorrect positioning (#2019)
fix: handle nested scale where the reference and offsetParent both had their own scale (#2019)
perf: add caching for expensive DOM calls. The cache only lives for a single computePosition
call, so there won't be any stale DOM checks. (#2030)
The userAgent check is now cached forever after the first call however
Published by github-actions[bot] almost 2 years ago
closeOnFocusOut
prop (#2022) (#2027)@floating-ui/react-dom-interactions
is now @floating-ui/react
. (#2027)
There are no breaking changes between v0.13.0
to this version, just the name of the package.
You should be able to easily do a find-and-replace with the string to change all your imports:
npm uninstall @floating-ui/react-dom-interactions
npm install @floating-ui/react
outsidePress
reactive to primitive values, but also referentially stable if specifying a function value (#2024) (#2027)Published by github-actions[bot] almost 2 years ago
fix(useHover): pointerType
is sometimes returned as pen
on Linux Chromium even while using a mouse, breaking mouseOnly: true
and also delays (which are always 0
for non-mouse input). (#2016)
There is also better fallback handling, whereby hover will forcefully work if pointerType
can't reliably be determined by the browser.
fix(useFocus): pointerType
ref getting unset during onPointerLeave
with touch emulation, preventing keyboardOnly
prop from reliably working. (#2016)
Published by github-actions[bot] almost 2 years ago
fix: avoid queueing updates excessively (#2014)
Avoid Please report: Excessive number of pending callbacks: 501.
error.
Published by github-actions[bot] almost 2 years ago
fix(useDismiss): ensure outsidePress
is referentially stable if specifying a function (#2010)
It caused the event listeners effect to cleanup then execute again on every render if you didn't use React.useCallback
on the value, causing issues.
fix(FloatingFocusManager): return focus to reference element only in applicable cases (#2007)
fix(useFocus): block focus if floating element was dismissed via escape key (#2007)
Published by github-actions[bot] almost 2 years ago
Published by github-actions[bot] almost 2 years ago
Published by github-actions[bot] almost 2 years ago
fix(FloatingPortal): prevent breaking FloatingFocusManager's guards={false}
prop if preserveTabOrder
is set to true (the default) (#2002)
fix(useListNavigation): unset activeIndex
if focus landed back on the reference while the floating element was open (#2006)
fix(build): externalize tabbable
library from bundle (#2002)
Published by github-actions[bot] almost 2 years ago
fix: don't includeScale
when converting offsetParent-relative rect to viewport-relative rect (#2004)
When a container of the floating element had been scaled, this led to incorrect clipping detection. This means the floating element could get incorrectly positioned, namely due to shift()
, or flip too early unexpectedly, etc.
fix(getBoundingClientRect): check for a virtual element's contextElement
scale if present (#2005)
Published by github-actions[bot] almost 2 years ago
fix(detectOverflow): pass correct fallback rect (#2000)
If platform.convertOffsetParentRelativeRectToViewportRelativeRect
was not available, then the correct rect was not passed. So a custom platform without that method actually did need it (even though it's optional).
Published by github-actions[bot] almost 2 years ago
feat(useDismiss): add two mechanisms to cancel an outsidePress
dismissal (#1983)
A custom guard to cancel the outside press if the event is inside a certain element:
useDismiss(context, {
// enabled, but can return false to cancel
outsidePress: (event) => !event.target.closest('.toast'),
});
For FloatingTree
s, add the ability to register a node to a custom parentId
, bypassing <FloatingNode />
lookups. A sibling floating element can mark itself as a child of another sibling despite not being inside its React tree. (#1983)
const nodeId = useFloatingNodeId(customParentId);
feat(FloatingFocusManager): add visuallyHiddenDismiss
option. In modal
mode, this appends and/or prepends a visually hidden dismiss buttons for when an explicit close button is not available, e.g. a root Menu component or a portaled combobox’s listbox. This allows a floating component to be dismissed without the user needing to select anything when they do not have an esc
key available. (#1985)
refactor: significantly improve focus handling throughout the library (Manager, useFocus/ListNavigation/Click hooks) (#1985)
focusItemOnOpen
works with touch screen readersuseListNavigation
🚨 BREAKING(FloatingFocusManager): Due to the improved focus management system, floating elements without tabbable content that use the useListNavigation
hook (e.g. Menu, Select) should always explicitly set initialFocus={-1}
on FloatingFocusManager
to prevent focus conflicts. This has been added to the documentation. (#1985)
<FloatingFocusManager context={context} initialFocus={-1}>
{/* floating element */}
</FloatingFocusManager>
⚠️ refactor(FloatingPortal): portal content by default no longer injects itself into a single root node with a default id of floating-ui-root
. Instead the portals have a unique id and get removed from the DOM when the FloatingPortal’s host component unmounts — when specifying an id
this logic can be bypassed however as it is assumed the node is static or controlled elsewhere. This better supports the new focus management system. (#1985)
fix(useInnerOffset): check scrollRef
onScroll (#1986)
When using keyboard nav to navigate list items, the offset did not change to expand the floating element's height when scrolling programmatically
fix(useHover): for safePolygon
, switch from pointermove
to mousemove
to reduce flakyness, particularly in Firefox (#1990)
fix(useEvent): work around minifier bug that prevented the callback from being freshly set (#1995)
fix: export ExtendedRefs
type (#1992)
Published by github-actions[bot] almost 2 years ago
feat: allow portalling with non-modal focus management (#1966)
FloatingPortal
now has a preserveTabOrder
prop (true
by default) which can disable tab context preservation with the portal.
🚨 BREAKING(FloatingFocusManager): removed endGuard
prop in favor of new guards
prop. It works the same but does not have any limitations: both the start and end guards are now removed so you can place your dialog anywhere on the page and it will just work. (#1966)
apple.com uses the same technique — it also supports shadow DOM
initialFocus
is set to -1
, the focus call is now entirely ignored (and does not fallback to the floating element) (#1966)