feat: apply skill-specific scaffolding and fix mini card heights
**Issue 1: Too much scaffolding on mastery skills** - Mastery skills have `recommendedScaffolding` defined but weren't being applied - "Five-digit mastery" should have zero scaffolding (no carry boxes, no answer boxes) **Issue 2: Variable card heights in mixed mode** - Mini skill cards used `minHeight` which allowed them to grow - Description text of varying lengths caused buttons to jump around **Fix 1: Auto-apply recommendedScaffolding in mastery mode** - validation.ts: Query skill by ID and apply its recommendedScaffolding - Single operator: Use skill's exact scaffolding rules - Mixed mode: Merge both skills, taking least scaffolding (most restrictive) - 5d-mastery skills now correctly show: - carryBoxes: 'never' - answerBoxes: 'never' - placeValueColors: 'when3PlusDigits' (shown for 5-digit, hidden otherwise) - tenFrames: 'never' **Fix 2: Enforce fixed height for mini cards** - Changed `minHeight` → `height: '5.5rem'` - Added `overflow: 'hidden'` to container - Added `flexShrink: 0` to header and title - Description truncates with ellipsis after 2 lines (`WebkitLineClamp: 2`) - Buttons now stay perfectly aligned Files changed: - `validation.ts`: Apply recommendedScaffolding from skills in mastery mode - `MasteryModePanel.tsx`: Fixed height (5.5rem) with 2-line description clamp 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
4a5294353e
commit
ee90182ff2
|
|
@ -287,9 +287,10 @@ export function MasteryModePanel({ formState, onChange, isDark = false }: Master
|
|||
border: '1px solid',
|
||||
borderColor: isDark ? 'gray.600' : 'gray.300',
|
||||
backgroundColor: isDark ? 'gray.600' : 'white',
|
||||
minHeight: '5.5rem',
|
||||
height: '5.5rem',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
overflow: 'hidden',
|
||||
})}
|
||||
>
|
||||
<div
|
||||
|
|
@ -300,11 +301,19 @@ export function MasteryModePanel({ formState, onChange, isDark = false }: Master
|
|||
marginBottom: '0.25rem',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '0.025em',
|
||||
flexShrink: 0,
|
||||
})}
|
||||
>
|
||||
Addition
|
||||
</div>
|
||||
<div className={css({ display: 'flex', alignItems: 'center', gap: '0.375rem' })}>
|
||||
<div
|
||||
className={css({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.375rem',
|
||||
flexShrink: 0,
|
||||
})}
|
||||
>
|
||||
<h4
|
||||
className={css({
|
||||
fontSize: '0.8125rem',
|
||||
|
|
@ -333,6 +342,11 @@ export function MasteryModePanel({ formState, onChange, isDark = false }: Master
|
|||
color: isDark ? 'gray.400' : 'gray.600',
|
||||
marginTop: '0.25rem',
|
||||
lineHeight: '1.3',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
display: '-webkit-box',
|
||||
WebkitLineClamp: 2,
|
||||
WebkitBoxOrient: 'vertical',
|
||||
})}
|
||||
>
|
||||
{currentAdditionSkill.description}
|
||||
|
|
@ -432,9 +446,10 @@ export function MasteryModePanel({ formState, onChange, isDark = false }: Master
|
|||
border: '1px solid',
|
||||
borderColor: isDark ? 'gray.600' : 'gray.300',
|
||||
backgroundColor: isDark ? 'gray.600' : 'white',
|
||||
minHeight: '5.5rem',
|
||||
height: '5.5rem',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
overflow: 'hidden',
|
||||
})}
|
||||
>
|
||||
<div
|
||||
|
|
@ -445,11 +460,19 @@ export function MasteryModePanel({ formState, onChange, isDark = false }: Master
|
|||
marginBottom: '0.25rem',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '0.025em',
|
||||
flexShrink: 0,
|
||||
})}
|
||||
>
|
||||
Subtraction
|
||||
</div>
|
||||
<div className={css({ display: 'flex', alignItems: 'center', gap: '0.375rem' })}>
|
||||
<div
|
||||
className={css({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.375rem',
|
||||
flexShrink: 0,
|
||||
})}
|
||||
>
|
||||
<h4
|
||||
className={css({
|
||||
fontSize: '0.8125rem',
|
||||
|
|
@ -478,6 +501,11 @@ export function MasteryModePanel({ formState, onChange, isDark = false }: Master
|
|||
color: isDark ? 'gray.400' : 'gray.600',
|
||||
marginTop: '0.25rem',
|
||||
lineHeight: '1.3',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
display: '-webkit-box',
|
||||
WebkitLineClamp: 2,
|
||||
WebkitBoxOrient: 'vertical',
|
||||
})}
|
||||
>
|
||||
{currentSubtractionSkill.description}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import type { WorksheetFormState, WorksheetConfig, ValidationResult } from './types'
|
||||
import type { DisplayRules } from './displayRules'
|
||||
import { getSkillById } from './skills'
|
||||
|
||||
/**
|
||||
* Get current date formatted as "Month Day, Year"
|
||||
|
|
@ -150,7 +151,9 @@ export function validateWorksheetConfig(formState: WorksheetFormState): Validati
|
|||
|
||||
if (mode === 'smart' || mode === 'mastery') {
|
||||
// Smart & Mastery modes: Use displayRules for conditional scaffolding
|
||||
const displayRules: DisplayRules = {
|
||||
|
||||
// Default display rules
|
||||
let baseDisplayRules: DisplayRules = {
|
||||
carryBoxes: 'whenRegrouping',
|
||||
answerBoxes: 'always',
|
||||
placeValueColors: 'always',
|
||||
|
|
@ -159,6 +162,67 @@ export function validateWorksheetConfig(formState: WorksheetFormState): Validati
|
|||
cellBorders: 'always',
|
||||
borrowNotation: 'whenRegrouping', // Subtraction: show when borrowing
|
||||
borrowingHints: 'never', // Subtraction: no hints by default
|
||||
}
|
||||
|
||||
// Mastery mode: Apply recommendedScaffolding from current skill(s)
|
||||
if (mode === 'mastery') {
|
||||
const operator = formState.operator ?? 'addition'
|
||||
|
||||
if (operator === 'mixed') {
|
||||
// Mixed mode: Merge scaffolding from both skills
|
||||
const addSkillId = formState.currentAdditionSkillId
|
||||
const subSkillId = formState.currentSubtractionSkillId
|
||||
|
||||
if (addSkillId && subSkillId) {
|
||||
const addSkill = getSkillById(addSkillId as any)
|
||||
const subSkill = getSkillById(subSkillId as any)
|
||||
|
||||
if (addSkill?.recommendedScaffolding && subSkill?.recommendedScaffolding) {
|
||||
// Use the LEAST scaffolding from both (most restrictive)
|
||||
// This ensures mastery-level problems have minimal scaffolding
|
||||
baseDisplayRules = {
|
||||
// Take 'never' if either skill recommends it
|
||||
carryBoxes:
|
||||
addSkill.recommendedScaffolding.carryBoxes === 'never' ||
|
||||
subSkill.recommendedScaffolding.carryBoxes === 'never'
|
||||
? 'never'
|
||||
: 'whenRegrouping',
|
||||
answerBoxes:
|
||||
addSkill.recommendedScaffolding.answerBoxes === 'never' ||
|
||||
subSkill.recommendedScaffolding.answerBoxes === 'never'
|
||||
? 'never'
|
||||
: 'always',
|
||||
placeValueColors:
|
||||
addSkill.recommendedScaffolding.placeValueColors === 'never' ||
|
||||
subSkill.recommendedScaffolding.placeValueColors === 'never'
|
||||
? 'never'
|
||||
: addSkill.recommendedScaffolding.placeValueColors,
|
||||
tenFrames: 'never', // Always off for mastery
|
||||
problemNumbers: 'always',
|
||||
cellBorders: 'always',
|
||||
borrowNotation: subSkill.recommendedScaffolding.borrowNotation,
|
||||
borrowingHints: 'never',
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Single operator: Use its recommendedScaffolding
|
||||
const skillId =
|
||||
operator === 'addition'
|
||||
? formState.currentAdditionSkillId
|
||||
: formState.currentSubtractionSkillId
|
||||
|
||||
if (skillId) {
|
||||
const skill = getSkillById(skillId as any)
|
||||
if (skill?.recommendedScaffolding) {
|
||||
baseDisplayRules = { ...skill.recommendedScaffolding }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const displayRules: DisplayRules = {
|
||||
...baseDisplayRules,
|
||||
...((formState.displayRules as any) ?? {}), // Override with provided rules if any
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue