feat: Maestro loading animation - bouncing music note on staff
Replaced generic spinning character with a custom SVG eighth note bouncing against four staff lines. Added note-bounce keyframe to Tailwind config (0.6s ease-in-out infinite). More on-brand for a music tool than a generic spinner.
This commit is contained in:
1 parent
b08d0b6782
commit
9df8a4f865
2 files changed
+42
-13
No files matched your search
@@ -19,6 +19,30 @@ interface Props {
|
||||
onStructuredResult?: (fields: PromptStructure, mode: 'generate' | 'complete') => void
|
||||
}
|
||||
|
||||
function BouncingNote() {
|
||||
return (
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 18 18"
|
||||
className="animate-note-bounce"
|
||||
aria-hidden="true"
|
||||
>
|
||||
{/* Staff lines */}
|
||||
<line x1="2" y1="5" x2="16" y2="5" stroke="currentColor" strokeWidth="0.7" opacity="0.4" />
|
||||
<line x1="2" y1="8" x2="16" y2="8" stroke="currentColor" strokeWidth="0.7" opacity="0.4" />
|
||||
<line x1="2" y1="11" x2="16" y2="11" stroke="currentColor" strokeWidth="0.7" opacity="0.4" />
|
||||
<line x1="2" y1="14" x2="16" y2="14" stroke="currentColor" strokeWidth="0.7" opacity="0.4" />
|
||||
{/* Note head */}
|
||||
<ellipse cx="5.5" cy="13" rx="2.5" ry="2" fill="currentColor" transform="rotate(-15 5.5 13)" />
|
||||
{/* Stem */}
|
||||
<line x1="7.8" y1="12.5" x2="7.8" y2="4" stroke="currentColor" strokeWidth="1.2" />
|
||||
{/* Flag */}
|
||||
<path d="M7.8 4 C10 5.5, 9.5 7.5, 7.8 8" fill="none" stroke="currentColor" strokeWidth="1" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default function MaestroButton({
|
||||
prompt,
|
||||
onResult,
|
||||
@@ -75,26 +99,26 @@ export default function MaestroButton({
|
||||
type="button"
|
||||
onClick={handleMaestro}
|
||||
disabled={isMaestroing}
|
||||
className={`${className} flex items-center justify-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md min-w-[140px] border transition-colors duration-200 ${
|
||||
className={`${className} flex items-center justify-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md min-w-[140px] border border-kithara-accent/30 transition-colors duration-200 ${
|
||||
isMaestroing
|
||||
? 'bg-kithara-accent/20 border-kithara-accent/30 text-kithara-accent animate-pulse'
|
||||
: 'bg-kithara-accent/10 border-kithara-accent/30 hover:bg-kithara-accent/25 hover:border-kithara-accent/50 text-kithara-accent'
|
||||
? 'bg-kithara-accent/20 text-kithara-accent'
|
||||
: 'bg-kithara-accent/10 text-kithara-accent hover:bg-kithara-accent/25 hover:border-kithara-accent/50'
|
||||
}`}
|
||||
title={mode === 'generate'
|
||||
? "Let Maestro write a creative prompt for you"
|
||||
: "Let Maestro complete your prompt with musical details"
|
||||
}
|
||||
>
|
||||
{isMaestroing ? (
|
||||
<>
|
||||
<span className="inline-block animate-spin">♩</span>
|
||||
<span className="truncate">
|
||||
{mode === 'generate' ? 'Dreaming...' : 'Composing...'}
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<span className="truncate">{label}</span>
|
||||
)}
|
||||
{isMaestroing ? (
|
||||
<>
|
||||
<BouncingNote />
|
||||
<span className="truncate">
|
||||
{mode === 'generate' ? 'Dreaming...' : 'Composing...'}
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<span className="truncate">{label}</span>
|
||||
)}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
@@ -19,9 +19,14 @@ export default {
|
||||
'0%': { transform: 'translateX(0)' },
|
||||
'100%': { transform: 'translateX(-50%)' },
|
||||
},
|
||||
'note-bounce': {
|
||||
'0%, 100%': { transform: 'translateY(0)' },
|
||||
'50%': { transform: 'translateY(-3px)' },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
'marquee': 'marquee-scroll linear infinite',
|
||||
'note-bounce': 'note-bounce 0.6s ease-in-out infinite',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user