-
Notifications
You must be signed in to change notification settings - Fork 1
improvments, fixes, new tool #446
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
update deps
Bumps [paneforge](https://github.com/svecosystem/paneforge/tree/HEAD/packages/paneforge) from 1.0.0-next.5 to 1.0.2. - [Release notes](https://github.com/svecosystem/paneforge/releases) - [Changelog](https://github.com/svecosystem/paneforge/blob/main/packages/paneforge/CHANGELOG.md) - [Commits](https://github.com/svecosystem/paneforge/commits/paneforge@1.0.2/packages/paneforge) --- updated-dependencies: - dependency-name: paneforge dependency-version: 1.0.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [tailwind-variants](https://github.com/heroui-inc/tailwind-variants) from 1.0.0 to 2.1.0. - [Release notes](https://github.com/heroui-inc/tailwind-variants/releases) - [Changelog](https://github.com/heroui-inc/tailwind-variants/blob/main/CHANGELOG.md) - [Commits](heroui-inc/tailwind-variants@v1.0.0...v2.1.0) --- updated-dependencies: - dependency-name: tailwind-variants dependency-version: 2.1.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
sidebar improvements
add stopwatcxh and timer
Co-authored-by: Inglan <96573515+Inglan@users.noreply.github.com>
…of groupItem.url Co-authored-by: Inglan <96573515+Inglan@users.noreply.github.com>
…33-4a02-b60b-4a2bd7551ac4 Fix sidebar sub-item active state to check individual URLs instead of parent group URL
…/tailwind-variants-2.1.0 Bump tailwind-variants from 1.0.0 to 2.1.0
…/paneforge-1.0.2 Bump paneforge from 1.0.0-next.5 to 1.0.2
WalkthroughThis change introduces a new Stopwatch & Timer tool as a Svelte page, updates navigation and homepage tool listings to include it, and adjusts sidebar and authentication UI styling and logic. Several dependencies are updated in package.json, including some version downgrades and a package relocation. The sidebar's active state logic and click behavior are refined, and grid layouts on the homepage are improved for responsiveness. Multiple UI components receive minor style and accessibility improvements. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant NavBar as Navigation/Menu
participant Home as Homepage
participant StopwatchPage as Stopwatch & Timer Page
User->>NavBar: Opens navigation menu
NavBar-->>User: Shows "Stopwatch & Timer" link
User->>Home: Views tool list
Home-->>User: Displays "Stopwatch & Timer" card
User->>StopwatchPage: Navigates to /tools/stopwatch-timer
StopwatchPage-->>User: Renders Stopwatch & Timer UI (tabs, controls)
User->>StopwatchPage: Interacts with stopwatch/timer (start, pause, lap, reset)
StopwatchPage-->>User: Updates UI, plays sound on timer finish
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~15–25 minutes Possibly related PRs
Suggested reviewers
Note 🔌 MCP (Model Context Protocol) integration is now available in Early Access!Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context. ✨ Finishing Touches
🧪 Generate unit tests
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. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
Deploying edutools-testing with
|
| Latest commit: |
b6d56f0
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://fe0f32c3.edutools-testing.pages.dev |
| Branch Preview URL: | https://main.edutools-testing.pages.dev |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🔭 Outside diff range comments (1)
src/lib/components/sidebar-auth.svelte (1)
101-114:list-noneplaced on Dialog.Trigger won’t remove bullets on nested li; target li directly
list-styleis not inherited. Apply it to the li children (Sidebar.MenuItem) instead of the Trigger wrapper.Apply this diff so the wrapper targets its direct li children:
- <Dialog.Trigger class="flex list-none flex-col gap-2"> + <Dialog.Trigger class="flex flex-col gap-2 [&>li]:list-none">
🧹 Nitpick comments (6)
src/routes/+page.svelte (1)
34-35: Responsive grid tweak improves small-screen UXSwitching to a single column on small screens and 3 cols at md is sensible.
Consider de-duplicating the tools list by deriving it from the navigation (or a shared tools config) to avoid divergence:
- Option A: import createMainNavigation() and map the “Tools” group items here.
- Option B: extract a shared tools array (e.g., lib/tools.ts) used by both navigation and this page.
src/routes/tools/stopwatch-timer/+page.svelte (5)
28-38: No hours handling informatTimeAfter 99 minutes the display rolls over incorrectly (e.g., 125 min → “125:00”).
If hour-level use is expected, extend the formatter or cap minutes at 59 and show hours.
120-141:AudioContextleakThe created
AudioContextis never closed, keeping an extra audio thread alive until page unload. Add:oscillator.stop(audioContext.currentTime + 1); +oscillator.onended = () => audioContext.close();
143-150: Reactive block does nothing
progressis calculated but never used, so the$effectruns unnecessarily every tick.
Either bindprogressto a progress-bar element or remove the block to save CPU.
240-257: Lap removal index off-by-one
removeLap(stopwatchLaps.length - index - 1)duplicates the earlierlapIndexmath; simpler & safer:- onclick={() => removeLap(stopwatchLaps.length - index - 1)} + onclick={() => removeLap(index)}Avoids errors if the surrounding logic changes.
312-317: Quick-set buttons mutate bound values without type coercion
bind:valueoninput type="number"still gives numbers as strings in some browsers; assigning
preset.minutes(number) is fine but later comparisons like(timerMinutes === 0)may facestringvsnumber.
Ensure numeric coercion:timerMinutes = Number(preset.minutes); timerSeconds = Number(preset.seconds);
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (6)
package.json(3 hunks)src/lib/components/app-sidebar.svelte(3 hunks)src/lib/components/sidebar-auth.svelte(1 hunks)src/lib/navigation.ts(1 hunks)src/routes/+page.svelte(2 hunks)src/routes/tools/stopwatch-timer/+page.svelte(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.*
⚙️ CodeRabbit Configuration File
**/*.*: Do not correct spelling errors or grammar mistakes.
Files:
src/lib/navigation.tssrc/lib/components/app-sidebar.sveltesrc/routes/+page.sveltesrc/lib/components/sidebar-auth.sveltesrc/routes/tools/stopwatch-timer/+page.sveltepackage.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (4)
src/lib/navigation.ts (1)
65-68: Add “Stopwatch & Timer” nav item — LGTMEntry is consistent with other Tools children and matches the new route.
src/routes/+page.svelte (1)
16-18: Tool list updated with Stopwatch & Timer — OKNew entry is consistent with existing entries and links to the expected route.
src/lib/components/app-sidebar.svelte (2)
131-135: Ensuring the sidebar opens when a group is clicked — good additionExplicitly calling
sidebar.setOpen(true)on group click improves discoverability in collapsed mode.
211-211: Non-group isActive equality check — LGTMDirect match for leaf routes is appropriate here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🔭 Outside diff range comments (1)
src/lib/components/ui/chart/chart-style.svelte (1)
15-23: Quote and escape the data attribute value in the generated selector.If id contains special characters (e.g., spaces, quotes, brackets), the unquoted selector [data-chart=${id}] can break. Quote and escape the value to harden the CSS.
Example (outside this range):
const esc = (v: string) => // Use native CSS.escape when available; otherwise minimal escaping for quoted strings (typeof CSS !== 'undefined' && CSS.escape) ? CSS.escape(v) : v.replace(/["\\\n\r\f]/g, (m) => `\\${m}`); let content = `${prefix} [data-chart="${esc(id)}"] {\n`;
🧹 Nitpick comments (2)
src/lib/components/ui/chart/chart-utils.ts (1)
44-49: Change to explicit undefined check is fine; consider simplifying the type narrowing for readability.Current logic is correct and consistent with the PR’s nullish semantics. You can make the property access clearer and avoid the verbose
keyof typeofassertions:- } else if ( - payloadPayload !== undefined && - key in payloadPayload && - typeof payloadPayload[key as keyof typeof payloadPayload] === 'string' - ) { - configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string; - } + } else if (payloadPayload !== undefined) { + const maybe = (payloadPayload as Record<string, unknown>)[key]; + if (typeof maybe === 'string') { + configLabelKey = maybe; + } + }src/lib/components/ui/avatar/avatar.svelte (1)
15-19: Expose busy state to assistive tech.If loadingStatus reflects image load, expose it via aria-busy for better a11y.
<AvatarPrimitive.Root bind:ref bind:loadingStatus data-slot="avatar" - class={cn('relative flex size-8 shrink-0 overflow-hidden rounded-full', className)} + class={cn('relative flex size-8 shrink-0 overflow-hidden rounded-full', className)} + aria-busy={loadingStatus === 'loading'} {...restProps} />
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (16)
package.json(3 hunks)src/lib/components/ui/avatar/avatar.svelte(1 hunks)src/lib/components/ui/carousel/carousel-previous.svelte(1 hunks)src/lib/components/ui/chart/chart-style.svelte(1 hunks)src/lib/components/ui/chart/chart-tooltip.svelte(2 hunks)src/lib/components/ui/chart/chart-utils.ts(1 hunks)src/lib/components/ui/command/command-item.svelte(1 hunks)src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte(1 hunks)src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte(1 hunks)src/lib/components/ui/sidebar/sidebar-rail.svelte(1 hunks)src/lib/components/ui/sidebar/sidebar.svelte(3 hunks)src/lib/components/ui/sonner/sonner.svelte(1 hunks)src/lib/components/ui/table/table-cell.svelte(1 hunks)src/lib/components/ui/table/table-head.svelte(1 hunks)src/lib/components/ui/table/table-row.svelte(1 hunks)src/lib/components/ui/tooltip/tooltip-content.svelte(1 hunks)
✅ Files skipped from review due to trivial changes (9)
- src/lib/components/ui/table/table-head.svelte
- src/lib/components/ui/sidebar/sidebar-rail.svelte
- src/lib/components/ui/table/table-cell.svelte
- src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte
- src/lib/components/ui/sonner/sonner.svelte
- src/lib/components/ui/table/table-row.svelte
- src/lib/components/ui/tooltip/tooltip-content.svelte
- src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte
- src/lib/components/ui/command/command-item.svelte
🚧 Files skipped from review as they are similar to previous changes (1)
- package.json
🧰 Additional context used
📓 Path-based instructions (1)
**/*.*
⚙️ CodeRabbit Configuration File
**/*.*: Do not correct spelling errors or grammar mistakes.
Files:
src/lib/components/ui/carousel/carousel-previous.sveltesrc/lib/components/ui/chart/chart-utils.tssrc/lib/components/ui/chart/chart-style.sveltesrc/lib/components/ui/avatar/avatar.sveltesrc/lib/components/ui/sidebar/sidebar.sveltesrc/lib/components/ui/chart/chart-tooltip.svelte
🔇 Additional comments (9)
src/lib/components/ui/chart/chart-style.svelte (1)
33-35: Switch to a real <style> element — cleaner and safer.Avoids raw HTML injection, keeps SSR/hydration clean, and updates reactively. LGTM.
src/lib/components/ui/chart/chart-tooltip.svelte (4)
57-57: Good switch to nullish coalescing for label key.Using
??preserves intentionally empty strings and zeros, preventing unintended fallbacks.
63-65: Correct use of nullish fallback when resolving config label.
?.label ?? labelensures only null/undefined triggers the fallback; avoids clobbering empty strings.
66-66: Tightened undefined check is appropriate.
value === undefinedallows valid falsy values (e.g.,'',0) to render.
144-148: Undefined-only guard for item value is correct.This shows
0and other falsy-but-valid values while still hiding truly absent values.src/lib/components/ui/avatar/avatar.svelte (1)
7-7: Verify bindableloadingStatuson AvatarPrimitive.RootProps for bits-ui@2.8.11We weren’t able to locate the bits-ui source locally to confirm that
AvatarPrimitive.RootPropsexposes aloadingStatusprop. Please double-check against your installed bits-ui v2.8.11 (in your localnode_modules) or the official API docs to ensure:
- The
loadingStatusprop exists onAvatarPrimitive.RootProps- It’s marked as
bindablein the TypeScript definitions- The runtime implementation supports binding to
loadingStatusAffected file & lines:
- src/lib/components/ui/avatar/avatar.svelte:
- Line 7:
loadingStatus = $bindable('loading'),- Line 15:
bind:loadingStatusNo other occurrences of
loadingStatuswere found in the codebase. If this prop isn’t available, update the component or types to avoid mismatches.src/lib/components/ui/sidebar/sidebar.svelte (3)
2-2: LGTM: Drawer import aligns with the mobile migration.Import swap is consistent with the new Drawer-based mobile sidebar.
89-90: Confirmed matching +2px offset for sidebar icon width calcThe
+2pxadjustment is applied identically in both variants (Line 76 and Line 89), so there is no gap/container width mismatch. No changes required.
76-77: Verified: the +2px accounts for the two 1px borders and matches token math
SIDEBAR_WIDTH_ICON is 3rem (48 px) and spacing(4) is 1rem (16 px), so calc(48 px + 16 px + 2 px) = 66 px. The extra 2 px covers the combined 1 px border on each side, preserving pixel‐perfect layout across densities. No change needed.
| {variant} | ||
| {size} | ||
| disabled={!emblaCtx.canScrollPrev} | ||
| aria-disabled={!emblaCtx.canScrollPrev} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Guard interactions when using aria-disabled (button remains operable).
Switching to aria-disabled does not prevent clicks/keys. Either keep native disabled or defensively no-op the handlers and remove pointer events when not scrollable.
Option A — keep native semantics:
- aria-disabled={!emblaCtx.canScrollPrev}
+ disabled={!emblaCtx.canScrollPrev}
+ aria-disabled={!emblaCtx.canScrollPrev}Option B — keep aria-disabled but guard behavior and visuals:
- onclick={emblaCtx.scrollPrev}
- onkeydown={emblaCtx.handleKeyDown}
+ onclick={() => emblaCtx.canScrollPrev && emblaCtx.scrollPrev()}
+ onkeydown={(e) => emblaCtx.canScrollPrev && emblaCtx.handleKeyDown(e)}And consider visual non-interactivity:
class={cn(
'absolute size-8 rounded-full',
emblaCtx.orientation === 'horizontal'
? 'top-1/2 -left-12 -translate-y-1/2'
: '-top-12 left-1/2 -translate-x-1/2 rotate-90',
+ !emblaCtx.canScrollPrev && 'pointer-events-none opacity-50',
className
)}Also applies to: 31-33
🤖 Prompt for AI Agents
In src/lib/components/ui/carousel/carousel-previous.svelte at line 23 and also
lines 31-33, aria-disabled is used but it does not prevent button interactions.
To fix this, either replace aria-disabled with the native disabled attribute to
prevent interaction or, if keeping aria-disabled, add logic to no-op click and
key handlers and apply CSS to disable pointer events and visually indicate
non-interactivity when scrolling is not possible.
| <svelte:element this={'style'}> | ||
| {themeContents} | ||
| </svelte:element> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Support strict CSP by allowing a nonce on the dynamic <style>.
Inline styles get blocked without 'unsafe-inline'. Expose an optional nonce and set it on the style element.
Apply within this block:
- <svelte:element this={'style'}>
+ <svelte:element this={'style'} nonce={nonce}>
{themeContents}
</svelte:element>Also update props in the script (outside this range):
let { id, config, nonce }: { id: string; config: ChartConfig; nonce?: string } = $props();🤖 Prompt for AI Agents
In src/lib/components/ui/chart/chart-style.svelte around lines 33 to 35, the
dynamic <style> element does not support a nonce attribute, which is required
for strict Content Security Policy (CSP) compliance. To fix this, add an
optional nonce prop to the component's script props definition, then set this
nonce attribute on the <svelte:element this={'style'}> tag. This allows inline
styles to be safely used without enabling 'unsafe-inline' in CSP.
| <Drawer.Root | ||
| bind:open={() => sidebar.openMobile, (v) => sidebar.setOpenMobile(v)} | ||
| direction="left" | ||
| {...restProps} | ||
| > |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mobile Drawer ignores side, drops ref, and spreads restProps on the wrong element.
- direction is hard-coded to "left";
sideprop is ignored (regression for right-sided sidebars). refisn’t forwarded in the mobile branch anymore.{...restProps}should likely target the rendered content container (parity with desktop), not the Drawer root.
Proposed fix:
- <Drawer.Root
- bind:open={() => sidebar.openMobile, (v) => sidebar.setOpenMobile(v)}
- direction="left"
- {...restProps}
- >
+ <Drawer.Root
+ bind:open={() => sidebar.openMobile, (v) => sidebar.setOpenMobile(v)}
+ direction={side}
+ >
- <Drawer.Content
+ <Drawer.Content
+ bind:this={ref}
data-sidebar="sidebar"
data-slot="sidebar"
data-mobile="true"
- class="bg-sidebar text-sidebar-foreground !top-2 !bottom-2 !left-2 rounded-xl !border-r-0 p-0 after:hidden"
- style="--sidebar-width: {SIDEBAR_WIDTH_MOBILE}; --initial-transform: calc(100% + 8px)"
+ class={cn(
+ 'bg-sidebar text-sidebar-foreground !top-2 !bottom-2 rounded-xl !border-r-0 p-0 after:hidden',
+ side === 'left' ? '!left-2' : '!right-2'
+ )}
+ style="--sidebar-width: {SIDEBAR_WIDTH_MOBILE}; --initial-transform: calc(100% + 8px)"
+ {...restProps}
>
<Drawer.Header class="sr-only">
<Drawer.Title>Sidebar</Drawer.Title>
<Drawer.Description>Displays the mobile sidebar.</Drawer.Description>
</Drawer.Header>
<div class="flex h-full w-full flex-col">
{@render children?.()}
</div>
</Drawer.Content>
</Drawer.Root>Also applies to: 42-48, 49-53, 56-57
🤖 Prompt for AI Agents
In src/lib/components/ui/sidebar/sidebar.svelte around lines 37 to 41 and also
lines 42 to 48, 49 to 53, and 56 to 57, the mobile Drawer component incorrectly
hardcodes the direction prop to "left" instead of using the side prop, does not
forward the ref, and spreads restProps on the Drawer.Root element instead of the
content container. To fix this, replace the hardcoded direction with the side
prop, ensure the ref is forwarded properly in the mobile branch, and move the
{...restProps} spread from Drawer.Root to the content container element to
maintain parity with the desktop version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (5)
src/routes/+layout.svelte (1)
51-53: Initialize engine on client only; guard against SSR/HMR overheadConsider running the init only in the browser to avoid needless SSR work and potential HMR double-inits during dev.
Apply this diff within this block:
-void particlesInit(async (engine) => { - await loadFull(engine); -}); +if (browser) { + void particlesInit(async (engine) => { + await loadFull(engine); + }); +}Add this import outside the selected lines:
import { browser } from '$app/environment';src/routes/+page.svelte (4)
40-41: Lower FPS cap to reduce battery/CPU usage120 FPS is overkill for most displays. Cap at 60 unless explicitly needed.
- fpsLimit: 120, + fpsLimit: 60,
26-29: Remove commented-out legacy hero background markupKeep the template lean; this block is obsolete after adopting Particles.
- <!-- <div - class="hero-background absolute top-0 left-0 h-full w-full bg-[linear-gradient(to_right,var(--muted)_1px,transparent_1px),linear-gradient(to_bottom,var(--muted)_1px,transparent_1px)] [mask-image:linear-gradient(0deg,_transparent,_var(--background))] bg-[size:24px_24px]" - ></div> -->
369-384: Remove unused CSS for old backgroundThe
.hero-backgroundstyles are no longer used; safe to delete.-<style> - .hero-background { - animation-name: background; - animation-duration: 0.5s; - animation-timing-function: linear; - animation-iteration-count: infinite; - } - @keyframes background { - 0% { - background-position: 0 0; - } - 100% { - background-position: 24px 24px; - } - } -</style>
22-26: Optional: respect prefers-reduced-motionConsider disabling movement or lowering particle count when users prefer reduced motion.
Outside this block, you can set a reactive options object:
<script lang="ts"> import { onMount } from 'svelte'; let particlesOptions: any = /* current options */; onMount(() => { const reduce = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches; if (reduce) { particlesOptions = { ...particlesOptions, fpsLimit: 30, particles: { ...particlesOptions.particles, move: { ...particlesOptions.particles.move, enable: false } } }; } }); </script>Then bind it:
<Particles options={particlesOptions} ... />
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (3)
package.json(2 hunks)src/routes/+layout.svelte(2 hunks)src/routes/+page.svelte(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- package.json
🧰 Additional context used
📓 Path-based instructions (1)
**/*.*
⚙️ CodeRabbit Configuration File
**/*.*: Do not correct spelling errors or grammar mistakes.
Files:
src/routes/+layout.sveltesrc/routes/+page.svelte
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (4)
src/routes/+layout.svelte (1)
27-29: LGTM: Global tsparticles imports added appropriatelyImports of
loadFullandparticlesInitare correct for enabling engine setup.src/routes/+page.svelte (3)
9-9: LGTM: Particles component importThis enables the new hero background; looks fine.
17-19: Stopwatch & Timer route and navigation verifiedAll references and routes for
/tools/stopwatch-timerare in place:
src/routes/tools/stopwatch-timer/directory exists- Navigation entry in
src/lib/navigation.ts(lines 66–67)- Listing in
src/routes/+page.svelte(lines 17–19)No further updates needed.
1-10: Import path$lib/gmaesis valid—no broken import
The module is defined insrc/lib/gmaes.tsand allgetGameByIdreferences correctly import from$lib/gmaes. No changes are required here.Likely an incorrect or invalid review comment.
src/routes/+page.svelte
Outdated
| <Particles | ||
| id="hero-background" | ||
| class="absolute top-0 right-0 bottom-0 left-0" | ||
| options={{ | ||
| autoPlay: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Hide decorative canvas from assistive tech
Particles is purely decorative. Add aria-hidden and role="presentation" on the canvas host.
- <Particles
+ <Particles
+ aria-hidden="true"
+ role="presentation"
id="hero-background"
class="absolute top-0 right-0 bottom-0 left-0"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <Particles | |
| id="hero-background" | |
| class="absolute top-0 right-0 bottom-0 left-0" | |
| options={{ | |
| autoPlay: true, | |
| <Particles | |
| aria-hidden="true" | |
| role="presentation" | |
| id="hero-background" | |
| class="absolute top-0 right-0 bottom-0 left-0" | |
| options={{ | |
| autoPlay: true, |
🤖 Prompt for AI Agents
In src/routes/+page.svelte around lines 29 to 33, the Particles component
renders a decorative canvas that should be hidden from assistive technologies.
Add the attributes aria-hidden="true" and role="presentation" to the Particles
component or its canvas host element to ensure it is ignored by screen readers
and other assistive tools.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (3)
src/routes/g/[id]/+page.ts (1)
1-1: Add typing for load (PageLoad) to catch issues at compile-timeTyping the load function helps validate return shape and parameters.
Option A (annotation):
import { error } from '@sveltejs/kit'; +import type { PageLoad } from './$types'; -export function load({ params }) { +export const load: PageLoad = ({ params }) => { const game = getGameById(params.id); if (!game) throw error(404, 'Not Found'); return { game }; -} +};Option B (satisfies for better inference):
import { error } from '@sveltejs/kit'; import type { PageLoad } from './$types'; export const load = (({ params }) => { const game = getGameById(params.id); if (!game) throw error(404, 'Not Found'); return { game }; }) satisfies PageLoad;Also applies to: 4-4
src/lib/components/ui/button/button.svelte (1)
7-7: Corner radius mismatch: default/icon → rounded-lg, but sm/lg → rounded-md
- In
src/lib/components/ui/button/button.svelte, the base style now usesrounded-lg(line 7), but thesm(line 21) andlg(line 23) sizes still forcerounded-md.- A repo scan shows these overrides affect dozens of
buttonVariants(...)usages across routes and UI components (e.g., backup, layout, calendar, pagination, alert-dialog).Choose one for consistency or confirm mixed radii are intentional:
Option A — inherit base
rounded-lgfor all sizes:- sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5', - lg: 'h-10 rounded-md px-6 has-[>svg]:px-4', + sm: 'h-8 gap-1.5 px-3 has-[>svg]:px-2.5', + lg: 'h-10 px-6 has-[>svg]:px-4',Option B — explicitly align to
rounded-lg:- sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5', - lg: 'h-10 rounded-md px-6 has-[>svg]:px-4', + sm: 'h-8 gap-1.5 rounded-lg px-3 has-[>svg]:px-2.5', + lg: 'h-10 rounded-lg px-6 has-[>svg]:px-4',Please verify design intent or apply one of the above.
src/lib/components/play.svelte (1)
69-71: LGTM on layout tweaks; optional modernization for iframe border attributeLooks good. Minor optional tweak: frameborder is obsolete in HTML5. Prefer CSS.
- <iframe src={gmaedata?.url} frameborder="0" class="grow rounded-lg" title={gmaedata?.name} - ></iframe> + <iframe src={gmaedata?.url} class="grow rounded-lg border-0" title={gmaedata?.name}></iframe>
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/lib/components/play.svelte(4 hunks)src/lib/components/ui/button/button.svelte(1 hunks)src/routes/g/[id]/+page.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.*
⚙️ CodeRabbit Configuration File
**/*.*: Do not correct spelling errors or grammar mistakes.
Files:
src/lib/components/ui/button/button.sveltesrc/routes/g/[id]/+page.tssrc/lib/components/play.svelte
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: build
- GitHub Check: Cloudflare Pages
🔇 Additional comments (2)
src/routes/g/[id]/+page.ts (1)
2-2: No issue with import specifier in src/routes/g/[id]/+page.tsThe module at
$lib/gmaesis defined insrc/lib/gmaes.tsand indeed exportsgetGameById. The import is correct as written—there is no$lib/gamesmodule to reference. Please disregard the previous suggestion to rename the import path.Likely an incorrect or invalid review comment.
src/lib/components/play.svelte (1)
97-97: LGTM: h-fit for the controls gridThis should reduce extra whitespace and avoid forcing vertical space. No issues spotted.
| import clsx from 'clsx'; | ||
| import posthog from 'posthog-js'; | ||
| import { onMount } from 'svelte'; | ||
| import { Bug } from '@lucide/svelte'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Align Lucide import style and verify package entrypoint
Other icons in this file use the scoped icon-path import pattern. For consistency (and to avoid potential bundler/treeshaking surprises depending on your Lucide version), consider importing Bug the same way.
Apply:
-import { Bug } from '@lucide/svelte';
+import Bug from '@lucide/svelte/icons/bug';Verification script to check current usage and package versions:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Lucide scoped imports:"
rg -n "from ['\"]@lucide/svelte" || true
echo -e "\nLucide unscoped imports:"
rg -n "from ['\"]lucide-svelte" || true
echo -e "\nPackage.json Lucide versions (scoped/unscoped, deps/devDeps):"
jq -r '
.dependencies["@lucide/svelte"],
.devDependencies["@lucide/svelte"],
.dependencies["lucide-svelte"],
.devDependencies["lucide-svelte"]
' package.json 2>/dev/nullLength of output: 10129
Align Bug icon import with scoped icon-path pattern
To maintain consistency with other icons and ensure optimal tree-shaking, use the direct icon-path import for the Bug icon:
- File:
src/lib/components/play.svelte, line 26
-import { Bug } from '@lucide/svelte';
+import Bug from '@lucide/svelte/icons/bug';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { Bug } from '@lucide/svelte'; | |
| import Bug from '@lucide/svelte/icons/bug'; |
🤖 Prompt for AI Agents
In src/lib/components/play.svelte at line 26, the Bug icon is imported from
'@lucide/svelte', which is inconsistent with the scoped icon-path pattern used
for other icons. Change the import to use the direct icon-path import for the
Bug icon to maintain consistency and improve tree-shaking.
| <Button | ||
| variant="outline" | ||
| href="https://github.com/EducationalTools/src/issues/new?template=bug_report.yml" | ||
| target="_blank" | ||
| > | ||
| <Bug /> | ||
| Report Bug | ||
| </Button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Add rel='noopener noreferrer' for security; also ensure Button supports href
Opening a new tab without rel can expose window.opener (reverse tabnabbing). Add rel. Also, if Button doesn’t natively support href, use an with buttonVariants.
Apply:
- <Button
- variant="outline"
- href="https://github.com/EducationalTools/src/issues/new?template=bug_report.yml"
- target="_blank"
- >
- <Bug />
- Report Bug
- </Button>
+ <Button
+ variant="outline"
+ href="https://github.com/EducationalTools/src/issues/new?template=bug_report.yml"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ <Bug class="h-6 w-6" />
+ Report Bug
+ </Button>If Button lacks href support, swap to:
<a
href="https://github.com/EducationalTools/src/issues/new?template=bug_report.yml"
target="_blank"
rel="noopener noreferrer"
class={buttonVariants({ variant: 'outline' })}
>
<Bug class="h-6 w-6" />
Report Bug
</a>Optional check to confirm the repo slug matches this project’s remote:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
REMOTE="$(git remote get-url origin 2>/dev/null || echo '')"
echo "Origin remote: $REMOTE"
# Extract owner/repo if GitHub-style
SLUG="$(sed -E 's#.*github.com[:/ ]([^/]+/[^/.]+)(\.git)?#\1#;t;d' <<<"$REMOTE" || true)"
echo "Detected slug: $SLUG"
echo "Configured bug-report URL slug: EducationalTools/src"
if [[ "$SLUG" != "EducationalTools/src" ]]; then
echo "Note: The bug-report URL points to EducationalTools/src, which differs from the detected slug: $SLUG"
echo "Please confirm this is intentional."
fiLength of output: 587
Add rel="noopener noreferrer" to external-link Button
Verified that the GitHub remote slug (EducationalTools/src) matches the configured URL and that our <Button> component accepts an href prop. Update the component in src/lib/components/play.svelte (lines 174–181) as follows:
- <Button
- variant="outline"
- href="https://github.com/EducationalTools/src/issues/new?template=bug_report.yml"
- target="_blank"
- >
- <Bug />
- Report Bug
- </Button>
+ <Button
+ variant="outline"
+ href="https://github.com/EducationalTools/src/issues/new?template=bug_report.yml"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ <Bug class="h-6 w-6" />
+ Report Bug
+ </Button>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <Button | |
| variant="outline" | |
| href="https://github.com/EducationalTools/src/issues/new?template=bug_report.yml" | |
| target="_blank" | |
| > | |
| <Bug /> | |
| Report Bug | |
| </Button> | |
| <Button | |
| variant="outline" | |
| href="https://github.com/EducationalTools/src/issues/new?template=bug_report.yml" | |
| target="_blank" | |
| rel="noopener noreferrer" | |
| > | |
| <Bug class="h-6 w-6" /> | |
| Report Bug | |
| </Button> |
🤖 Prompt for AI Agents
In src/lib/components/play.svelte around lines 174 to 181, the external link
Button lacks the rel="noopener noreferrer" attribute, which is important for
security and performance when using target="_blank". Add rel="noopener
noreferrer" to the Button component to ensure safe handling of the external
link.
| export function load({ url }) { | ||
| let gmae = getGameById(url.pathname.split('/').slice(2).join('/')); | ||
| if (!gmae) throw error(404, 'Not Found'); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
load must return serializable data; use params.id instead of parsing URL
SvelteKit provides route params; parsing url.pathname is brittle. Also, the function currently returns nothing.
Apply this diff:
-export function load({ url }) {
- let gmae = getGameById(url.pathname.split('/').slice(2).join('/'));
- if (!gmae) throw error(404, 'Not Found');
-}
+export function load({ params }) {
+ const game = getGameById(params.id);
+ if (!game) throw error(404, 'Not Found');
+ return { game };
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function load({ url }) { | |
| let gmae = getGameById(url.pathname.split('/').slice(2).join('/')); | |
| if (!gmae) throw error(404, 'Not Found'); | |
| } | |
| export function load({ params }) { | |
| let game = getGameById(params.id); | |
| if (!game) throw error(404, 'Not Found'); | |
| return { game }; | |
| } |
🤖 Prompt for AI Agents
In src/routes/g/[id]/+page.ts around lines 4 to 7, the load function incorrectly
parses the URL pathname to get the game ID and does not return any data. Replace
the URL parsing with using the provided params.id to get the game ID, and ensure
the function returns a serializable object containing the game data or throws a
404 error if not found.
Summary by CodeRabbit
New Features
Improvements
Chores