Show tooltips for all composer controls (#3173)
* fix(app): restore composer control tooltips Composite composer triggers dropped tooltip interaction props or the anchor ref, so hover either never opened the tooltip or left it off-screen. Preserve pressable props and compose menu refs at the trigger boundaries. * fix(app): align mode tooltip typography
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @vitest-environment jsdom
|
||||
*/
|
||||
import React, { createRef } from "react";
|
||||
import { render } from "@testing-library/react";
|
||||
import { Text, type View } from "react-native";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { MenuRoot, MenuTrigger } from "./menu-root";
|
||||
|
||||
beforeEach(() => vi.stubGlobal("React", React));
|
||||
|
||||
describe("MenuTrigger", () => {
|
||||
it("forwards its rendered trigger to callers", () => {
|
||||
const triggerRef = createRef<View>();
|
||||
|
||||
render(
|
||||
<MenuRoot>
|
||||
<MenuTrigger ref={triggerRef} accessibilityLabel="Open menu">
|
||||
<Text>Open</Text>
|
||||
</MenuTrigger>
|
||||
</MenuRoot>,
|
||||
);
|
||||
|
||||
expect(triggerRef.current).not.toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,14 @@
|
||||
import { useCallback, type PropsWithChildren, type ReactElement, type ReactNode } from "react";
|
||||
import {
|
||||
forwardRef,
|
||||
useCallback,
|
||||
type PropsWithChildren,
|
||||
type ReactElement,
|
||||
type ReactNode,
|
||||
type Ref,
|
||||
} from "react";
|
||||
import {
|
||||
Pressable,
|
||||
type View,
|
||||
type PressableProps,
|
||||
type PressableStateCallbackType,
|
||||
type StyleProp,
|
||||
@@ -49,14 +57,29 @@ export interface MenuTriggerProps extends Omit<PressableProps, "style" | "childr
|
||||
children: ReactNode | ((state: MenuTriggerState) => ReactNode);
|
||||
}
|
||||
|
||||
export function MenuTrigger({
|
||||
children,
|
||||
disabled,
|
||||
style,
|
||||
...props
|
||||
}: MenuTriggerProps): ReactElement {
|
||||
function assignRef<T>(ref: Ref<T> | undefined, value: T | null): void {
|
||||
if (!ref) return;
|
||||
if (typeof ref === "function") {
|
||||
ref(value);
|
||||
return;
|
||||
}
|
||||
Object.assign(ref, { current: value });
|
||||
}
|
||||
|
||||
export const MenuTrigger = forwardRef<View, MenuTriggerProps>(function MenuTrigger(
|
||||
{ children, disabled, style, ...props },
|
||||
forwardedRef,
|
||||
): ReactElement {
|
||||
const ctx = useMenuContext("MenuTrigger");
|
||||
|
||||
const handleTriggerRef = useCallback(
|
||||
(node: View | null) => {
|
||||
assignRef(ctx.triggerRef, node);
|
||||
assignRef(forwardedRef, node);
|
||||
},
|
||||
[ctx.triggerRef, forwardedRef],
|
||||
);
|
||||
|
||||
const handlePress = useCallback(() => {
|
||||
if (disabled) return;
|
||||
ctx.setOpen(!ctx.open);
|
||||
@@ -83,7 +106,7 @@ export function MenuTrigger({
|
||||
return (
|
||||
<Pressable
|
||||
{...props}
|
||||
ref={ctx.triggerRef}
|
||||
ref={handleTriggerRef}
|
||||
collapsable={false}
|
||||
disabled={disabled}
|
||||
onPress={handlePress}
|
||||
@@ -92,4 +115,4 @@ export function MenuTrigger({
|
||||
{renderChildren}
|
||||
</Pressable>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user