Compare commits

...

37 Commits

Author SHA1 Message Date
semantic-release-bot
321d9aea10 chore(release): 4.32.0 [skip ci]
## [4.32.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.31.1...v4.32.0) (2025-10-20)

### Features

* **levels:** add dark mode styling and responsive scaling to abacus ([92e1e62](92e1e62132))
2025-10-20 12:50:34 +00:00
Thomas Hallock
92e1e62132 feat(levels): add dark mode styling and responsive scaling to abacus
Improvements to the levels page abacus display:
- Added showNumbers={true} to show place value numbers
- Styled for dark background with light gray columns and reckoning bar
- Colored beads (blue heaven, green earth) for better visibility
- Dynamic scaling: large (2.5x) for Kyu levels, smaller for Dan levels
- Added horizontal overflow for very wide Dan level abacuses (30 columns)
- Formula: scaleFactor = Math.min(2.5, 20 / digits)

The abacus now fits gracefully at all levels and is clearly visible
on the dark page background.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 07:49:28 -05:00
semantic-release-bot
84d980bb24 chore(release): 4.31.1 [skip ci]
## [4.31.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.31.0...v4.31.1) (2025-10-20)

### Bug Fixes

* **levels:** use correct AbacusReact API with direct props ([892b377](892b377eb3))
2025-10-20 12:47:01 +00:00
Thomas Hallock
892b377eb3 fix(levels): use correct AbacusReact API with direct props
Fixed abacus not rendering by using the correct API:
- Removed non-existent useAbacusConfig import
- Changed from config object to direct props (value, columns, scaleFactor)
- Added scaleFactor=1.5 for better visibility

The abacus now properly displays with the appropriate number of columns
based on the selected kyu/dan level.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 07:45:53 -05:00
semantic-release-bot
bc21095fa1 chore(release): 4.31.0 [skip ci]
## [4.31.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.30.0...v4.31.0) (2025-10-20)

### Features

* **levels:** implement interactive slider for exploring kyu & dan ranks ([eb3b100](eb3b100056))
2025-10-20 12:41:45 +00:00
Thomas Hallock
eb3b100056 feat(levels): implement interactive slider for exploring kyu & dan ranks
Replace static grid layout with an interactive range slider that allows
users to explore all 21 kyu and dan levels dynamically. The slider updates
a single AbacusReact component showing the appropriate number of columns
(2-30 digits) based on the selected rank.

Features:
- HTML range input slider from 10th Kyu to 10th Dan
- Dynamic abacus visualization using @soroban/abacus-react
- Real-time updates of level metadata (emoji, name, min score)
- Color-coded borders matching progression levels
- Reference markers for key ranks

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 07:40:19 -05:00
semantic-release-bot
276f6f0744 chore(release): 4.30.0 [skip ci]
## [4.30.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.29.0...v4.30.0) (2025-10-20)

### Features

* **levels:** create true horizontal slider with abacus visualizations ([6d734f1](6d734f1d51))
2025-10-20 12:34:34 +00:00
Thomas Hallock
6d734f1d51 feat(levels): create true horizontal slider with abacus visualizations
Replace carousel with actual horizontal slider showing all 21 ranks:
- Continuous scrollable view of 10 Kyu levels + 11 Dan levels
- Each level card displays:
  - Level name, emoji, and metadata
  - Visual abacus showing digit mastery (2-30 columns)
  - Color-coded by progression (green→blue→violet→amber)
- Simplified abacus columns with proper visual structure
- Visual transition marker between Kyu and Dan sections
- Color legend for all four progression stages
- Fully mobile-responsive horizontal scrolling

Also add documentation note about using @soroban/abacus-react for all
abacus visualizations in the codebase.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 07:33:36 -05:00
semantic-release-bot
03b9b1228b chore(release): 4.29.0 [skip ci]
## [4.29.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.28.0...v4.29.0) (2025-10-20)

### Features

* **levels:** replace kyu grid with interactive slider and abacus visualizations ([10978e8](10978e890b))
2025-10-20 12:30:16 +00:00
Thomas Hallock
10978e890b feat(levels): replace kyu grid with interactive slider and abacus visualizations
Replace cluttered static grid of kyu level cards with an elegant horizontal slider.
Each level now features:
- Interactive slider with left/right navigation buttons
- Keyboard navigation support (arrow keys)
- Visual abacus showing digit mastery progression (2-10 columns)
- Clickable progress indicators
- Smooth transitions and hover effects
- Mobile-responsive design

The abacus visualizations provide an intuitive representation of the student's
progression through each level, showing the increasing number of digit columns
they master from 10th Kyu (2 digits) to 1st Kyu (10 digits).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 07:29:11 -05:00
semantic-release-bot
6d86281c63 chore(release): 4.28.0 [skip ci]
## [4.28.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.27.0...v4.28.0) (2025-10-20)

### Features

* **levels:** add informational footer section ([0b1bff7](0b1bff7eab))
2025-10-20 12:24:15 +00:00
Thomas Hallock
0b1bff7eab feat(levels): add informational footer section
Add comprehensive "About This Ranking System" section at the bottom of the
page explaining the Japan Abacus Federation ranking system and its purpose.

Features:
- Educational context about the JAF ranking system
- Explanation of progressive difficulty structure
- Clear disclaimer about educational vs certification purposes
- Professional styling matching the rest of the page
- Mobile-responsive padding and typography

