Compare commits

...

30 Commits

Author SHA1 Message Date
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
semantic-release-bot
aa9d389540 chore(release): 4.22.0 [skip ci]
## [4.22.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.21.1...v4.22.0) (2025-10-20)

### Features

* **homepage:** enhance "What You'll Learn" with visual cards ([d142342](d1423420e6))

### Bug Fixes

* **tutorial:** reduce tooltip z-index to scroll under nav bar ([47640f3](47640f3486))
2025-10-20 10:55:50 +00:00
Thomas Hallock
d1423420e6 feat(homepage): enhance "What You'll Learn" with visual cards
Replace simple checklist with rich visual cards for each learning objective.
Each card now includes:
- Large prominent icon
- Title and description
- Example/demo text
- Hover effects
- Card-based layout with subtle borders

Makes the section more engaging and less text-heavy, better balanced with
the tutorial demo on the left.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 05:54:44 -05:00
Thomas Hallock
47640f3486 fix(tutorial): reduce tooltip z-index to scroll under nav bar
Change tutorial tooltip z-index from 1000 to 50 so it scrolls under the
app nav bar (z-index 100) along with the abacus. This prevents the coaching
text from appearing layered above the nav while the abacus it points to is
hidden beneath it.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 05:54:44 -05:00
semantic-release-bot
cb7595c95b chore(release): 4.21.1 [skip ci]
## [4.21.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.21.0...v4.21.1) (2025-10-20)

### Code Refactoring

* **homepage:** rearrange tutorial demo layout side by side ([8b4ecee](8b4eceebfa))
2025-10-20 10:52:32 +00:00
Thomas Hallock
8b4eceebfa refactor(homepage): rearrange tutorial demo layout side by side
Restructure "Learn by Doing" section to display tutorial and "What You'll
Learn" side by side. Items now display vertically instead of in a 2x2 grid.

Changes:
- Tutorial positioned on left with flex: 1
- "What You'll Learn" section positioned on right
- Items arranged vertically using stack layout
- Increased container max-width from 900px to 1200px
- Responsive: stacks vertically on mobile, side-by-side on md+ screens

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 05:51:29 -05:00
semantic-release-bot
850fd33943 chore(release): 4.21.0 [skip ci]
## [4.21.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.20.7...v4.21.0) (2025-10-20)

### Features

* **tutorial:** add silentErrors prop to suppress error messages ([8835e1c](8835e1c57a))
2025-10-20 10:50:59 +00:00
Thomas Hallock
8835e1c57a feat(tutorial): add silentErrors prop to suppress error messages
Add silentErrors prop to TutorialPlayer to allow suppressing "That's not
the highlighted bead" error messages. Used on homepage to provide a less
intrusive demo experience.

Changes:
- Add silentErrors prop to TutorialPlayerProps interface
- Conditionally skip error dispatch when silentErrors is true
- Pass silentErrors={true} from homepage TutorialPlayer

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 05:49:43 -05:00
Thomas Hallock
b635ed1c2d chore(home): reduce abacus tutorial to single column
Changed abacusColumns from 2 to 1 for the homepage tutorial demo.
Since the "Friends of 5" (2+3) demonstration only needs the ones place,
a single column is more focused and less distracting.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 05:44:24 -05:00
semantic-release-bot
4e6cecfe27 chore(release): 4.20.7 [skip ci]
## [4.20.7](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.20.6...v4.20.7) (2025-10-20)

### Bug Fixes

* **home:** use Panda CSS token() for dynamic colors and center arrows properly ([d52ba63](d52ba6373a))
2025-10-20 02:37:39 +00:00
Thomas Hallock
d52ba6373a fix(home): use Panda CSS token() for dynamic colors and center arrows properly
**Changes:**
- Use Panda CSS token() function for dynamic color references instead of inline hex values
- Fix arrow positioning to be centered in gap between progression stages
- Document Panda CSS dynamic token usage pattern

**Color Token Fix:**
Panda CSS css() requires static values at build time. For dynamic token references,
use the token() function with inline styles:
- Import: token from styled-system/tokens
- Usage: style={{ color: token(stage.color) }}
- Token paths marked as const for TypeScript literal types

