Compare commits

..

2 Commits

Author SHA1 Message Date
semantic-release-bot
9a688c1574 chore(release): 4.33.0 [skip ci]
## [4.33.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.32.1...v4.33.0) (2025-10-20)

### Features

* **abacus-react:** add BigInt support for 30-digit Dan level abacuses ([0ab4cc2](0ab4cc2880))
* **levels:** add hover interaction and smooth React Spring transitions ([fd2b633](fd2b6338a8))
2025-10-20 13:43:10 +00:00
Thomas Hallock
fd2b6338a8 feat(levels): add hover interaction and smooth React Spring transitions
Add hover/touch support and smooth animations to the levels page slider
for an enhanced interactive experience.

Changes:
- Add hover/touch move handlers to slider for instant level preview
- Integrate React Spring for smooth scale transitions between levels
- Animate abacus container with smooth scale transformations
- Support both mouse and touch events for mobile compatibility
- Update UI text to mention hover, drag, and touch interactions

The slider now responds immediately to mouse/touch position, making it
easy to explore different levels by simply hovering over the slider.
React Spring provides smooth transitions when switching between levels
with different abacus sizes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 08:41:58 -05:00
3 changed files with 64 additions and 21 deletions

View File

@@ -1,3 +1,11 @@
## [4.33.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.32.1...v4.33.0) (2025-10-20)
### Features
* **abacus-react:** add BigInt support for 30-digit Dan level abacuses ([0ab4cc2](https://github.com/antialias/soroban-abacus-flashcards/commit/0ab4cc288066b75a6ea4371f65098db5c0fc8847))
* **levels:** add hover interaction and smooth React Spring transitions ([fd2b633](https://github.com/antialias/soroban-abacus-flashcards/commit/fd2b6338a84c3bbc683eff216a8da3b155749f0f))
## [4.32.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.32.0...v4.32.1) (2025-10-20)

View File

@@ -1,6 +1,7 @@
'use client'
import { useState } from 'react'
import { useRef, useState } from 'react'
import { useSpring, animated } from '@react-spring/web'
import { AbacusReact } from '@soroban/abacus-react'
import { PageWithNav } from '@/components/PageWithNav'
import { css } from '../../../styled-system/css'
@@ -121,12 +122,36 @@ const allLevels = [
export default function LevelsPage() {
const [currentIndex, setCurrentIndex] = useState(0)
const sliderRef = useRef<HTMLInputElement>(null)
const currentLevel = allLevels[currentIndex]
// Calculate scale factor based on number of columns to fit the page
// Smaller scale for more columns (Dan levels with 30 columns)
const scaleFactor = Math.min(2.5, 20 / currentLevel.digits)
// Animate scale factor with React Spring for smooth transitions
const animatedProps = useSpring({
scaleFactor,
config: { tension: 280, friction: 60 },
})
// Handle mouse/touch move over slider for hover interaction
const handleSliderHover = (
e: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>
) => {
if (!sliderRef.current) return
const rect = sliderRef.current.getBoundingClientRect()
const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX
const x = clientX - rect.left
const percentage = Math.max(0, Math.min(1, x / rect.width))
const newIndex = Math.round(percentage * (allLevels.length - 1))
if (newIndex !== currentIndex) {
setCurrentIndex(newIndex)
}
}
// Generate an interesting non-zero number to display on the abacus
// Use a suffix pattern so rightmost digits stay constant as columns increase
// This prevents beads from shifting: ones always 9, tens always 8, etc.
@@ -263,7 +288,7 @@ export default function LevelsPage() {
</div>
{/* Abacus Display */}
<div
<animated.div
className={css({
display: 'flex',
justifyContent: 'center',
@@ -275,6 +300,9 @@ export default function LevelsPage() {
borderColor: 'gray.700',
overflowX: 'auto',
})}
style={{
transform: animatedProps.scaleFactor.to((s) => `scale(${s / scaleFactor})`),
}}
>
<AbacusReact
value={displayValue}
@@ -283,7 +311,7 @@ export default function LevelsPage() {
showNumbers={true}
customStyles={darkStyles}
/>
</div>
</animated.div>
{/* Digit Count */}
<div className={css({ textAlign: 'center', color: 'gray.400', fontSize: 'sm' })}>
@@ -308,26 +336,33 @@ export default function LevelsPage() {
Explore All Levels
</h3>
<p className={css({ fontSize: 'sm', color: 'gray.400' })}>
Drag the slider to see each rank
Hover, drag, or touch the slider to see each rank
</p>
</div>
{/* Range Slider */}
<input
type="range"
min="0"
max={allLevels.length - 1}
value={currentIndex}
onChange={(e) => setCurrentIndex(Number(e.target.value))}
className={css({
w: '100%',
h: '2',
bg: 'gray.700',
rounded: 'full',
outline: 'none',
cursor: 'pointer',
})}
/>
{/* Range Slider with hover support */}
<div
onMouseMove={handleSliderHover}
onTouchMove={handleSliderHover}
className={css({ position: 'relative' })}
>
<input
ref={sliderRef}
type="range"
min="0"
max={allLevels.length - 1}
value={currentIndex}
onChange={(e) => setCurrentIndex(Number(e.target.value))}
className={css({
w: '100%',
h: '2',
bg: 'gray.700',
rounded: 'full',
outline: 'none',
cursor: 'pointer',
})}
/>
</div>
{/* Level Markers */}
<div

View File

@@ -1,6 +1,6 @@
{
"name": "soroban-monorepo",
"version": "4.32.1",
"version": "4.33.0",
"private": true,
"description": "Beautiful Soroban Flashcard Generator - Monorepo",
"workspaces": [