Powerpoint_AI / components /editor /GenerationProgress.tsx
Reubencf's picture
Polish editor UI: loading card, green buttons, image picker
db8d188
Raw
History Blame Contribute Delete
2.87 kB
/*
* GenerationProgress.tsx
* Purpose: A polished full-screen progress overlay shown while the AI generates a deck.
* The backend call is a single async request with no streaming progress, so this eases a
* determinate-looking bar toward ~92% and cycles through human-readable stage labels, then
* snaps to 100% when it unmounts (i.e. generation finished).
* Used by: GoogleSlidesEditor (rendered while isGenerating is true).
* Depends on: React only.
*/
'use client';
import React, { useEffect, useRef, useState } from 'react';
const STAGES = [
'Understanding your topic',
'Outlining the structure',
'Writing slide content',
'Designing the layout',
'Applying your theme',
'Finishing touches',
];
export default function GenerationProgress() {
const [progress, setProgress] = useState(8);
const progressRef = useRef(8);
useEffect(() => {
// Ease toward a ceiling so the bar always feels alive but never "completes" early.
// The real completion is the component unmounting, which removes the overlay entirely.
const id = window.setInterval(() => {
const current = progressRef.current;
const ceiling = 92;
const next = Math.min(ceiling, current + Math.max(0.4, (ceiling - current) * 0.06));
progressRef.current = next;
setProgress(next);
}, 220);
return () => window.clearInterval(id);
}, []);
const pct = Math.round(progress);
const stageIndex = Math.min(STAGES.length - 1, Math.floor((progress / 100) * STAGES.length));
return (
<div className="absolute inset-0 z-50 flex items-center justify-center bg-gray-900/60 backdrop-blur-sm">
<div className="w-[min(440px,90vw)] rounded-2xl bg-white p-8 shadow-2xl" style={{ fontFamily: 'Inter, sans-serif' }}>
{/* Title */}
<div className="mb-6">
<span className="text-sm font-semibold tracking-tight text-gray-900">Creating your presentation</span>
</div>
{/* Progress bar */}
<div className="mb-3 h-2.5 w-full overflow-hidden rounded-full bg-gray-100">
<div
className="h-full rounded-full transition-[width] duration-300 ease-out"
style={{
width: `${pct}%`,
backgroundImage:
'linear-gradient(90deg, #ef4444 0%, #f97316 55%, #fb923c 100%)',
}}
/>
</div>
{/* Stage label + percentage */}
<div className="flex items-center justify-between">
<div className="flex items-center gap-2 text-sm text-gray-600">
<span>{STAGES[stageIndex]}…</span>
</div>
<span className="tabular-nums text-sm font-semibold text-gray-900">{pct}%</span>
</div>
<p className="mt-5 text-xs text-gray-400">This usually takes a few moments. Please don’t refresh the page.</p>
</div>
</div>
);
}