CAL-1664: Improve flash of toggle group when rerendering (#8900)
* CAL-1664: Improve flash of toggle group when rerendering, because active element moves into position. * Added back newlinepull/8869/head^2
parent
2147cc82a5
commit
4137f63ec7
|
@ -1,6 +1,6 @@
|
|||
import * as RadixToggleGroup from "@radix-ui/react-toggle-group";
|
||||
import type { ReactNode } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
import { classNames } from "@calcom/lib";
|
||||
import { Tooltip } from "@calcom/ui";
|
||||
|
@ -29,7 +29,7 @@ const OptionalTooltipWrapper = ({
|
|||
|
||||
export const ToggleGroup = ({ options, onValueChange, isFullWidth, ...props }: ToggleGroupProps) => {
|
||||
const [value, setValue] = useState<string | undefined>(props.defaultValue);
|
||||
const [activeToggleElement, setActiveToggleElement] = useState<null | HTMLButtonElement>(null);
|
||||
const activeRef = useRef<HTMLSpanElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (value && onValueChange) onValueChange(value);
|
||||
|
@ -48,9 +48,15 @@ export const ToggleGroup = ({ options, onValueChange, isFullWidth, ...props }: T
|
|||
)}>
|
||||
{/* Active toggle. It's a separate element so we can animate it nicely. */}
|
||||
<span
|
||||
ref={activeRef}
|
||||
aria-hidden
|
||||
className="bg-emphasis absolute top-[4px] bottom-[4px] left-0 z-[0] rounded-[4px] transition-all"
|
||||
style={{ left: activeToggleElement?.offsetLeft, width: activeToggleElement?.offsetWidth }}
|
||||
className={classNames(
|
||||
"bg-emphasis absolute top-[4px] bottom-[4px] left-0 z-[0] rounded-[4px]",
|
||||
// Disable the animation until after initial render, that way when the component would
|
||||
// rerender the styles are immediately set and we don't see a flash moving the element
|
||||
// into position because of the animation.
|
||||
activeRef?.current && "transition-all"
|
||||
)}
|
||||
/>
|
||||
{options.map((option) => (
|
||||
<OptionalTooltipWrapper key={option.value} tooltipText={option.tooltip}>
|
||||
|
@ -65,8 +71,12 @@ export const ToggleGroup = ({ options, onValueChange, isFullWidth, ...props }: T
|
|||
isFullWidth && "w-full"
|
||||
)}
|
||||
ref={(node) => {
|
||||
if (node && value === option.value && activeToggleElement !== node) {
|
||||
setActiveToggleElement(node);
|
||||
if (node && value === option.value) {
|
||||
// Sets position of active toggle element with inline styles.
|
||||
// This way we trigger as little rerenders as possible.
|
||||
if (!activeRef.current || activeRef?.current.style.left === `${node.offsetLeft}px`) return;
|
||||
activeRef.current.style.left = `${node.offsetLeft}px`;
|
||||
activeRef.current.style.width = `${node.offsetWidth}px`;
|
||||
}
|
||||
return node;
|
||||
}}>
|
||||
|
|
Loading…
Reference in New Issue