feat(practice): inline emoji with random pause phrases
- Put emoji (🤔/☕) and phrase on same line in header - Add random phrases for auto-pause: "This one's a thinker!", "Brain at work!", "Deep thoughts happening...", etc. - Horizontal layout with avatar on left, title/timer on right - Smaller avatar (56px) for more compact layout 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
0ee14a71b6
commit
c13feddfbb
|
|
@ -1,6 +1,6 @@
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useMemo, useState } from 'react'
|
||||||
import { useTheme } from '@/contexts/ThemeContext'
|
import { useTheme } from '@/contexts/ThemeContext'
|
||||||
import type { SessionPart, SessionPlan } from '@/db/schema/session-plans'
|
import type { SessionPart, SessionPlan } from '@/db/schema/session-plans'
|
||||||
import { css } from '../../../styled-system/css'
|
import { css } from '../../../styled-system/css'
|
||||||
|
|
@ -55,6 +55,18 @@ function getPartTypeEmoji(type: SessionPart['type']): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fun phrases for auto-pause
|
||||||
|
const AUTO_PAUSE_PHRASES = [
|
||||||
|
"This one's a thinker!",
|
||||||
|
'Taking your time? Smart!',
|
||||||
|
'Deep thoughts happening...',
|
||||||
|
'Brain at work!',
|
||||||
|
'No rush!',
|
||||||
|
'Thinking cap on!',
|
||||||
|
'Processing...',
|
||||||
|
'Working it out!',
|
||||||
|
]
|
||||||
|
|
||||||
// Intl formatters for duration display
|
// Intl formatters for duration display
|
||||||
const secondsFormatter = new Intl.NumberFormat('en', {
|
const secondsFormatter = new Intl.NumberFormat('en', {
|
||||||
style: 'unit',
|
style: 'unit',
|
||||||
|
|
@ -258,6 +270,13 @@ export function SessionPausedModal({
|
||||||
// Toggle for showing stats details
|
// Toggle for showing stats details
|
||||||
const [showStats, setShowStats] = useState(false)
|
const [showStats, setShowStats] = useState(false)
|
||||||
|
|
||||||
|
// Pick a random phrase once per pause (stable while modal is open)
|
||||||
|
const autoPausePhrase = useMemo(
|
||||||
|
() => AUTO_PAUSE_PHRASES[Math.floor(Math.random() * AUTO_PAUSE_PHRASES.length)],
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
[pauseInfo?.pausedAt?.getTime()]
|
||||||
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isOpen || !pauseInfo?.pausedAt) {
|
if (!isOpen || !pauseInfo?.pausedAt) {
|
||||||
setPauseDuration(0)
|
setPauseDuration(0)
|
||||||
|
|
@ -324,74 +343,60 @@ export function SessionPausedModal({
|
||||||
})}
|
})}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
{/* Hero section with avatar */}
|
{/* Hero section with avatar and title */}
|
||||||
<div
|
<div
|
||||||
className={css({
|
className={css({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: '0.75rem',
|
gap: '0.75rem',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{/* Thinking character */}
|
{/* Student avatar */}
|
||||||
<div
|
<div
|
||||||
|
data-element="student-avatar"
|
||||||
className={css({
|
className={css({
|
||||||
position: 'relative',
|
width: '56px',
|
||||||
|
height: '56px',
|
||||||
|
borderRadius: '50%',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
fontSize: '2rem',
|
||||||
|
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
|
||||||
|
flexShrink: 0,
|
||||||
})}
|
})}
|
||||||
|
style={{ backgroundColor: student.color }}
|
||||||
>
|
>
|
||||||
<div
|
{student.emoji}
|
||||||
data-element="student-avatar"
|
|
||||||
className={css({
|
|
||||||
width: '72px',
|
|
||||||
height: '72px',
|
|
||||||
borderRadius: '50%',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
fontSize: '2.5rem',
|
|
||||||
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
|
|
||||||
})}
|
|
||||||
style={{ backgroundColor: student.color }}
|
|
||||||
>
|
|
||||||
{student.emoji}
|
|
||||||
</div>
|
|
||||||
{/* Thought bubble */}
|
|
||||||
<div
|
|
||||||
className={css({
|
|
||||||
position: 'absolute',
|
|
||||||
top: '-8px',
|
|
||||||
right: '-12px',
|
|
||||||
fontSize: '1.5rem',
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{isAutoTimeout ? '🤔' : '☕'}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Greeting with integrated timer */}
|
{/* Title with emoji and timer */}
|
||||||
<div className={css({ textAlign: 'center' })}>
|
<div>
|
||||||
<h2
|
<h2
|
||||||
className={css({
|
className={css({
|
||||||
fontSize: '1.25rem',
|
fontSize: '1.125rem',
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
color: isDark ? 'gray.100' : 'gray.800',
|
color: isDark ? 'gray.100' : 'gray.800',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: '0.375rem',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{isAutoTimeout ? "This one's a thinker!" : 'Break Time!'}
|
<span>{isAutoTimeout ? '🤔' : '☕'}</span>
|
||||||
|
<span>{isAutoTimeout ? autoPausePhrase : 'Break Time!'}</span>
|
||||||
</h2>
|
</h2>
|
||||||
{pauseInfo && (
|
{pauseInfo && (
|
||||||
<p
|
<p
|
||||||
className={css({
|
className={css({
|
||||||
fontSize: '0.875rem',
|
fontSize: '0.8125rem',
|
||||||
color: isDark ? 'gray.400' : 'gray.500',
|
color: isDark ? 'gray.500' : 'gray.400',
|
||||||
marginTop: '0.25rem',
|
marginTop: '0.125rem',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
⏱️{' '}
|
⏱️{' '}
|
||||||
<span
|
<span
|
||||||
className={css({
|
className={css({
|
||||||
fontFamily: 'monospace',
|
fontFamily: 'monospace',
|
||||||
color: isDark ? 'gray.300' : 'gray.600',
|
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{formatDurationFriendly(pauseDuration)}
|
{formatDurationFriendly(pauseDuration)}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue