Conversation
WalkthroughThis 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
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
Possibly related PRs
📜 Recent review detailsConfiguration used: .coderabbit.yaml 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms (3)
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
Documentation and Community
|
Deploying edutools-testing with
|
| 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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (4)
src/lib/stores.ts (1)
6-6: Persisted-value migration is missingChanging the default theme from
shadcn-zinc-darktoshadcn-zincis 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 → ThemesConsider 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 asdefaultMode="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:foregroundclass likely undefined; duplicates colour classThe new class list contains both
text-sidebar-primary-foregroundand a bareforegroundtoken:'class="text-sidebar-primary-foreground foreground …"'Unless you have a custom Tailwind utility named
foreground, this will:
- Compile to nothing (dead selector)
- 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, andsetModeare 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
DropdownMenuonly if another PR will consume it soon.)
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 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.sveltesrc/lib/stores.tssrc/lib/components/app-sidebar.sveltesrc/lib/components/settings.sveltesrc/lib/theme.tssrc/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 backgroundRemoving
text-foregroundmeans 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 referencesSeveral theme identifiers were removed (
*-dark,material-*, etc.). Make sure:
- No residual CSS selectors reference the old names.
- Settings history / bookmarks that point to removed themes degrade gracefully (see store migration note).
- 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 forshadcn-zinclight mode look correct.Switching from a global
:roottohtml:has(#theme.shadcn-zinc)cleanly isolates properties to when that theme is active.
41-73: Dark variant forshadcn-zincis properly defined.Using
html.dark:has(#theme.shadcn-zinc)aligns with the updated dark-mode toggle logic.
74-117:black-whitelight theme variables are consistent.All color and shadow properties are correctly set for the monochrome theme.
119-161:black-whitedark theme variant is well scoped.Properties invert appropriately for dark mode under
html.dark:has(#theme.black-white).
163-205:catppuccinlight theme definitions look good.Color palette and shadows follow the Catppuccin specification accurately.
207-249:catppuccindark variant is correctly implemented.Dark-mode values under
html.dark:has(#theme.catppuccin)match the expected design tokens.
251-293:catppuccin-darkertheme variables are valid.All custom properties and shadows adhere to the darker Catppuccin style.
339-381:cyberpunklight theme variables are correct.Bright accent and muted tones are appropriately set for the Cyberpunk style.
383-425:cyberpunkdark variant is properly scoped.Dark mode under
html.dark:has(#theme.cyberpunk)aligns with the light definitions.
427-469:vercellight theme variables are accurate.Clean separation of whites and greys fits the Vercel brand aesthetic.
471-513:verceldark theme variant is implemented correctly.Dark-mode tokens invert as expected under
html.dark:has(#theme.vercel).
515-557: Newgoogle-classroomtheme missing dark variant and not mentioned in summary.You’ve added a
google-classroomlight theme but no correspondinghtml.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.
| <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> |
There was a problem hiding this comment.
🛠️ 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.
| 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); | ||
| } |
There was a problem hiding this comment.
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.
|
@coderabbitai can you remove unneeded imports |
|
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: Length of output: 21903 Based on my analysis, I found unused imports in Task: Remove unused imports from settings.svelte
The unused imports are:
All other imports in the modified files appear to be properly used. Another agent will execute these changes for you. ⏳ Preparing changes... |
|
A summary of the edits CodeRabbit can apply:
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.svelteRemove 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.
|
|
Creating a commit in the current branch to apply the edits... The changes have been committed to the current branch. Commit ID: |
Summary by CodeRabbit
New Features
Enhancements
Style
Bug Fixes