Skip to content

Commit

Permalink
fix(NcCheckboxRadioSwitch): Pass attrs to input if available
Browse files Browse the repository at this point in the history
If not button type, pass the attrs to the input element to allow setting aria tags like `aria-invalid` and `aria-errormessage`

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
  • Loading branch information
susnux committed Apr 22, 2024
1 parent 2d9e6eb commit 21ae8f6
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 27 deletions.
4 changes: 2 additions & 2 deletions src/components/NcCheckboxRadioSwitch/NcCheckboxContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
-->

<template>
<span :id="!isButtonType ? `${id}-label` : undefined"
<span :id="!isButtonType ? `${inputId}-label` : undefined"
class="checkbox-content"
:class="{
['checkbox-content-' + type]: true,
Expand Down Expand Up @@ -87,7 +87,7 @@ export default {
/**
* Unique id attribute of the input to label
*/
id: {
inputId: {
type: String,
default: null,
},
Expand Down
75 changes: 50 additions & 25 deletions src/components/NcCheckboxRadioSwitch/NcCheckboxRadioSwitch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
This is a simple input checkbox, radio and switch design.
Please have a look at proper usage and recommendations: https://material.io/components/checkboxes

Note: All attributes on the element are passed to the inner input element - except for the button type.

### Standard checkbox
```vue
<template>
Expand Down Expand Up @@ -259,21 +261,25 @@ export default {

<template>
<component :is="computedWrapperElement"
:id="wrapperId"
:id="wrapperId ?? (isButtonType ? id : null)"
:aria-label="isButtonType && ariaLabel ? ariaLabel : undefined"
:class="{
['checkbox-radio-switch-' + type]: type,
'checkbox-radio-switch--checked': isChecked,
'checkbox-radio-switch--disabled': disabled,
'checkbox-radio-switch--indeterminate': hasIndeterminate ? indeterminate : false,
'checkbox-radio-switch--button-variant': buttonVariant,
'checkbox-radio-switch--button-variant-v-grouped': buttonVariant && buttonVariantGrouped === 'vertical',
'checkbox-radio-switch--button-variant-h-grouped': buttonVariant && buttonVariantGrouped === 'horizontal',
'button-vue': isButtonType,
}"
class="checkbox-radio-switch"
:style="cssVars"
:class="[
$props.class,
{
['checkbox-radio-switch-' + type]: type,
'checkbox-radio-switch--checked': isChecked,
'checkbox-radio-switch--disabled': disabled,
'checkbox-radio-switch--indeterminate': hasIndeterminate ? indeterminate : false,
'checkbox-radio-switch--button-variant': buttonVariant,
'checkbox-radio-switch--button-variant-v-grouped': buttonVariant && buttonVariantGrouped === 'vertical',
'checkbox-radio-switch--button-variant-h-grouped': buttonVariant && buttonVariantGrouped === 'horizontal',
'button-vue': isButtonType,
},
].flat()"
:style="wrapperStyle"
:type="isButtonType ? 'button' : null"
v-bind="isButtonType ? $attrs : {} "
v-on="isButtonType ? listeners : {}">
<input v-if="!isButtonType"
:id="id"
Expand All @@ -287,8 +293,9 @@ export default {
:indeterminate.prop="hasIndeterminate ? indeterminate : null"
:required="required"
:name="name"
v-bind="$attrs"
v-on="listeners">
<NcCheckboxContent :id="id"
<NcCheckboxContent :input-id="id"
class="checkbox-radio-switch__content"
icon-class="checkbox-radio-switch__icon"
text-class="checkbox-radio-switch__text"
Expand Down Expand Up @@ -324,6 +331,9 @@ export default {
NcCheckboxContent,
},
// We need to pass attributes to the input element
inheritAttrs: false,
props: {
/**
* Unique id attribute of the input
Expand Down Expand Up @@ -458,6 +468,22 @@ export default {
type: String,
default: null,
},
/**
* The class(es) to pass to the wrapper / root element of the component
*/
class: {
type: [String, Array, Object],
default: '',
},
/**
* The style to pass to the wrapper / root element of the component
*/
style: {
type: [String, Array, Object],
default: '',
},
},
emits: ['update:modelValue'],
Expand All @@ -477,6 +503,17 @@ export default {
return 'span'
},
wrapperStyle() {
return [
this.style,
// CSS local variables for this component
{
'--icon-size': this.size + 'px',
'--icon-height': (this.type === TYPE_SWITCH ? 16 : this.size) + 'px',
},
].flat()
},
listeners() {
if (this.isButtonType) {
return {
Expand All @@ -499,18 +536,6 @@ export default {
: 24
},
/**
* Css local variables for this component
*
* @return {object}
*/
cssVars() {
return {
'--icon-size': this.size + 'px',
'--icon-height': (this.type === TYPE_SWITCH ? 16 : this.size) + 'px',
}
},
/**
* Return the input type.
* Switch is not an official type
Expand Down
52 changes: 52 additions & 0 deletions tests/unit/components/NcCheckboxRadioSwitch/checkbox.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* @copyright Copyright (c) 2024 Ferdinand Thiessen <opensource@fthiessen.de>
*
* @author Ferdinand Thiessen <opensource@fthiessen.de>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

import { shallowMount } from '@vue/test-utils'
import NcCheckboxRadioSwitch from '../../../../src/components/NcCheckboxRadioSwitch/NcCheckboxRadioSwitch.vue'

describe('NcCheckboxRadioSwitch', () => {
it('sets text content', () => {
const wrapper = shallowMount(NcCheckboxRadioSwitch, {
slots: {
default: 'Test',
},
})

expect(wrapper.text()).toContain('Test')
})

it('forwards aria-invalid and aria-errormessage to input', () => {
const wrapper = shallowMount(NcCheckboxRadioSwitch, {
slots: {
default: 'Test',
},
attrs: {
'aria-invalid': 'true',
'aria-errormessage': 'id-test',
},
})

const input = wrapper.find('input')
expect(input.attributes('aria-invalid')).toBe('true')
expect(input.attributes('aria-errormessage')).toBe('id-test')
})
})

0 comments on commit 21ae8f6

Please sign in to comment.