feat(app): add header tooltips + shortcuts (#16)
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import type { PropsWithChildren, ReactElement } from "react";
|
||||
import { 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";
|
||||
|
||||
export function HeaderToggleButton({
|
||||
onPress,
|
||||
tooltipLabel,
|
||||
tooltipKeys,
|
||||
tooltipSide,
|
||||
tooltipDelayDuration = 0,
|
||||
style,
|
||||
disabled,
|
||||
children,
|
||||
...props
|
||||
}: PropsWithChildren<
|
||||
Omit<PressableProps, "style" | "onPress"> & {
|
||||
onPress: NonNullable<PressableProps["onPress"]>;
|
||||
tooltipLabel: string;
|
||||
tooltipKeys: ShortcutKey[];
|
||||
tooltipSide: "left" | "right" | "top" | "bottom";
|
||||
tooltipDelayDuration?: number;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
}
|
||||
>): ReactElement {
|
||||
const tooltipTestID =
|
||||
typeof props.testID === "string" && props.testID.length > 0
|
||||
? `${props.testID}-tooltip`
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<Tooltip delayDuration={tooltipDelayDuration} enabledOnDesktop enabledOnMobile={false}>
|
||||
<TooltipTrigger
|
||||
{...props}
|
||||
disabled={disabled}
|
||||
onPress={(e) => {
|
||||
onPress(e);
|
||||
}}
|
||||
style={[styles.button, style]}
|
||||
>
|
||||
{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} textStyle={styles.shortcutText} />
|
||||
</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,
|
||||
},
|
||||
shortcutText: {
|
||||
color: theme.colors.popoverForeground,
|
||||
},
|
||||
}));
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { ReactNode } from "react";
|
||||
import { Pressable, Text, View } from "react-native";
|
||||
import { Text } from "react-native";
|
||||
import { StyleSheet, UnistylesRuntime, useUnistyles } from "react-native-unistyles";
|
||||
import { Menu, PanelLeft } from "lucide-react-native";
|
||||
import { ScreenHeader } from "./screen-header";
|
||||
import { HeaderToggleButton } from "./header-toggle-button";
|
||||
import { usePanelStore } from "@/stores/panel-store";
|
||||
|
||||
interface MenuHeaderProps {
|
||||
@@ -28,19 +29,20 @@ export function MenuHeader({ title, rightContent }: MenuHeaderProps) {
|
||||
<ScreenHeader
|
||||
left={
|
||||
<>
|
||||
<Pressable
|
||||
<HeaderToggleButton
|
||||
onPress={toggleAgentList}
|
||||
style={styles.menuButton}
|
||||
tooltipLabel="Toggle sidebar"
|
||||
tooltipKeys={["mod", "B"]}
|
||||
tooltipSide="right"
|
||||
testID="menu-button"
|
||||
nativeID="menu-button"
|
||||
collapsable={false}
|
||||
accessible
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={isOpen ? "Close menu" : "Open menu"}
|
||||
accessibilityState={{ expanded: isOpen }}
|
||||
>
|
||||
<MenuIcon size={isMobile ? 20 : 16} color={menuIconColor} />
|
||||
</Pressable>
|
||||
</HeaderToggleButton>
|
||||
{title && (
|
||||
<Text style={styles.title} numberOfLines={1}>
|
||||
{title}
|
||||
@@ -58,13 +60,6 @@ const styles = StyleSheet.create((theme) => ({
|
||||
left: {
|
||||
gap: theme.spacing[2],
|
||||
},
|
||||
menuButton: {
|
||||
padding: {
|
||||
xs: theme.spacing[3],
|
||||
md: theme.spacing[2],
|
||||
},
|
||||
borderRadius: theme.borderRadius.lg,
|
||||
},
|
||||
title: {
|
||||
flex: 1,
|
||||
fontSize: theme.fontSize.base,
|
||||
|
||||
Reference in New Issue
Block a user