fix: add mode descriptions and remove double borders

Address two issues with the tab-style mode selector:

1. Add back helpful description text
   - Each mode now shows its description below the tabs
   - Description updates based on active tab
   - Preserves the helpful context from the old button layout

2. Remove double borders
   - Remove wrapper div that added extra background/padding
   - Let mode-specific controls use their own styling
   - Eliminates visual layering conflicts
   - Creates cleaner, more native tab-to-content flow

Mode descriptions:
- 🎯 Smart: "Research-backed progressive difficulty with adaptive scaffolding per problem"
- 🎛️ Manual: "Full control over display options with uniform scaffolding across all problems"
- 🎓 Mastery: "Skill-based progression with automatic review mixing for pedagogical practice"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock 2025-11-10 16:15:40 -06:00
parent 8910f6a197
commit 6f2f6d444c
2 changed files with 99 additions and 88 deletions

View File

@ -105,39 +105,28 @@ export function ConfigPanel({ formState, onChange, isDark = false }: ConfigPanel
isDark={isDark}
/>
{/* Mode Selector Tabs */}
{/* Mode Selector Tabs with description */}
<ModeSelector
currentMode={formState.mode ?? 'smart'}
onChange={handleModeChange}
isDark={isDark}
/>
{/* Mode-specific controls as tab content */}
<div
data-element="mode-content"
className={stack({
gap: '3',
padding: '1.5rem',
backgroundColor: isDark ? 'gray.700' : 'gray.50',
borderRadius: '0 0 8px 8px',
marginTop: '-1.5rem', // Connect visually to tabs
})}
>
{/* Smart Mode Controls */}
{(!formState.mode || formState.mode === 'smart') && (
<SmartModeControls formState={formState} onChange={onChange} isDark={isDark} />
)}
{/* Mode-specific controls - no wrapper, let controls style themselves */}
{/* Smart Mode Controls */}
{(!formState.mode || formState.mode === 'smart') && (
<SmartModeControls formState={formState} onChange={onChange} isDark={isDark} />
)}
{/* Manual Mode Controls */}
{formState.mode === 'manual' && (
<ManualModeControls formState={formState} onChange={onChange} isDark={isDark} />
)}
{/* Manual Mode Controls */}
{formState.mode === 'manual' && (
<ManualModeControls formState={formState} onChange={onChange} isDark={isDark} />
)}
{/* Mastery Mode Controls */}
{formState.mode === 'mastery' && (
<MasteryModePanel formState={formState} onChange={onChange} isDark={isDark} />
)}
</div>
{/* Mastery Mode Controls */}
{formState.mode === 'mastery' && (
<MasteryModePanel formState={formState} onChange={onChange} isDark={isDark} />
)}
</div>
)
}

View File

@ -18,93 +18,115 @@ export function ModeSelector({ currentMode, onChange, isDark = false }: ModeSele
id: 'smart' as const,
emoji: '🎯',
label: 'Smart Difficulty',
description: 'Research-backed progressive difficulty with adaptive scaffolding per problem',
},
{
id: 'manual' as const,
emoji: '🎛️',
label: 'Manual Control',
description: 'Full control over display options with uniform scaffolding across all problems',
},
{
id: 'mastery' as const,
emoji: '🎓',
label: 'Mastery Progression',
description: 'Skill-based progression with automatic review mixing for pedagogical practice',
},
]
const currentModeData = modes.find((m) => m.id === currentMode)
return (
<div
data-component="mode-selector-tabs"
className={css({
display: 'flex',
gap: '0.5rem',
borderBottom: '2px solid',
borderColor: isDark ? 'gray.600' : 'gray.200',
marginBottom: '1.5rem',
})}
>
{modes.map((mode) => {
const isActive = currentMode === mode.id
return (
<button
key={mode.id}
type="button"
data-action={`select-${mode.id}-mode`}
data-selected={isActive}
onClick={() => onChange(mode.id)}
className={css({
flex: 1,
padding: '1rem 1.5rem',
border: 'none',
borderBottom: '3px solid',
borderBottomColor: isActive ? 'blue.500' : 'transparent',
backgroundColor: isActive
? isDark
? 'gray.700'
: 'white'
: isDark
? 'gray.800'
: 'gray.50',
color: isActive
? isDark
? 'blue.300'
: 'blue.600'
: isDark
? 'gray.400'
: 'gray.600',
cursor: 'pointer',
transition: 'all 0.2s',
fontSize: '0.95rem',
fontWeight: isActive ? '700' : '500',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '0.5rem',
borderTopLeftRadius: '8px',
borderTopRightRadius: '8px',
_hover: {
<div data-component="mode-selector-tabs">
{/* Tab buttons */}
<div
className={css({
display: 'flex',
gap: '0.5rem',
borderBottom: '2px solid',
borderColor: isDark ? 'gray.600' : 'gray.200',
})}
>
{modes.map((mode) => {
const isActive = currentMode === mode.id
return (
<button
key={mode.id}
type="button"
data-action={`select-${mode.id}-mode`}
data-selected={isActive}
onClick={() => onChange(mode.id)}
className={css({
flex: 1,
padding: '1rem 1.5rem',
border: 'none',
borderBottom: '3px solid',
borderBottomColor: isActive ? 'blue.500' : 'transparent',
backgroundColor: isActive
? isDark
? 'gray.700'
: 'white'
: isDark
? 'gray.700'
: 'gray.100',
borderBottomColor: isActive ? 'blue.500' : isDark ? 'gray.500' : 'gray.400',
? 'gray.800'
: 'gray.50',
color: isActive
? isDark
? 'blue.300'
: 'blue.600'
: isDark
? 'gray.300'
: 'gray.700',
},
})}
>
<span className={css({ fontSize: '1.25rem' })}>{mode.emoji}</span>
<span>{mode.label}</span>
</button>
)
})}
? 'gray.400'
: 'gray.600',
cursor: 'pointer',
transition: 'all 0.2s',
fontSize: '0.95rem',
fontWeight: isActive ? '700' : '500',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '0.5rem',
borderTopLeftRadius: '8px',
borderTopRightRadius: '8px',
_hover: {
backgroundColor: isActive
? isDark
? 'gray.700'
: 'white'
: isDark
? 'gray.700'
: 'gray.100',
borderBottomColor: isActive ? 'blue.500' : isDark ? 'gray.500' : 'gray.400',
color: isActive
? isDark
? 'blue.300'
: 'blue.600'
: isDark
? 'gray.300'
: 'gray.700',
},
})}
>
<span className={css({ fontSize: '1.25rem' })}>{mode.emoji}</span>
<span>{mode.label}</span>
</button>
)
})}
</div>
{/* Description of active mode */}
{currentModeData && (
<p
className={css({
fontSize: 'sm',
color: isDark ? 'gray.400' : 'gray.600',
mt: '3',
mb: '3',
px: '2',
lineHeight: '1.5',
})}
>
{currentModeData.description}
</p>
)}
</div>
)
}