92 lines
2.5 KiB
TypeScript
92 lines
2.5 KiB
TypeScript
import { type ReactNode, useState } from "react";
|
|
import { Pressable, View } from "react-native";
|
|
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
|
import { X } from "lucide-react-native";
|
|
import { isNative } from "@/constants/platform";
|
|
import { useIsCompactFormFactor } from "@/constants/layout";
|
|
|
|
interface AttachmentPillProps {
|
|
onOpen: () => void;
|
|
onRemove: () => void;
|
|
openAccessibilityLabel: string;
|
|
removeAccessibilityLabel: string;
|
|
disabled?: boolean;
|
|
testID?: string;
|
|
children: ReactNode;
|
|
}
|
|
|
|
export function AttachmentPill({
|
|
onOpen,
|
|
onRemove,
|
|
openAccessibilityLabel,
|
|
removeAccessibilityLabel,
|
|
disabled = false,
|
|
testID,
|
|
children,
|
|
}: AttachmentPillProps) {
|
|
const { theme } = useUnistyles();
|
|
const isCompact = useIsCompactFormFactor();
|
|
const [isBodyHovered, setIsBodyHovered] = useState(false);
|
|
const [isCloseHovered, setIsCloseHovered] = useState(false);
|
|
const alwaysShow = isNative || isCompact;
|
|
const showRemove = alwaysShow || isBodyHovered || isCloseHovered;
|
|
return (
|
|
<View style={styles.wrapper}>
|
|
<Pressable
|
|
testID={testID}
|
|
onPress={onOpen}
|
|
disabled={disabled}
|
|
onHoverIn={() => setIsBodyHovered(true)}
|
|
onHoverOut={() => setIsBodyHovered(false)}
|
|
accessibilityRole="button"
|
|
accessibilityLabel={openAccessibilityLabel}
|
|
style={styles.body}
|
|
>
|
|
{children}
|
|
</Pressable>
|
|
<Pressable
|
|
onPress={onRemove}
|
|
disabled={disabled}
|
|
onHoverIn={() => setIsCloseHovered(true)}
|
|
onHoverOut={() => setIsCloseHovered(false)}
|
|
hitSlop={8}
|
|
accessibilityRole="button"
|
|
accessibilityLabel={removeAccessibilityLabel}
|
|
style={[styles.closeButton, !showRemove && styles.closeButtonHidden]}
|
|
>
|
|
<X size={12} color={theme.colors.foregroundMuted} />
|
|
</Pressable>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create((theme) => ({
|
|
wrapper: {
|
|
position: "relative",
|
|
},
|
|
body: {
|
|
borderRadius: theme.borderRadius.md,
|
|
borderWidth: theme.borderWidth[1],
|
|
borderColor: theme.colors.borderAccent,
|
|
overflow: "hidden",
|
|
},
|
|
closeButton: {
|
|
position: "absolute",
|
|
top: -8,
|
|
left: -8,
|
|
width: 24,
|
|
height: 24,
|
|
borderRadius: 12,
|
|
backgroundColor: theme.colors.surface2,
|
|
borderWidth: theme.borderWidth[1],
|
|
borderColor: theme.colors.border,
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
zIndex: 1,
|
|
},
|
|
closeButtonHidden: {
|
|
opacity: 0,
|
|
pointerEvents: "none",
|
|
},
|
|
}));
|