Skip to content

Instantly share code, notes, and snippets.

@huksley
Created December 2, 2022 20:56
Show Gist options
  • Save huksley/c7a70567d8a399b5d6cb206aa0a3107b to your computer and use it in GitHub Desktop.
Save huksley/c7a70567d8a399b5d6cb206aa0a3107b to your computer and use it in GitHub Desktop.
Resizable element for responsive test. Based on TailwindCSS implementation
import { motion, useTransform, useMotionValue } from "framer-motion";
import { useEffect, useRef } from "react";
function Well({
as: Component = "div",
style,
className,
containerClassName,
html,
children
}: {
as?: "div";
style?: React.CSSProperties;
className?: string;
containerClassName?: string;
html?: string;
children: React.ReactNode;
}) {
return (
<div className={containerClassName}>
<Component style={style} className={"relative overflow-hidden"}>
<div
className={"relative overflow-x-hidden" + (className ? " " + className : "")}
{...(html ? { dangerouslySetInnerHTML: { __html: html } } : { children })}
/>
</Component>
</div>
);
}
export const Example = () => {
return (
<div>
<h3 className="my-3">
Resizable div. Nothing can be on the right side because it really occupies full width.
</h3>
<div className="border-0">
<ResizableElement>
<div className="border bg-slate-500/10 rounded-[6px] p-2">
fadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads fadsads
fadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads fadsads
fadsads fadsads fadsads fadsadsfadsads
</div>
</ResizableElement>
</div>
<h3 className="my-3">With a lot of content and border around.</h3>
<div className="border">
<ResizableElement>
fadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads fadsads
fadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads fadsads
fadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads fadsads
fadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads
fadsadsfadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads
fadsads fadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads
fadsads fadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads
fadsads fadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads
fadsads fadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads
fadsads fadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads
fadsads fadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads
fadsadsfadsads fadsads fadsads fadsadsfadsads fadsadsfadsadsfadsadsfadsads fadsads
fadsads
</ResizableElement>
</div>
</div>
);
};
export const ResizableElement = ({
style,
...props
}: {
style?: React.CSSProperties;
className?: string;
containerClassName?: string;
html?: string;
children: React.ReactNode;
}) => {
const containerRef = useRef<HTMLDivElement>(null);
const trackedHorizontal = useMotionValue(0);
const handleRef = useRef<HTMLDivElement>(null);
const marginRight = useTransform(trackedHorizontal, x => -x);
useEffect(() => {
const observer = new window.ResizeObserver(() => {
trackedHorizontal.set(0);
});
if (containerRef.current) {
observer.observe(containerRef.current);
}
return () => {
observer.disconnect();
};
}, [trackedHorizontal]);
useEffect(() => {
if (handleRef.current) {
handleRef.current.onselectstart = () => false;
}
}, [handleRef]);
return (
<div ref={containerRef} className="relative">
<div className="pr-3.5">
<Well
as={motion.div as unknown as "div"}
style={{
...style,
marginRight: marginRight as unknown as string
}}
{...props}
/>
</div>
<motion.div
ref={handleRef}
drag="x"
_dragX={trackedHorizontal}
dragMomentum={false}
dragElastic={0}
dragConstraints={containerRef}
className="pointer-events-auto absolute top-0 right-0 h-full flex-column items-center hidden md:flex cursor-ew-resize"
style={{ x: trackedHorizontal }}
onDragStart={() => {
document.documentElement.classList.add("dragging-ew");
}}
onDragEnd={() => {
document.documentElement.classList.remove("dragging-ew");
}}
>
<div className="w-2 h-[50%] py-2 bg-slate-500/30 hover:bg-slate-500/20 rounded-full" />
</motion.div>
</div>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment