Skip to content

Commit

Permalink
fix(radio): group elements sends focus and blur event. Closes #623
Browse files Browse the repository at this point in the history
  • Loading branch information
hirsch88 committed Nov 2, 2022
1 parent 7fecfca commit d044693
Show file tree
Hide file tree
Showing 11 changed files with 513 additions and 193 deletions.
10 changes: 8 additions & 2 deletions packages/components/cypress/component/bal-radio.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import BalRadioTest from './bal-radio.vue'
describe('bal-radio.cy.ts', () => {
describe('radio', () => {
it('should have a default slot', () => {
cy.mount(BalRadio, { slots: { default: () => 'My label' } })
cy.mount(BalRadio as any, { slots: { default: () => 'My label' } })
cy.get('bal-radio').contains('My label')
cy.get('bal-radio').find('input').should('not.be.checked')
})
Expand All @@ -14,17 +14,23 @@ describe('bal-radio.cy.ts', () => {
let onClickSpy: Cypress.Agent<sinon.SinonSpy>
let onBalChangeSpy: Cypress.Agent<sinon.SinonSpy>
let onBalInputSpy: Cypress.Agent<sinon.SinonSpy>
let onBalFocusSpy: Cypress.Agent<sinon.SinonSpy>
let onBalBlurSpy: Cypress.Agent<sinon.SinonSpy>

beforeEach(() => {
onClickSpy = cy.spy().as('click')
onBalChangeSpy = cy.spy().as('balChange')
onBalInputSpy = cy.spy().as('balInput')
onBalFocusSpy = cy.spy().as('balFocus')
onBalBlurSpy = cy.spy().as('balBlur')

cy.mount(BalRadioTest, {
cy.mount(BalRadioTest as any, {
props: {
onClick: onClickSpy,
onBalInput: onBalInputSpy,
onBalChange: onBalChangeSpy,
onBalFocus: onBalFocusSpy,
onBalBlur: onBalBlurSpy,
},
})
})
Expand Down
6 changes: 3 additions & 3 deletions packages/components/cypress/component/bal-radio.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { BalRadioGroup, BalRadio } from '../../.storybook/vue/components'

<template>
<BalRadioGroup>
<BalRadio name="radio-test" value="1">Radio 1</BalRadio>
<BalRadio name="radio-test" value="2">Radio 2</BalRadio>
<BalRadio name="radio-test" value="3">Radio 3</BalRadio>
<BalRadio name="radio-test" value="1" label="Radio 1"></BalRadio>
<BalRadio name="radio-test" value="2" label="Radio 2"></BalRadio>
<BalRadio name="radio-test" value="3" label="Radio 3"></BalRadio>
</BalRadioGroup>
</template>
63 changes: 39 additions & 24 deletions packages/components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export namespace Components {
"value": boolean;
}
interface BalApp {
"setFocus": (elements: HTMLElement[]) => Promise<void>;
}
interface BalBadge {
/**
Expand Down Expand Up @@ -1753,10 +1754,6 @@ export namespace Components {
"value"?: string | number;
}
interface BalRadio {
/**
* If `true`, the radio is selected.
*/
"checked": boolean;
/**
* If `true`, the element is not mutable, focusable, or even submitted with the form. The user can neither edit nor focus on the control, nor its form control descendants.
*/
Expand Down Expand Up @@ -1785,6 +1782,10 @@ export namespace Components {
* @deprecated If `true` the radio has no label
*/
"isEmpty": boolean;
/**
* Label of the radio item.
*/
"label": string;
/**
* If `true` the radio has no label
*/
Expand All @@ -1801,20 +1802,18 @@ export namespace Components {
* If `true`, the user must fill in a value before submitting a form.
*/
"required": boolean;
"setButtonTabindex": (value: number) => Promise<void>;
"setFocus": (ev: any) => Promise<void>;
/**
* Sets blur on the native `input`. Use this method instead of the global `input.blur()`.
*/
"setBlur": () => Promise<void>;
/**
* Sets the focus on the checkbox input element.
*/
"setFocus": () => Promise<void>;
/**
* Value of the radio item, if checked the whole group has this value.
* the value of the radio.
*/
"value": number | string | boolean;
"value"?: any | null;
}
interface BalRadioGroup {
/**
* If `true`, the radios can be deselected.
*/
"allowEmptySelection": boolean;
/**
* If `true`, the element is not mutable, focusable, or even submitted with the form. The user can neither edit nor focus on the control, nor its form control descendants.
*/
Expand All @@ -1837,9 +1836,9 @@ export namespace Components {
"readonly"?: boolean;
"setValue": (value: number | string | boolean) => Promise<void>;
/**
* The value of the control.
* the value of the radio group.
*/
"value": number | string | boolean;
"value"?: any | null;
/**
* Displays the checkboxes vertically
*/
Expand Down Expand Up @@ -5134,10 +5133,6 @@ declare namespace LocalJSX {
"value"?: string | number;
}
interface BalRadio {
/**
* If `true`, the radio is selected.
*/
"checked"?: boolean;
/**
* If `true`, the element is not mutable, focusable, or even submitted with the form. The user can neither edit nor focus on the control, nor its form control descendants.
*/
Expand All @@ -5162,6 +5157,10 @@ declare namespace LocalJSX {
* @deprecated If `true` the radio has no label
*/
"isEmpty"?: boolean;
/**
* Label of the radio item.
*/
"label"?: string;
/**
* If `true` the radio has no label
*/
Expand Down Expand Up @@ -5195,11 +5194,15 @@ declare namespace LocalJSX {
*/
"required"?: boolean;
/**
* Value of the radio item, if checked the whole group has this value.
* the value of the radio.
*/
"value"?: number | string | boolean;
"value"?: any | null;
}
interface BalRadioGroup {
/**
* If `true`, the radios can be deselected.
*/
"allowEmptySelection"?: boolean;
/**
* If `true`, the element is not mutable, focusable, or even submitted with the form. The user can neither edit nor focus on the control, nor its form control descendants.
*/
Expand All @@ -5216,18 +5219,30 @@ declare namespace LocalJSX {
* The name of the control, which is submitted with the form data.
*/
"name"?: string;
/**
* Emitted when the toggle loses focus.
*/
"onBalBlur"?: (event: BalRadioGroupCustomEvent<FocusEvent>) => void;
/**
* Emitted when the checked property has changed.
*/
"onBalChange"?: (event: BalRadioGroupCustomEvent<Events.BalRadioGroupChangeDetail>) => void;
/**
* Emitted when the toggle has focus.
*/
"onBalFocus"?: (event: BalRadioGroupCustomEvent<FocusEvent>) => void;
/**
* Emitted when the checked property has changed.
*/
"onBalInput"?: (event: BalRadioGroupCustomEvent<Events.BalRadioGroupChangeDetail>) => void;
/**
* If `true` the element can not mutated, meaning the user can not edit the control.
*/
"readonly"?: boolean;
/**
* The value of the control.
* the value of the radio group.
*/
"value"?: number | string | boolean;
"value"?: any | null;
/**
* Displays the checkboxes vertically
*/
Expand Down
28 changes: 26 additions & 2 deletions packages/components/src/components/bal-app/bal-app.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
import { Component, Host, h, Event, EventEmitter } from '@stencil/core'
import { Component, Host, h, Event, EventEmitter, Method } from '@stencil/core'
import globalScript from '../../global'
import { isBrowser } from '../../utils/browser'
import { rIC } from '../../utils/helpers'
import { Loggable, Logger, LogInstance } from '../../utils/log'

@Component({
tag: 'bal-app',
})
export class App {
export class App implements Loggable {
private focusVisible?: any
log!: LogInstance

@Logger('bal-app')
createLogger(log: LogInstance) {
this.log = log
}

/**
* @internal
* Tells if the components are ready
*/
@Event({ bubbles: true, composed: true }) balAppLoad!: EventEmitter<boolean>

connectedCallback() {
Expand All @@ -14,6 +28,16 @@ export class App {

componentDidLoad() {
this.balAppLoad.emit(true)
rIC(async () => {
import('../../utils/focus-visible').then(module => (this.focusVisible = module.startFocusVisible()))
})
}

@Method()
async setFocus(elements: HTMLElement[]) {
if (this.focusVisible) {
this.focusVisible.setFocus(elements)
}
}

render() {
Expand Down
Loading

0 comments on commit d044693

Please sign in to comment.