Skip to content

fix: lint error free#1854

Merged
shinokada merged 5 commits intothemesberg:mainfrom
shinokada:lint-fix
Nov 25, 2025
Merged

fix: lint error free#1854
shinokada merged 5 commits intothemesberg:mainfrom
shinokada:lint-fix

Conversation

@shinokada
Copy link
Copy Markdown
Collaborator

@shinokada shinokada commented Nov 24, 2025

🔗 Related issue (optional)

Closes #


📑 Description


🔍 PR Type

  • Bug fix
  • Feature
  • Documentation
  • Refactor / Code cleanup
  • Build / Tooling
  • Other (please describe)

🚦 PR Status

  • Draft (work in progress, not ready for review)
  • Ready for review ✅

✅ Checklist

  • My code follows the existing code style
  • I have run pnpm check && pnpm test:e2e and all tests pass
  • CoderabbitAI review has been completed and actionable suggestions were reviewed
  • I have updated documentation if my changes require it
  • My PR is based on the latest main branch (not the published npm version)
  • I have checked accessibility where applicable (ARIA, keyboard nav, etc.)
  • I have reviewed the rendered component in the browser

🧪 Screenshots / Demos (optional)


⚠️ Breaking Changes (optional)


ℹ️ Additional Information

Summary by CodeRabbit

  • Refactor

    • Improved type safety and added optional id fields to item types.
    • Stabilized list rendering by adding keys across many components.
    • Narrowed event/handler typings and tightened several internal signatures.
    • Dropdown item rendering now prefers link → button → container; export path adjusted for UI helpers.
  • Chores

    • Expanded lint ignore patterns and disabled a few lint rules.
    • Lint workflow now runs formatting as a pre-step.
    • Build config adjusted to skip pre-bundling one dependency.
    • PR template checklist updated to run linting earlier.
  • Documentation

    • Local setup adds a command to copy latest docs; markdown loader enforces required metadata.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown

vercel bot commented Nov 24, 2025

@shinokada is attempting to deploy a commit to the Themesberg Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Nov 24, 2025

Walkthrough

