mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-24 10:12:44 +00:00
99 lines
2.8 KiB
TypeScript
99 lines
2.8 KiB
TypeScript
import type { ReactElement, ReactNode } from "react";
|
|
import {
|
|
Platform,
|
|
Text,
|
|
View,
|
|
type PressableProps,
|
|
type StyleProp,
|
|
type ViewStyle,
|
|
} from "react-native";
|
|
import { StyleSheet } from "react-native-unistyles";
|
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
|
import { Shortcut } from "@/components/ui/shortcut";
|
|
import type { ShortcutKey } from "@/utils/format-shortcut";
|
|
|
|
interface HeaderToggleButtonState {
|
|
hovered: boolean;
|
|
pressed: boolean;
|
|
}
|
|
|
|
interface HeaderToggleButtonProps extends Omit<PressableProps, "style" | "onPress" | "children"> {
|
|
onPress: NonNullable<PressableProps["onPress"]>;
|
|
tooltipLabel: string;
|
|
tooltipKeys: ShortcutKey[];
|
|
tooltipSide: "left" | "right" | "top" | "bottom";
|
|
tooltipDelayDuration?: number;
|
|
style?: StyleProp<ViewStyle>;
|
|
children: ReactNode | ((state: HeaderToggleButtonState) => ReactNode);
|
|
}
|
|
|
|
export function HeaderToggleButton({
|
|
onPress,
|
|
tooltipLabel,
|
|
tooltipKeys,
|
|
tooltipSide,
|
|
tooltipDelayDuration = 0,
|
|
style,
|
|
disabled,
|
|
children,
|
|
...props
|
|
}: HeaderToggleButtonProps): ReactElement {
|
|
const tooltipTestID =
|
|
typeof props.testID === "string" && props.testID.length > 0
|
|
? `${props.testID}-tooltip`
|
|
: undefined;
|
|
const expandedState = (props.accessibilityState as { expanded?: boolean } | undefined)?.expanded;
|
|
const ariaExpandedProps =
|
|
Platform.OS === "web" && typeof expandedState === "boolean"
|
|
? ({ "aria-expanded": expandedState } as any)
|
|
: null;
|
|
|
|
return (
|
|
<Tooltip delayDuration={tooltipDelayDuration} enabledOnDesktop enabledOnMobile={false}>
|
|
<TooltipTrigger
|
|
{...props}
|
|
{...ariaExpandedProps}
|
|
disabled={disabled}
|
|
onPress={(e) => {
|
|
onPress(e);
|
|
}}
|
|
style={[styles.button, style]}
|
|
>
|
|
{typeof children === "function"
|
|
? (state: { pressed: boolean; hovered?: boolean }) =>
|
|
children({ hovered: Boolean(state.hovered), pressed: state.pressed })
|
|
: children}
|
|
</TooltipTrigger>
|
|
<TooltipContent testID={tooltipTestID} side={tooltipSide} align="center" offset={8}>
|
|
<View style={styles.tooltipRow}>
|
|
<Text style={styles.tooltipText}>{tooltipLabel}</Text>
|
|
<Shortcut keys={tooltipKeys} style={styles.shortcut} />
|
|
</View>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create((theme) => ({
|
|
button: {
|
|
padding: {
|
|
xs: theme.spacing[3],
|
|
md: theme.spacing[2],
|
|
},
|
|
borderRadius: theme.borderRadius.lg,
|
|
},
|
|
tooltipRow: {
|
|
flexDirection: "row",
|
|
alignItems: "center",
|
|
gap: theme.spacing[2],
|
|
},
|
|
tooltipText: {
|
|
fontSize: theme.fontSize.sm,
|
|
color: theme.colors.popoverForeground,
|
|
},
|
|
shortcut: {
|
|
backgroundColor: theme.colors.surface3,
|
|
borderColor: theme.colors.borderAccent,
|
|
},
|
|
}));
|