Skip to content

checkbox corrections#1745

Merged
shinokada merged 4 commits intothemesberg:mainfrom
jjagielka:checkbox
Aug 31, 2025
Merged

checkbox corrections#1745
shinokada merged 4 commits intothemesberg:mainfrom
jjagielka:checkbox

Conversation

@jjagielka
Copy link
Copy Markdown
Contributor

@jjagielka jjagielka commented Aug 31, 2025

📑 Description

Few corrections to check boxes:

  • Checkbox - add the group variable management from CheckboxButton as it is valid for Checkbox as well
  • removal of redundant <div> around checkbox label
  • CheckboxButton re-written as subclass of Checkbox
  • few connected types corrections

Status

  • Not Completed
  • Completed

✅ Checks

  • My pull request adheres to the code style of this project
  • My code requires changes to the documentation
  • I have updated the documentation and api-check directory as required
  • All the tests and check have passed by running pnpm check && pnpm test:e2e
  • My pull request is based on the latest commit (not the npm version).
  • I have checked the page with https://validator.unl.edu/

ℹ Additional Information

Summary by CodeRabbit

  • New Features

    • CheckboxButton gains variant-driven options (inline, pill, outline, size, color, shadow).
    • New variant types exposed for checkbox/button theming.
  • Bug Fixes

    • Checkbox reliably syncs checked state with groups, including wrapped checkboxes.
  • Refactor

    • CheckboxButton delegates input behavior to Checkbox for consistent visuals and interaction.
    • Checkbox public API simplified (removed indeterminate/group props; disabled handled natively).

@vercel
Copy link
Copy Markdown

vercel bot commented Aug 31, 2025

@jjagielka 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 Aug 31, 2025

Walkthrough

Refactors Checkbox to remove indeterminate and CheckboxItem, tighten public props (remove group/indeterminate), add reactive group syncing with explicit group mutation on change, replace div wrappers with Label, make CheckboxButton delegate input behavior to Checkbox, and update theme/types to variant-based typings and CheckboxButton variants.

Changes

Cohort / File(s) Summary of changes
Checkbox core changes
src/lib/forms/checkbox/Checkbox.svelte
Removed CheckboxItem import and indeterminate prop; stopped defaulting disabled in destructuring (now uses disabled ?? false); replaced div wrappers with Label; added reactive effects to sync checked with group when value defined and to mutate/reassign group (push/splice) when checked changes; per-choice rendering uses Label and children({ value, checked, disabled }) when provided.
CheckboxButton now uses Checkbox
src/lib/forms/checkbox/CheckboxButton.svelte
Replaced inlined input and custom group logic with embedded <Checkbox bind:group bind:checked ...>; added imports for Checkbox, CheckboxButtonProps, and getTheme; adjusted default bindables (group/checked) and removed local group mutation logic while keeping theme-driven buttonClass logic.
Theme variant/type tweaks
src/lib/forms/checkbox/theme.ts
CheckboxVariants type now omits "disabled"; checkbox theme adds explicit disabled: { true: {...}, false: {} } branches; exported new CheckboxButtonVariants type.
Types & public API adjustments
src/lib/types.ts
CheckboxProps now omits only "children" and "color" (re-allowing disabled on input); removed group and indeterminate from CheckboxProps; labelProps refined to Omit<LabelProps, "children">; CheckboxButtonProps redesigned to extend CheckboxButtonVariants, drop legacy group/value/checked fields and add inline, pill, outline, size, color, shadow.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Checkbox as Checkbox.svelte
  participant Group as group (array)

  rect rgba(230,245,255,0.6)
    note over Checkbox: Reactive sync when value or group changes
    Checkbox->>Checkbox: $: if value !== undefined -> checked = group.includes(value)
  end

  User->>Checkbox: Toggle input
  rect rgba(240,255,230,0.6)
    Checkbox->>Checkbox: onChange handler runs
    alt checked == true and value defined
      Checkbox->>Group: push(value) if missing
    else checked == false and value defined
      Checkbox->>Group: splice(index,1) if present
    end
    Checkbox->>Group: group = [...group]  (reassign to trigger bindings)
  end
