Skip to content

Commit

Permalink
fix(ResizablePanel): new drag look (#545)
Browse files Browse the repository at this point in the history
  • Loading branch information
tenphi authored Dec 12, 2024
1 parent c467337 commit 8a460c3
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/empty-actors-carry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cube-dev/ui-kit': patch
---

New drag appearance for ResizablePanel to avoid confusion with a scrollbar.
1 change: 1 addition & 0 deletions src/_internal/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './use-timer';
export * from './use-effect-once';
export * from './use-warn';
export * from './use-is-first-render';
export * from './use-debounced-value';
50 changes: 50 additions & 0 deletions src/_internal/hooks/use-debounced-value.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useState, useEffect, useRef } from 'react';

export function useDebouncedValue<T>(
value: T,
delay: number = 300,
maxWait?: number,
): T {
const [debouncedValue, setDebouncedValue] = useState(value);
const lastValueRef = useRef(value);
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const maxWaitTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

useEffect(() => {
// If value returns to the original while waiting, clear timeouts
if (value === lastValueRef.current) {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
if (maxWaitTimeoutRef.current) clearTimeout(maxWaitTimeoutRef.current);
return;
}

// Handle delay
timeoutRef.current = setTimeout(() => {
setDebouncedValue(value);
lastValueRef.current = value;
if (maxWaitTimeoutRef.current) {
clearTimeout(maxWaitTimeoutRef.current);
maxWaitTimeoutRef.current = null;
}
}, delay);

// Handle maxWait if provided
if (maxWait && !maxWaitTimeoutRef.current) {
maxWaitTimeoutRef.current = setTimeout(() => {
setDebouncedValue(value);
lastValueRef.current = value;
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null;
}
}, maxWait);
}

return () => {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
if (maxWaitTimeoutRef.current) clearTimeout(maxWaitTimeoutRef.current);
};
}, [value, delay, maxWait]);

return debouncedValue;
}
54 changes: 40 additions & 14 deletions src/components/layout/ResizablePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useHover, useMove } from 'react-aria';

import { BasePropsWithoutChildren, Styles, tasty } from '../../tasty/index';
import { mergeProps, useCombinedRefs } from '../../utils/react';
import { useEvent } from '../../_internal/hooks';
import { useDebouncedValue, useEvent } from '../../_internal/hooks';

import { Panel, CubePanelProps } from './Panel';

Expand Down Expand Up @@ -103,31 +103,48 @@ const HandlerElement = tasty({
},

Drag: {
hide: {
'': false,
disabled: true,
display: 'grid',
gap: '2bw',
flow: {
'': 'row',
horizontal: 'column',
},
gridColumns: {
'': '3px 3px 3px 3px 3px',
horizontal: 'auto',
},
gridRows: {
'': 'auto',
horizontal: '3px 3px 3px 3px 3px',
},
width: {
'': '3x',
'': 'auto',
horizontal: '3px',
},
height: {
'': '3px',
horizontal: '3x',
},
radius: true,
fill: {
'': '#dark-03',
'hovered | drag': '#dark-02',
disabled: '#dark-04',
horizontal: 'auto',
},
inset: {
'': '3px 50% auto auto',
horizontal: '50% 3px auto auto',
},
transform: {
'': 'translate(-50%, 0)',
horizontal: 'translate(0, -50%)',
},
position: 'absolute',
transition: 'theme',
},

DragPart: {
radius: true,
fill: {
'': '#dark-03',
'hovered | drag': '#dark-02',
disabled: '#dark-04',
},
},
},
});

Expand All @@ -139,14 +156,15 @@ const Handler = (props: HandlerProps) => {
const { direction = 'right', isDisabled } = props;
const { hoverProps, isHovered } = useHover({});
const isHorizontal = direction === 'left' || direction === 'right';
const localIsHovered = useDebouncedValue(isHovered, 150);

return (
<HandlerElement
{...mergeProps(
hoverProps,
{
mods: {
hovered: isHovered,
hovered: localIsHovered,
horizontal: isHorizontal,
disabled: isDisabled,
},
Expand All @@ -156,7 +174,15 @@ const Handler = (props: HandlerProps) => {
)}
>
<div data-element="Track" />
<div data-element="Drag" />
{!isDisabled ? (
<div data-element="Drag">
<div data-element="DragPart" />
<div data-element="DragPart" />
<div data-element="DragPart" />
<div data-element="DragPart" />
<div data-element="DragPart" />
</div>
) : null}
</HandlerElement>
);
};
Expand Down

0 comments on commit 8a460c3

Please sign in to comment.