Skip to content

New Seasonal Valentine's Theme#126

Open
amah853 wants to merge 10 commits intonicolaschan:masterfrom
amah853:valentines
Open

New Seasonal Valentine's Theme#126
amah853 wants to merge 10 commits intonicolaschan:masterfrom
amah853:valentines

Conversation

@amah853
Copy link
Copy Markdown

@amah853 amah853 commented Jan 20, 2026

This pull request adds several new themes to the bell schedule countdown app and improves the way seasonal and debug themes are handled. The most significant changes are the addition of new color themes (including special effects for some), updates to the theme manager to support these themes, and a minor documentation cleanup.

Theme Addition:

  • Added new theme: Valentines. The Valentines theme includes a seasonal activation (February only) and interactive animated heart effects.
  • Updated ThemeManager.ts to import and register the new themes, making them available in the app.

Theme Availability and Debugging:

  • Added a debug mode to ThemeManager that allows developers to enable all themes by visiting the app on localhost with a mode=debug URL parameter. This makes it easier to test seasonal and special themes outside their normal activation periods.

Note: Debug mode ONLY works if the instance is being hosted on localhost or 127.0.0.1.

You can preview the Valentines theme here:
Valentines Preview

@amah853
Copy link
Copy Markdown
Author

amah853 commented Jan 20, 2026

@nicolaschan

@amah853
Copy link
Copy Markdown
Author

amah853 commented Jan 20, 2026

@copilot please review

@amah853
Copy link
Copy Markdown
Author

amah853 commented Jan 22, 2026

heres an updated screenshot for the heart timer:
Screenshot 2026-01-21 at 9 56 00 PM

@amah853
Copy link
Copy Markdown
Author

amah853 commented Jan 26, 2026

@nicolaschan the duplicate commits have been fixed :)

Removed unnecessary blank lines for cleaner code.
@amah853
Copy link
Copy Markdown
Author

amah853 commented Jan 27, 2026

@nicolaschan I cleaned up the whitespace on lines 126, 129, 133, and 140. The tests should pass now if you try it again!

@nicolaschan
Copy link
Copy Markdown
Owner

Thanks for the effort here @amah853! It's a pretty effect. I think with a few tweaks for accessibility and edge cases plus a few code cleanups we'll be good to go.

@amah853
Copy link
Copy Markdown
Author

amah853 commented Jan 27, 2026

Sounds good! I just saw the updated test results and am working on them now. Copilot explained it was a formatting issue and some trailing whitespace, so I'll fix that and get back to you.

Would you like me to work on the accessibility and edge cases or is that something you were planning to do? I have no problem implementing them-- just asking.

@nicolaschan

@nicolaschan
Copy link
Copy Markdown
Owner

Go ahead! I think you're in a better position to consider how you'd like it to look since you're the original author

@nicolaschan
Copy link
Copy Markdown
Owner

By the way, you should be able to run the tests and lint locally. See the commands to use in .github/workflows/test.yaml

Copy link
Copy Markdown
Owner

@nicolaschan nicolaschan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here’s my detailed feedback. Meant to submit it yesterday but forgot to hit send, sorry!

Comment thread src/themes/Valentines.js Outdated
drawHeartCountdown: drawHeartCountdown,
enabled: (secrets) => {
const now = new Date()
return (now.getMonth() + 1) === 2 // February
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd expect Valentine's day theme to be only on Valentine's day

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe if Valentine's day is on the weekend we could do the week leading up to it. Continuing to show Valentine's day after it has passed feels odd.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I also want users to see the theme for more then one day? How about Feb 9-Feb 19? That gives them a 10 day window with Valentine's being directly in the middle of that.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about 10 days ending on Valentine's day? That way it won't continue occurring after Valentines' day which I think is odd.

That would also match the behavior of the Halloween theme well: https://github.com/nicolaschan/bell/blob/6727149a96c7d0095b74c06cdc2deaa048dedc63/src/themes/Halloween.js#L9C1-L9C63

Comment thread src/ThemeManager.ts Outdated
}
}

