Skip to content

feat(Checkbox/Switch): add support for custom true/false values#2410

Open
NicolaSpadari wants to merge 3 commits intounovue:v2from
NicolaSpadari:v2
Open

feat(Checkbox/Switch): add support for custom true/false values#2410
NicolaSpadari wants to merge 3 commits intounovue:v2from
NicolaSpadari:v2

Conversation

@NicolaSpadari
Copy link

@NicolaSpadari NicolaSpadari commented Jan 23, 2026

🔗 Linked issue

#2409

❓ Type of change

Add ability to pass optional :true-value and :false-value to both Checkbox and Switch components.

  • 📖 Documentation (updates to the documentation, readme or JSdoc annotations)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

Like native Vue behavior, this helps binding to custom values instead trueor false, like 1and 0.
Useful for bind data to DB responses that use 1 for true and 0 for false.

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

Summary by CodeRabbit

  • New Features

    • Checkbox and Switch now support custom true/false values (string, numeric, and other types) for v-model bindings.
  • Documentation

    • Added "Custom Values" examples showing string and numeric mappings and live v-model displays.
    • Updated feature lists to reflect custom value support.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 23, 2026

📝 Walkthrough

Walkthrough

This PR adds generic support for custom true/false values to Checkbox and Switch components via a type parameter T, new trueValue/falseValue props, updated v-model/emits logic, and documentation + story examples demonstrating string and numeric custom values.

Changes

Cohort / File(s) Summary
Documentation
docs/content/docs/components/checkbox.md, docs/content/docs/components/switch.md
Added "Supports custom true/false values" and new "Custom Values" examples showing trueValue/falseValue usage with string and numeric v-model bindings.
Checkbox Implementation
packages/core/src/Checkbox/CheckboxRoot.vue, packages/core/src/Checkbox/story/Checkbox.story.vue
Made CheckboxRoot generic <T = boolean>; added trueValue?: T and falseValue?: T; updated modelValue/defaultValue types and v-model wiring to `T
Switch Implementation
packages/core/src/Switch/SwitchRoot.vue, packages/core/src/Switch/SwitchThumb.vue, packages/core/src/Switch/Switch.story.vue
Made SwitchRoot generic <T = boolean>; added trueValue?: T and falseValue?: T; model wiring now uses T, exposes computed checked (based on trueValue) in context instead of raw modelValue; updated toggle and template bindings to use checked; added story variants for string/number custom values.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Poem

🐰
I hopped through props and generic light,
Tucked true and false to suit your sight.
Strings or numbers — choose with glee,
My checkbox and switch now roam free.
Hooray for values, small and bright! 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main feature: adding support for custom true/false values to Checkbox and Switch components.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@docs/content/docs/components/checkbox.md`:
- Around line 111-121: The example script is using ref() but never imports it;
update the <script setup> import list to include ref from Vue so the reactive
refs (acceptTerms and permission) work correctly—add an import of ref from 'vue'
alongside the existing imports (Icon, CheckboxIndicator, CheckboxRoot) so ref,
acceptTerms, and permission are defined.

In `@docs/content/docs/components/switch.md`:
- Around line 96-104: The example in the Switch docs uses Vue's ref() (variables
status and enabled with SwitchRoot and SwitchThumb) but doesn't import ref;
update the <script setup> block to import ref from 'vue' (e.g., add import { ref
} from 'vue') so status and enabled are defined correctly and the example
compiles.

In `@packages/core/src/Checkbox/CheckboxRoot.vue`:
- Line 89: Replace the strict equality in the isChecked computed so object
trueValue comparisons work: change the implementation of isChecked (which
currently uses modelValue.value === props.trueValue) to use isEqual from ohash
(i.e., isEqual(modelValue.value, props.trueValue)); ensure isEqual is imported
where other utilities like isValueEqualOrExist are used and keep the computed
declaration name isChecked and references to modelValue and props.trueValue
unchanged.
🧹 Nitpick comments (2)
packages/core/src/Checkbox/CheckboxRoot.vue (1)

82-85: Type casts bypass type safety — consider documenting or refining.

The as any casts on props and emits are necessary due to Vue's limitations with generic component typing in useVModel, but they hide potential type mismatches. This is a known limitation.

Consider adding a brief inline comment explaining why the casts are needed for future maintainers:

-const modelValue = useVModel(props as any, 'modelValue', emits as any, {
+// Type casts required due to Vue's generic component limitations with useVModel
+const modelValue = useVModel(props as any, 'modelValue', emits as any, {
packages/core/src/Switch/SwitchRoot.vue (1)

52-53: Type-unsafe default values when generic T is non-boolean.

The factory function pattern with double casting is a known Vue/TypeScript workaround. However, if a user binds a non-boolean v-model (e.g., Ref<number>) but forgets to provide trueValue/falseValue, the component will silently assign boolean true/false to their model, potentially causing runtime issues without TypeScript warnings.

Consider adding a runtime warning in development mode when modelValue is provided but its type doesn't match the default trueValue/falseValue:

💡 Optional: Add dev-mode runtime check
// In setup, after modelValue initialization:
if (import.meta.env.DEV) {
  if (props.modelValue !== undefined && props.modelValue !== null) {
    const valueType = typeof props.modelValue
    if (valueType !== 'boolean' && props.trueValue === true) {
      console.warn('[SwitchRoot] Non-boolean modelValue detected but trueValue/falseValue not provided. Consider setting explicit trueValue and falseValue props.')
    }
  }
}

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