Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Tappable): force activated/hovered state (#7906) #7910

Merged
merged 1 commit into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 30 additions & 27 deletions packages/vkui/src/components/Clickable/useState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,13 @@ function useHover({ hovered, hasHover = true, lockState, setParentStateLock }: U
(isHover: boolean) => {
setHoveredStateLocal(isHover);

const isHovered = calculateStateValue({
hasState: hasHover,
isLocked: lockState,
stateValueControlled: Boolean(hovered),
stateValueLocal: isHover,
});
const isHovered =
hovered ??
calculateStateValue({
hasState: hasHover,
isLocked: lockState,
stateValueLocal: isHover,
});

// проверка сделана чтобы реже вызывать обновление состояния
// контекста родителя
Expand All @@ -122,12 +123,13 @@ function useHover({ hovered, hasHover = true, lockState, setParentStateLock }: U
handleHover(false);
};

const isHovered = calculateStateValue({
hasState: hasHover,
isLocked: lockState,
stateValueControlled: Boolean(hovered),
stateValueLocal: hoveredStateLocal,
});
const isHovered =
hovered ??
calculateStateValue({
hasState: hasHover,
isLocked: lockState,
stateValueLocal: hoveredStateLocal,
});

return {
isHovered,
Expand Down Expand Up @@ -194,12 +196,13 @@ function useActive({
setActivated(false, activeEffectDelay);
};

const isActivated = calculateStateValue({
hasState: hasActive,
isLocked: lockStateRef.current,
stateValueControlled: Boolean(activated),
stateValueLocal: activatedState,
});
const isActivated =
activated ??
calculateStateValue({
hasState: hasActive,
isLocked: lockStateRef.current,
stateValueLocal: activatedState,
});

return {
isActivated,
Expand Down Expand Up @@ -262,9 +265,12 @@ function useLockRef(
export function useState({
hovered,
hasHover,
activated,
hasActive,
activeEffectDelay,
unlockParentHover,
...restProps
hoverClassName,
activeClassName,
}: StateProps): {
stateClassName: string;
setLockHoverBubblingImmediate: (...args: any[]) => void;
Expand All @@ -286,15 +292,14 @@ export function useState({
});

const { isActivated, ...activeEvent } = useActive({
...restProps,
activated,
hasActive,
activeEffectDelay,
lockStateRef: lockActiveStateRef,
setParentStateLock: setParentStateLockActiveBubbling,
});

const stateClassName = classNames(
isHovered && restProps.hoverClassName,
isActivated && restProps.activeClassName,
);
const stateClassName = classNames(isHovered && hoverClassName, isActivated && activeClassName);
const handlers = mergeCalls(hoverEvent, activeEvent);

return {
Expand All @@ -309,13 +314,11 @@ export function useState({
function calculateStateValue({
hasState,
isLocked,
stateValueControlled,
stateValueLocal,
}: {
hasState: boolean;
isLocked: boolean;
stateValueControlled: boolean;
stateValueLocal: boolean;
}): boolean {
return hasState && !isLocked && (stateValueControlled || stateValueLocal);
return hasState && !isLocked && stateValueLocal;
}
23 changes: 14 additions & 9 deletions packages/vkui/src/components/Tappable/Tappable.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,12 @@ describe(Tappable, () => {
it('activates during longtap', async () => {
render(<TappableTest onClick={noop} />);
fireEvent.pointerDown(tappable());
expect(tappable()).not.toHaveClass(styles['Tappable--activated-background']);
await waitFor(() => expect(tappable()).toHaveClass(styles['Tappable--activated-background']));
act(jest.runOnlyPendingTimers);
expect(tappable()).toHaveClass(styles['Tappable--activated-background']);

fireEvent.pointerUp(tappable());
expect(tappable()).toHaveClass(styles['Tappable--activated-background']);
act(jest.runOnlyPendingTimers);
expect(tappable()).not.toHaveClass(styles['Tappable--activated-background']);
});

it('does not activate on child Tappable click', async () => {
Expand Down Expand Up @@ -264,12 +265,16 @@ describe(Tappable, () => {
expect(tappable()).not.toHaveClass(styles['Tappable--activated-background']);
});

it('on hasActive=false', () => {
const h = render(<TappableTest />);
fireEvent.mouseDown(tappable());
act(jest.runAllTimers);
h.rerender(<TappableTest hasActive={false} />);
expect(tappable()).not.toHaveClass(styles['Tappable--activated-background']);
it('on hasActive=false', async () => {
render(<TappableTest hasActive={false} onClick={noop} />);
await userEvent.click(tappable());
let errored = false;
await waitFor(() =>
expect(tappable()).toHaveClass(styles['Tappable--activated-background']),
).catch(() => {
errored = true;
});
expect(errored).toBeTruthy();
});

it('on child hover', async () => {
Expand Down