7.5.0 • Published 11 months ago
use-rects v7.5.0
use-rects
Package that allows to resolve DOM elements sizes and positions
Contents
usePopupPosition
Allows you to quickly build dropdowns
flip
- used to allow popup to change position if there is no space for original alignpessimistic
allows to show popup separated from anchor egdes, cause there is no proper fitalign
-topleft
|bottomleft
|bottomright
|topright
trackVisible
- hides dropdown if anchor is hidden/obstructed on the page. Doesn't count anything with 'absolute', 'fixed', etc. as obstruction
Example of the component
Just copy-paste and use this a base (with some tailwind)
import React, { useState } from 'react';
import { usePopupPosition } from 'use-rects';
export const Dropdown = () => {
const [open, setOpen] = useState(false);
// const handleClose = () => setOpen(false);
const handleToggle = () => setOpen(o => !o);
const { popupRef, anchorRef, popupPosition } = usePopupPosition({
delay: 15,
flip: true,
align: 'bottomleft',
});
return (
<div ref={anchorRef} className="relative">
<div onClick={handleToggle}>Trigger</div>
{open && (
<div
ref={popupRef}
style={{
...popupPosition.style,
width: popupPosition.meta?.anchorWidth,
}}
className="fixed z-popper py-2"
>
<div className="shadow-sm rounded">Dropdown</div>
</div>
)}
</div>
);
};
Troublesooting
You still have to build your own dropdown. So remember this:
- add Z-index of you own if needed
trackVisible
won't work if you have 'fixed' your navbars and other parts of the layout- dropdown must have 'height'. don't make it's content with 0 height and make some magic inside
- use results of the hook for position only. don't style this popup. Add your div inside and style it. Insluding margin, borders, etc.
returns:
type PopupStyle = {
top?: number;
bottom?: number;
left?: number;
right?: number;
opacity?: 1 | 0;
position?: 'fixed';
display?: 'none' | undefined;
};
type UsePopupResult = {
style: PopupStyle;
meta?: { pessimistic?: boolean; flip?: boolean; anchorWidth?: number };
};
type ReturnType = {
popupRef: (node: HTMLDivElement) => void;
anchorRef: (node: HTMLDivElement) => void;
anchorPosition: Position;
popupPosition: UsePopupResult;
};
example:
const Dropdown = () => {
const [open, setOpen] = useState(false);
const { popupRef, anchorRef, popupPosition } = usePopupPosition({
delay: 50,
});
return (
<div style={{ position: 'relative' }}>
<input
readOnly
ref={anchorRef}
onClick={() => setOpen(true)}
value="test me"
/>
{!!open && (
<div
ref={popupRef}
onClick={() => setOpen(false)}
style={{ position: 'fixed', ...popupPosition.style }}
>
DROPDOWN
</div>
)}
</div>
);
};
Use resulting style inside of container. If you need extra margins - don't apply them in combination with flip
. Put another container inside and style it
useContainerSize
returns:
type ReturnType = {
containerRef: React.MutableRefObject<any>;
height: number;
width: number;
};
example:
const { height, width, containerRef: ref } = useContainerSize({ delay: 20 });
return <div ref={ref} />;
useElementPosition
returns:
type ReturnType = [(node: HTMLDivElement) => void, Position];
example:
const [ref, position] = useElementPosition({
delay: 20,
});
return <div ref={ref} />;
7.4.0
11 months ago
7.3.0
11 months ago
7.1.2
11 months ago
7.2.0
11 months ago
7.1.1
11 months ago
7.1.0
11 months ago
7.5.0
11 months ago
7.0.0
11 months ago
6.0.0
11 months ago
5.1.0
11 months ago
5.0.0
11 months ago
4.3.0
11 months ago
4.2.0
11 months ago
4.1.0
11 months ago
4.0.1
11 months ago
4.0.0
11 months ago
3.0.0
11 months ago
2.1.0
11 months ago
2.0.3
11 months ago
2.0.2
11 months ago
2.0.1
11 months ago
2.0.0
11 months ago
1.2.1
11 months ago