From bf44ea7864fbd8dc661306c3dbebbd06cf02b58c Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Sat, 25 Mar 2023 21:31:52 -0700 Subject: [PATCH] Animate sidebar transition --- package-lock.json | 62 ++++++++++++++++++++++++++ package.json | 1 + src-web/components/RequestResponse.tsx | 17 +++---- src-web/components/Workspace.tsx | 10 ++++- src-web/components/core/Tabs/Tabs.tsx | 4 +- 5 files changed, 80 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7c2378ed..af6e7b9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@lezer/highlight": "^1.1.3", "@lezer/lr": "^1.3.3", "@radix-ui/react-icons": "^1.2.0", + "@react-hook/resize-observer": "^1.2.6", "@tailwindcss/container-queries": "^0.1.0", "@tanstack/query-sync-storage-persister": "^4.27.1", "@tanstack/react-query": "^4.28.0", @@ -1021,6 +1022,11 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@juggle/resize-observer": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==" + }, "node_modules/@lezer/common": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.2.tgz", @@ -1238,6 +1244,35 @@ "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" }, + "node_modules/@react-hook/latest": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@react-hook/latest/-/latest-1.0.3.tgz", + "integrity": "sha512-dy6duzl+JnAZcDbNTfmaP3xHiKtbXYOaz3G51MGVljh548Y8MWzTr+PHLOfvpypEVW9zwvl+VyKjbWKEVbV1Rg==", + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/@react-hook/passive-layout-effect": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@react-hook/passive-layout-effect/-/passive-layout-effect-1.2.1.tgz", + "integrity": "sha512-IwEphTD75liO8g+6taS+4oqz+nnroocNfWVHWz7j+N+ZO2vYrc6PV1q7GQhuahL0IOR7JccFTsFKQ/mb6iZWAg==", + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/@react-hook/resize-observer": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@react-hook/resize-observer/-/resize-observer-1.2.6.tgz", + "integrity": "sha512-DlBXtLSW0DqYYTW3Ft1/GQFZlTdKY5VAFIC4+km6IK5NiPPDFchGbEJm1j6pSgMqPRHbUQgHJX7RaR76ic1LWA==", + "dependencies": { + "@juggle/resize-observer": "^3.3.1", + "@react-hook/latest": "^1.0.2", + "@react-hook/passive-layout-effect": "^1.2.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, "node_modules/@remix-run/router": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.4.0.tgz", @@ -7957,6 +7992,11 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "@juggle/resize-observer": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==" + }, "@lezer/common": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.2.tgz", @@ -8170,6 +8210,28 @@ "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" }, + "@react-hook/latest": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@react-hook/latest/-/latest-1.0.3.tgz", + "integrity": "sha512-dy6duzl+JnAZcDbNTfmaP3xHiKtbXYOaz3G51MGVljh548Y8MWzTr+PHLOfvpypEVW9zwvl+VyKjbWKEVbV1Rg==", + "requires": {} + }, + "@react-hook/passive-layout-effect": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@react-hook/passive-layout-effect/-/passive-layout-effect-1.2.1.tgz", + "integrity": "sha512-IwEphTD75liO8g+6taS+4oqz+nnroocNfWVHWz7j+N+ZO2vYrc6PV1q7GQhuahL0IOR7JccFTsFKQ/mb6iZWAg==", + "requires": {} + }, + "@react-hook/resize-observer": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@react-hook/resize-observer/-/resize-observer-1.2.6.tgz", + "integrity": "sha512-DlBXtLSW0DqYYTW3Ft1/GQFZlTdKY5VAFIC4+km6IK5NiPPDFchGbEJm1j6pSgMqPRHbUQgHJX7RaR76ic1LWA==", + "requires": { + "@juggle/resize-observer": "^3.3.1", + "@react-hook/latest": "^1.0.2", + "@react-hook/passive-layout-effect": "^1.2.0" + } + }, "@remix-run/router": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.4.0.tgz", diff --git a/package.json b/package.json index 5ef6fe5e..a5ebabea 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "@lezer/highlight": "^1.1.3", "@lezer/lr": "^1.3.3", "@radix-ui/react-icons": "^1.2.0", + "@react-hook/resize-observer": "^1.2.6", "@tailwindcss/container-queries": "^0.1.0", "@tanstack/query-sync-storage-persister": "^4.27.1", "@tanstack/react-query": "^4.28.0", diff --git a/src-web/components/RequestResponse.tsx b/src-web/components/RequestResponse.tsx index b6bcdf1f..82720265 100644 --- a/src-web/components/RequestResponse.tsx +++ b/src-web/components/RequestResponse.tsx @@ -1,9 +1,8 @@ +import useResizeObserver from '@react-hook/resize-observer'; import classnames from 'classnames'; import type { CSSProperties, MouseEvent as ReactMouseEvent } from 'react'; -import React, { memo, useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react'; -import { useWindowSize } from 'react-use'; +import React, { memo, useCallback, useMemo, useRef, useState } from 'react'; import { useKeyValue } from '../hooks/useKeyValue'; -import { useSidebarDisplay } from '../hooks/useSidebarDisplay'; import { clamp } from '../lib/clamp'; import { RequestPane } from './RequestPane'; import { ResizeHandle } from './ResizeHandle'; @@ -19,7 +18,7 @@ const drag = { gridArea: 'drag' }; const DEFAULT = 0.5; const MIN_WIDTH_PX = 10; -const MIN_HEIGHT_PX = 100; +const MIN_HEIGHT_PX = 30; const STACK_VERTICAL_WIDTH = 600; export const RequestResponse = memo(function RequestResponse({ style }: Props) { @@ -34,13 +33,9 @@ export const RequestResponse = memo(function RequestResponse({ style }: Props) { null, ); - const windowSize = useWindowSize(); - const sidebar = useSidebarDisplay(); - useLayoutEffect(() => { - if (!containerRef.current) return; - const { width } = containerRef.current.getBoundingClientRect(); - setVertical(width < STACK_VERTICAL_WIDTH); - }, [containerRef.current, windowSize, sidebar.width, sidebar.hidden]); + useResizeObserver(containerRef, ({ contentRect }) => { + setVertical(contentRect.width < STACK_VERTICAL_WIDTH); + }); const styles = useMemo( () => ({ diff --git a/src-web/components/Workspace.tsx b/src-web/components/Workspace.tsx index 1e4180b4..b5059642 100644 --- a/src-web/components/Workspace.tsx +++ b/src-web/components/Workspace.tsx @@ -64,7 +64,15 @@ export default function Workspace() { ); return ( -
+
({ >
- + {tabs.map((t) => { const isActive = t.value === value; const btnClassName = classnames(