import type { ReactNode } from 'react';
import { useCallback, useState } from 'react';
import { Modal, Pressable, StyleSheet, Text, View } from 'react-native';
import { AppIcon, APP_ICON_SIZE } from './app-icon';
import { fonts, m3Colors, m3Elevation, spacing } from '../theme/proulr-theme';
export type FloatingCreateMenuAction = {
id: string;
label: string;
tone?: 'primary' | 'surface';
icon: ReactNode;
onPress: () => void;
};
const MAIN_FAB_SIZE = 56;
const ACTION_FAB_SIZE = 48;
export function FloatingCreateMenu({
bottomInset,
actions,
accessibilityLabel = 'Criar conteúdo',
}: {
bottomInset: number;
actions: FloatingCreateMenuAction[];
accessibilityLabel?: string;
}) {
const [open, setOpen] = useState(false);
const close = useCallback(() => setOpen(false), []);
const onActionPress = useCallback(
(action: FloatingCreateMenuAction) => {
close();
action.onPress();
},
[close],
);
const orderedActions = actions;
return (
<>
setOpen((value) => !value)}
accessibilityRole="button"
accessibilityLabel={open ? 'Fechar menu de criação' : accessibilityLabel}
style={({ pressed }) => [
styles.mainFab,
{ bottom: bottomInset + spacing.sm },
open && styles.mainFabOpen,
pressed && { opacity: 0.9 },
]}
>
{orderedActions.map((action) => {
const isPrimary = action.tone === 'primary';
return (
onActionPress(action)}
accessibilityRole="button"
accessibilityLabel={action.label}
style={({ pressed }) => [styles.labelBtn, pressed && { opacity: 0.85 }]}
>
{action.label}
onActionPress(action)}
accessibilityRole="button"
accessibilityLabel={action.label}
style={({ pressed }) => [
styles.actionFab,
isPrimary ? styles.actionFabPrimary : styles.actionFabSurface,
pressed && { opacity: 0.9 },
]}
>
{action.icon}
);
})}
>
);
}
const styles = StyleSheet.create({
mainFab: {
position: 'absolute',
right: spacing.sm,
width: MAIN_FAB_SIZE,
height: MAIN_FAB_SIZE,
borderRadius: MAIN_FAB_SIZE / 2,
backgroundColor: m3Colors.secondary,
alignItems: 'center',
justifyContent: 'center',
zIndex: 20,
...m3Elevation.level3,
},
mainFabOpen: {
backgroundColor: m3Colors.surfaceContainerHighest,
borderWidth: 1,
borderColor: m3Colors.outlineVariant,
},
overlay: {
flex: 1,
},
backdrop: {
...StyleSheet.absoluteFill,
backgroundColor: m3Colors.scrim,
},
stack: {
position: 'absolute',
right: spacing.sm,
alignItems: 'flex-end',
gap: spacing.md,
},
row: {
flexDirection: 'row',
alignItems: 'center',
gap: spacing.sm,
},
labelBtn: {
paddingHorizontal: spacing.sm,
paddingVertical: spacing.xs,
},
label: {
color: m3Colors.onSurface,
fontFamily: fonts.semibold,
fontSize: 16,
},
actionFab: {
width: ACTION_FAB_SIZE,
height: ACTION_FAB_SIZE,
borderRadius: ACTION_FAB_SIZE / 2,
alignItems: 'center',
justifyContent: 'center',
...m3Elevation.level2,
},
actionFabPrimary: {
backgroundColor: m3Colors.primary,
},
actionFabSurface: {
backgroundColor: m3Colors.inverseSurface,
},
});