Skip to content

add theming#382

Merged
ingoau merged 31 commits intomainfrom
218-feature-theming
Jun 17, 2025
Merged

add theming#382
ingoau merged 31 commits intomainfrom
218-feature-theming

Conversation

@ingoau
Copy link
Member

@ingoau ingoau commented Jun 17, 2025

Summary by CodeRabbit

  • New Features

    • Added multiple new visual themes, including "black-white", "catppuccin", "catppuccin-darker", "terminal", "cyberpunk", and "vercel", each with light and dark modes.
    • Introduced a theme toggle button in settings for quickly switching between light and dark color modes.
  • Enhancements

    • Updated default theme to "shadcn-zinc" (light mode) for new users.
    • Simplified and updated the list of available themes for easier selection.
    • Improved theme switching transitions for a smoother user experience.
  • Style

    • Refined sidebar button styles by removing scaling effects and adjusting color classes.
  • Bug Fixes

    • Enabled mode transition animations by setting explicit transition control in layout component.

@ingoau ingoau linked an issue Jun 17, 2025 that may be closed by this pull request
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 17, 2025

Walkthrough

This update overhauls the application's theming system by introducing multiple new CSS themes and simplifying the theme selection logic. It updates theme variable definitions in CSS, modifies the theme selector UI to include a mode toggle, changes the default theme, and reduces the set of available themes to a smaller, curated list.

Changes

File(s) Change Summary
src/app.css Replaced root and dark theme selectors with :has()-based selectors; added several new theme variants with comprehensive CSS variable definitions for both light and dark modes.
src/lib/components/app-sidebar.svelte Removed transition and scale effects from sidebar menu buttons; adjusted background and text color classes.
src/lib/components/settings.svelte Added a theme mode toggle button (light/dark) next to the theme selection dialog; imported and used mode management utilities.
src/lib/stores.ts Changed the default theme in the preferences store from 'shadcn-zinc-dark' to 'shadcn-zinc'.
src/lib/theme.ts Replaced a large, specific theme list with a smaller, more general set of themes; updated some theme labels.
src/routes/+layout.svelte Set disableTransitions={false} explicitly on the <ModeWatcher> component.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SettingsComponent
    participant ModeWatcher
    participant ThemeStore
    participant CSS

    User->>SettingsComponent: Clicks theme toggle button
    SettingsComponent->>ModeWatcher: Calls toggleMode()
    ModeWatcher->>ThemeStore: Updates mode (light/dark)
    ThemeStore->>CSS: Applies corresponding theme variables via :has() selector
    CSS-->>User: UI updates with new theme and mode
Loading

Possibly related PRs

  • add settings #370: Refactors the settings UI to a more complex panel, including a theme selection dialog—related due to overlapping modifications in settings.svelte and enhancements to theme and settings controls.

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 368039f and 195ea4b.