Loading
sequenceDiagram
  autonumber
  participant User
  participant CheckboxButton as CheckboxButton.svelte
  participant Checkbox as Checkbox.svelte
  participant Group as group

  User->>CheckboxButton: Click visual button
  CheckboxButton->>Checkbox: Delegated hidden input (bind:group, bind:checked)
  Checkbox->>Checkbox: Handle change and sync group
  Checkbox->>Group: mutate and reassign
  Checkbox-->>CheckboxButton: bind updates reflected
  CheckboxButton-->>User: visual state updated via theme classes
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Issues #1538 — Modifies CheckboxButton and checkbox components; likely overlaps with CheckboxButton refactor to use Checkbox.
  • fix: types clean up #1609 — Touches checkbox theme/types; related to the variant/type adjustments here.
  • Upgrade to Tailwind 4.0 #1532 — Also updates CheckboxButton-related props/types (shadow/visual API), relevant to the Button ↔ Checkbox changes.

Poem

I nibble keys and hop in cheer,
No indeterminate, the path is clear.
I push and splice to keep the band,
A label hug, a cleaner hand.
Bound together — check and dance 🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

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

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: 7

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/checkbox/theme.ts (1)

85-90: Malformed variant shape for “inline”.

false is nested under true, so the “false” branch never applies and you create an invalid slot key named “false”. Make the options siblings:

     inline: {
-      true: {
-        div: "inline-flex",
-        false: "flex items-center"
-      }
+      true: { div: "inline-flex" },
+      false: { div: "flex items-center" }
     },
src/lib/types.ts (1)

689-696: Add group and checked to CheckboxButtonProps.
Include strongly-typed group and checked props to match the bindings in CheckboxButton.svelte.

 export interface CheckboxButtonProps extends CheckboxButtonVariants, Omit<HTMLInputAttributes, "size" | "checked"> {
   inline?: boolean;
   pill?: boolean;
   outline?: boolean;
   size?: ButtonProps["size"];
   color?: ButtonProps["color"];
   shadow?: boolean;
+  // Bindable state forwarded to inner <Checkbox>
+  group?: any[];
+  checked?: boolean;
 }
♻️ Duplicate comments (1)
src/lib/forms/checkbox/Checkbox.svelte (1)

53-70: ESLint: Each block requires a key.

The linter hint is valid for this block (svelte/require-each-key). The key fix above resolves it.

🧹 Nitpick comments (1)
src/lib/forms/checkbox/theme.ts (1)

83-84: Redundant “rounded” variant class.

Base slot already contains rounded-sm; the rounded: true branch adds it again. Either remove from base or from the variant to avoid duplication. Safe to keep as-is, but consider trimming.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4317c80 and ceb2b4d.

📒 Files selected for processing (4)
  • src/lib/forms/checkbox/Checkbox.svelte (1 hunks)
  • src/lib/forms/checkbox/CheckboxButton.svelte (1 hunks)
  • src/lib/forms/checkbox/theme.ts (3 hunks)
  • src/lib/types.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/lib/forms/checkbox/theme.ts (1)
src/lib/theme/themeUtils.ts (1)
  • Classes (14-16)
src/lib/types.ts (1)
src/lib/forms/checkbox/theme.ts (2)
  • CheckboxVariants (4-4)
  • CheckboxButtonVariants (105-105)
🪛 ESLint
src/lib/forms/checkbox/Checkbox.svelte

[error] 53-62: Each block should have a key

(svelte/require-each-key)

⏰ 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: Playwright and Lint
🔇 Additional comments (1)
src/lib/forms/checkbox/CheckboxButton.svelte (1)

17-17: LGTM: delegating input semantics to Checkbox simplifies state and fixes group sync.

Wrapping Checkbox with bind:group/bind:checked and forwarding ...restProps is the right call.

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: 4

♻️ Duplicate comments (1)
src/lib/forms/checkbox/Checkbox.svelte (1)

55-59: Use live group state for checked; slot should reflect current selection.

Static choice.checked doesn’t update after toggles; derive from group.

-      <input type="checkbox" value={choice.value} checked={choice.checked ?? false} {disabled} bind:group {...restProps} {onchange} class={base({ class: clsx(theme?.base, className) })} />
+      <input type="checkbox" value={choice.value} checked={group?.includes?.(choice.value) ?? false} {disabled} bind:group {...restProps} {onchange} class={base({ class: clsx(theme?.base, className) })} />
@@
-        {@render children({ value: choice.value, checked: choice.checked, disabled })}
+        {@render children({ value: choice.value, checked: group?.includes?.(choice.value) ?? false, disabled })}
🧹 Nitpick comments (2)
src/lib/forms/checkbox/CheckboxButton.svelte (1)

9-9: Doc default mismatch for group.

