Files
eranos/src/components/FabButton.tsx
T
Chad Curtis 5eb6af1ab6 Compose send: use FabButton matching app FAB shape; extract FabButton component
- Extract FabButton from FloatingComposeButton (avatar shape mask + primary bg)
- FloatingComposeButton now delegates to FabButton
- ComposeLetterSheet: replace inline send button with FabButton FAB,
  fixed bottom-right on mobile, sticky in column on desktop
- Remove separate page-level send button from compose header
2026-03-26 16:51:31 -05:00

55 lines
1.8 KiB
TypeScript

import { useMemo } from 'react';
import { useCurrentUser } from '@/hooks/useCurrentUser';
import { getAvatarShape, getEmojiMaskUrl } from '@/lib/avatarShape';
interface FabButtonProps {
onClick: () => void;
icon: React.ReactNode;
disabled?: boolean;
className?: string;
title?: string;
}
/**
* Reusable FAB that inherits the current user's avatar shape (emoji mask or
* circle fallback), matching the FloatingComposeButton style exactly.
*/
export function FabButton({ onClick, icon, disabled, className = '', title }: FabButtonProps) {
const { metadata } = useCurrentUser();
const avatarShape = getAvatarShape(metadata);
const shapeMaskStyle = useMemo<React.CSSProperties | undefined>(() => {
if (!avatarShape) return undefined;
const maskUrl = getEmojiMaskUrl(avatarShape);
if (!maskUrl) return undefined;
return {
WebkitMaskImage: `url(${maskUrl})`,
maskImage: `url(${maskUrl})`,
WebkitMaskSize: 'contain',
maskSize: 'contain' as string,
WebkitMaskRepeat: 'no-repeat',
maskRepeat: 'no-repeat' as string,
WebkitMaskPosition: 'center',
maskPosition: 'center' as string,
};
}, [avatarShape]);
return (
<button
onClick={onClick}
disabled={disabled}
title={title}
className={`relative size-16 transition-transform hover:scale-105 active:scale-95 disabled:opacity-40 disabled:pointer-events-none ${className}`}
style={{ filter: 'drop-shadow(0 2px 8px hsl(var(--primary) / 0.25))' }}
>
<div
className={`absolute inset-0 bg-primary ${shapeMaskStyle ? '' : 'rounded-full'}`}
style={shapeMaskStyle}
/>
<span className="absolute inset-0 flex items-center justify-center text-primary-foreground">
{icon}
</span>
</button>
);
}