Phase 6 complete: Final polish with educational context and disclaimers.

All phases complete! The /levels page now provides:
- Complete kyu level information (10th to 1st)
- Dan level ladder visualization (Pre-1st Dan to 10th Dan)
- Exam requirements and scoring details
- Educational context and disclaimers

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 07:23:10 -05:00
semantic-release-bot
f70ded30b9 chore(release): 4.27.0 [skip ci]
## [4.27.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.26.0...v4.27.0) (2025-10-20)

### Features

* **levels:** add Dan levels ladder visualization ([c18012c](c18012cb50))
2025-10-20 12:18:57 +00:00
Thomas Hallock
c18012cb50 feat(levels): add Dan levels ladder visualization
Add comprehensive Dan level section (Pre-1st Dan to 10th Dan) with score-based
ranking system. Display as vertical ladder showing progression from 90 to 290
points.

Features:
- Dan exam requirements box (30-digit problems, 3× 1st Kyu complexity)
- Ladder visualization with 11 Dan ranks
- Japanese names (Shodan, Nidan, etc.)
- Score thresholds for each rank
- Amber/gold color theme for master ranks
- Hover effects on each ladder rung
- Mobile-responsive design

Phase 4 complete: Full Dan ranking system with official JAF requirements.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 07:17:51 -05:00
semantic-release-bot
25a3356547 chore(release): 4.26.0 [skip ci]
## [4.26.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.25.1...v4.26.0) (2025-10-20)

### Features

* **levels:** add kyu level data and cards ([6463a3b](6463a3b2f6))
2025-10-20 12:15:15 +00:00
Thomas Hallock
6463a3b2f6 feat(levels): add kyu level data and cards
Add comprehensive kyu level information from 10th to 1st Kyu with detailed
exam requirements. Display data in responsive grid of color-coded cards.

Data includes:
- Duration, pass thresholds, and point requirements
- Problem types with digit complexity for each operation
- Color-coded by difficulty (green → blue → violet)
- Hover effects and mobile-responsive layout

Phase 2 complete: All 10 kyu levels with official JAF requirements.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 07:14:16 -05:00
semantic-release-bot
7f6c486e9c chore(release): 4.25.1 [skip ci]
## [4.25.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.25.0...v4.25.1) (2025-10-20)

### Code Refactoring

* **homepage:** make entire "Your Journey" card clickable ([3f30810](3f30810271))
2025-10-20 12:08:33 +00:00
Thomas Hallock
3f30810271 refactor(homepage): make entire "Your Journey" card clickable
Transform the journey section into an interactive card that navigates to
/levels. Remove separate button in favor of whole-card clickability with
clear hover feedback.

Changes:
- Wrap entire card in Link component
- Add hover effects: lift, violet border, purple shadow
- Add subtle arrow indicator in top-right corner
- Update text: "Click to learn about the official Japanese ranking system"

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 07:07:34 -05:00
semantic-release-bot
4968e2c846 chore(release): 4.25.0 [skip ci]
## [4.25.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.24.3...v4.25.0) (2025-10-20)

### Features

* **levels:** add Kyu & Dan levels page with homepage link ([39b1e7d](39b1e7de16))

### Styles

* **homepage:** adjust journey emoji sizing and spacing ([2a0e469](2a0e469e83))
2025-10-20 11:51:46 +00:00
Thomas Hallock
39b1e7de16 feat(levels): add Kyu & Dan levels page with homepage link
Create new /levels page with hero section explaining the Japanese soroban
ranking system (10th Kyu to 10th Dan). Add navigation link from homepage
"Your Journey" section with violet-themed button styling.

Phase 1 complete: basic page structure and routing ready for content.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 06:50:35 -05:00
Thomas Hallock
2a0e469e83 style(homepage): adjust journey emoji sizing and spacing
Increase emoji size from 3xl to 5xl for better visual presence.
Tighten spacing between emojis and labels by setting gap to 0 and
adding negative top margin (-2) to level labels.

Changes:
- Increase emoji fontSize from '3xl' to '5xl'
- Remove emoji bottom margin (mb: '0')
- Remove gap between emoji and labels (gap: '0')
- Add negative top margin to level labels (mt: '-2')

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 06:37:59 -05:00
semantic-release-bot
b3541e6b8a chore(release): 4.24.3 [skip ci]
## [4.24.3](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.24.2...v4.24.3) (2025-10-20)

### Code Refactoring

* **homepage:** align all skill icon panes horizontally ([4b04e86](4b04e8673d))
2025-10-20 11:22:23 +00:00
Thomas Hallock
4b04e8673d refactor(homepage): align all skill icon panes horizontally
Removed horizontal padding for all skill icon containers to ensure
consistent alignment across the "What You'll Learn" section.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 06:21:25 -05:00
semantic-release-bot
75a84dc148 chore(release): 4.24.2 [skip ci]
## [4.24.2](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.24.1...v4.24.2) (2025-10-20)

### Code Refactoring

* **homepage:** tighten mini abacus vertical padding ([514d07e](514d07ecb5))
2025-10-20 11:17:40 +00:00
Thomas Hallock
514d07ecb5 refactor(homepage): tighten mini abacus vertical padding
Reduced vertical padding from token '5' to '4' in the "Read and set
numbers" card icon container for better visual balance.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 06:16:37 -05:00
semantic-release-bot
e37ee87ea3 chore(release): 4.24.1 [skip ci]
## [4.24.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.24.0...v4.24.1) (2025-10-20)