Code defaults to group = $bindable() while docs say $bindable([]). Align one of them.

-@prop group = $bindable([])
+@prop group = $bindable()

Also applies to: 29-31

src/lib/forms/checkbox/Checkbox.svelte (1)

38-47: Prefer immutable updates over push/splice + reassignment.

Reduces accidental in-place mutation and reads clearer.

-        group.push(value);
-        group = group;
+        group = [...group, value];
@@
-        group.splice(index, 1);
-        group = group;
+        group = [...group.slice(0, index), ...group.slice(index + 1)];
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ceb2b4d and 32fde50.

📒 Files selected for processing (3)
  • src/lib/forms/checkbox/Checkbox.svelte (1 hunks)
  • src/lib/forms/checkbox/CheckboxButton.svelte (1 hunks)
  • src/lib/forms/checkbox/theme.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/forms/checkbox/theme.ts
⏰ 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: Playwright and Lint
🔇 Additional comments (1)
src/lib/forms/checkbox/Checkbox.svelte (1)

53-53: Good: each-block is keyed.

Prevents DOM diff issues and satisfies linter.

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: 2

♻️ Duplicate comments (2)
src/lib/forms/checkbox/Checkbox.svelte (2)

45-49: Drive “checked” from group (live state) instead of static choice.checked.

Ensures SSR hydration correctness and reflects user toggles. Also pass live checked to the slot.

-      <input type="checkbox" value={choice.value} checked={choice.checked ?? false} {disabled} bind:group {...restProps} class={base({ class: clsx(theme?.base, className) })} />
+      <input type="checkbox" value={choice.value} checked={group?.includes?.(choice.value) ?? false} {disabled} bind:group {...restProps} class={base({ class: clsx(theme?.base, className) })} />
@@
-        {@render children({ value: choice.value, checked: choice.checked, disabled })}
+        {@render children({ value: choice.value, checked: group?.includes?.(choice.value) ?? false, disabled })}

Manually toggle a choice and verify the slot receives the updated checked value.


43-43: Key the each-block by choice.value, not the component value.

Using (value ?? i) will produce unstable/non-unique keys across items.

