diff --git a/CHANGELOG.md b/CHANGELOG.md
index 08334de..caf21dd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [1.0.6] - 2025-07-23
+### Added
+- Checkbox component
+
+### Fixed
+- VLabel `required-tip` slot
+- VHint UI style
+
## [1.0.5] - 2025-07-22
### Added
- Input component
diff --git a/README.md b/README.md
index 1e65271..6872d61 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,3 @@
# visua-vue
-**Current version: v1.0.5**
\ No newline at end of file
+**Current version: v1.0.6**
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 696bb58..eb36326 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@cellule-financiere-pmo/visua-vue",
- "version": "1.0.5",
+ "version": "1.0.6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@cellule-financiere-pmo/visua-vue",
- "version": "1.0.5",
+ "version": "1.0.6",
"license": "ISC",
"dependencies": {
"@cellule-financiere-pmo/visua": "1.1.3",
diff --git a/package.json b/package.json
index e69ad57..4db8cd9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@cellule-financiere-pmo/visua-vue",
- "version": "1.0.5",
+ "version": "1.0.6",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/src/App.vue b/src/App.vue
index 42b178a..e582a0d 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -3,7 +3,8 @@
// import VButtonGroupView from '../template/VButtonGroupView.vue';
// import VLinkView from '../template/VLinkView.vue';
// import VAccordionView from '../template/VAccordionView.vue';
-import VInputView from '../template/VInputView.vue';
+// import VInputView from '../template/VInputView.vue';
+import VCheckboxView from '../template/VCheckboxView.vue';
@@ -12,5 +13,6 @@ import VInputView from '../template/VInputView.vue';
-
+
+
diff --git a/src/assets/style/primevue-configuration.css b/src/assets/style/primevue-configuration.css
index 1ae4ed8..c381491 100644
--- a/src/assets/style/primevue-configuration.css
+++ b/src/assets/style/primevue-configuration.css
@@ -7,3 +7,4 @@
@import './primevue-style/divider.css';
@import './primevue-style/various.css';
@import './primevue-style/form.css';
+@import './primevue-style/checkbox.css';
diff --git a/src/assets/style/primevue-style/checkbox.css b/src/assets/style/primevue-style/checkbox.css
new file mode 100644
index 0000000..635532a
--- /dev/null
+++ b/src/assets/style/primevue-style/checkbox.css
@@ -0,0 +1,32 @@
+:root{
+ /* size */
+ --p-checkbox-width: 1.5rem;
+ --p-checkbox-height: 1.5rem;
+ --p-checkbox-sm-width: 1rem;
+ --p-checkbox-sm-height: 1rem;
+ /* border */
+ --p-checkbox-border-radius: 0px;
+ --p-checkbox-border-color: var(--border-action-high-blue-france);
+ --p-checkbox-hover-border-color: var(--border-action-high-blue-france);
+ /* background */
+ --p-checkbox-background: var(--background-default-grey);
+ /* icon */
+ --p-checkbox-icon-size: 1rem;
+ --p-checkbox-icon-sm-size: 1rem;
+ --p-checkbox-icon-color: var(--background-default-grey);
+ /* focus */
+ --p-checkbox-checked-focus-border-color: var(--border-action-high-blue-france);
+ --p-checkbox-focus-border-color: var(--border-action-high-blue-france);
+ --p-checkbox-focus-ring-color: var(--focus-color);
+ --p-checkbox-focus-ring-width: var(--focus-width);
+ --p-checkbox-focus-ring-style: var(--focus-style);
+ --p-checkbox-focus-ring-offset: var(--focus-offset);
+ /* checked */
+ --p-checkbox-checked-border-color: var(--border-action-high-blue-france);
+ --p-checkbox-checked-background: var(--border-active-blue-france);
+ --p-checkbox-icon-checked-color: var(--background-default-grey);
+ /* checked:hover */
+ --p-checkbox-icon-checked-hover-color: var(--background-default-grey);
+ --p-checkbox-checked-hover-border-color: var(--border-action-high-blue-france);
+ --p-checkbox-checked-hover-background: var(--border-active-blue-france);
+}
diff --git a/src/components/checkbox/IVCheckbox.type.ts b/src/components/checkbox/IVCheckbox.type.ts
new file mode 100644
index 0000000..ed4f537
--- /dev/null
+++ b/src/components/checkbox/IVCheckbox.type.ts
@@ -0,0 +1,89 @@
+/**
+ * Interface representing the props for a CheckBox Vue component.
+ */
+export default interface IVCheckBox {
+ /**
+ * The unique identifier for the checkbox element.
+ */
+ id?: string;
+
+ /**
+ * The name attribute for the checkbox input.
+ */
+ name?: string;
+
+ /**
+ * Indicates whether the checkbox is required in a form.
+ */
+ required?: boolean;
+
+ /**
+ * The value associated with the checkbox.
+ */
+ value?: unknown;
+
+ /**
+ * Whether the checkbox is initially checked.
+ */
+ checked?: boolean;
+
+ /**
+ * The bound value of the checkbox, can be a boolean or an array of values.
+ */
+ modelValue: Array | boolean;
+
+ /**
+ * If true, renders the checkbox in a smaller size.
+ */
+ small?: boolean;
+
+ /**
+ * If true, displays the checkbox inline with other elements.
+ */
+ inline?: boolean;
+
+ /**
+ * If true, the checkbox is read-only and cannot be changed by the user.
+ */
+ readonly?: boolean;
+
+ /**
+ * Opacity level applied when the checkbox is read-only.
+ */
+ readonlyOpacity?: number;
+
+ /**
+ * The label text displayed next to the checkbox.
+ */
+ label?: string;
+
+ /**
+ * The error message shown when validation fails.
+ */
+ errorMessage?: string;
+
+ /**
+ * The message shown when the checkbox input is valid.
+ */
+ validMessage?: string;
+
+ /**
+ * Additional hint or helper text displayed below the checkbox.
+ */
+ hint?: string;
+
+ /**
+ * If true, disables the checkbox input.
+ */
+ disabled?: boolean;
+
+ /**
+ * Visual style of the checkbox, can be 'normal', 'error', or 'success'.
+ */
+ type?: 'normal' | 'error' | 'success';
+
+ /**
+ * If true, the checkbox operates in binary mode (boolean value).
+ */
+ binary?: boolean;
+}
diff --git a/src/components/checkbox/VCheckbox.vue b/src/components/checkbox/VCheckbox.vue
new file mode 100644
index 0000000..9992c58
--- /dev/null
+++ b/src/components/checkbox/VCheckbox.vue
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
diff --git a/src/components/hint/VHint.vue b/src/components/hint/VHint.vue
index 455181a..1a3b039 100644
--- a/src/components/hint/VHint.vue
+++ b/src/components/hint/VHint.vue
@@ -39,21 +39,28 @@ const severity = computed(() => {
{{ props.title }}
+
+
+
diff --git a/src/components/label/VLabel.vue b/src/components/label/VLabel.vue
index ae1cd1e..10a1144 100644
--- a/src/components/label/VLabel.vue
+++ b/src/components/label/VLabel.vue
@@ -24,12 +24,11 @@ const props = withDefaults(defineProps(), {
:aria-disabled="props.disabled"
>
{{ props.label }}
-
- *
-
+
+
+ *
+
+
(), {
.success {color: var(--text-default-success);}
.error {color: var(--text-default-error);}
.disabled {color: var(--text-disabled-grey);}
-.required {color: var(--minor-red-marianne);}
+.required {
+ color: var(--minor-red-marianne);
+ display: inline;
+}
diff --git a/test/VCheckbox.spec.ts b/test/VCheckbox.spec.ts
new file mode 100644
index 0000000..acce989
--- /dev/null
+++ b/test/VCheckbox.spec.ts
@@ -0,0 +1,98 @@
+import { describe, it, expect } from 'vitest'
+import { mount } from '@vue/test-utils'
+import VCheckbox from '../src/components/checkbox/VCheckbox.vue'
+import PrimeCheckbox from 'primevue/checkbox'
+
+const globalConfig = {
+ global: {
+ components: {
+ Checkbox: PrimeCheckbox
+ },
+ mocks: {
+ $primevue: {
+ config: {}
+ }
+ },
+ stubs: {
+ VLabel: true,
+ VHint: true,
+ }
+ }
+}
+
+describe('VCheckbox.vue', () => {
+ it('adds value to modelValue array when checkbox is clicked (multiple mode)', async () => {
+ const wrapper = mount(VCheckbox, {
+ props: {
+ label: 'Fruit',
+ modelValue: [],
+ value: 'pomme'
+ },
+ global: globalConfig.global
+ });
+
+ const input = wrapper.find('input[type="checkbox"]');
+ await input.setValue(true);
+
+ const emitted = wrapper.emitted('update:modelValue');
+ expect(emitted).toBeTruthy();
+ expect(emitted?.[0]?.[0]).toContain('pomme');
+ });
+
+ it('removes value from modelValue array when checkbox is unchecked (multiple mode)', async () => {
+ const wrapper = mount(VCheckbox, {
+ props: {
+ label: 'Fruit',
+ modelValue: ['pomme'],
+ value: 'pomme'
+ },
+ global: globalConfig.global
+ });
+
+ const input = wrapper.find('input[type="checkbox"]');
+ await input.setValue(false);
+
+ const emitted = wrapper.emitted('update:modelValue');
+ expect(emitted).toBeTruthy();
+ expect(emitted?.[0]?.[0]).not.toContain('pomme');
+ });
+
+ it('emits change, focus and blur events', async () => {
+ const wrapper = mount(VCheckbox, {
+ props: {
+ label: 'Test Checkbox',
+ modelValue: false
+ },
+ global: globalConfig.global
+ });
+ const input = wrapper.find('input[type="checkbox"]');
+ await input.trigger('focus');
+ await input.trigger('blur');
+ await input.trigger('change');
+ expect(wrapper.emitted('focus')).toBeTruthy();
+ expect(wrapper.emitted('blur')).toBeTruthy();
+ expect(wrapper.emitted('change')).toBeTruthy();
+ });
+
+ it('applies error and success classes based on props', () => {
+ const errorWrapper = mount(VCheckbox, {
+ props: {
+ label: 'Error Checkbox',
+ modelValue: false,
+ errorMessage: 'Error occurred'
+ },
+ global: globalConfig.global
+ });
+ expect(errorWrapper.find('.p-checkbox.error').exists()).toBe(true);
+
+ const successWrapper = mount(VCheckbox, {
+ props: {
+ label: 'Success Checkbox',
+ modelValue: true,
+ validMessage: 'Valid input'
+ },
+ global: globalConfig.global
+ });
+ expect(successWrapper.find('.p-checkbox.success').exists()).toBe(true);
+ });
+});