Adds stable keys to many Svelte {#each} blocks, tightens TypeScript typings and public types, changes DropdownItem props/rendering and markdown loader validation, expands ESLint ignores/rules, prepends a formatting step to lint, and excludes flowbite-svelte from Vite optimizeDeps.

Changes

Cohort / File(s) Summary
Build & Linting
eslint.config.js, package.json, vite.config.ts
Expanded ESLint ignores list and disabled additional rules; lint script now runs pnpm format before prettier & eslint; added optimizeDeps.exclude: ["flowbite-svelte"] to Vite config.
Keyed list rendering (many components)
src/lib/carousel/Carousel.svelte, src/lib/carousel/CarouselIndicators.svelte, src/lib/carousel/Thumbnails.svelte, src/lib/gallery/Gallery.svelte, src/lib/datepicker/Datepicker.svelte, src/lib/rating/*, src/lib/skeleton/ListPlaceholder.svelte, src/lib/stepper/*, src/lib/step-indicator/StepIndicator.svelte, src/lib/table/TableBody.svelte, src/lib/table/TableHead.svelte, src/lib/pagination/*, src/lib/forms/*, src/lib/timeline/*, src/lib/mega-menu/MegaMenu.svelte, src/lib/list-group/Listgroup.svelte
Added explicit keys to many {#each} blocks (various key expressions: image.src, idx, item.value, time, step.id, i, etc.). Minor related refactors (e.g., Listgroup click handler no longer passes item).
Dropdown, docs, and loader
src/lib/dropdown/DropdownItem.svelte, src/routes/docs-examples/components/dropdown/Events.svelte, src/routes/utils/markdown-loader.ts
DropdownItem now imports DropdownItemProps from $lib/types, accepts href and onclick, and renders anchor → button → div branches; event example narrows to MouseEvent; markdown loader enforces title and dir and returns structured metadata.
Types & public API shapes
src/lib/types.ts, src/lib/index.ts
Added optional `id?: string
Utilities & typing refinements
src/lib/uiHelpers.svelte.ts, src/lib/utils/Popper.svelte, src/lib/utils/debounce.ts, src/lib/utils/Arrow.svelte
Tightened clickOutside signatures and update method types; narrowed Popper event-handler type; changed debounce helper argument/return types toward unknown; suppressed unused-import warnings in Arrow.svelte.
Small typing / minor logic changes
src/lib/navbar/NavLi.svelte, src/lib/navbar/NavUl.svelte, src/lib/forms/select/MultiSelect.svelte, src/lib/forms/select/Select.svelte, src/lib/forms/floating-label/FloatingLabelInput.svelte, src/lib/forms/tags/Tags.svelte, src/lib/forms/timepicker/Timepicker.svelte, src/lib/dialog/Dialog.svelte
Narrowed event and function parameter types, adjusted generics (SelectOptionType<T>), removed a ts-ignore in Dialog.cancel(), added keys to several lists, and other small API-surface refinements.

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant DropdownItem
  Browser->>DropdownItem: render(props)
  alt props.href defined
    Note right of DropdownItem `#bbf0d6`: anchor branch (href)
    DropdownItem->>Browser: output <a href=...>
  else props.onclick defined
    Note right of DropdownItem `#fff1b6`: button branch (onclick)
    DropdownItem->>Browser: output <button onclick=...>
  else
    Note right of DropdownItem `#f0e6ff`: default branch (div)
    DropdownItem->>Browser: output <div ...>
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Areas to inspect carefully:

  • src/lib/types.ts — many public type changes (new id fields, new DropdownItemProps, narrowed signatures).
  • src/lib/dropdown/DropdownItem.svelte — rendering branches (anchor → button → div) and prop precedence.
  • src/lib/list-group/Listgroup.svelte — click handler no longer receives item; verify consumers.
  • src/lib/uiHelpers.svelte.ts, src/lib/utils/Popper.svelte, src/lib/utils/debounce.ts — tightened signatures may surface type errors.

Possibly related PRs

Poem

🐰
I hopped through lists and tucked each key in place,
I tightened types and left not a loose trace.
I split the dropdown path — anchor, button, then div,
A tidy little hop so the build may live. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is incomplete and largely empty. The template is present but not filled in—no description of changes, no related issue linked, and only one PR type is selected with no additional context explaining what lint errors were fixed or why. Fill in the description section detailing which lint errors were fixed, why these changes were necessary, and provide context for the refactoring. Link a related issue if applicable.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: lint error free' clearly describes the main change as a linting fix/cleanup, which aligns with the refactor/cleanup classification and the extensive modifications throughout the codebase addressing lint issues.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30c4a0d and a525c06.

📒 Files selected for processing (1)
  • .github/pull_request_template.md (1 hunks)
🔇 Additional comments (1)
.github/pull_request_template.md (1)

45-45: No issues identified. The lint command is properly defined and sequenced.

Verification confirms:

  • lint script exists and is correctly defined: pnpm format && prettier --check . && eslint .
  • check script exists: svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
  • test:e2e script exists: playwright test
  • ✅ Command sequence is logical and achieves the lint-first workflow objective

The addition of pnpm lint to line 45 of the PR template properly guides contributors through the correct pre-submission workflow.


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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/lib/forms/tags/Tags.svelte (1)

172-179: Use tag value as key instead of index.

Using index as the key can cause incorrect DOM reconciliation when tags are deleted. Since deleteField removes items from the array, the remaining tags shift indices, and Svelte may incorrectly reuse DOM nodes.

Apply this diff:

-  {#each value as tag, index (index)}
+  {#each value as tag, index (tag)}

Note: This assumes tag values are unique. If duplicate tags are allowed (when unique=false), consider using a combination like (tag + '-' + index) or refactoring to use objects with stable IDs.

src/lib/stepper/ProgressStepper.svelte (1)

8-8: Typo in variable name.

The variable name restrorps should likely be restProps (note the transposed letters).

-let { children, steps = [], class: className, classes, ...restrorps }: ProgressStepperProps = $props();
+let { children, steps = [], class: className, classes, ...restProps }: ProgressStepperProps = $props();

Also update line 17:

-<ol class={base({ class: clsx(theme?.base, className) })} {...restrorps}>
+<ol class={base({ class: clsx(theme?.base, className) })} {...restProps}>
🧹 Nitpick comments (13)
src/lib/rating/AdvancedRating.svelte (1)

34-41: Keyed each-block looks good; consider label as key if lists can reorder

Using an index key here is fine and an improvement over an unkeyed loop. If ratings can be reordered or items inserted/removed dynamically and label is unique and stable, you could make DOM diffing a bit more robust (and consistent with ScoreRating.svelte) by keying on label instead:

-{#each ratings as { label, rating }, i (i)}
+{#each ratings as { label, rating } (label)}

Purely optional; current change is acceptable as-is.

src/lib/rating/Rating.svelte (1)

29-39: Keyed star loops are fine; you can simplify key choice if desired

Adding keys to the full and gray star loops looks good and shouldn’t change behavior. Given these stars are purely positional, you could simplify the first loop’s key to match the second one if you don’t need the rating component in the key:

-    {#each Array(fullStars) as _, i (i + rating)}
+    {#each Array(fullStars) as _, i (i)}

This keeps things a bit more uniform while still satisfying keyed-each requirements. Not strictly necessary, the current form is valid.

src/lib/mega-menu/MegaMenu.svelte (1)

20-20: Consider using a stable identifier if available.

Using the index as a key works for static lists. If items can be reordered or if each item has a unique identifier property, consider using that instead for more reliable DOM reconciliation.

src/lib/utils/Arrow.svelte (1)

10-12: Valid approach to suppress import warnings.

The void prefix pattern explicitly suppresses unused import warnings while keeping the functions available for the $effect block at line 33. This is a clear way to communicate intent.

Alternative approach if preferred:

-  // Prevent unused import warnings - these functions are used in the $effect below
-  void getSide;
-  void getOppositePlacement;
+  // eslint-disable-next-line @typescript-eslint/no-unused-vars
src/lib/forms/floating-label/FloatingLabelInput.svelte (1)

196-206: Consider using suggestion text as key instead of index.

Using (i) as the key may cause DOM reuse issues when the filtered suggestions change. Since suggestion strings should be unique within the filtered list, using (item) would provide more stable DOM reconciliation.

Apply this diff:

-      {#each filteredSuggestions as item, i (i)}
+      {#each filteredSuggestions as item, i (item)}

The index variable i will still work correctly for the selectedIndex logic—keys only affect DOM node identity, not the iteration index values.

src/lib/timeline/ActivityItem.svelte (1)

40-40: Consider using a stable identifier instead of index as key.

Using the index (i) as a key can cause issues if the activities array is reordered, filtered, or has items inserted/removed. If each activity has a unique stable identifier (e.g., id), use that instead for more reliable DOM reconciliation.

If activities have an id field, apply this pattern:

-{#each activities as { title: name, date, src, alt, text: activity }, i (i)}
+{#each activities as { title: name, date, src, alt, text: activity, id } (id)}
src/lib/timeline/GroupItem.svelte (1)

34-34: Consider using a stable identifier instead of index as key.

Using the index (i) as a key can cause rendering issues if the timelines array is reordered, filtered, or has items inserted/removed. If each timeline has a unique stable identifier (e.g., id or href if unique), use that instead.

If timelines have an id field, apply this pattern:

-{#each timelines as { name, src, alt, isPrivate, href, comment }, i (i)}
+{#each timelines as { name, src, alt, isPrivate, href, comment, id } (id)}

Or if href is unique:

-{#each timelines as { name, src, alt, isPrivate, href, comment }, i (i)}
+{#each timelines as { name, src, alt, isPrivate, href, comment } (href)}
src/lib/stepper/ProgressStepper.svelte (1)

21-21: Consider using a stable identifier instead of index as key.

Using (index) as a key can cause issues if the steps array is reordered or dynamically modified. If each step has a unique stable identifier like step.id, use that instead for reliable DOM reconciliation.

If steps have an id field:

-{#each steps as step, index (index)}
+{#each steps as step, index (step.id)}
src/lib/table/TableBody.svelte (1)

20-22: Index-based keys may cause issues with table sorting/filtering.

Using index keys (i) and (j) for table rows and cells can lead to incorrect rendering when rows are sorted, filtered, or reordered—common operations in data tables. Consider using stable identifiers from the data.

If rows have unique identifiers, use them:

-{#each bodyItems as row, i (i)}
+{#each bodyItems as row (row.id || JSON.stringify(row))}
   <TableBodyRow>
-    {#each getCellValues(row) as cellValue, j (j)}
+    {#each getCellValues(row) as cellValue, j (j)}
       <TableBodyCell>{cellValue ?? ""}</TableBodyCell>
     {/each}
   </TableBodyRow>
{/each}

Note: For the inner loop over cells, (j) may be acceptable if cell order is truly static, but the outer row key is more critical.

src/lib/carousel/Carousel.svelte (1)

183-188: Keyed preload loop aligns with DOM diffing best practices

Using (image.src) as the key in the preload each-block improves reconciliation and matches the keyed patterns elsewhere in the PR. As long as src is stable/unique per image, this is a solid choice.

src/lib/navbar/NavUl.svelte (1)

35-41: Stronger typing for getDefaultParams, but confirm custom transition support

Narrowing getDefaultParams to typeof slide | typeof fly | typeof fade | typeof scale matches the internal branching and improves type safety. However, this also means any custom transition function passed via transition will now be rejected by TypeScript even though the runtime fallback branch still exists.

If consumers are expected to use only these built-in transitions, this is fine. If custom transitions should remain supported, consider widening the parameter type (e.g., to the full transition function type) while still special-casing these four by reference equality.

src/lib/stepper/TimelineStepper.svelte (1)

21-49: Keyed steps loop improves stability; index key acceptable with stable ordering

Adding (index) to the each steps block gives Svelte a stable key for DOM reconciliation, which is good. Using the index as the key works well as long as the steps array is only appended/trimmed and not frequently reordered; if reordering is a real use case, consider a stable step.id-style key instead.

src/lib/pagination/Pagination.svelte (1)

33-39: Keyed pages loop improves reconciliation; consider ID key if available

Adding (i) to the each pages block gives Svelte a stable key, which is an improvement over an unkeyed loop. If pages can be reordered or spliced in the middle, and if an intrinsic identifier (e.g., page.id or href) exists and is stable, using that as the key would further reduce DOM churn.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b010f7 and f6865c2.

📒 Files selected for processing (41)
  • eslint.config.js (1 hunks)
  • package.json (1 hunks)
  • src/lib/carousel/Carousel.svelte (1 hunks)
  • src/lib/carousel/CarouselIndicators.svelte (1 hunks)
  • src/lib/carousel/Thumbnails.svelte (1 hunks)
  • src/lib/datepicker/Datepicker.svelte (2 hunks)
  • src/lib/dialog/Dialog.svelte (0 hunks)
  • src/lib/forms/floating-label/FloatingLabelInput.svelte (1 hunks)
  • src/lib/forms/select/MultiSelect.svelte (4 hunks)
  • src/lib/forms/select/Select.svelte (1 hunks)
  • src/lib/forms/tags/Tags.svelte (2 hunks)
  • src/lib/forms/timepicker/Timepicker.svelte (2 hunks)
  • src/lib/gallery/Gallery.svelte (1 hunks)
  • src/lib/list-group/Listgroup.svelte (1 hunks)
  • src/lib/mega-menu/MegaMenu.svelte (1 hunks)
  • src/lib/navbar/NavLi.svelte (1 hunks)
  • src/lib/navbar/NavUl.svelte (1 hunks)
  • src/lib/pagination/Pagination.svelte (1 hunks)
  • src/lib/pagination/PaginationNav.svelte (1 hunks)
  • src/lib/rating/AdvancedRating.svelte (1 hunks)
  • src/lib/rating/Rating.svelte (1 hunks)
  • src/lib/rating/ScoreRating.svelte (2 hunks)
  • src/lib/skeleton/ListPlaceholder.svelte (1 hunks)
  • src/lib/step-indicator/StepIndicator.svelte (1 hunks)
  • src/lib/stepper/BreadcrumbStepper.svelte (1 hunks)
  • src/lib/stepper/DetailedStepper.svelte (1 hunks)
  • src/lib/stepper/ProgressStepper.svelte (1 hunks)
  • src/lib/stepper/Stepper.svelte (1 hunks)
  • src/lib/stepper/TimelineStepper.svelte (1 hunks)
  • src/lib/stepper/VerticalStepper.svelte (1 hunks)
  • src/lib/table/TableBody.svelte (1 hunks)
  • src/lib/table/TableHead.svelte (1 hunks)
  • src/lib/timeline/ActivityItem.svelte (1 hunks)
  • src/lib/timeline/GroupItem.svelte (1 hunks)
  • src/lib/types.ts (4 hunks)
  • src/lib/uiHelpers.svelte.ts (2 hunks)
  • src/lib/utils/Arrow.svelte (1 hunks)
  • src/lib/utils/Popper.svelte (1 hunks)
  • src/lib/utils/debounce.ts (2 hunks)
  • src/routes/docs-examples/components/dropdown/Events.svelte (1 hunks)
  • src/routes/utils/markdown-loader.ts (2 hunks)
💤 Files with no reviewable changes (1)
  • src/lib/dialog/Dialog.svelte
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2024-11-22T08:37:27.996Z
Learnt from: mrh1997
Repo: themesberg/flowbite-svelte PR: 1442
File: src/lib/utils/Popper.svelte:144-145
Timestamp: 2024-11-22T08:37:27.996Z
Learning: In `src/lib/utils/Popper.svelte`, inconsistencies in event handling (e.g., using both `mouseenter`/`mouseleave` and `pointerenter`/`pointerleave`) may be intentional to minimize modifications and reduce the risk of new problems.

Applied to files:

  • src/lib/navbar/NavLi.svelte
  • src/lib/utils/Arrow.svelte
  • src/lib/utils/Popper.svelte
  • src/lib/uiHelpers.svelte.ts
  • src/routes/docs-examples/components/dropdown/Events.svelte
  • src/lib/list-group/Listgroup.svelte
📚 Learning: 2025-09-04T10:33:41.720Z
Learnt from: jjagielka
Repo: themesberg/flowbite-svelte PR: 1751
File: src/lib/tabs/TabItem.svelte:33-33
Timestamp: 2025-09-04T10:33:41.720Z
Learning: In Svelte 5, DOM event handlers should use function props like `onclick`, `onchange`, `oninput` etc. The `on:click`, `on:change` syntax from previous Svelte versions is deprecated/obsolete in Svelte 5.

Applied to files:

  • src/lib/navbar/NavLi.svelte
  • src/routes/docs-examples/components/dropdown/Events.svelte
📚 Learning: 2025-11-03T10:08:17.733Z
Learnt from: jjagielka
Repo: themesberg/flowbite-svelte PR: 1819
File: src/lib/tour/Tour.svelte:21-24
Timestamp: 2025-11-03T10:08:17.733Z
Learning: In Svelte 5 components, custom event handler props should follow the lowercase naming convention (e.g., `oncomplete`, `onskip`, `onopen`) rather than camelCase (e.g., `onComplete`, `onSkip`, `onOpen`), consistent with DOM event handlers like `onclick`, `onchange`, etc.

Applied to files:

  • src/lib/navbar/NavLi.svelte
  • src/routes/docs-examples/components/dropdown/Events.svelte
📚 Learning: 2024-10-18T09:38:03.879Z
Learnt from: Chizaruu
Repo: themesberg/flowbite-svelte PR: 1465
File: src/lib/forms/Timepicker.svelte:105-116
Timestamp: 2024-10-18T09:38:03.879Z
Learning: In `Timepicker.svelte`, the `Dropdown` opens as intended and is used exclusively with the 'dropdown' and 'timerange-dropdown' Timepicker types.

Applied to files:

  • src/routes/docs-examples/components/dropdown/Events.svelte
  • src/lib/forms/timepicker/Timepicker.svelte
📚 Learning: 2025-08-31T14:31:57.582Z
Learnt from: jjagielka
Repo: themesberg/flowbite-svelte PR: 1745
File: src/lib/forms/checkbox/CheckboxButton.svelte:16-17
Timestamp: 2025-08-31T14:31:57.582Z
Learning: In Svelte 5, the `on:event` syntax for event forwarding is obsolete. Event handlers are passed as callback props (e.g., `onchange`, `oninput`) through `{...restProps}` instead of using `on:change`, `on:input` etc.

Applied to files:

  • src/routes/docs-examples/components/dropdown/Events.svelte
📚 Learning: 2025-08-31T13:01:17.658Z
Learnt from: jjagielka
Repo: themesberg/flowbite-svelte PR: 1745
File: src/lib/forms/checkbox/Checkbox.svelte:22-27
Timestamp: 2025-08-31T13:01:17.658Z
Learning: createEventDispatcher is deprecated in Svelte 5. Components should use callback props instead of event dispatchers for event handling.

Applied to files:

  • src/routes/docs-examples/components/dropdown/Events.svelte
🔇 Additional comments (33)
src/lib/rating/ScoreRating.svelte (1)

34-46: Good use of keyed each-blocks with label

Keying both ratings and ratings2 by label is a solid choice and should give stable DOM reconciliation, assuming labels are unique within each list. No behavioral regressions here; just improved diffing.

If there’s any chance of duplicate labels within the same list, it’s worth double‑checking that upstream to keep keys unique and avoid surprising updates.

Also applies to: 51-63

src/lib/skeleton/ListPlaceholder.svelte (1)

17-17: LGTM! Appropriate use of index key for static placeholders.

Using the index as a key is suitable here since the items are purely presentational placeholders generated from a count, with no reordering or dynamic updates expected.

src/lib/step-indicator/StepIndicator.svelte (1)

48-48: LGTM! Index key is acceptable for typical step indicator usage.

Using the index as a key works well for step indicators where the steps array is typically static. If steps become more dynamic (reordering, additions, removals), consider using stable identifiers instead.

src/lib/table/TableHead.svelte (1)

35-35: LGTM! Index key is appropriate for table headers.

Table header items are typically static configurations, so using the index as a key is reasonable and provides the benefits of keyed iteration for DOM reconciliation.

src/lib/forms/select/Select.svelte (1)

66-66: Excellent! Using stable identifier as key.

Using item.value as the key is the correct approach for select options. This ensures proper DOM reconciliation when items are added, removed, or reordered.

src/lib/stepper/DetailedStepper.svelte (1)

21-21: Excellent! Using stable identifier as key.

Using step.id as the key is the correct approach for stepper items. This ensures proper DOM reconciliation and component state preservation when steps are updated.

src/lib/stepper/VerticalStepper.svelte (1)

21-21: Excellent! Using stable identifier as key.

Using step.id as the key is the correct approach and maintains consistency with other stepper components in the codebase.

src/lib/carousel/Thumbnails.svelte (1)

34-34: LGTM: Keyed iteration improves DOM reconciliation.

The explicit key (image.src || idx) is well-chosen—src provides stable identity for images, with index as a sensible fallback.

src/lib/forms/tags/Tags.svelte (1)

196-212: LGTM: Using suggestion text as key is appropriate.

Since filteredSuggestions are unique strings that get filtered (not reordered), using (suggestion) as the key provides stable identity.

src/lib/gallery/Gallery.svelte (1)

28-38: LGTM: Appropriate key for gallery items.

The key (item.src || i) uses the image source as a stable identifier with index fallback, ensuring proper DOM reconciliation.

src/lib/forms/timepicker/Timepicker.svelte (2)

248-252: LGTM: Using option.value as key is appropriate.

The option.value provides a unique, stable identifier for dropdown options.


398-402: LGTM: Using time string as key is appropriate.

Time strings (e.g., "00:00") serve as unique identifiers for inline button options.

src/lib/forms/select/MultiSelect.svelte (4)

48-67: LGTM: Type safety improvement from any to generic T.

Replacing SelectOptionType<any> with SelectOptionType<T> provides better type checking and inference.


83-94: LGTM: Consistent use of generic type T.

The signature and filter operation now use the correct generic type instead of any.


109-109: LGTM: More specific event type.

Casting to Event instead of any improves type safety.


201-203: LGTM: Using item.value as key is appropriate.

The value property provides a unique identifier for select items, ensuring proper DOM reconciliation.

src/lib/datepicker/Datepicker.svelte (3)

463-474: LGTM: Index is stable for fixed month array.

Since monthNames is a fixed 12-element array that never reorders, using (index) as the key is appropriate.


490-492: LGTM: Weekday names as keys are stable.

The weekday strings (e.g., "Mon", "Tue") provide unique, stable identifiers for this fixed-order list.


493-516: LGTM: Date objects provide unique identity.

Using Date objects as keys works because Svelte compares by object identity, and getDaysInMonth creates fresh Date instances for each calendar render.

src/lib/stepper/BreadcrumbStepper.svelte (1)

22-22: LGTM! Good use of stable key.

Using step.id as the key is the correct approach for list rendering. This ensures proper DOM reconciliation when steps are reordered or modified.

package.json (1)

24-24: Verify lint script workflow intention.

The lint script now runs pnpm format (which writes files) before prettier --check (which only checks). This means formatting is automatically applied before checking, so prettier --check will always pass.

If the goal is to enforce formatting without auto-fixing, remove pnpm format. If the goal is to auto-format then check other aspects, this is correct but consider renaming to "lint:fix" or similar for clarity.

Typical patterns:

  • Check-only: prettier --check . && eslint .
  • Auto-fix: prettier --write . && eslint . --fix

Which workflow is intended here?

src/routes/utils/markdown-loader.ts (2)

34-34: Improved type safety with explicit cast.

The parenthesized type assertion (await filesMap[filePath]()) as MarkdownModule ensures proper typing of the imported markdown module.


43-57: Change is compatible with all consumers—verification confirms no breaking issues.

All 9 page components that use this loader access only data.content. None of them reference data.title, data.dir, or any other properties from the return value. The new return structure { content, title, dir } is compatible with current usage patterns.

src/lib/utils/Popper.svelte (1)

178-178: LGTM! Improved type safety.

Tightening the event handler type from any to (ev: Event) => void removes unnecessary use of any and provides better type checking without changing runtime behavior.

src/lib/list-group/Listgroup.svelte (1)

31-31: LGTM!

Adding a keyed each block improves DOM reconciliation and aligns with the broader pattern of keyed iterations across the codebase.

src/lib/utils/debounce.ts (1)

16-48: LGTM!

The type safety improvements replace any with unknown for return types and internal parameters. The eslint-disable comment is appropriately scoped for the unavoidable any[] in the generic function parameters. The public API remains unchanged, and these internal changes improve type safety without affecting runtime behavior.

eslint.config.js (1)

34-62: LGTM!

The ESLint configuration updates are well-justified:

  • The expanded ignores appropriately exclude SvelteKit-specific files while preserving docs-examples for linting.
  • The Svelte 5 runes file exclusions address known parser limitations.
  • The new rule disables are appropriate for a component library context and align with common patterns in the codebase.
src/lib/types.ts (2)

246-246: LGTM!

The type tightening changes improve type safety:

  • dot: object → Record<string, unknown> provides better type information
  • params: object → ParamsType ensures consistency with transition parameter types
  • onchange: {} → void corrects what appears to be an unintended empty object literal

Also applies to: 272-272, 423-423


196-196: No issues found — the onclick signature change is safe.

After verification, the onclick type change from Function to () => void aligns with actual component usage. The AnchorButtonDivAttributes type is used exclusively by DropdownItem, which simply spreads the props without calling the handler. All onclick handlers in the codebase follow the () => void pattern (direct function references or arrow functions with no parameters), and no code attempts to pass MouseEvent or other parameters to onclick handlers.

src/lib/uiHelpers.svelte.ts (1)

30-56: LGTM!

The explicit TypeScript type annotations improve type safety throughout the clickOutside function. The cast of event.target to Node on line 33 is appropriate for the contains check, and all changes preserve the existing runtime behavior.

src/lib/carousel/CarouselIndicators.svelte (1)

22-22: LGTM!

Adding a keyed each block using the index improves DOM reconciliation and aligns with the consistent pattern of keyed iterations throughout this PR.

src/lib/stepper/Stepper.svelte (1)

21-21: LGTM!

Adding a keyed each block using the index improves DOM reconciliation and is consistent with the keyed iteration pattern applied across stepper components in this PR.

src/lib/pagination/PaginationNav.svelte (1)

88-94: Good use of keyed each for page numbers

Using (page) as the key for pageNumbers is appropriate here—page numbers are unique in the rendered range and this will make updates (e.g., current page shifts) more predictable for Svelte’s diffing.

Comment on lines +20 to 31
function handleClick(event: MouseEvent) {
// Close the mobile menu when a link is clicked
if (restProps.href !== undefined && !navState.hidden) {
navState.hidden = true;
}

// Call original onclick handler if provided
if (onclick) {
onclick(event);
// Cast to appropriate event type for the handler
onclick(event as never);
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove the unsafe type cast to never.

While tightening the event parameter type from any to MouseEvent is good (line 20), casting the event to never on line 29 is problematic:

  • The never type represents values that never occur and is used to suppress type errors rather than fix them.
  • This defeats TypeScript's type safety and hides potential type mismatches.
  • According to the learnings, Svelte 5 uses lowercase event handler props like onclick that should accept standard DOM event types.

Root cause: The NavLiProps type likely defines onclick with a signature that doesn't match MouseEvent. Check the type definition and either:

  1. Update NavLiProps.onclick to accept (event: MouseEvent) => void, or
  2. If a different signature is needed, cast to the correct type instead of never

Apply this diff to remove the unsafe cast:

   // Call original onclick handler if provided
   if (onclick) {
-    // Cast to appropriate event type for the handler
-    onclick(event as never);
+    onclick(event);
   }

Then verify or fix the type definition in src/lib/types.ts for NavLiProps.

📝 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.

Suggested change
function handleClick(event: MouseEvent) {
// Close the mobile menu when a link is clicked
if (restProps.href !== undefined && !navState.hidden) {
navState.hidden = true;
}
// Call original onclick handler if provided
if (onclick) {
onclick(event);
// Cast to appropriate event type for the handler
onclick(event as never);
}
}
function handleClick(event: MouseEvent) {
// Close the mobile menu when a link is clicked
if (restProps.href !== undefined && !navState.hidden) {
navState.hidden = true;
}
// Call original onclick handler if provided
if (onclick) {
onclick(event);
}
}
🤖 Prompt for AI Agents
In src/lib/navbar/NavLi.svelte around lines 20-31, remove the unsafe cast to
`never` when calling `onclick` and instead pass the original MouseEvent; then
update the NavLiProps definition (likely in src/lib/types.ts) so `onclick` is
typed as `(event: MouseEvent) => void` (or the correct DOM event type you need)
so the call can be `onclick(event)` without casting; if a different event
signature is required, change the prop type to that exact signature and use that
type when invoking the handler.

Copy link
Copy Markdown
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: 1

🧹 Nitpick comments (7)
src/lib/stepper/Stepper.svelte (1)

20-47: Keying by optional step.id can cause unstable updates when id is missing

{#each steps as step, index (step.id)} assumes step.id is present and unique, but Step.id is optional. If callers omit id or reuse it, Svelte will treat multiple items as having the same key (or undefined), which can lead to odd DOM reuse when steps changes (reordering, insertion, removal).

Consider either:

  • Making id effectively required for Step (and documenting it), or
  • Using a fallback key, e.g. (step.id ?? index) or similar, to preserve stable behavior for existing consumers who don’t pass id.
src/lib/pagination/Pagination.svelte (1)

33-39: Href‑based key is fragile when href is optional or duplicated

Keying pages as {#each pages as { name, href, active, size } (href)} assumes every item has a unique href. Since href is optional, items without it will share the same undefined key, and repeated hrefs will also collide, which can cause DOM reuse issues when pages changes.

Either:

  • Treat href as required/unique for pages and document that expectation, or
  • Use a composite/fallback key, e.g. destructure the item as page, index and key (page.href ?? String(index)).
src/lib/timeline/ActivityItem.svelte (1)

40-59: Optional ActivityType.id + (id) key can lead to key collisions

The loop {#each activities as { title: name, date, src, alt, text: activity, id } (id)} keys solely on id, but ActivityType.id is optional. When id is missing or reused, multiple items share the same key (or undefined), which can confuse Svelte’s diffing if activities is updated.

Either require id for activities passed to this component, or add a fallback key (e.g. (id ?? src ?? index)) so existing callers without ids don’t see subtle update issues.

src/lib/timeline/GroupItem.svelte (1)

34-71: Keying timelines solely by optional id risks unstable DOM reuse

{#each timelines as { name, src, alt, isPrivate, href, comment, id } (id)} uses id as the only key, but GroupTimelineType.id is optional. When it’s omitted or duplicated, Svelte will reuse DOM nodes under a shared key, which can misalign content if timelines changes.

Consider either:

  • Treating id as required/unique for timelines, or
  • Using a safer key like (id ?? href ?? name ?? index) (adjusting the each signature to get index if needed).
src/lib/dropdown/DropdownItem.svelte (1)

6-50: DropdownItem href/onclick behavior and docs look solid; simplify finalClass

The new props typing, isActive guard, and branching order (href → button with onclick → plain <div>) align well with the documented API and with how other anchor/button/div unions are modeled.

One nit: finalClass is currently a single‑element array, which then gets bound directly to class. Svelte will stringify it, but a plain string is clearer and better matches expected types:

-  let finalClass = $derived([
-    isActive 
-      ? active({ class: clsx(theme?.active, styling.active) }) 
-      : base({ class: clsx(theme?.base, className) })
-  ]);
+  let finalClass = $derived(
+    isActive
+      ? active({ class: clsx(theme?.active, styling.active) })
+      : base({ class: clsx(theme?.base, className) })
+  );

Also applies to: 57-65

src/lib/types.ts (2)

245-248: Type narrowings on dot, params, and CarouselProps.onchange

  • AvatarProps.dot?: Record<string, unknown> and BannerProps.params?: ParamsType are nice improvements over looser any/broader shapes; they better reflect how those props are actually used.
  • CarouselProps.onchange?: (x: HTMLImgAttributes) => void also makes the callback contract explicit. Note that this disallows async handlers typed as returning Promise<void>; if you expect users to use async functions here, you may want () => void | Promise<void> instead.

Overall these are good, but they do slightly tighten the public typing surface; worth double‑checking docs/examples to ensure they still compile cleanly.

Also applies to: 265-274, 412-425


1598-1607: New id fields and BodyRow shape tie into keyed rendering; watch optionality

You’ve added optional id fields to:

  • ProgressStep, TimelineStep
  • ActivityType
  • GroupTimelineType

and tightened BodyRow to:

export type BodyRow = CellValue[] | (Record<string, CellValue> & { id: string | number });

This lines up with the Svelte components now keying lists on id and, for table body objects, requiring an id so object rows can be keyed stably.

Two follow‑ups to consider:

  • Because all these ids are optional in the types (except BodyRow’s object case), components that key on (id) should either:
    • Treat id as required in their docs, or
    • Use a fallback key when id is absent, to avoid undefined/duplicate keys.
  • BodyRow’s object variant is now a breaking type change for consumers who previously passed plain Record<string, CellValue> without an id. That’s probably fine, but it’s worth calling out in release notes since it’s a public type.

Also applies to: 1657-1663, 1727-1732, 1808-1814, 1850-1857

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f6865c2 and 002b7f5.

📒 Files selected for processing (16)
  • src/lib/dropdown/DropdownItem.svelte (2 hunks)
  • src/lib/forms/floating-label/FloatingLabelInput.svelte (1 hunks)
  • src/lib/list-group/Listgroup.svelte (1 hunks)
  • src/lib/mega-menu/MegaMenu.svelte (1 hunks)
  • src/lib/navbar/NavLi.svelte (1 hunks)
  • src/lib/pagination/Pagination.svelte (1 hunks)
  • src/lib/rating/AdvancedRating.svelte (1 hunks)
  • src/lib/rating/Rating.svelte (1 hunks)
  • src/lib/stepper/ProgressStepper.svelte (1 hunks)
  • src/lib/stepper/Stepper.svelte (1 hunks)
  • src/lib/stepper/TimelineStepper.svelte (1 hunks)
  • src/lib/table/TableBody.svelte (1 hunks)
  • src/lib/timeline/ActivityItem.svelte (1 hunks)
  • src/lib/timeline/GroupItem.svelte (1 hunks)
  • src/lib/types.ts (10 hunks)
  • src/routes/docs-examples/components/dropdown/Events.svelte (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/lib/forms/floating-label/FloatingLabelInput.svelte
  • src/lib/stepper/TimelineStepper.svelte
  • src/lib/table/TableBody.svelte
  • src/lib/stepper/ProgressStepper.svelte
  • src/lib/mega-menu/MegaMenu.svelte
  • src/routes/docs-examples/components/dropdown/Events.svelte
  • src/lib/rating/Rating.svelte
  • src/lib/navbar/NavLi.svelte
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2024-10-18T09:38:03.879Z
Learnt from: Chizaruu
Repo: themesberg/flowbite-svelte PR: 1465
File: src/lib/forms/Timepicker.svelte:105-116
Timestamp: 2024-10-18T09:38:03.879Z
Learning: In `Timepicker.svelte`, the `Dropdown` opens as intended and is used exclusively with the 'dropdown' and 'timerange-dropdown' Timepicker types.

Applied to files:

  • src/lib/dropdown/DropdownItem.svelte
📚 Learning: 2024-11-22T08:37:27.996Z
Learnt from: mrh1997
Repo: themesberg/flowbite-svelte PR: 1442
File: src/lib/utils/Popper.svelte:144-145
Timestamp: 2024-11-22T08:37:27.996Z
Learning: In `src/lib/utils/Popper.svelte`, inconsistencies in event handling (e.g., using both `mouseenter`/`mouseleave` and `pointerenter`/`pointerleave`) may be intentional to minimize modifications and reduce the risk of new problems.

Applied to files:

  • src/lib/dropdown/DropdownItem.svelte
  • src/lib/list-group/Listgroup.svelte
🔇 Additional comments (3)
src/lib/list-group/Listgroup.svelte (2)

19-25: Good simplification—addresses past review feedback.

The removal of the unused item parameter clarifies intent and directly implements Option 1 from the previous review. The onclick handler now receives only the MouseEvent, which is cleaner. Note that if consumers previously expected item data in the click handler, they'll need to track it separately (e.g., via closure or data attributes).


30-30: Keyed each-block improves DOM diffing stability.

Adding (i) as the key is beneficial for component lifecycle management. Be aware that using index as a key can cause issues if items are reordered, inserted in the middle, or removed from non-terminal positions. For list groups where items are typically appended or replaced wholesale, this is acceptable.

src/lib/types.ts (1)

193-197: Anchor/button/div attribute union and DropdownItemProps align with component behavior

AnchorButtonDivAttributes now clearly models three disjoint cases: anchor (href present), button (href absent, onclick present), and div (href/onclick both absent). The new DropdownItemProps interface mirrors this pattern via href/onclick plus a classes object and index signature, which matches how DropdownItem.svelte branches between <a>, <button>, and <div>.

This looks consistent and should help prevent accidental combinations like href + onclick on the same logical variant. Just be aware this tightens typings slightly for consumers that may have relied on looser unions before.

Also applies to: 647-661

{@render globalText()}
{/if}
{#each ratings as { label, rating }}
{#each ratings as { label, rating } (label)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

Keyed each-block improves DOM tracking.

Adding (label) as the key is a Svelte best practice that helps the framework efficiently track which items changed. For rating components where labels typically represent unique categories (e.g., "5 star", "4 star"), this choice is appropriate.

Verify that label values in the ratings array are always unique. If duplicate labels are possible, consider using a guaranteed unique identifier (like an index combined with label, or an ID field if available in the type definition).


🏁 Script executed:

#!/bin/bash
# Description: Check the AdvancedRatingProps type definition to see if there's a unique ID field available

# Search for the AdvancedRatingProps type definition
ast-grep --pattern $'export interface AdvancedRatingProps {
  $$$
}'

# Also search for any rating-related types that might define the structure
rg -n "type.*[Rr]ating.*=" --type=ts -A 10

Length of output: 1991


Consider adding a unique identifier to RatingItem for robust keying.

The label field can be null | undefined (per RatingItem type in src/lib/types.ts:1284), meaning multiple items could have the same or missing label. While adding (label) as a key satisfies the lint requirement and is better than no key, it doesn't guarantee unique DOM identity during reordering or state updates.

Recommendation: Add an id field to RatingItem in src/lib/types.ts:1284 and use that as the key instead:

  • Update the type: { id: string; label: string | null | undefined; rating: number }
  • Update the key to: (id)

This ensures proper DOM tracking regardless of label content.

🤖 Prompt for AI Agents
In src/lib/rating/AdvancedRating.svelte around line 34, the each block uses
(label) as a key but label can be null/duplicate; add a stable unique id to
RatingItem and use it as the key. Update the RatingItem type definition in
src/lib/types.ts (around line 1284) to include id: string, update any code that
constructs RatingItem to populate id (UUID or deterministic unique string), and
change the each block key to (id) so DOM identity remains stable during
reordering and updates.

@shinokada shinokada merged commit a7cb84e into themesberg:main Nov 25, 2025
1 of 2 checks passed
@shinokada shinokada deleted the lint-fix branch November 25, 2025 07:26
@coderabbitai coderabbitai bot mentioned this pull request Dec 17, 2025
15 tasks
@coderabbitai coderabbitai bot mentioned this pull request Jan 3, 2026
15 tasks
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.

1 participant