From 21196a68035a00a9d2dc5c0d0ed4e03c5caba140 Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Mon, 25 Mar 2019 13:46:23 -0300 Subject: [PATCH 1/2] feat(form-checkbox/radio): allow no label in plain mode (fixes #2911) Closes #2911 --- src/mixins/form-radio-check.js | 37 +++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/mixins/form-radio-check.js b/src/mixins/form-radio-check.js index 2ad961c9783..901696093e9 100644 --- a/src/mixins/form-radio-check.js +++ b/src/mixins/form-radio-check.js @@ -32,6 +32,11 @@ export default { // Only applicable when rendered with button style type: String, default: null + }, + ariaLabel: { + // Placed on the input if present. + type: String, + default: null } }, data() { @@ -172,7 +177,9 @@ export default { 'form-check-input': this.is_Plain, 'custom-control-input': this.is_Custom, 'is-valid': this.get_State === true && !this.is_BtnMode, - 'is-invalid': this.get_State === false && !this.is_BtnMode + 'is-invalid': this.get_State === false && !this.is_BtnMode, + // https://github.com/bootstrap-vue/bootstrap-vue/issues/2911 + 'position-static': this.is_Plain && !defaultSlot }, directives: [ { @@ -190,7 +197,8 @@ export default { disabled: this.is_Disabled, required: this.is_Required, autocomplete: 'off', - 'aria-required': this.is_Required || null + 'aria-required': this.is_Required || null, + 'aria-label': this.ariaLabel || null }, domProps: { value: this.value, @@ -209,17 +217,22 @@ export default { return button } else { // Not button mode - const label = h( - 'label', - { - class: { - 'form-check-label': this.is_Plain, - 'custom-control-label': this.is_Custom + let label = h(false) + // If no label content in plain mode we dont render the label + // https://github.com/bootstrap-vue/bootstrap-vue/issues/2911 + if (!(this.is_Plain && !defaultSlot)) { + label = h( + 'label', + { + class: { + 'form-check-label': this.is_Plain, + 'custom-control-label': this.is_Custom + }, + attrs: { for: this.safeId() } }, - attrs: { for: this.safeId() } - }, - defaultSlot - ) + defaultSlot + ) + } // Wrap it in a div return h( 'div', From 0e261b9d9f1e8df77e9e7001b8899bd555c31b6c Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Mon, 25 Mar 2019 14:13:09 -0300 Subject: [PATCH 2/2] Update form-checkbox.spec.js --- .../form-checkbox/form-checkbox.spec.js | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/components/form-checkbox/form-checkbox.spec.js b/src/components/form-checkbox/form-checkbox.spec.js index b6d0c0ce3da..0ac0492b53d 100644 --- a/src/components/form-checkbox/form-checkbox.spec.js +++ b/src/components/form-checkbox/form-checkbox.spec.js @@ -58,6 +58,35 @@ describe('form-checkbox', () => { wrapper.destroy() }) + it('default does not have aria-label attribute on input', async () => { + const wrapper = mount(Input, { + propsData: { + checked: false + }, + slots: { + default: 'foobar' + } + }) + expect(wrapper.find('input').attributes('aria-label')).not.toBeDefined() + + wrapper.destroy() + }) + + it('has aria-label attribute on input when aria-label provided', async () => { + const wrapper = mount(Input, { + propsData: { + checked: false, + ariaLabel: 'bar' + }, + slots: { + default: 'foo' + } + }) + expect(wrapper.find('input').attributes('aria-label')).toBe('bar') + + wrapper.destroy() + }) + it('default has input class custom-control-input', async () => { const wrapper = mount(Input, { propsData: { @@ -70,6 +99,7 @@ describe('form-checkbox', () => { const input = wrapper.find('input') expect(input.classes().length).toEqual(1) expect(input.classes()).toContain('custom-control-input') + expect(input.classes()).not.toContain('position-static') wrapper.destroy() }) @@ -481,6 +511,34 @@ describe('form-checkbox', () => { wrapper.destroy() }) + it('plain does not have class position-static when label provided', async () => { + const wrapper = mount(Input, { + propsData: { + plain: true, + checked: false + }, + slots: { + default: 'foobar' + } + }) + expect(wrapper.find('input').classes()).not.toContain('position-static') + + wrapper.destroy() + }) + + it('plain has no label when no default slot content', async () => { + const wrapper = mount(Input, { + propsData: { + plain: true, + checked: false + } + }) + expect(wrapper.find('label').exists()).toBe(false) + expect(wrapper.find('input').classes()).toContain('position-static') + + wrapper.destroy() + }) + it('plain has no input validation classes by default', async () => { const wrapper = mount(Input, { propsData: {