**Arrow Positioning Fix:**
Arrows between stages were positioned based on element width, not gap width.
Now properly centered using:
- left: 100% (position at right edge)
- marginLeft: 0.5rem (half of 1rem gap)
- transform: translate(-50%, -50%) (center on that point)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-19 21:36:30 -05:00
semantic-release-bot
002c2888ac chore(release): 4.20.6 [skip ci]
## [4.20.6](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.20.5...v4.20.6) (2025-10-20)

### Bug Fixes

* **homepage:** use inline styles for journey level colors ([5d85e89](5d85e898d6)), closes [#4ade80](https://github.com/antialias/soroban-abacus-flashcards/issues/4ade80) [#60a5](https://github.com/antialias/soroban-abacus-flashcards/issues/60a5) [#a78](https://github.com/antialias/soroban-abacus-flashcards/issues/a78) [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24)
2025-10-20 01:14:49 +00:00
Thomas Hallock
5d85e898d6 fix(homepage): use inline styles for journey level colors
Changed progression level text from Panda CSS tokens to inline hex colors:
- 10 Kyu: #4ade80 (green)
- 5 Kyu: #60a5fa (blue)
- 1 Kyu: #a78bfa (purple)
- Dan: #fbbf24 (gold)

This ensures all text displays with proper colors regardless of CSS loading.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-19 20:13:39 -05:00
semantic-release-bot
eed890dc81 chore(release): 4.20.5 [skip ci]
## [4.20.5](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.20.4...v4.20.5) (2025-10-20)

### Bug Fixes

* **docker:** include Panda CSS styled-system in production image ([57fabff](57fabffe60))
2025-10-20 01:12:42 +00:00
Thomas Hallock
57fabffe60 fix(docker): include Panda CSS styled-system in production image
The styled-system directory containing generated Panda CSS was being
created during build but not copied to the production image, causing
all Panda CSS classes to be undefined at runtime.

This fix copies the generated styled-system directory from the builder
stage to the production image, ensuring styles.css is available.

Fixes missing CSS definitions for classes like fs_xl, font_bold, text_blue.400

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-19 20:11:38 -05:00
semantic-release-bot
89fb670f93 chore(release): 4.20.4 [skip ci]
## [4.20.4](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.20.3...v4.20.4) (2025-10-19)

### Bug Fixes

* **homepage:** use inline styles for Your Journey text contrast ([8e51390](8e51390018)), closes [#e5e7](https://github.com/antialias/soroban-abacus-flashcards/issues/e5e7) [#e5e7](https://github.com/antialias/soroban-abacus-flashcards/issues/e5e7) [#9ca3](https://github.com/antialias/soroban-abacus-flashcards/issues/9ca3) [#d1d5](https://github.com/antialias/soroban-abacus-flashcards/issues/d1d5)
2025-10-19 19:07:08 +00:00
Thomas Hallock
8e51390018 fix(homepage): use inline styles for Your Journey text contrast
Switched from Panda CSS to direct inline styles with hex colors:
- Labels (Beginner/Intermediate/Advanced/Master): #e5e7eb (light gray)
- Subtitle: #e5e7eb (light gray)
- Arrows: #9ca3af (medium gray)
- Footer: #d1d5db (light gray)

This bypasses any CSS framework issues and applies colors directly.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-19 14:06:02 -05:00
6 changed files with 413 additions and 58 deletions

View File

@@ -1,3 +1,95 @@
## [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)
### Features
* **homepage:** enhance "What You'll Learn" with visual cards ([d142342](https://github.com/antialias/soroban-abacus-flashcards/commit/d1423420e653b26b2f89d9d17ae5d597807d6979))
### Bug Fixes
* **tutorial:** reduce tooltip z-index to scroll under nav bar ([47640f3](https://github.com/antialias/soroban-abacus-flashcards/commit/47640f3486c6d4a7107d59bdcce043f76fabbb1d))
## [4.21.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.21.0...v4.21.1) (2025-10-20)
### Code Refactoring
* **homepage:** rearrange tutorial demo layout side by side ([8b4ecee](https://github.com/antialias/soroban-abacus-flashcards/commit/8b4eceebfaaaf07e38ea64c7fe015aec86ac754f))
## [4.21.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.20.7...v4.21.0) (2025-10-20)
### Features
* **tutorial:** add silentErrors prop to suppress error messages ([8835e1c](https://github.com/antialias/soroban-abacus-flashcards/commit/8835e1c57ab8adcecefe0db082360dd98fbfaac7))
## [4.20.7](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.20.6...v4.20.7) (2025-10-20)
### Bug Fixes
* **home:** use Panda CSS token() for dynamic colors and center arrows properly ([d52ba63](https://github.com/antialias/soroban-abacus-flashcards/commit/d52ba6373a4577655dc1e5f5ff4926af7f7d96c3))
## [4.20.6](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.20.5...v4.20.6) (2025-10-20)
### Bug Fixes
* **homepage:** use inline styles for journey level colors ([5d85e89](https://github.com/antialias/soroban-abacus-flashcards/commit/5d85e898d65d44d8d09bee952fad44b5a9c0cd20)), closes [#4ade80](https://github.com/antialias/soroban-abacus-flashcards/issues/4ade80) [#60a5](https://github.com/antialias/soroban-abacus-flashcards/issues/60a5) [#a78](https://github.com/antialias/soroban-abacus-flashcards/issues/a78) [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24)
## [4.20.5](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.20.4...v4.20.5) (2025-10-20)
### Bug Fixes
* **docker:** include Panda CSS styled-system in production image ([57fabff](https://github.com/antialias/soroban-abacus-flashcards/commit/57fabffe605d953b4a4d7e05032401cbf1ab2d14))
## [4.20.4](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.20.3...v4.20.4) (2025-10-19)
### Bug Fixes
* **homepage:** use inline styles for Your Journey text contrast ([8e51390](https://github.com/antialias/soroban-abacus-flashcards/commit/8e5139001818d7013e1b2654ac707f7429316d58)), closes [#e5e7](https://github.com/antialias/soroban-abacus-flashcards/issues/e5e7) [#e5e7](https://github.com/antialias/soroban-abacus-flashcards/issues/e5e7) [#9ca3](https://github.com/antialias/soroban-abacus-flashcards/issues/9ca3) [#d1d5](https://github.com/antialias/soroban-abacus-flashcards/issues/d1d5)
## [4.20.3](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.20.2...v4.20.3) (2025-10-19)

View File

@@ -59,6 +59,9 @@ RUN adduser --system --uid 1001 nextjs
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/.next ./apps/web/.next
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/public ./apps/web/public
# Copy Panda CSS generated styles
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/styled-system ./apps/web/styled-system
# Copy server files (compiled from TypeScript)
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/server.js ./apps/web/
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/dist ./apps/web/dist

View File

@@ -0,0 +1,76 @@
# Panda CSS Dynamic Token Usage
## Problem: Dynamic Color Tokens Not Working
When using Panda CSS, color tokens like `blue.400`, `purple.400`, etc. don't work when used dynamically through variables in the `css()` function.
## Root Cause
Panda CSS's `css()` function requires **static values at build time**. It cannot process dynamic token references like:
```typescript
// ❌ This doesn't work
const color = 'blue.400'
css({ color: color }) // Panda can't resolve this at build time
```
The `css()` function performs static analysis during the build process to generate CSS classes. It cannot handle runtime-dynamic token paths.
## Solution: Use the `token()` Function
Panda CSS provides a `token()` function specifically for resolving token paths to their actual values at runtime:
```typescript
import { token } from '../../styled-system/tokens'
// ✅ This works
const stages = [
{ 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' },
] as const
// Use with inline styles, not css()
<div style={{ color: token(stage.color) }}>
```
## Important Notes
1. **Use `as const`**: TypeScript needs the array marked as `const` so the token strings are treated as literal types, not generic strings. The `token()` function expects the `Token` literal type.
2. **Use inline styles**: When using `token()`, apply colors via the `style` prop, not through the `css()` function:
```typescript
// ✅ Correct
<div style={{ color: token(stage.color) }}>
// ❌ Won't work
<div className={css({ color: token(stage.color) })}>
```
3. **Static tokens in css()**: For static usage, you CAN use tokens directly in `css()`:
```typescript
// ✅ This works because it's static
css({ color: 'blue.400' })
```
## How token() Works
The `token()` function:
- Takes a token path like `"colors.blue.400"`
- Looks it up in the generated token registry (`styled-system/tokens/index.mjs`)
- Returns the actual CSS value (e.g., `"#60a5fa"`)
- Happens at runtime, not build time
## Token Type Definition
The `Token` type is a union of all valid token paths:
```typescript
type Token = "colors.blue.400" | "colors.green.400" | "colors.violet.400" | ...
```
This is defined in `styled-system/tokens/tokens.d.ts`.
## Reference Implementation
See `src/app/page.tsx` lines 404-434 for a working example of dynamic token usage in the "Your Journey" section.

View File

@@ -1,11 +1,65 @@
'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'
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}
styles={darkStyles}
/>
</div>
</div>
)
}
export default function HomePage() {
// Extract just the "Friends of 5" step (2+3=5) for homepage demo
@@ -215,54 +269,170 @@ export default function HomePage() {
border: '1px solid',
borderColor: 'gray.700',
shadow: 'lg',
maxW: '900px',
maxW: '1200px',
mx: 'auto',
})}
>
{/* What you'll learn - above tutorial */}
<div
className={css({
mb: '8',
pb: '6',
borderBottom: '1px solid',
borderColor: 'gray.700',
display: 'flex',
flexDirection: { base: 'column', md: 'row' },
gap: '8',
alignItems: { base: 'center', md: 'flex-start' },
})}
>
<h3
{/* Tutorial on the left */}
<div className={css({ flex: '1' })}>
<TutorialPlayer
tutorial={friendsOf5Tutorial}
isDebugMode={false}
showDebugPanel={false}
hideNavigation={true}
hideTooltip={true}
silentErrors={true}
abacusColumns={1}
theme="dark"
/>
</div>
{/* What you'll learn on the right */}
<div
className={css({
fontSize: 'xl',
fontWeight: 'bold',
color: 'white',
mb: '4',
textAlign: 'center',
flex: '0 0 auto',
minW: '340px',
maxW: { base: '100%', md: '420px' },
})}
>
What You'll Learn
</h3>
<div className={grid({ columns: { base: 1, sm: 2 }, gap: '3' })}>
{[
'Read and set numbers on an abacus',
'Add and subtract with "friends" techniques',
'Multiply and divide fluently',
'Calculate mentally without the abacus',
].map((skill, i) => (
<div key={i} className={hstack({ gap: '3' })}>
<span className={css({ color: 'yellow.400', fontSize: 'lg' })}>✓</span>
<span className={css({ color: 'gray.300', fontSize: 'sm' })}>{skill}</span>
</div>
))}
<h3
className={css({
fontSize: '2xl',
fontWeight: 'bold',
color: 'white',
mb: '6',
})}
>
What You'll Learn
</h3>
<div className={stack({ gap: '5' })}>
{[
{
icon: '🔢',
title: 'Read and set numbers',
desc: 'Master abacus number representation from zero to thousands',
example: '0-9999',
badge: 'Foundation',
},
{
icon: '🤝',
title: 'Friends techniques',
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 with advanced techniques',
example: '12×34',
badge: 'Advanced',
},
{
icon: '🧠',
title: 'Mental calculation',
desc: 'Visualize and compute without the physical tool (Anzan)',
example: 'Speed math',
badge: 'Expert',
},
].map((skill, i) => (
<div
key={i}
className={css({
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.15)',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
transition: 'all 0.2s',
_hover: {
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: '3xl',
minW: '50px',
textAlign: 'center',
bg: 'rgba(255, 255, 255, 0.1)',
borderRadius: 'lg',
py: i === 0 ? '4' : '2',
px: i === 0 ? '3' : '2',
})}
>
{i === 0 ? <MiniAbacus /> : skill.icon}
</div>
<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: 'gray.300',
fontSize: 'xs',
lineHeight: '1.5',
})}
>
{skill.desc}
</div>
<div
className={css({
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}
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
<TutorialPlayer
tutorial={friendsOf5Tutorial}
isDebugMode={false}
showDebugPanel={false}
hideNavigation={true}
hideTooltip={true}
abacusColumns={2}
theme="dark"
/>
</div>
</section>
@@ -379,9 +549,7 @@ export default function HomePage() {
>
Your Journey
</h2>
<p className={css({ color: 'rgba(229, 231, 235, 1)', fontSize: 'md' })}>
Progress from beginner to master
</p>
<p style={{ color: '#e5e7eb', fontSize: '16px' }}>Progress from beginner to master</p>
</div>
<div
@@ -402,12 +570,14 @@ export default function HomePage() {
flexWrap: 'wrap',
})}
>
{[
{ level: '10 Kyu', label: 'Beginner', color: 'green.400' },
{ level: '5 Kyu', label: 'Intermediate', color: 'blue.400' },
{ level: '1 Kyu', label: 'Advanced', color: 'purple.400' },
{ level: 'Dan', label: 'Master', color: 'yellow.400' },
].map((stage, i) => (
{(
[
{ 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' },
] as const
).map((stage, i) => (
<div
key={i}
className={stack({
@@ -421,22 +591,32 @@ export default function HomePage() {
className={css({
fontSize: 'xl',
fontWeight: 'bold',
color: stage.color,
})}
style={{ color: token(stage.color) }}
>
{stage.level}
</div>
<div className={css({ fontSize: 'sm', color: 'rgba(229, 231, 235, 1)' })}>
<div
className={css({
fontSize: 'sm',
color: 'gray.300',
})}
>
{stage.label}
</div>
{i < 3 && (
<div
style={{
position: 'absolute',
left: '100%',
marginLeft: '0.5rem',
top: '50%',
transform: 'translate(-50%, -50%)',
fontSize: '20px',
color: '#9ca3af',
}}
className={css({
display: { base: 'none', md: 'block' },
position: 'absolute',
right: '-50%',
fontSize: 'xl',
color: 'rgba(156, 163, 175, 1)',
})}
>
@@ -446,12 +626,14 @@ export default function HomePage() {
))}
</div>
<div
style={{
textAlign: 'center',
fontSize: '14px',
color: '#d1d5db',
fontStyle: 'italic',
}}
className={css({
mt: '6',
textAlign: 'center',
fontSize: 'sm',
color: 'rgba(209, 213, 219, 1)',
fontStyle: 'italic',
})}
>
You'll progress through all these levels eventually

View File

@@ -217,6 +217,7 @@ interface TutorialPlayerProps {
showDebugPanel?: boolean
hideNavigation?: boolean
hideTooltip?: boolean
silentErrors?: boolean
abacusColumns?: number
theme?: 'light' | 'dark'
onStepChange?: (stepIndex: number, step: TutorialStep) => void
@@ -233,6 +234,7 @@ function TutorialPlayerContent({
showDebugPanel = false,
hideNavigation = false,
hideTooltip = false,
silentErrors = false,
abacusColumns = 5,
theme = 'light',
onStepChange,
@@ -638,7 +640,7 @@ function TutorialPlayerContent({
maxWidth: '200px',
minWidth: '150px',
wordBreak: 'break-word',
zIndex: 1000,
zIndex: 50,
opacity: 0.95,
transition: 'all 0.3s ease',
transform: showCelebration ? 'scale(1.05)' : 'scale(1)',
@@ -909,7 +911,7 @@ function TutorialPlayerContent({
)
})
if (!isCorrectBead) {
if (!isCorrectBead && !silentErrors) {
const errorMessage = "That's not the highlighted bead. Try clicking the highlighted bead."
dispatch({
type: 'SET_ERROR',

View File

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