Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions apps/web/src/components/founder/AlphabetIndex/AlphabetBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,26 @@ const FACE_DOTS: Record<number, [string, string][]> = {

function DiceDockItem({ onClick }: { onClick: () => void }) {
const [rolling, setRolling] = useState(false);
const [jumping, setJumping] = useState(false);
const [showTooltip, setShowTooltip] = useState(false);
const rollingRef = useRef(false);

useEffect(() => { rollingRef.current = rolling; }, [rolling]);

// Jump d'attention toutes les 4.5s
useEffect(() => {
const interval = setInterval(() => {
if (!rollingRef.current) {
setJumping(true);
setTimeout(() => setJumping(false), 750);
}
}, 4500);
return () => clearInterval(interval);
}, []);

const handleClick = () => {
if (rolling) return;
setJumping(false);
setRolling(true);
setTimeout(() => {
setRolling(false);
Expand All @@ -95,9 +111,9 @@ function DiceDockItem({ onClick }: { onClick: () => void }) {

return (
<div
className="dock-item dock-dice"
className={`dock-item dock-dice${jumping ? ' jumping' : ''}`}
onClick={handleClick}
onMouseEnter={() => setShowTooltip(true)}
onMouseEnter={() => { setShowTooltip(true); setJumping(false); }}
onMouseLeave={() => setShowTooltip(false)}
>
<div className="dice-scene">
Expand Down
44 changes: 38 additions & 6 deletions apps/web/src/components/founder/AlphabetIndex/alphabetIndex.css
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,19 @@

/* === DOCK DICE (random button after Z) === */
.dock-dice {
width: calc(26px * var(--s));
height: calc(30px * var(--s));
width: calc(32px * var(--s));
height: calc(34px * var(--s));
border-radius: 6px;
position: relative;
transition: width 150ms ease, height 150ms ease;
}

/* 3D dice scene — provides perspective */
.dice-scene {
--dice-half: calc(7px * var(--s));
width: calc(14px * var(--s));
height: calc(14px * var(--s));
perspective: calc(84px * var(--s));
--dice-half: calc(9px * var(--s));
width: calc(18px * var(--s));
height: calc(18px * var(--s));
perspective: calc(108px * var(--s));
flex-shrink: 0;
transition: width 150ms ease, height 150ms ease, perspective 150ms ease;
}
Expand Down Expand Up @@ -105,6 +105,23 @@
border-radius: 15%;
background: rgba(20, 20, 40, 0.85);
border: 1px solid rgba(255, 255, 255, 0.2);
animation: diceFacePulse 2s ease-in-out infinite;
}

@keyframes diceFacePulse {
0%, 100% {
border-color: rgba(255, 255, 255, 0.2);
box-shadow: none;
}
50% {
border-color: rgba(255, 255, 255, 0.65);
box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.15), 0 0 6px rgba(255, 255, 255, 0.2);
}
}

/* Pas de pulse pendant le roll */
.dice-inner.rolling .dice-face {
animation: none;
}

.face-1 { transform: rotateY(0deg) translateZ(var(--dice-half)); }
Expand Down Expand Up @@ -138,6 +155,21 @@
animation: diceRoll 800ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* Idle jump — attire l'attention toutes les ~4.5s */
@keyframes diceJump {
0% { transform: translateY(0) scaleX(1) scaleY(1); }
12% { transform: translateY(0) scaleX(1.15) scaleY(0.82); } /* compression départ */
38% { transform: translateY(-9px) scaleX(0.88) scaleY(1.12); } /* en l'air */
55% { transform: translateY(-9px) scaleX(0.88) scaleY(1.12); } /* flottement */
78% { transform: translateY(0) scaleX(1.12) scaleY(0.88); } /* impact sol */
90% { transform: translateY(-3px) scaleX(0.97) scaleY(1.03); } /* mini rebond */
100% { transform: translateY(0) scaleX(1) scaleY(1); }
}

.dock-dice.jumping {
animation: diceJump 750ms cubic-bezier(0.36, 0.07, 0.19, 0.97);
}

/* Glassmorphism tooltip (same glass style as .founder-mini-card) */
.dice-tooltip {
position: absolute;
Expand Down