feat: move difficulty parameters into Smart mode

Group difficulty configuration parameters inside Smart Difficulty mode:
- Digit Range moved from always-visible to Smart mode
- Regrouping Frequency moved from always-visible to Smart mode
- These are difficulty tuning parameters, not general settings

Changes:
- Add DigitRangeSection to top of SmartModeControls
- Add RegroupingFrequencyPanel to bottom of SmartModeControls
- Extract RegroupingFrequencyPanel as standalone component
- Remove both from ConfigPanel's always-visible section

🤖 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 18:12:23 -06:00
parent 804fb1a2f6
commit 4b667587f8
2 changed files with 184 additions and 12 deletions

View File

@ -0,0 +1,168 @@
'use client'
import * as Slider from '@radix-ui/react-slider'
import { css } from '../../../../../../../styled-system/css'
import { stack } from '../../../../../../../styled-system/patterns'
import type { WorksheetFormState } from '../../types'
export interface RegroupingFrequencyPanelProps {
formState: WorksheetFormState
onChange: (updates: Partial<WorksheetFormState>) => void
isDark?: boolean
}
export function RegroupingFrequencyPanel({
formState,
onChange,
isDark = false,
}: RegroupingFrequencyPanelProps) {
return (
<div
data-section="regrouping"
className={css({
bg: isDark ? 'gray.800' : 'gray.50',
border: '1px solid',
borderColor: isDark ? 'gray.600' : 'gray.200',
rounded: 'xl',
p: '3',
})}
>
<div className={stack({ gap: '2.5' })}>
<div
className={css({
fontSize: 'xs',
fontWeight: 'semibold',
color: isDark ? 'gray.400' : 'gray.500',
textTransform: 'uppercase',
letterSpacing: 'wider',
})}
>
Regrouping Frequency
</div>
{/* Current values display */}
<div
className={css({
display: 'flex',
justifyContent: 'space-between',
fontSize: 'xs',
color: isDark ? 'gray.400' : 'gray.600',
})}
>
<div>
Both:{' '}
<span
className={css({
color: 'brand.600',
fontWeight: 'semibold',
})}
>
{Math.round((formState.pAllStart || 0) * 100)}%
</span>
</div>
<div>
Any:{' '}
<span
className={css({
color: 'brand.600',
fontWeight: 'semibold',
})}
>
{Math.round((formState.pAnyStart || 0.25) * 100)}%
</span>
</div>
</div>
{/* Double-thumbed range slider */}
<Slider.Root
className={css({
position: 'relative',
display: 'flex',
alignItems: 'center',
userSelect: 'none',
touchAction: 'none',
width: 'full',
height: '6',
})}
value={[(formState.pAllStart || 0) * 100, (formState.pAnyStart || 0.25) * 100]}
onValueChange={(values) => {
onChange({
pAllStart: values[0] / 100,
pAnyStart: values[1] / 100,
})
}}
min={0}
max={100}
step={5}
minStepsBetweenThumbs={0}
>
<Slider.Track
className={css({
position: 'relative',
flexGrow: 1,
bg: 'gray.200',
rounded: 'full',
height: '1.5',
})}
>
<Slider.Range
className={css({
position: 'absolute',
bg: 'brand.500',
rounded: 'full',
height: 'full',
})}
/>
</Slider.Track>
<Slider.Thumb
className={css({
display: 'block',
width: '3.5',
height: '3.5',
bg: 'white',
boxShadow: '0 2px 4px rgba(0,0,0,0.15)',
rounded: 'full',
border: '2px solid',
borderColor: 'brand.500',
cursor: 'pointer',
_hover: { transform: 'scale(1.1)' },
_focus: {
outline: 'none',
boxShadow: '0 0 0 3px rgba(59, 130, 246, 0.3)',
},
})}
/>
<Slider.Thumb
className={css({
display: 'block',
width: '3.5',
height: '3.5',
bg: 'white',
boxShadow: '0 2px 4px rgba(0,0,0,0.15)',
rounded: 'full',
border: '2px solid',
borderColor: 'brand.600',
cursor: 'pointer',
_hover: { transform: 'scale(1.1)' },
_focus: {
outline: 'none',
boxShadow: '0 0 0 3px rgba(59, 130, 246, 0.3)',
},
})}
/>
</Slider.Root>
<div
className={css({
fontSize: '2xs',
color: isDark ? 'gray.400' : 'gray.500',
lineHeight: '1.3',
})}
>
Regrouping difficulty at worksheet start (Both = all columns regroup, Any = at least one
column regroups)
</div>
</div>
</div>
)
}

View File

@ -25,6 +25,8 @@ import {
} from '../../difficultyProfiles' } from '../../difficultyProfiles'
import type { DisplayRules } from '../../displayRules' import type { DisplayRules } from '../../displayRules'
import { getScaffoldingSummary } from './utils' import { getScaffoldingSummary } from './utils'
import { RegroupingFrequencyPanel } from './RegroupingFrequencyPanel'
import { DigitRangeSection } from './DigitRangeSection'
export interface SmartModeControlsProps { export interface SmartModeControlsProps {
formState: WorksheetFormState formState: WorksheetFormState
@ -74,22 +76,21 @@ export function SmartModeControls({ formState, onChange, isDark = false }: Smart
} }
return ( return (
<div <div data-section="smart-mode" className={stack({ gap: '3' })}>
data-section="difficulty" {/* Digit Range */}
className={css({ <DigitRangeSection
bg: 'gray.50', digitRange={formState.digitRange}
border: '1px solid', onChange={(digitRange) => onChange({ digitRange })}
borderColor: 'gray.200', isDark={isDark}
rounded: 'xl', />
p: '3',
})} {/* Difficulty Level */}
> <div data-section="difficulty" className={stack({ gap: '2.5' })}>
<div className={stack({ gap: '2.5' })}>
<div <div
className={css({ className={css({
fontSize: 'xs', fontSize: 'xs',
fontWeight: 'semibold', fontWeight: 'semibold',
color: 'gray.500', color: isDark ? 'gray.400' : 'gray.500',
textTransform: 'uppercase', textTransform: 'uppercase',
letterSpacing: 'wider', letterSpacing: 'wider',
})} })}
@ -1478,6 +1479,9 @@ export function SmartModeControls({ formState, onChange, isDark = false }: Smart
) )
})()} })()}
</div> </div>
{/* Regrouping Frequency */}
<RegroupingFrequencyPanel formState={formState} onChange={onChange} isDark={isDark} />
</div> </div>
) )
} }