private isDebugMode (): boolean {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is useful but can we separate it into another PR? I think we should actually solve this with the existing enableDevMode so that you can mock the time and see the themes available. This would let you E2E test that your theme appears on the right dates too.

Right now this is how I mock the time in the JS console:

bellTimer.correctedDate.enableDevMode(new Date('2026-02-16 9:20'), 0)

We should update the theme available function in the seasonal themes to take the actual bellTimer instance instead of using new Date().

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh, didn't see this in the codebase. I'll remove the debug mode.

Comment thread src/ui/Page1.js Outdated
// Check if current theme is Valentines
if (themeManager.currentTheme.name === 'Valentines') {
// Draw heart countdown instead of circle - same size and behavior
Valentines.drawHeartCountdown(ctx, posX, posY, radius, proportion)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate the creativity but there are a few problems with this that make me think we should keep the circle.

  • With a circle, the angle matches the area. If there's 10% of the time remaining you see 10% of the circle's area. With a heart, that no longer holds so at a glance the proportion of time remaining is misleading, especially near the beginning/end of the period.
  • The heart outline results in poor contrast (see the screenshot). I'm straining my eyes trying to make it out against the background and also read the text layered on top of it.
  • This isn't the right place to put the heart draw code. The UI shouldn't depend directly on a concrete theme. Instead if we were to do this, we should abstract out a common interface for the themes so we don't have to special case a theme in the UI rendering code.
Image

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I see how that might be hard to read when the theme gets darker. I'll change it back to a circle, it was more of a last-minute idea and not really that important to me.

Comment thread src/themes/Valentines.js
theme: BasicColorTheme(
ColorSchemeTransformations.fromObjectStrings,
BasicTiming,
[{
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of these color choices have very low contrast which makes it hard to read, especially if you have poor eyesight, bad lighting, or a bad screen.

Can we check each color combination and ensure all of the text on all of the combinations are easily readable?

You can use this in the JS console to mock the time to check them:

bellTimer.correctedDate.enableDevMode(new Date('2026-02-16 9:21'), 0) 
Image

Comment thread src/themes/Valentines.js Outdated
}

module.exports = {
name: 'Valentines',
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: "Valentine's"

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix!

Comment thread src/themes/Valentines.js Outdated
ctx.globalAlpha = heart.opacity
ctx.fillStyle = heart.clicked ? '#ffffff' : heart.color

// Calculate pulse scale (subtle pulse between 0.9 and 1.1)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to comment obvious code.

Such comments don't add much value and tend to get out of date with changes, which I think this one already is because the next line looks like it will vary between 0.7 and 1.3 not 0.9 and 1.1.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's because I changed the pulse scale later and forget to fix the comment. Regardless, I'll remove the comment.

Comment thread src/themes/Valentines.js Outdated
drawHeart(ctx, heart.x, heart.y, currentSize * pulseScale, heart.rotation)
ctx.fill()

if (heart.y > window.innerHeight + 50) {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the magic + 50 from? If it's important, let's give it a variable name.

Comment thread src/themes/Valentines.js Outdated
canvas.addEventListener('mousedown', (e) => {
for (const heart of hearts) {
const distance = Math.sqrt(Math.pow(heart.x - e.x, 2) + Math.pow(heart.y - e.y, 2))
if (distance < heart.size) {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying this out I noticed that the hitbox doesn't match the heart size. When I clicked large hearts near the edge but still within the heart it didn't register.

Looking at this code I think that's because heart.size is just the base size but it may be scaled upon render to appear larger than the heart.size.

Comment thread src/themes/Valentines.js Outdated
const currentSize = heart.clicked ? heart.size * 1.5 : heart.size

drawHeart(ctx, heart.x, heart.y, currentSize * pulseScale, heart.rotation)
ctx.fill()
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be part of drawing the heart in drawHeart?

Comment thread src/themes/Valentines.js
hearts.add({
x: Math.random() * window.innerWidth,
y: -20,
size: 30 + Math.random() * 30,
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should we do about hearts covering up the text, especially on mobile where the screen is small but the hearts are the same size as on desktop?

Image

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idk, I thought this looked nice but I can see how it might be intrusive. I'll model the hearts to be underneath the text.

@amah853
Copy link
Copy Markdown
Author

amah853 commented Feb 2, 2026

@nicolaschan when I ran the changes locally it passed 101 of 102 tests, and the failing part is not caused by my changes to the Valentine's theme. Do you want me to fix it, even though its unrelated to this PR?

the error is in BellTimer-test.js at line 34. The error "Cannot read property 'should' of undefined"

@nicolaschan
Copy link
Copy Markdown
Owner

If it's unrelated it would be better to put in a separate PR. But the CI works on the master branch so I think it is probably an issue with your local setup.

@amah853
Copy link
Copy Markdown
Author

amah853 commented Feb 2, 2026

bell % yarn lint 2>&1 | tail -20 yarn run v1.22.22 $ standard && tslint -e "**/*.js" --project . standard: Use JavaScript Standard Style (https://standardjs.com) standard: Run standard --fix to automatically fix some problems. /Users/AhmadGamer/Projects/bell/src/BellTimer.js:14:3: Block must not be padded by blank lines. error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

I'm running ChromeHeadless for my tests not Firefox, so that's probably the issue. Also, I forgot to run lint tests 😅
It's passing on my machine (other then the issue above)

@amah853
Copy link
Copy Markdown
Author

amah853 commented Feb 2, 2026

Github Actions is outputting the same error:

yarn run v1.22.22 $ standard && tslint -e "**/*.js" --project . standard: Use JavaScript Standard Style (https://standardjs.com/) standard: Run standard --fix to automatically fix some problems. /home/runner/work/bell/bell/src/BellTimer.js:14:3: Block must not be padded by blank lines. error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. Error: Process completed with exit code 1.

@nicolaschan
Copy link
Copy Markdown
Owner

It looks like it's because you removed the devMode method in BellTimer.js in this PR

@amah853
Copy link
Copy Markdown
Author

amah853 commented Feb 2, 2026

Ohhh, submitting a fix now!

@amah853
Copy link
Copy Markdown
Author

amah853 commented Feb 2, 2026

@nicolaschan ready to merge?

@nicolaschan
Copy link
Copy Markdown
Owner

Can you please do a line-by-line self review of your changes before asking me to review again?

There are some obvious issues I don't think you intend to be there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants