From ee90182ff2b2e9247a38ad464fc25e646e9b8cf0 Mon Sep 17 00:00:00 2001 From: Thomas Hallock Date: Mon, 10 Nov 2025 14:18:05 -0600 Subject: [PATCH] feat: apply skill-specific scaffolding and fix mini card heights MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **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 --- .../config-panel/MasteryModePanel.tsx | 36 ++++++++-- .../create/worksheets/addition/validation.ts | 66 ++++++++++++++++++- 2 files changed, 97 insertions(+), 5 deletions(-) diff --git a/apps/web/src/app/create/worksheets/addition/components/config-panel/MasteryModePanel.tsx b/apps/web/src/app/create/worksheets/addition/components/config-panel/MasteryModePanel.tsx index e7222c11..5e5c9508 100644 --- a/apps/web/src/app/create/worksheets/addition/components/config-panel/MasteryModePanel.tsx +++ b/apps/web/src/app/create/worksheets/addition/components/config-panel/MasteryModePanel.tsx @@ -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', })} >
Addition
-
+

{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', })} >
Subtraction
-
+

{currentSubtractionSkill.description} diff --git a/apps/web/src/app/create/worksheets/addition/validation.ts b/apps/web/src/app/create/worksheets/addition/validation.ts index ca40a3fc..6b308b3d 100644 --- a/apps/web/src/app/create/worksheets/addition/validation.ts +++ b/apps/web/src/app/create/worksheets/addition/validation.ts @@ -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 }