### Bug Fixes

* **homepage:** adjust mini abacus container height ([c4066d6](c4066d6879))
* **homepage:** fix MiniAbacus runtime error and improve sizing ([1fa0df8](1fa0df85f7))
* **homepage:** use correct AbacusReact API and fix clipping/styling issues ([1432afd](1432afd6e6))
* **homepage:** use direct conditionals for mini abacus padding ([38ef16a](38ef16a8f9))

### Styles

* **homepage:** add more padding around mini abacus ([c5103d0](c5103d049f))
* **homepage:** balance mini abacus padding horizontally and vertically ([2f0304e](2f0304eb81))
* **homepage:** increase mini abacus padding to '5' ([1da9ed1](1da9ed1ce6))
2025-10-20 11:11:51 +00:00
Thomas Hallock
38ef16a8f9 fix(homepage): use direct conditionals for mini abacus padding
Replace spread operator with direct conditional values for py and px
to ensure proper application with Panda CSS.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 06:10:44 -05:00
Thomas Hallock
2f0304eb81 style(homepage): balance mini abacus padding horizontally and vertically
Use py: '5' and px: '3' instead of uniform padding to create visually
equal spacing on all sides of the animated abacus.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 06:09:49 -05:00
Thomas Hallock
1da9ed1ce6 style(homepage): increase mini abacus padding to '5'
Double the padding from '3' to '5' for more generous vertical spacing
around the animated abacus.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 06:09:13 -05:00
Thomas Hallock
c5103d049f style(homepage): add more padding around mini abacus
Increase padding from '2' to '3' on the mini abacus icon container
to provide more vertical space between the abacus and the card border.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 06:08:52 -05:00
Thomas Hallock
c4066d6879 fix(homepage): adjust mini abacus container height
Set container height to 80px to prevent excess vertical space while
keeping the abacus fully visible and centered.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 06:07:41 -05:00
Thomas Hallock
1432afd6e6 fix(homepage): use correct AbacusReact API and fix clipping/styling issues
Use the correct pattern for AbacusReact:
- Call useAbacusConfig() without parameters for global config
- Pass individual props (value, columns, beadShape, styles) instead of config object
- No more timing hacks - the proper API doesn't have initialization issues

Fix display issues:
- Remove fixed height and overflow:hidden to prevent clipping
- Add dark theme styles for columnPosts and reckoningBar
- Reduce scale from 0.7 to 0.6 with proper transform origin

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 06:06:42 -05:00
Thomas Hallock
1fa0df85f7 fix(homepage): fix MiniAbacus runtime error and improve sizing
Fix "Cannot read properties of undefined (reading 'earthActive')" error by:
- Adding 500ms initialization delay before starting value cycling
- Starting with value 123 instead of 0 to show valid state immediately
- Splitting ready state management into separate useEffect

Also improve container sizing:
- Set explicit width (75px) and height (75px)
- Add transform scale(0.7) to fit better in card icon space
- Add overflow hidden to contain the component
- Increase cycle interval to 2.5s for smoother transitions

The error occurred because the AbacusReact component was trying to access
column states before they were fully initialized. The delay ensures proper
initialization before animation starts.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 06:06:42 -05:00
semantic-release-bot
8baeba6987 chore(release): 4.24.0 [skip ci]
## [4.24.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.23.0...v4.24.0) (2025-10-20)

### Features

* **homepage:** add animated mini abacus to "Read and set numbers" card ([e028e34](e028e342ad))
2025-10-20 11:01:48 +00:00
Thomas Hallock
e028e342ad feat(homepage): add animated mini abacus to "Read and set numbers" card
Replace static 🔢 emoji with a functional 3-column abacus that cycles through
random 3-digit numbers (0-999) every 2 seconds. Uses dark theme styling to
match the homepage aesthetic.

Changes:
- Create MiniAbacus component using AbacusReact
- Cycle through random numbers using useState/useEffect
- Constrain height to ~75px as specified
- Conditionally render in first skill card (i === 0)
- Use theme="dark" to match tutorial abacus styling

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 06:00:46 -05:00
semantic-release-bot
263237a152 chore(release): 4.23.0 [skip ci]
## [4.23.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.22.0...v4.23.0) (2025-10-20)

### Features

* **homepage:** add more visual embellishments to learning cards ([4ec1b95](4ec1b952f2))
2025-10-20 10:57:15 +00:00
Thomas Hallock
4ec1b952f2 feat(homepage): add more visual embellishments to learning cards
Significantly enhance "What You'll Learn" section with:
- Larger icons (3xl) with background containers
- Skill level badges (Foundation/Core/Advanced/Expert)
- More padding and spacing throughout
- Gradient backgrounds on cards
- Box shadows with depth
- Hover lift animations
- Longer, more detailed descriptions
- Example text styled as highlighted code badges
- Increased container width for better balance

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 05:56:02 -05:00
5 changed files with 724 additions and 35 deletions

View File