📒 Files selected for processing (1)
  • src/lib/components/settings.svelte (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/components/settings.svelte
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: format
  • GitHub Check: build
  • GitHub Check: Cloudflare Pages

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Jun 17, 2025

Deploying edutools-testing with  Cloudflare Pages  Cloudflare Pages

Latest commit: 195ea4b
Status: ✅  Deploy successful!
Preview URL: https://30aefd11.edutools-testing.pages.dev
Branch Preview URL: https://218-feature-theming.edutools-testing.pages.dev

View logs

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
src/lib/stores.ts (1)

6-6: Persisted-value migration is missing

Changing the default theme from shadcn-zinc-dark to shadcn-zinc is fine for new users, but existing local-storage data may still hold the retired value. That results in:

• incorrect colour palette (CSS variables not found)
• empty radio selection in Settings → Themes

Consider a one-time migration or runtime fallback such as:

-if ($preferencesStore.theme === 'shadcn-zinc-dark') {
-  $preferencesStore.theme = 'shadcn-zinc';
-}
+if ($preferencesStore.theme?.endsWith('-dark')) {
+  $preferencesStore.theme = $preferencesStore.theme.replace(/-dark$/, '');
+}

Place it in an early startup (e.g. layout onMount) so legacy users are auto-upgraded.

src/routes/+layout.svelte (1)

87-87: Minor prop-syntax nit

defaultMode={'dark'} passes the same string as defaultMode="dark"; the braces are unnecessary noise in Svelte markup.

-<ModeWatcher disableTransitions={false} defaultMode={'dark'} />
+<ModeWatcher disableTransitions={false} defaultMode="dark" />

Purely cosmetic, feel free to ignore if you prefer the current style.

src/lib/components/app-sidebar.svelte (1)

157-159: foreground class likely undefined; duplicates colour class

The new class list contains both text-sidebar-primary-foreground and a bare foreground token:

'class="text-sidebar-primary-foreground foreground …"'

Unless you have a custom Tailwind utility named foreground, this will:

  1. Compile to nothing (dead selector)
  2. Confuse future maintainers

Recommend dropping the stray token:

-'text-sidebar-primary-foreground foreground flex …'
+'text-sidebar-primary-foreground flex …'
src/lib/components/settings.svelte (1)

13-17: Dead imports can be trimmed

DropdownMenu, resetMode, mode, and setMode are imported but never used after the refactor. This generates Rollup warnings and slightly increases bundle size.

-import * as DropdownMenu from '$lib/components/ui/dropdown-menu/index.js';
-import { resetMode, mode, setMode, toggleMode } from 'mode-watcher';
+import { toggleMode } from 'mode-watcher';

(Keep DropdownMenu only if another PR will consume it soon.)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b5cc3dd and 368039f.

📒 Files selected for processing (6)
  • src/app.css (1 hunks)
  • src/lib/components/app-sidebar.svelte (4 hunks)
  • src/lib/components/settings.svelte (2 hunks)
  • src/lib/stores.ts (1 hunks)
  • src/lib/theme.ts (1 hunks)
  • src/routes/+layout.svelte (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.*`: Do not correct spelling errors or grammar mistakes.

**/*.*: Do not correct spelling errors or grammar mistakes.

  • src/routes/+layout.svelte
  • src/lib/stores.ts
  • src/lib/components/app-sidebar.svelte
  • src/lib/components/settings.svelte
  • src/lib/theme.ts
  • src/app.css
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (14)
src/lib/components/app-sidebar.svelte (1)

181-182: Lost colour on search icon background

Removing text-foreground means the icon now inherits the parent colour, which might be invisible on certain themes. If that was unintentional, re-add a text colour utility (e.g., text-muted-foreground) to keep consistent contrast.

src/lib/theme.ts (1)

2-9: Contract change: clean-up dangling references

Several theme identifiers were removed (*-dark, material-*, etc.). Make sure:

  1. No residual CSS selectors reference the old names.
  2. Settings history / bookmarks that point to removed themes degrade gracefully (see store migration note).
  3. Any docs or screenshots are updated to reflect the new, shorter list.

No code change required here; flagging for awareness.

src/app.css (12)

6-39: Scoped theme variables for shadcn-zinc light mode look correct.

Switching from a global :root to html:has(#theme.shadcn-zinc) cleanly isolates properties to when that theme is active.


41-73: Dark variant for shadcn-zinc is properly defined.

Using html.dark:has(#theme.shadcn-zinc) aligns with the updated dark-mode toggle logic.


74-117: black-white light theme variables are consistent.

All color and shadow properties are correctly set for the monochrome theme.


119-161: black-white dark theme variant is well scoped.

Properties invert appropriately for dark mode under html.dark:has(#theme.black-white).


163-205: catppuccin light theme definitions look good.

Color palette and shadows follow the Catppuccin specification accurately.


207-249: catppuccin dark variant is correctly implemented.

Dark-mode values under html.dark:has(#theme.catppuccin) match the expected design tokens.


251-293: catppuccin-darker theme variables are valid.

All custom properties and shadows adhere to the darker Catppuccin style.


339-381: cyberpunk light theme variables are correct.

Bright accent and muted tones are appropriately set for the Cyberpunk style.


383-425: cyberpunk dark variant is properly scoped.

Dark mode under html.dark:has(#theme.cyberpunk) aligns with the light definitions.


427-469: vercel light theme variables are accurate.

Clean separation of whites and greys fits the Vercel brand aesthetic.


471-513: vercel dark theme variant is implemented correctly.

Dark-mode tokens invert as expected under html.dark:has(#theme.vercel).


515-557: New google-classroom theme missing dark variant and not mentioned in summary.

You’ve added a google-classroom light theme but no corresponding html.dark:has(#theme.google-classroom) block.
Also, the PR summary omits this theme. Please verify if this was intentional.

Likely an incorrect or invalid review comment.

Comment on lines +48 to +79
<div class="flex flex-row gap-2">
<Dialog.Root>
<Dialog.Trigger
class={clsx(buttonVariants({ variant: 'outline' }), 'w-fit justify-start')}
>
{themeTriggerContent}
<ChevronDownIcon class="opacity-50" />
</Dialog.Trigger>

<Dialog.Content class="p-0">
<div class="max-h-[80vh] overflow-auto p-6">
<RadioGroup.Root bind:value={$preferencesStore.theme}>
{#each themes as theme}
<div class="flex items-center space-x-2">
<RadioGroup.Item value={theme.value} id={theme.value} />
<Label for={theme.value}>{theme.label}</Label>
</div>
{/each}
</RadioGroup.Root>
</div>
</Dialog.Content>
</Dialog.Root>
<Button onclick={toggleMode} variant="outline" size="icon">
<SunIcon
class="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90"
/>
<MoonIcon
class="absolute h-[1.2rem] w-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0"
/>
<span class="sr-only">Toggle theme</span>
</Button>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Theme picker UX: button label doesn’t update after selection

themeTriggerContent is computed once via $derived, but the variable is not reactive to subsequent changes because $derived captures the value at definition time. Observed result: the button continues to show the old theme name until the dialog is reopened.

A quick reactive fix:

-const themeTriggerContent = $derived(
-  themes.find((t) => t.value === $preferencesStore.theme)?.label ?? 'No theme :D'
-);
+$: themeTriggerContent =
+  themes.find((t) => t.value === $preferencesStore.theme)?.label ?? 'No theme :D';

This leverages Svelte’s $: reactive label without introducing additional state helpers.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/lib/components/settings.svelte between lines 48 and 79, the theme picker
button label does not update reactively after a theme selection because
themeTriggerContent is computed once via $derived and does not react to changes.
To fix this, replace the $derived usage with a reactive statement using Svelte's
$: label that updates themeTriggerContent whenever the theme value changes,
ensuring the button label reflects the current theme immediately.

Comment on lines +295 to +337
html:has(#theme.terminal) {
--background: #000000;
--foreground: #00ff00;
--card: #000000;
--card-foreground: #00ff00;
--popover: #000000;
--popover-foreground: #00ff00;
--primary: #008000;
--primary-foreground: #ffffff;
--secondary: #004000;
--secondary-foreground: #ffffff;
--muted: #111111;
--muted-foreground: #00ff00;
--accent: #111111;
--accent-foreground: #00ff00;
--destructive: #ff0000;
--destructive-foreground: #ffffff;
--border: #111111;
--input: #00ff00;
--ring: #00ff00;
--chart-1: #008000;
--chart-2: #004000;
--chart-3: #002000;
--chart-4: #000080;
--chart-5: #000040;
--sidebar: #000000;
--sidebar-foreground: #00ff00;
--sidebar-primary: #008000;
--sidebar-primary-foreground: #ffffff;
--sidebar-accent: #00ff00;
--sidebar-accent-foreground: #000000;
--sidebar-border: #444444;
--sidebar-ring: #00ff00;
--radius: 8px;
--shadow-2xs: 0px 2px 4px 0px hsl(0 0% 0% / 0.1);
--shadow-xs: 0px 2px 4px 0px hsl(0 0% 0% / 0.1);
--shadow-sm: 0px 2px 4px 0px hsl(0 0% 0% / 0.2), 0px 1px 2px -1px hsl(0 0% 0% / 0.2);
--shadow: 0px 2px 4px 0px hsl(0 0% 0% / 0.2), 0px 1px 2px -1px hsl(0 0% 0% / 0.2);
--shadow-md: 0px 2px 4px 0px hsl(0 0% 0% / 0.2), 0px 2px 4px -1px hsl(0 0% 0% / 0.2);
--shadow-lg: 0px 2px 4px 0px hsl(0 0% 0% / 0.2), 0px 4px 6px -1px hsl(0 0% 0% / 0.2);
--shadow-xl: 0px 2px 4px 0px hsl(0 0% 0% / 0.2), 0px 8px 10px -1px hsl(0 0% 0% / 0.2);
--shadow-2xl: 0px 2px 4px 0px hsl(0 0% 0% / 0.5);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Missing dark-mode selector for terminal theme.

You’ve defined only the light variant (html:has(#theme.terminal)). If a dark variant is intended, add an html.dark:has(#theme.terminal) block.

🤖 Prompt for AI Agents
In src/app.css between lines 295 and 337, you have defined CSS variables for the
terminal theme only under the light mode selector html:has(#theme.terminal). To
support dark mode, add a corresponding css block using the selector
html.dark:has(#theme.terminal) with appropriate variable values for dark mode
styling. This will ensure the terminal theme adapts correctly when dark mode is
active.

@ingoau
Copy link
Member Author

ingoau commented Jun 17, 2025

@coderabbitai can you remove unneeded imports

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 17, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@Inglan I'll help you identify and remove unused imports from the files in this PR. Let me analyze the modified files to find any unused imports.


🏁 Script executed:

#!/bin/bash
# First, let's examine all the modified files to identify their imports and usage
echo "=== Analyzing src/lib/components/app-sidebar.svelte ==="
cat src/lib/components/app-sidebar.svelte

echo -e "\n=== Analyzing src/lib/components/settings.svelte ==="
cat src/lib/components/settings.svelte

echo -e "\n=== Analyzing src/lib/stores.ts ==="
cat src/lib/stores.ts

echo -e "\n=== Analyzing src/lib/theme.ts ==="
cat src/lib/theme.ts

echo -e "\n=== Analyzing src/routes/+layout.svelte ==="
cat src/routes/+layout.svelte

Length of output: 21903


Based on my analysis, I found unused imports in src/lib/components/settings.svelte. Let me create a plan to remove them:

Task: Remove unused imports from settings.svelte

  • Remove CircleAlertIcon import (not used in template)
  • Remove unused mode-watcher imports: resetMode, mode, setMode (only toggleMode is used)

The unused imports are:

  • CircleAlertIcon - imported but never used in the template
  • resetMode, mode, setMode - imported from mode-watcher but only toggleMode is actually used

All other imports in the modified files appear to be properly used. Another agent will execute these changes for you.


⏳ Preparing changes...

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 17, 2025

A summary of the edits CodeRabbit can apply:

Remove unused imports from src/lib/components/settings.svelte file to clean up the codebase.

A plan of each step that CodeRabbit will take in order to execute the edits for each file (with inline rough draft snippets):

✏️ src/lib/components/settings.svelte

Remove the unused CircleAlertIcon import from line 12 completely. Delete the entire line:

import CircleAlertIcon from '@lucide/svelte/icons/circle-alert';

This import is not used anywhere in the component template or script.


Modify the mode-watcher import on line 16 to only import toggleMode, removing the unused imports resetMode, mode, and setMode. Change the line from:

import { resetMode, mode, setMode, toggleMode } from 'mode-watcher';

to:

import { toggleMode } from 'mode-watcher';

The toggleMode function is used in the template on line 70 in the Button's onclick handler, but the other three functions are not used anywhere in the component.


After making these changes, verify that the file maintains proper syntax and that all remaining imports are properly used throughout the component. The final result should have the CircleAlertIcon import completely removed and the mode-watcher import reduced to only include toggleMode, keeping the component functionality intact while removing unused code.

  • Created local commit - (🔄 Check again to try again)

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 17, 2025

Creating a commit in the current branch to apply the edits...

The changes have been committed to the current branch. Commit ID: 195ea4b0be27fcf9ab70ec136500266da02e2b28

@ingoau ingoau merged commit ba3ec83 into main Jun 17, 2025
5 checks passed
@delete-merged-branch delete-merged-branch bot deleted the 218-feature-theming branch June 17, 2025 06:34
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.

[Feature] Theming

1 participant