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