@@ -1,3 +1,123 @@
## [4.32.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.31.1...v4.32.0) (2025-10-20)
### Features
* **levels:** add dark mode styling and responsive scaling to abacus ([92e1e62](https://github.com/antialias/soroban-abacus-flashcards/commit/92e1e621321039206f65b3605f5797bbdc6beafc))
## [4.31.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.31.0...v4.31.1) (2025-10-20)
### Bug Fixes
* **levels:** use correct AbacusReact API with direct props ([892b377](https://github.com/antialias/soroban-abacus-flashcards/commit/892b377eb3bbd555dd2566bf58e946e9faa7b9f6))
## [4.31.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.30.0...v4.31.0) (2025-10-20)
### Features
* **levels:** implement interactive slider for exploring kyu & dan ranks ([eb3b100](https://github.com/antialias/soroban-abacus-flashcards/commit/eb3b1000563536d4143ba1f4ec04e59e8dd2e608))
## [4.30.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.29.0...v4.30.0) (2025-10-20)
### Features
* **levels:** create true horizontal slider with abacus visualizations ([6d734f1](https://github.com/antialias/soroban-abacus-flashcards/commit/6d734f1d51f5ba1367f55923e58bd977413d754e))
## [4.29.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.28.0...v4.29.0) (2025-10-20)
### Features
* **levels:** replace kyu grid with interactive slider and abacus visualizations ([10978e8](https://github.com/antialias/soroban-abacus-flashcards/commit/10978e890beee65dea78ddcce52cfe5315d58063))
## [4.28.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.27.0...v4.28.0) (2025-10-20)
### Features
* **levels:** add informational footer section ([0b1bff7](https://github.com/antialias/soroban-abacus-flashcards/commit/0b1bff7eab8f5da84ae309dbda336e168c2fe3fd))
## [4.27.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.26.0...v4.27.0) (2025-10-20)
### Features
* **levels:** add Dan levels ladder visualization ([c18012c](https://github.com/antialias/soroban-abacus-flashcards/commit/c18012cb505a1f2a86ebed7579b379a4d7d97f2c))
## [4.26.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.25.1...v4.26.0) (2025-10-20)
### Features
* **levels:** add kyu level data and cards ([6463a3b](https://github.com/antialias/soroban-abacus-flashcards/commit/6463a3b2f6371ebebac1048197fb44178997d2ef))
## [4.25.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.25.0...v4.25.1) (2025-10-20)
### Code Refactoring
* **homepage:** make entire "Your Journey" card clickable ([3f30810](https://github.com/antialias/soroban-abacus-flashcards/commit/3f30810271418f3acf3df17e41d9a897a3312c34))
## [4.25.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.24.3...v4.25.0) (2025-10-20)
### Features
* **levels:** add Kyu & Dan levels page with homepage link ([39b1e7d](https://github.com/antialias/soroban-abacus-flashcards/commit/39b1e7de16f15412c91cf648c714e31e2de7a6bc))
### Styles
* **homepage:** adjust journey emoji sizing and spacing ([2a0e469](https://github.com/antialias/soroban-abacus-flashcards/commit/2a0e469e83b99c88f091bfecd770e0b4c1cb6310))
## [4.24.3](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.24.2...v4.24.3) (2025-10-20)
### Code Refactoring
* **homepage:** align all skill icon panes horizontally ([4b04e86](https://github.com/antialias/soroban-abacus-flashcards/commit/4b04e8673da228863d4ec1869897ee431fa3d753))
## [4.24.2](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.24.1...v4.24.2) (2025-10-20)
### Code Refactoring
* **homepage:** tighten mini abacus vertical padding ([514d07e](https://github.com/antialias/soroban-abacus-flashcards/commit/514d07ecb5f65a3c0982b8e90994e1c17ebaa59c))
## [4.24.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.24.0...v4.24.1) (2025-10-20)
### Bug Fixes
* **homepage:** adjust mini abacus container height ([c4066d6](https://github.com/antialias/soroban-abacus-flashcards/commit/c4066d687925bbe7737ebfeefdada7365ff97c6c))
* **homepage:** fix MiniAbacus runtime error and improve sizing ([1fa0df8](https://github.com/antialias/soroban-abacus-flashcards/commit/1fa0df85f7d3988cbc61701d89476419ccf0a13c))
* **homepage:** use correct AbacusReact API and fix clipping/styling issues ([1432afd](https://github.com/antialias/soroban-abacus-flashcards/commit/1432afd6e6bd547bd0da76dbeea1c2b71244826f))
* **homepage:** use direct conditionals for mini abacus padding ([38ef16a](https://github.com/antialias/soroban-abacus-flashcards/commit/38ef16a8f91f8ab4ad0d717b0321e2002636fafb))
### Styles
* **homepage:** add more padding around mini abacus ([c5103d0](https://github.com/antialias/soroban-abacus-flashcards/commit/c5103d049f73a8f7ef26915edfbef9ea56d59094))
* **homepage:** balance mini abacus padding horizontally and vertically ([2f0304e](https://github.com/antialias/soroban-abacus-flashcards/commit/2f0304eb81cdf84c21b0554c9cd4bd5478896dd8))
* **homepage:** increase mini abacus padding to '5' ([1da9ed1](https://github.com/antialias/soroban-abacus-flashcards/commit/1da9ed1ce6995c605622fc2863f248e5e91ab9c3))
## [4.24.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.23.0...v4.24.0) (2025-10-20)
### Features
* **homepage:** add animated mini abacus to "Read and set numbers" card ([e028e34](https://github.com/antialias/soroban-abacus-flashcards/commit/e028e342ad4bc01491e05a4ba074628155926fd8))
## [4.23.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.22.0...v4.23.0) (2025-10-20)
### Features
* **homepage:** add more visual embellishments to learning cards ([4ec1b95](https://github.com/antialias/soroban-abacus-flashcards/commit/4ec1b952f202d50f6db287c41732ec65ca17c142))
## [4.22.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.21.1...v4.22.0) (2025-10-20)

View File

@@ -121,6 +121,31 @@ className="bg-blue-200 border-gray-300 text-brand-600"
See `.claude/GAME_THEMES.md` for standardized color theme usage in arcade games.
## Abacus Visualizations
**CRITICAL: This project uses @soroban/abacus-react for all abacus visualizations.**
- All abacus displays MUST use components from `@soroban/abacus-react`
- Package location: `packages/abacus-react`
- Main components: `AbacusReact`, `useAbacusConfig`, `useAbacusDisplay`
- DO NOT create custom abacus visualizations
- DO NOT manually draw abacus columns, beads, or bars
**Common Mistakes to Avoid:**
- ❌ Don't create custom abacus components or SVGs
- ❌ Don't manually render abacus beads or columns
- ✅ Always use `AbacusReact` from `@soroban/abacus-react`
- ✅ Use `useAbacusConfig` for abacus configuration
- ✅ Use `useAbacusDisplay` for reading abacus state
**Example Usage:**
```typescript
import { AbacusReact, useAbacusConfig } from '@soroban/abacus-react'
const config = useAbacusConfig({ columns: 5 })
<AbacusReact config={config} initialNumber={123} />
```
## Known Issues
### @soroban/abacus-react TypeScript Module Resolution

View File

@@ -0,0 +1,408 @@
'use client'
import { useState } from 'react'
import { AbacusReact } from '@soroban/abacus-react'
import { PageWithNav } from '@/components/PageWithNav'
import { css } from '../../../styled-system/css'
import { container, stack } from '../../../styled-system/patterns'
// Combine all levels into one array for the slider
const allLevels = [
{ level: '10th Kyu', emoji: '🧒', color: 'green', digits: 2, type: 'kyu' as const },
{ level: '9th Kyu', emoji: '🧒', color: 'green', digits: 2, type: 'kyu' as const },
{ level: '8th Kyu', emoji: '🧒', color: 'green', digits: 3, type: 'kyu' as const },
{ level: '7th Kyu', emoji: '🧒', color: 'green', digits: 4, type: 'kyu' as const },
{ level: '6th Kyu', emoji: '🧑', color: 'blue', digits: 5, type: 'kyu' as const },
{ level: '5th Kyu', emoji: '🧑', color: 'blue', digits: 6, type: 'kyu' as const },
{ level: '4th Kyu', emoji: '🧑', color: 'blue', digits: 7, type: 'kyu' as const },
{ level: '3rd Kyu', emoji: '🧔', color: 'violet', digits: 8, type: 'kyu' as const },
{ level: '2nd Kyu', emoji: '🧔', color: 'violet', digits: 9, type: 'kyu' as const },
{ level: '1st Kyu', emoji: '🧔', color: 'violet', digits: 10, type: 'kyu' as const },
{
level: 'Pre-1st Dan',
name: 'Jun-Shodan',
minScore: 90,
emoji: '🧙',
color: 'amber',
digits: 30,
type: 'dan' as const,
},
{
level: '1st Dan',
name: 'Shodan',
minScore: 100,
emoji: '🧙',
color: 'amber',
digits: 30,
type: 'dan' as const,
},
{
level: '2nd Dan',
name: 'Nidan',
minScore: 120,
emoji: '🧙‍♂️',
color: 'amber',
digits: 30,
type: 'dan' as const,
},
{
level: '3rd Dan',
name: 'Sandan',
minScore: 140,
emoji: '🧙‍♂️',
color: 'amber',
digits: 30,
type: 'dan' as const,
},
{
level: '4th Dan',
name: 'Yondan',
minScore: 160,
emoji: '🧙‍♀️',
color: 'amber',
digits: 30,
type: 'dan' as const,
},
{
level: '5th Dan',
name: 'Godan',
minScore: 180,
emoji: '🧙‍♀️',
color: 'amber',
digits: 30,
type: 'dan' as const,
},
{
level: '6th Dan',
name: 'Rokudan',
minScore: 200,
emoji: '🧝',
color: 'amber',
digits: 30,
type: 'dan' as const,
},
{
level: '7th Dan',
name: 'Nanadan',
minScore: 220,
emoji: '🧝',
color: 'amber',
digits: 30,
type: 'dan' as const,
},
{
level: '8th Dan',
name: 'Hachidan',
minScore: 250,
emoji: '🧝‍♂️',
color: 'amber',
digits: 30,
type: 'dan' as const,
},
{
level: '9th Dan',
name: 'Kudan',
minScore: 270,
emoji: '🧝‍♀️',
color: 'amber',
digits: 30,
type: 'dan' as const,
},
{
level: '10th Dan',
name: 'Judan',
minScore: 290,
emoji: '👑',
color: 'amber',
digits: 30,
type: 'dan' as const,
},
] as const
export default function LevelsPage() {
const [currentIndex, setCurrentIndex] = useState(0)
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)
return (
<PageWithNav navTitle="Kyu & Dan Levels" navEmoji="📊">
<div className={css({ bg: 'gray.900', minHeight: '100vh', pb: '12' })}>
{/* Hero Section */}
<div
className={css({
background:
'linear-gradient(135deg, rgba(17, 24, 39, 1) 0%, rgba(124, 58, 237, 0.3) 50%, rgba(17, 24, 39, 1) 100%)',
color: 'white',
py: { base: '12', md: '16' },
position: 'relative',
overflow: 'hidden',
})}
>
<div
className={css({
position: 'absolute',
inset: 0,
opacity: 0.1,
backgroundImage:
'radial-gradient(circle at 2px 2px, rgba(255, 255, 255, 0.15) 1px, transparent 0)',
backgroundSize: '40px 40px',
})}
/>
<div className={container({ maxW: '6xl', px: '4', position: 'relative' })}>
<div className={css({ textAlign: 'center', maxW: '5xl', mx: 'auto' })}>
<h1
className={css({
fontSize: { base: '3xl', md: '5xl', lg: '6xl' },
fontWeight: 'bold',
mb: '4',
lineHeight: 'tight',
background: 'linear-gradient(135deg, #fbbf24 0%, #f59e0b 50%, #fbbf24 100%)',
backgroundClip: 'text',
color: 'transparent',
})}
>
Understanding Kyu & Dan Levels
</h1>
<p
className={css({
fontSize: { base: 'lg', md: 'xl' },
color: 'gray.300',
mb: '6',
maxW: '3xl',
mx: 'auto',
lineHeight: '1.6',
})}
>
Slide through the complete progression from beginner to master
</p>
</div>
</div>
</div>
{/* Main content */}
<div className={container({ maxW: '6xl', px: '4', py: '12' })}>
<section className={stack({ gap: '8' })}>
{/* Current Level Display */}
<div
className={css({
bg: 'rgba(0, 0, 0, 0.4)',
border: '2px solid',
borderColor:
currentLevel.color === 'green'
? 'green.500'
: currentLevel.color === 'blue'
? 'blue.500'
: currentLevel.color === 'violet'
? 'violet.500'
: 'amber.500',
rounded: 'xl',
p: { base: '6', md: '8' },
})}
>
{/* Level Info */}
<div className={css({ textAlign: 'center', mb: '6' })}>
<div className={css({ fontSize: '5xl', mb: '3' })}>{currentLevel.emoji}</div>
<h2
className={css({
fontSize: { base: '2xl', md: '3xl' },
fontWeight: 'bold',
color:
currentLevel.color === 'green'
? 'green.400'
: currentLevel.color === 'blue'
? 'blue.400'
: currentLevel.color === 'violet'
? 'violet.400'
: 'amber.400',
mb: '2',
})}
>
{currentLevel.level}
</h2>
{'name' in currentLevel && (
<div className={css({ fontSize: 'md', color: 'gray.400', mb: '1' })}>
{currentLevel.name}
</div>
)}
{'minScore' in currentLevel && (
<div className={css({ fontSize: 'sm', color: 'gray.500' })}>
Minimum Score: {currentLevel.minScore} points
</div>
)}
</div>
{/* Abacus Display */}
<div
className={css({
display: 'flex',
justifyContent: 'center',
mb: '6',
p: '6',
bg: 'rgba(0, 0, 0, 0.3)',
rounded: 'lg',
border: '1px solid',
borderColor: 'gray.700',
overflowX: 'auto',
})}
>
<AbacusReact
value={0}
columns={currentLevel.digits}
scaleFactor={scaleFactor}
showNumbers={true}
customStyles={{
reckoningBar: { stroke: '#9ca3af', strokeWidth: 3 },
columnPosts: { stroke: '#6b7280' },
numerals: { color: '#d1d5db', fontSize: '14px', fontWeight: 'normal' },
heavenBeads: { fill: '#60a5fa' },
earthBeads: { fill: '#34d399' },
}}
/>
</div>
{/* Digit Count */}
<div className={css({ textAlign: 'center', color: 'gray.400', fontSize: 'sm' })}>
Requires mastery of <strong>{currentLevel.digits}-digit</strong> calculations
</div>
</div>
{/* Slider Control */}
<div
className={css({
bg: 'rgba(0, 0, 0, 0.3)',
border: '1px solid',
borderColor: 'gray.700',
rounded: 'xl',
p: '6',
})}
>
<div className={css({ mb: '4', textAlign: 'center' })}>
<h3
className={css({ fontSize: 'lg', fontWeight: 'bold', color: 'white', mb: '2' })}
>
Explore All Levels
</h3>
<p className={css({ fontSize: 'sm', color: 'gray.400' })}>
Drag 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',
})}
/>
{/* Level Markers */}
<div
className={css({
display: 'flex',
justifyContent: 'space-between',
mt: '4',
fontSize: 'xs',
color: 'gray.500',
})}
>
<span>10th Kyu</span>
<span>1st Kyu</span>
<span>10th Dan</span>
</div>
</div>
{/* Legend */}
<div
className={css({
display: 'flex',
flexWrap: 'wrap',
gap: '6',
justifyContent: 'center',
p: '6',
bg: 'rgba(0, 0, 0, 0.3)',
rounded: 'lg',
border: '1px solid',
borderColor: 'gray.700',
})}
>
<div className={css({ display: 'flex', alignItems: 'center', gap: '2' })}>
<div className={css({ w: '4', h: '4', bg: 'green.500', rounded: 'sm' })} />
<span className={css({ fontSize: 'sm', color: 'gray.300' })}>
Beginner (10-7 Kyu)
</span>
</div>
<div className={css({ display: 'flex', alignItems: 'center', gap: '2' })}>
<div className={css({ w: '4', h: '4', bg: 'blue.500', rounded: 'sm' })} />
<span className={css({ fontSize: 'sm', color: 'gray.300' })}>
Intermediate (6-4 Kyu)
</span>
</div>
<div className={css({ display: 'flex', alignItems: 'center', gap: '2' })}>
<div className={css({ w: '4', h: '4', bg: 'violet.500', rounded: 'sm' })} />
<span className={css({ fontSize: 'sm', color: 'gray.300' })}>
Advanced (3-1 Kyu)
</span>
</div>
<div className={css({ display: 'flex', alignItems: 'center', gap: '2' })}>
<div className={css({ w: '4', h: '4', bg: 'amber.500', rounded: 'sm' })} />
<span className={css({ fontSize: 'sm', color: 'gray.300' })}>
Master (Dan ranks)
</span>
</div>
</div>
{/* Info Section */}
<div
className={css({
bg: 'rgba(0, 0, 0, 0.4)',
border: '1px solid',
borderColor: 'gray.700',
rounded: 'xl',
p: { base: '6', md: '8' },
})}
>
<h3
className={css({
fontSize: { base: 'xl', md: '2xl' },
fontWeight: 'bold',
color: 'white',
mb: '4',
})}
>
About This Ranking System
</h3>
<div className={stack({ gap: '4' })}>
<p className={css({ color: 'gray.300', lineHeight: '1.6' })}>
This ranking system is based on the official examination structure used by the{' '}
<strong className={css({ color: 'white' })}>Japan Abacus Federation</strong>. It
represents a standardized progression from beginner (10th Kyu) to master level
(10th Dan), used internationally for soroban proficiency assessment.
</p>
<p className={css({ color: 'gray.300', lineHeight: '1.6' })}>
The system is designed to gradually increase in difficulty. Kyu levels progress
from 2-digit calculations at 10th Kyu to 10-digit calculations at 1st Kyu. Dan
levels all require mastery of 30-digit calculations, with ranks awarded based on
exam scores.
</p>
</div>
</div>
</section>
</div>
</div>
</PageWithNav>
)
}

View File

@@ -1,6 +1,8 @@
'use client'
import Link from 'next/link'
import { useEffect, useState } from 'react'
import { AbacusReact, useAbacusConfig } from '@soroban/abacus-react'
import { PageWithNav } from '@/components/PageWithNav'
import { TutorialPlayer } from '@/components/tutorial/TutorialPlayer'
import { getTutorialForEditor } from '@/utils/tutorialConverter'
@@ -8,6 +10,57 @@ import { css } from '../../styled-system/css'
import { container, grid, hstack, stack } from '../../styled-system/patterns'
import { token } from '../../styled-system/tokens'
// Mini abacus that cycles through random 3-digit numbers
function MiniAbacus() {
const [currentValue, setCurrentValue] = useState(123)
const appConfig = useAbacusConfig()
useEffect(() => {
// Cycle through random 3-digit numbers every 2.5 seconds
const interval = setInterval(() => {
const randomNum = Math.floor(Math.random() * 1000) // 0-999
setCurrentValue(randomNum)
}, 2500)
return () => clearInterval(interval)
}, [])
// Dark theme styles for the abacus
const darkStyles = {
columnPosts: {
fill: 'rgba(255, 255, 255, 0.3)',
stroke: 'rgba(255, 255, 255, 0.2)',
strokeWidth: 2,
},
reckoningBar: {
fill: 'rgba(255, 255, 255, 0.4)',
stroke: 'rgba(255, 255, 255, 0.25)',
strokeWidth: 3,
},
}
return (
<div
className={css({
width: '75px',
height: '80px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
})}
>
<div className={css({ transform: 'scale(0.6)', transformOrigin: 'center center' })}>
<AbacusReact
value={currentValue}
columns={3}
beadShape={appConfig.beadShape}
customStyles={darkStyles}
/>
</div>
</div>
)
}
export default function HomePage() {
// Extract just the "Friends of 5" step (2+3=5) for homepage demo
const fullTutorial = getTutorialForEditor()
@@ -246,83 +299,117 @@ export default function HomePage() {
<div
className={css({
flex: '0 0 auto',
minW: '320px',
maxW: { base: '100%', md: '400px' },
minW: '340px',
maxW: { base: '100%', md: '420px' },
})}
>
<h3
className={css({
fontSize: 'xl',
fontSize: '2xl',
fontWeight: 'bold',
color: 'white',
mb: '5',
mb: '6',
})}
>
What You'll Learn
</h3>
<div className={stack({ gap: '4' })}>
<div className={stack({ gap: '5' })}>
{[
{
icon: '🔢',
title: 'Read and set numbers',
desc: 'Master abacus number representation',
desc: 'Master abacus number representation from zero to thousands',
example: '0-9999',
badge: 'Foundation',
},
{
icon: '🤝',
title: 'Friends techniques',
desc: 'Add and subtract with complements',
desc: 'Add and subtract using complement pairs and mental shortcuts',
example: '5 = 2+3',
badge: 'Core',
},
{
icon: '',
title: 'Multiply & divide',
desc: 'Fluent multi-digit calculations',
desc: 'Fluent multi-digit calculations with advanced techniques',
example: '12×34',
badge: 'Advanced',
},
{
icon: '🧠',
title: 'Mental calculation',
desc: 'Visualize and compute without the tool',
example: 'Anzan',
desc: 'Visualize and compute without the physical tool (Anzan)',
example: 'Speed math',
badge: 'Expert',
},
].map((skill, i) => (
<div
key={i}
className={css({
bg: 'rgba(255, 255, 255, 0.05)',
borderRadius: 'lg',
p: '3',
bg: 'linear-gradient(135deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.03))',
borderRadius: 'xl',
p: '4',
border: '1px solid',
borderColor: 'rgba(255, 255, 255, 0.1)',
borderColor: 'rgba(255, 255, 255, 0.15)',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
transition: 'all 0.2s',
_hover: {
bg: 'rgba(255, 255, 255, 0.08)',
borderColor: 'rgba(255, 255, 255, 0.2)',
bg: 'linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05))',
borderColor: 'rgba(255, 255, 255, 0.25)',
transform: 'translateY(-2px)',
boxShadow: '0 6px 16px rgba(0, 0, 0, 0.4)',
},
})}
>
<div className={hstack({ gap: '3', alignItems: 'flex-start' })}>
<div
className={css({
fontSize: '2xl',
minW: '40px',
fontSize: '3xl',
width: '75px',
height: '115px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
textAlign: 'center',
bg: 'rgba(255, 255, 255, 0.1)',
borderRadius: 'lg',
})}
>
{skill.icon}
{i === 0 ? <MiniAbacus /> : skill.icon}
</div>
<div className={stack({ gap: '1', flex: '1' })}>
<div className={stack({ gap: '2', flex: '1' })}>
<div className={hstack({ gap: '2', alignItems: 'center' })}>
<div
className={css({
color: 'white',
fontSize: 'md',
fontWeight: 'bold',
})}
>
{skill.title}
</div>
<div
className={css({
bg: 'rgba(250, 204, 21, 0.2)',
color: 'yellow.400',
fontSize: '2xs',
fontWeight: 'semibold',
px: '2',
py: '0.5',
borderRadius: 'md',
})}
>
{skill.badge}
</div>
</div>
<div
className={css({
color: 'white',
fontSize: 'sm',
fontWeight: 'semibold',
color: 'gray.300',
fontSize: 'xs',
lineHeight: '1.5',
})}
>
{skill.title}
</div>
<div className={css({ color: 'gray.400', fontSize: 'xs' })}>
{skill.desc}
</div>
<div
@@ -330,7 +417,13 @@ export default function HomePage() {
color: 'yellow.400',
fontSize: 'xs',
fontFamily: 'mono',
fontWeight: 'semibold',
mt: '1',
bg: 'rgba(250, 204, 21, 0.1)',
px: '2',
py: '1',
borderRadius: 'md',
w: 'fit-content',
})}
>
{skill.example}
@@ -461,15 +554,44 @@ export default function HomePage() {
<p style={{ color: '#e5e7eb', fontSize: '16px' }}>Progress from beginner to master</p>
</div>
<div
<Link
href="/levels"
className={css({
bg: 'rgba(0, 0, 0, 0.4)',
border: '1px solid',
borderColor: 'gray.700',
rounded: 'xl',
p: '8',
display: 'block',
transition: 'all 0.2s',
cursor: 'pointer',
position: 'relative',
_hover: {
bg: 'rgba(0, 0, 0, 0.5)',
borderColor: 'violet.500',
transform: 'translateY(-2px)',
boxShadow: '0 8px 16px rgba(124, 58, 237, 0.2)',
},
})}
>
{/* Subtle arrow indicator */}
<div
className={css({
position: 'absolute',
top: '4',
right: '4',
fontSize: 'xl',
color: 'gray.500',
transition: 'all 0.2s',
_groupHover: {
color: 'violet.400',
transform: 'translateX(4px)',
},
})}
>
</div>
<div
className={css({
display: 'flex',
@@ -481,25 +603,39 @@ export default function HomePage() {
>
{(
[
{ level: '10 Kyu', label: 'Beginner', color: 'colors.green.400' },
{ level: '5 Kyu', label: 'Intermediate', color: 'colors.blue.400' },
{ level: '1 Kyu', label: 'Advanced', color: 'colors.violet.400' },
{ level: 'Dan', label: 'Master', color: 'colors.amber.400' },
{ level: '10 Kyu', label: 'Beginner', color: 'colors.green.400', emoji: '🧒' },
{
level: '5 Kyu',
label: 'Intermediate',
color: 'colors.blue.400',
emoji: '🧑',
},
{ level: '1 Kyu', label: 'Advanced', color: 'colors.violet.400', emoji: '🧔' },
{ level: 'Dan', label: 'Master', color: 'colors.amber.400', emoji: '🧙' },
] as const
).map((stage, i) => (
<div
key={i}
className={stack({
gap: '2',
gap: '0',
textAlign: 'center',
flex: '1',
position: 'relative',
})}
>
<div
className={css({
fontSize: '5xl',
mb: '0',
})}
>
{stage.emoji}
</div>
<div
className={css({
fontSize: 'xl',
fontWeight: 'bold',
mt: '-2',
})}
style={{ color: token(stage.color) }}
>
@@ -545,9 +681,9 @@ export default function HomePage() {
mt: '6',
})}
>
You'll progress through all these levels eventually
Click to learn about the official Japanese ranking system →
</div>
</div>
</Link>
</section>
{/* Additional Tools Section */}

View File

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