Fix: Improve onboarding tour UI and button styles

- Added an arrow connecting the text in the banner to the button in the onboarding tour.
- Adjusted the "Grupos" button style to match the original design, ensuring a white background and black text.
This commit is contained in:
gpt-engineer-app[bot] 2025-06-22 00:32:29 +00:00
parent 71026e9b63
commit bfad740ccb

View File

@ -95,6 +95,138 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
};
};
const getArrowStyle = () => {
if (!currentStepData.spotlight) return { display: 'none' };
const element = document.querySelector(`[data-tour="${currentStepData.spotlight}"]`);
const card = document.querySelector('.onboarding-card');
if (!element || !card) return { display: 'none' };
const elementRect = element.getBoundingClientRect();
const cardRect = card.getBoundingClientRect();
// Calcular posição da seta
const elementCenterX = elementRect.left + elementRect.width / 2;
const elementCenterY = elementRect.top + elementRect.height / 2;
const cardCenterX = cardRect.left + cardRect.width / 2;
const cardCenterY = cardRect.top + cardRect.height / 2;
// Calcular ângulo e distância
const deltaX = elementCenterX - cardCenterX;
const deltaY = elementCenterY - cardCenterY;
const angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Posicionar a seta no meio do caminho
const arrowX = cardCenterX + (deltaX * 0.6);
const arrowY = cardCenterY + (deltaY * 0.6);
return {
position: 'fixed' as const,
left: arrowX,
top: arrowY,
transform: `translate(-50%, -50%) rotate(${angle}deg)`,
zIndex: 9999,
pointerEvents: 'none' as const,
width: '60px',
height: '3px',
background: 'linear-gradient(90deg, rgba(59, 130, 246, 0.8) 0%, rgba(59, 130, 246, 0.4) 100%)',
borderRadius: '2px',
filter: 'drop-shadow(0 2px 4px rgba(59, 130, 246, 0.3))',
};
};
const getArrowHeadStyle = () => {
if (!currentStepData.spotlight) return { display: 'none' };
const element = document.querySelector(`[data-tour="${currentStepData.spotlight}"]`);
const card = document.querySelector('.onboarding-card');
if (!element || !card) return { display: 'none' };
const elementRect = element.getBoundingClientRect();
const cardRect = card.getBoundingClientRect();
const elementCenterX = elementRect.left + elementRect.width / 2;
const elementCenterY = elementRect.top + elementRect.height / 2;
const cardCenterX = cardRect.left + cardRect.width / 2;
const cardCenterY = cardRect.top + cardRect.height / 2;
const deltaX = elementCenterX - cardCenterX;
const deltaY = elementCenterY - cardCenterY;
const angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
// Posicionar a ponta da seta mais próxima do elemento
const arrowHeadX = cardCenterX + (deltaX * 0.75);
const arrowHeadY = cardCenterY + (deltaY * 0.75);
return {
position: 'fixed' as const,
left: arrowHeadX,
top: arrowHeadY,
transform: `translate(-50%, -50%) rotate(${angle}deg)`,
zIndex: 9999,
pointerEvents: 'none' as const,
width: '0',
height: '0',
borderLeft: '8px solid rgba(59, 130, 246, 0.8)',
borderTop: '6px solid transparent',
borderBottom: '6px solid transparent',
filter: 'drop-shadow(0 2px 4px rgba(59, 130, 246, 0.3))',
};
};
// Estilo para destacar o elemento com fundo branco e texto preto
const highlightElementStyle = () => {
if (!currentStepData.spotlight) return;
const element = document.querySelector(`[data-tour="${currentStepData.spotlight}"]`) as HTMLElement;
if (!element) return;
// Aplicar estilos diretamente no elemento
element.style.backgroundColor = '#ffffff';
element.style.color = '#000000';
element.style.fontWeight = '600';
element.style.boxShadow = '0 0 20px rgba(59, 130, 246, 0.6)';
element.style.border = '2px solid rgba(59, 130, 246, 0.8)';
element.style.borderRadius = '8px';
element.style.position = 'relative';
element.style.zIndex = '9999';
};
// Remover estilos quando não há spotlight
const removeHighlightStyle = () => {
const elements = document.querySelectorAll('[data-tour]') as NodeListOf<HTMLElement>;
elements.forEach(element => {
element.style.backgroundColor = '';
element.style.color = '';
element.style.fontWeight = '';
element.style.boxShadow = '';
element.style.border = '';
element.style.borderRadius = '';
element.style.position = '';
element.style.zIndex = '';
});
};
// Aplicar ou remover highlight baseado no step atual
React.useEffect(() => {
if (currentStepData.spotlight) {
// Pequeno delay para garantir que o DOM foi renderizado
setTimeout(() => {
highlightElementStyle();
}, 100);
} else {
removeHighlightStyle();
}
// Cleanup quando o componente for desmontado
return () => {
removeHighlightStyle();
};
}, [currentStep, currentStepData.spotlight]);
return (
<>
{/* Overlay escuro */}
@ -103,14 +235,22 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
style={{ zIndex: 9997 }}
/>
{/* Spotlight */}
{/* Spotlight transparente */}
{currentStepData.spotlight && (
<div style={getSpotlightStyle()} />
)}
{/* Seta moderna conectando o card ao elemento */}
{currentStepData.spotlight && (
<>
<div style={getArrowStyle()} />
<div style={getArrowHeadStyle()} />
</>
)}
{/* Card do tour */}
<div className="fixed inset-0 flex items-center justify-center z-[9999] p-4">
<Card className="w-full max-w-md bg-white shadow-2xl border-2 border-blue-200">
<Card className="onboarding-card w-full max-w-md bg-white shadow-2xl border-2 border-blue-200">
<CardContent className="p-6">
<div className="flex justify-between items-start mb-4">
<h3 className="text-xl font-bold text-gray-800">
@ -146,7 +286,7 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
<Button
variant="outline"
onClick={onSkip}
className="hover:bg-gray-100 transition-colors"
className="hover:bg-gray-100 transition-colors font-semibold"
>
Pular Tour
</Button>