[eric] onboarding: claude design language (starburst mark on intro, thinking-pulse finish, starburst card emblem)

This commit is contained in:
ciregenz
2026-07-15 01:38:12 -07:00
parent db99781847
commit 6ad74bea0b
3 changed files with 45 additions and 9 deletions
@@ -8,6 +8,7 @@ import { useClaudeTokens } from '@/shared/styles/ThemeContext';
import type { ClaudeTokens } from '@/shared/styles/claudeTokens';
import { useOnboardingV3Pipeline } from './useOnboardingV3Pipeline';
import { GRAIN_URL } from './beats/BeatShell';
import Starburst from './Starburst';
import BeatConnect from './beats/BeatConnect';
import BeatApps from './beats/BeatApps';
import BeatTheme from './beats/BeatTheme';
@@ -63,11 +64,19 @@ const IntroBeat: React.FC<{ c: ClaudeTokens; line: string; sub?: string; onNext:
}}
/>
<div style={{ position: 'absolute', inset: 0, backgroundImage: GRAIN_URL, opacity: 0.14, pointerEvents: 'none', mixBlendMode: 'overlay' }} />
<motion.div
initial={{ opacity: 0, scale: 0.4, rotate: -80 }}
animate={{ opacity: 1, scale: 1, rotate: 0 }}
transition={{ type: 'spring', stiffness: 160, damping: 18, delay: 0.2 }}
style={{ position: 'relative', marginBottom: 22 }}
>
<Starburst size={44} from={c.accent.hover} to={c.accent.primary} />
</motion.div>
<motion.h1
initial={{ opacity: 0, y: 16, filter: 'blur(8px)' }}
animate={{ opacity: 1, y: 0, filter: 'blur(0px)' }}
transition={{ duration: 0.7, delay: 0.35, ease: [0.22, 1, 0.36, 1] }}
style={{ position: 'relative', margin: 0, fontSize: 'clamp(2.4rem, 5vw, 3.8rem)', fontWeight: 700, color: c.text.inverse, letterSpacing: '-0.02em', textAlign: 'center', padding: '0 24px' }}
transition={{ duration: 0.7, delay: 0.45, ease: [0.22, 1, 0.36, 1] }}
style={{ position: 'relative', margin: 0, fontSize: 'clamp(2.4rem, 5vw, 3.8rem)', fontWeight: 600, color: c.text.inverse, letterSpacing: '-0.01em', textAlign: 'center', padding: '0 24px' }}
>
{line}
</motion.h1>
@@ -202,8 +211,15 @@ const OnboardingV3Root: React.FC = () => {
))}
</motion.div>
{finishing && (
<div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', background: c.bg.page }}>
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} style={{ fontSize: '1.05rem', color: c.text.tertiary }}>
<div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', gap: 18, alignItems: 'center', justifyContent: 'center', background: c.bg.page }}>
<motion.div
initial={{ opacity: 0, scale: 0.7 }}
animate={{ opacity: [0, 1, 0.55, 1], scale: [0.7, 1, 0.92, 1], rotate: [0, 0, 22, 45] }}
transition={{ duration: 4.5, times: [0, 0.2, 0.6, 1], repeat: 3 }}
>
<Starburst size={40} from={c.accent.hover} to={c.accent.pressed} />
</motion.div>
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} style={{ fontSize: '1.02rem', color: c.text.tertiary }}>
Setting up your canvas...
</motion.div>
</div>
@@ -0,0 +1,21 @@
import React from 'react';
// Claude's signature asterisk mark, drawn as 8 rounded rays around a hollow center; gradient runs hover->pressed so it wears whatever accent the user picked.
const Starburst: React.FC<{ size: number; from: string; to: string }> = ({ size, from, to }) => {
const id = React.useId();
return (
<svg width={size} height={size} viewBox="-50 -50 100 100" style={{ display: 'block' }}>
<defs>
<linearGradient id={id} x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stopColor={from} />
<stop offset="100%" stopColor={to} />
</linearGradient>
</defs>
{Array.from({ length: 8 }, (unused, i) => (
<rect key={i} x={-7} y={-46} width={14} height={34} rx={7} fill={`url(#${id})`} transform={`rotate(${i * 45})`} />
))}
</svg>
);
};
export default Starburst;
@@ -3,6 +3,7 @@ import { motion } from 'framer-motion';
import { Dices } from 'lucide-react';
import type { ClaudeTokens } from '@/shared/styles/claudeTokens';
import type { ProviderIdentity } from '../onboardingV3Api';
import Starburst from '../Starburst';
import BeatShell from './BeatShell';
const EPITHETS = [
@@ -52,11 +53,9 @@ const BeatCard: React.FC<{
display: 'flex', flexDirection: 'column', position: 'relative',
}}
>
<div style={{
width: 168, height: 158, alignSelf: 'flex-start',
borderRadius: '6% 64% 6% 64%',
background: `linear-gradient(135deg, ${c.accent.hover}, ${c.accent.primary} 70%, ${c.accent.pressed})`,
}} />
<div style={{ alignSelf: 'flex-start', marginLeft: -8, marginTop: -4 }}>
<Starburst size={158} from={c.accent.hover} to={c.accent.pressed} />
</div>
<input
value={name}
onChange={(e) => setName(e.target.value.slice(0, 18))}