revert: remove all color-coding attempts for difficulty presets
Reverting commits: - 0a5812c9 fix(worksheets): use white text on colored backgrounds - 5d8ac63c feat(worksheets): use more vibrant and distinct difficulty colors - e641b5e3 feat(worksheets): implement true RGB color interpolation - a7cef56f fix(worksheets): increase color visibility for difficulty presets - a09a1cbb feat(worksheets): add color-coding to difficulty presets Returning to simple, uncolored preset buttons. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,6 @@ import { ModeSelector } from './ModeSelector'
|
||||
import {
|
||||
DIFFICULTY_PROFILES,
|
||||
DIFFICULTY_PROGRESSION,
|
||||
DIFFICULTY_COLORS,
|
||||
makeHarder,
|
||||
makeEasier,
|
||||
calculateOverallDifficulty,
|
||||
@@ -25,7 +24,6 @@ import {
|
||||
SCAFFOLDING_PROGRESSION,
|
||||
findNearestValidState,
|
||||
getProfileFromConfig,
|
||||
getInterpolatedColor,
|
||||
type DifficultyLevel,
|
||||
type DifficultyMode,
|
||||
} from '../difficultyProfiles'
|
||||
@@ -424,15 +422,6 @@ export function ConfigPanel({ formState, onChange }: ConfigPanelProps) {
|
||||
let nearestEasier: DifficultyLevel | null = null
|
||||
let nearestHarder: DifficultyLevel | null = null
|
||||
let customDescription: React.ReactNode = ''
|
||||
let buttonColors = isCustom
|
||||
? {
|
||||
bg: 'orange.50' as const,
|
||||
border: 'orange.400' as const,
|
||||
text: 'orange.600' as const,
|
||||
}
|
||||
: currentProfile
|
||||
? DIFFICULTY_COLORS[currentProfile]
|
||||
: DIFFICULTY_COLORS.earlyLearner
|
||||
|
||||
if (isCustom) {
|
||||
const currentRegrouping = calculateRegroupingIntensity(pAnyStart, pAllStart)
|
||||
@@ -484,14 +473,6 @@ export function ConfigPanel({ formState, onChange }: ConfigPanelProps) {
|
||||
? harderPresets[0].presetName
|
||||
: distances[distances.length - 1].presetName
|
||||
|
||||
// Get interpolated color based on position between nearest presets
|
||||
buttonColors = getInterpolatedColor(
|
||||
nearestEasier,
|
||||
nearestHarder,
|
||||
currentRegrouping,
|
||||
currentScaffolding
|
||||
)
|
||||
|
||||
// Generate custom description
|
||||
const regroupingPercent = Math.round(currentRegrouping * 10)
|
||||
const scaffoldingSummary = getScaffoldingSummary(displayRules)
|
||||
@@ -607,8 +588,8 @@ export function ConfigPanel({ formState, onChange }: ConfigPanelProps) {
|
||||
px: '3',
|
||||
py: '2.5',
|
||||
border: '2px solid',
|
||||
borderColor: buttonColors.border,
|
||||
bg: buttonColors.bg,
|
||||
borderColor: isCustom ? 'orange.400' : 'gray.300',
|
||||
bg: isCustom ? 'orange.50' : 'white',
|
||||
rounded: 'lg',
|
||||
cursor: 'pointer',
|
||||
transition: 'all 0.15s',
|
||||
@@ -618,7 +599,7 @@ export function ConfigPanel({ formState, onChange }: ConfigPanelProps) {
|
||||
textAlign: 'left',
|
||||
gap: '2',
|
||||
_hover: {
|
||||
opacity: 0.9,
|
||||
borderColor: isCustom ? 'orange.500' : 'brand.400',
|
||||
},
|
||||
})}
|
||||
>
|
||||
@@ -656,7 +637,7 @@ export function ConfigPanel({ formState, onChange }: ConfigPanelProps) {
|
||||
<div
|
||||
className={css({
|
||||
fontSize: 'xs',
|
||||
color: buttonColors.text,
|
||||
color: isCustom ? 'orange.600' : 'gray.500',
|
||||
lineHeight: '1.3',
|
||||
h: '14',
|
||||
display: 'flex',
|
||||
@@ -724,7 +705,6 @@ export function ConfigPanel({ formState, onChange }: ConfigPanelProps) {
|
||||
{DIFFICULTY_PROGRESSION.map((presetName) => {
|
||||
const preset = DIFFICULTY_PROFILES[presetName]
|
||||
const isSelected = currentProfile === presetName && !isCustom
|
||||
const presetColors = DIFFICULTY_COLORS[presetName]
|
||||
|
||||
// Generate preset description
|
||||
const regroupingPercent = Math.round(
|
||||
@@ -763,14 +743,12 @@ export function ConfigPanel({ formState, onChange }: ConfigPanelProps) {
|
||||
rounded: 'md',
|
||||
cursor: 'pointer',
|
||||
outline: 'none',
|
||||
bg: isSelected ? presetColors.bg : 'transparent',
|
||||
borderLeft: '3px solid',
|
||||
borderColor: presetColors.border,
|
||||
bg: isSelected ? 'brand.50' : 'transparent',
|
||||
_hover: {
|
||||
bg: presetColors.bg,
|
||||
bg: 'brand.50',
|
||||
},
|
||||
_focus: {
|
||||
bg: presetColors.bg,
|
||||
bg: 'brand.100',
|
||||
},
|
||||
})}
|
||||
>
|
||||
@@ -778,7 +756,7 @@ export function ConfigPanel({ formState, onChange }: ConfigPanelProps) {
|
||||
className={css({
|
||||
fontSize: 'sm',
|
||||
fontWeight: 'semibold',
|
||||
color: presetColors.text,
|
||||
color: isSelected ? 'brand.700' : 'gray.700',
|
||||
})}
|
||||
>
|
||||
{preset.label}
|
||||
@@ -786,7 +764,7 @@ export function ConfigPanel({ formState, onChange }: ConfigPanelProps) {
|
||||
<div
|
||||
className={css({
|
||||
fontSize: 'xs',
|
||||
color: presetColors.text,
|
||||
color: isSelected ? 'brand.600' : 'gray.500',
|
||||
lineHeight: '1.3',
|
||||
})}
|
||||
>
|
||||
|
||||
@@ -363,103 +363,6 @@ export interface DifficultyProfile {
|
||||
* Pre-defined difficulty profiles that map to pedagogical progression
|
||||
* Each profile balances problem complexity (regrouping) with scaffolding support
|
||||
*/
|
||||
/**
|
||||
* Color palette for difficulty levels (RGB values for interpolation)
|
||||
* Vibrant, distinct progression: emerald → cyan → purple → amber → crimson
|
||||
* Darker backgrounds with white text for better contrast
|
||||
*/
|
||||
const DIFFICULTY_RGB = {
|
||||
beginner: { bg: [16, 185, 129], border: [5, 150, 105], text: [255, 255, 255] }, // emerald - fresh, encouraging
|
||||
earlyLearner: { bg: [6, 182, 212], border: [8, 145, 178], text: [255, 255, 255] }, // cyan - calm, learning
|
||||
intermediate: { bg: [168, 85, 247], border: [147, 51, 234], text: [255, 255, 255] }, // purple - transitional
|
||||
advanced: { bg: [245, 158, 11], border: [217, 119, 6], text: [255, 255, 255] }, // amber - warming up
|
||||
expert: { bg: [220, 38, 38], border: [185, 28, 28], text: [255, 255, 255] }, // crimson - intense
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Color palette for difficulty levels (Panda CSS tokens)
|
||||
* Used for preset buttons in dropdown menu
|
||||
*/
|
||||
export const DIFFICULTY_COLORS = {
|
||||
beginner: { bg: 'emerald.500', border: 'emerald.600', text: 'white' },
|
||||
earlyLearner: { bg: 'cyan.500', border: 'cyan.600', text: 'white' },
|
||||
intermediate: { bg: 'purple.500', border: 'purple.600', text: 'white' },
|
||||
advanced: { bg: 'amber.500', border: 'amber.600', text: 'white' },
|
||||
expert: { bg: 'red.600', border: 'red.700', text: 'white' },
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Linearly interpolate between two RGB colors
|
||||
*/
|
||||
function interpolateRGB(color1: number[], color2: number[], weight: number): number[] {
|
||||
return [
|
||||
Math.round(color1[0] + (color2[0] - color1[0]) * weight),
|
||||
Math.round(color1[1] + (color2[1] - color1[1]) * weight),
|
||||
Math.round(color1[2] + (color2[2] - color1[2]) * weight),
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert RGB array to CSS string
|
||||
*/
|
||||
function rgbToString(rgb: number[]): string {
|
||||
return `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`
|
||||
}
|
||||
|
||||
/**
|
||||
* Get interpolated color between two presets based on distance
|
||||
* Uses pythagorean distance in 2D difficulty space to blend colors
|
||||
*/
|
||||
export function getInterpolatedColor(
|
||||
nearestEasier: DifficultyLevel,
|
||||
nearestHarder: DifficultyLevel,
|
||||
currentRegrouping: number,
|
||||
currentScaffolding: number
|
||||
): { bg: string; border: string; text: string } {
|
||||
const easierProfile = DIFFICULTY_PROFILES[nearestEasier]
|
||||
const harderProfile = DIFFICULTY_PROFILES[nearestHarder]
|
||||
|
||||
// Calculate positions in 2D space
|
||||
const easierRegrouping = calculateRegroupingIntensity(
|
||||
easierProfile.regrouping.pAnyStart,
|
||||
easierProfile.regrouping.pAllStart
|
||||
)
|
||||
const easierScaffolding = calculateScaffoldingLevel(easierProfile.displayRules, easierRegrouping)
|
||||
|
||||
const harderRegrouping = calculateRegroupingIntensity(
|
||||
harderProfile.regrouping.pAnyStart,
|
||||
harderProfile.regrouping.pAllStart
|
||||
)
|
||||
const harderScaffolding = calculateScaffoldingLevel(harderProfile.displayRules, harderRegrouping)
|
||||
|
||||
// Calculate distances
|
||||
const distanceToEasier = Math.sqrt(
|
||||
(currentRegrouping - easierRegrouping) ** 2 + (currentScaffolding - easierScaffolding) ** 2
|
||||
)
|
||||
const distanceToHarder = Math.sqrt(
|
||||
(currentRegrouping - harderRegrouping) ** 2 + (currentScaffolding - harderScaffolding) ** 2
|
||||
)
|
||||
|
||||
// Calculate interpolation weight (0 = easier, 1 = harder)
|
||||
const totalDistance = distanceToEasier + distanceToHarder
|
||||
const weight = totalDistance > 0 ? distanceToEasier / totalDistance : 0.5
|
||||
|
||||
// Get RGB values for both presets
|
||||
const easierRGB = DIFFICULTY_RGB[nearestEasier]
|
||||
const harderRGB = DIFFICULTY_RGB[nearestHarder]
|
||||
|
||||
// Interpolate each color channel
|
||||
const bgRGB = interpolateRGB(easierRGB.bg, harderRGB.bg, weight)
|
||||
const borderRGB = interpolateRGB(easierRGB.border, harderRGB.border, weight)
|
||||
const textRGB = interpolateRGB(easierRGB.text, harderRGB.text, weight)
|
||||
|
||||
return {
|
||||
bg: rgbToString(bgRGB),
|
||||
border: rgbToString(borderRGB),
|
||||
text: rgbToString(textRGB),
|
||||
}
|
||||
}
|
||||
|
||||
export const DIFFICULTY_PROFILES: Record<string, DifficultyProfile> = {
|
||||
beginner: {
|
||||
name: 'beginner',
|
||||
|
||||
Reference in New Issue
Block a user