-  {#each choices as choice, i (value ?? i)}
+  {#each choices as choice, i (choice.value ?? i)}
🧹 Nitpick comments (1)
src/lib/forms/checkbox/Checkbox.svelte (1)

16-21: Guard against non-array group to avoid runtime errors.

Minor safety: if a consumer accidentally passes a non-array, includes will throw.

-  $effect(() => {
-    if (value !== undefined) {
-      checked = group.includes(value);
-    }
-  });
+  $effect(() => {
+    if (value !== undefined && Array.isArray(group)) {
+      checked = group.includes(value);
+    }
+  });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 32fde50 and d71fbe0.

📒 Files selected for processing (1)
  • src/lib/forms/checkbox/Checkbox.svelte (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: jjagielka
PR: themesberg/flowbite-svelte#1745
File: src/lib/forms/checkbox/CheckboxButton.svelte:9-9
Timestamp: 2025-08-31T12:57:33.616Z
Learning: In CheckboxButtonProps interface, `checked` is explicitly omitted from HTMLInputAttributes via `Omit<HTMLInputAttributes, "size" | "checked">`, so if a component needs to bind to `checked`, it must be explicitly declared in the interface.
📚 Learning: 2025-08-31T12:57:33.616Z
Learnt from: jjagielka
PR: themesberg/flowbite-svelte#1745
File: src/lib/forms/checkbox/CheckboxButton.svelte:9-9
Timestamp: 2025-08-31T12:57:33.616Z
Learning: In CheckboxButtonProps interface, `checked` is explicitly omitted from HTMLInputAttributes via `Omit<HTMLInputAttributes, "size" | "checked">`, so if a component needs to bind to `checked`, it must be explicitly declared in the interface.

Applied to files:

  • src/lib/forms/checkbox/Checkbox.svelte
📚 Learning: 2025-08-31T14:31:57.562Z
Learnt from: jjagielka
PR: themesberg/flowbite-svelte#1745
File: src/lib/forms/checkbox/CheckboxButton.svelte:16-17
Timestamp: 2025-08-31T14:31:57.562Z
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/lib/forms/checkbox/Checkbox.svelte
📚 Learning: 2025-08-31T13:01:17.611Z
Learnt from: jjagielka
PR: themesberg/flowbite-svelte#1745
File: src/lib/forms/checkbox/Checkbox.svelte:22-27
Timestamp: 2025-08-31T13:01:17.611Z
Learning: createEventDispatcher is deprecated in Svelte 5. Components should use callback props instead of event dispatchers for event handling.

Applied to files:

  • src/lib/forms/checkbox/Checkbox.svelte
📚 Learning: 2024-11-22T08:37:27.996Z
Learnt from: mrh1997
PR: themesberg/flowbite-svelte#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/forms/checkbox/Checkbox.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: Playwright and Lint
🔇 Additional comments (3)
src/lib/forms/checkbox/Checkbox.svelte (3)

4-4: Imports look good.

Type-only import and Label usage align with the refactor.


14-14: LGTM on derived theming.

Passing disabled: disabled ?? false into the theme helper is reasonable.


53-59: Single-checkbox branch looks good.

bind:checked + slot props are consistent; no issues spotted.

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

♻️ Duplicate comments (1)
src/lib/forms/checkbox/Checkbox.svelte (1)

47-47: Pass live checked state to slot (don’t use static choice.checked).

Use current membership so slot consumers see updates.

-        {@render children({ value: choice.value, checked: choice.checked, disabled })}
+        {@render children({ value: choice.value, checked: group?.includes?.(choice.value) ?? false, disabled })}
🧹 Nitpick comments (3)
src/lib/forms/checkbox/Checkbox.svelte (3)

28-28: Remove unreachable branch (checked is never undefined).

checked defaults via $bindable(false), so this line never runs.

-    if (checked === undefined) checked = index >= 0;

24-26: Refresh comment to reflect Svelte 5 context.

The note references an old Svelte 3 REPL; clarify it’s a current Svelte 5 workaround or link the relevant issue.

-    // There's a bug in Svelte and bind:group is not working with wrapped checkbox
-    // This workaround is taken from:
-    // https://svelte.dev/repl/de117399559f4e7e9e14e2fc9ab243cc?version=3.12.1
+    // Svelte 5 note: bind:group can break when the input is wrapped; keep group in sync for single-checkbox usage.
+    // (Track upstream issue here if available.)

7-7: Add missing group prop to CheckboxProps. checked is already defined (boolean | null), but group isn’t. Define group?: unknown[] (or a more specific array type) in src/lib/types.ts’s CheckboxProps.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d71fbe0 and e9c2857.

📒 Files selected for processing (1)
  • src/lib/forms/checkbox/Checkbox.svelte (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-08-31T14:31:57.562Z
Learnt from: jjagielka
PR: themesberg/flowbite-svelte#1745
File: src/lib/forms/checkbox/CheckboxButton.svelte:16-17
Timestamp: 2025-08-31T14:31:57.562Z
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/lib/forms/checkbox/Checkbox.svelte
📚 Learning: 2025-08-31T13:01:17.611Z
Learnt from: jjagielka
PR: themesberg/flowbite-svelte#1745
File: src/lib/forms/checkbox/Checkbox.svelte:22-27
Timestamp: 2025-08-31T13:01:17.611Z
Learning: createEventDispatcher is deprecated in Svelte 5. Components should use callback props instead of event dispatchers for event handling.

Applied to files:

  • src/lib/forms/checkbox/Checkbox.svelte
📚 Learning: 2024-11-22T08:37:27.996Z
Learnt from: mrh1997
PR: themesberg/flowbite-svelte#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/forms/checkbox/Checkbox.svelte
📚 Learning: 2025-08-31T15:34:05.270Z
Learnt from: jjagielka
PR: themesberg/flowbite-svelte#1745
File: src/lib/forms/checkbox/Checkbox.svelte:22-39
Timestamp: 2025-08-31T15:34:05.270Z
Learning: In Svelte 5, `$state` provides deep reactivity, meaning array mutations like `push()`, `splice()`, `pop()`, etc. trigger reactivity automatically. Unlike previous Svelte versions, immutable updates (spread operator, filter) are not required for `$state` arrays to trigger reactive updates.

Applied to files:

  • src/lib/forms/checkbox/Checkbox.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: Playwright and Lint
🔇 Additional comments (1)
src/lib/forms/checkbox/Checkbox.svelte (1)

43-44: Keyed each-block: good.

Stable key avoids DOM diff issues and satisfies the linter.

@shinokada shinokada merged commit c31e48b into themesberg:main Aug 31, 2025
1 of 2 checks passed
@jjagielka jjagielka deleted the checkbox branch September 2, 2025 19:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants