Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

Commit e57e61c

Browse files
authored
feat(Accordion): disabled accordion title (#2290)
* disabled accordion title
1 parent ec4dd3f commit e57e61c

File tree

5 files changed

+60
-5
lines changed

5 files changed

+60
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
4444
- Add optional wrapper function to `List` which can be used to inject custom scrollbars to `Dropdown` @jurokapsiar ([#2092](https://github.com/microsoft/fluent-ui-react/pull/2092))
4545
- Add `useTelemetry()` hook for adding telemetry information for the Fluent components and improve return types for the `useStyles` and `useStateManager` hooks @mnajdova ([#2257](https://github.com/microsoft/fluent-ui-react/pull/2257))
4646
- Add `target` prop to `EventListener` component and `useEventListener()` hook @layershifter ([#2287](https://github.com/microsoft/fluent-ui-react/pull/2287))
47+
- Add `disabled` prop accordion title @jurokapsiar ([#2290](https://github.com/microsoft/fluent-ui-react/pull/2290))
4748

4849
### Documentation
4950
- Add per-component performance charts @miroslavstastny ([#2240](https://github.com/microsoft/fluent-ui-react/pull/2240))

packages/accessibility/src/behaviors/Accordion/accordionTitleBehavior.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Accessibility } from '../../types'
44
/**
55
* @description
66
* Adds accessibility attributed to implement the Accordion design pattern.
7-
* Adds 'aria-disabled' to the 'content' slot with a value based on active and canBeCollapsed props.
7+
* Adds 'aria-disabled' to the 'content' slot with a value based on disabled, active and canBeCollapsed props.
88
* Adds role='heading' and aria-level='3' if the element type is not a header.
99
*
1010
* @specification
@@ -16,6 +16,7 @@ import { Accessibility } from '../../types'
1616
*/
1717
const accordionTitleBehavior: Accessibility<AccordionTitleBehaviorProps> = props => {
1818
const isHeading = /(h\d{1})$/.test(props.as)
19+
const forcedOpen = props.active && !props.canBeCollapsed
1920
return {
2021
attributes: {
2122
root: {
@@ -24,7 +25,7 @@ const accordionTitleBehavior: Accessibility<AccordionTitleBehaviorProps> = props
2425
},
2526
content: {
2627
'aria-expanded': !!props.active,
27-
'aria-disabled': !!(props.active && !props.canBeCollapsed),
28+
'aria-disabled': !!(forcedOpen || props.disabled),
2829
'aria-controls': props.accordionContentId,
2930
role: 'button',
3031
tabIndex: 0,
@@ -49,6 +50,8 @@ type AccordionTitleBehaviorProps = {
4950
active?: boolean
5051
/** If at least one panel needs to stay active and this title does not correspond to the last active one. */
5152
canBeCollapsed?: boolean
53+
/** An accordion title can show it is currently unable to be interacted with. */
54+
disabled?: boolean
5255
/** Id of the content it owns. */
5356
accordionContentId?: string
5457
}

packages/react/src/components/Accordion/AccordionTitle.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ export interface AccordionTitleProps
3838
/** If at least one panel needs to stay active and this title does not correspond to the last active one. */
3939
canBeCollapsed?: boolean
4040

41+
/** An accordion title can show it is currently unable to be interacted with. */
42+
disabled?: boolean
43+
4144
/** AccordionTitle index inside Accordion. */
4245
index?: number
4346

@@ -78,6 +81,7 @@ class AccordionTitle extends UIComponent<WithAsProp<AccordionTitleProps>, any> {
7881
active: PropTypes.bool,
7982
contentRef: customPropTypes.ref,
8083
canBeCollapsed: PropTypes.bool,
84+
disabled: PropTypes.bool,
8185
index: PropTypes.number,
8286
onClick: PropTypes.func,
8387
indicator: customPropTypes.itemShorthand,
@@ -97,7 +101,9 @@ class AccordionTitle extends UIComponent<WithAsProp<AccordionTitleProps>, any> {
97101
}
98102

99103
handleClick = (e: React.SyntheticEvent) => {
100-
_.invoke(this.props, 'onClick', e, this.props)
104+
if (!this.props.disabled) {
105+
_.invoke(this.props, 'onClick', e, this.props)
106+
}
101107
}
102108

103109
handleFocus = (e: React.SyntheticEvent) => {

packages/react/src/themes/teams/components/Accordion/accordionTitleStyles.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { ComponentSlotStylesPrepared } from '@fluentui/styles'
22
import { AccordionTitleProps } from '../../../../components/Accordion/AccordionTitle'
33

44
const accordionTitleStyles: ComponentSlotStylesPrepared<AccordionTitleProps> = {
5-
root: () => ({
5+
root: ({ props: p }) => ({
66
display: 'inline-block',
77
verticalAlign: 'middle',
88
padding: '.5rem 0',
9-
cursor: 'pointer',
9+
cursor: p.disabled ? 'default' : 'pointer',
1010
}),
1111
indicator: () => ({
1212
userSelect: 'none',

packages/react/test/specs/components/Accordion/AccordionTitle-test.tsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import * as React from 'react'
2+
import * as keyboardKey from 'keyboard-key'
13
import AccordionTitle from 'src/components/Accordion/AccordionTitle'
24
import { isConformant, handlesAccessibility } from 'test/specs/commonTests'
5+
import { mountWithProvider } from 'test/utils'
36

47
describe('AccordionTitle', () => {
58
isConformant(AccordionTitle, {
@@ -21,4 +24,46 @@ describe('AccordionTitle', () => {
2124
})
2225
})
2326
})
27+
28+
const getContent = wrapper => wrapper.find(`div.${AccordionTitle.slotClassNames.content}`)
29+
30+
describe('click handler', () => {
31+
it('is called on click', () => {
32+
const onClick = jest.fn()
33+
const wrapper = mountWithProvider(<AccordionTitle onClick={onClick} />)
34+
35+
getContent(wrapper).simulate('click')
36+
expect(onClick).toHaveBeenCalled()
37+
})
38+
39+
it('is not called on click for disabled title', () => {
40+
const onClick = jest.fn()
41+
const wrapper = mountWithProvider(<AccordionTitle onClick={onClick} disabled={true} />)
42+
43+
getContent(wrapper).simulate('click')
44+
expect(onClick).not.toHaveBeenCalled()
45+
})
46+
})
47+
48+
describe('Enter key', () => {
49+
it('calls onClick', () => {
50+
const onClick = jest.fn()
51+
const wrapper = mountWithProvider(<AccordionTitle onClick={onClick} />)
52+
53+
getContent(wrapper).simulate('keydown', {
54+
keyCode: keyboardKey.Enter,
55+
})
56+
expect(onClick).toHaveBeenCalled()
57+
})
58+
59+
it('does not call onClick for disabled title', () => {
60+
const onClick = jest.fn()
61+
const wrapper = mountWithProvider(<AccordionTitle onClick={onClick} disabled={true} />)
62+
63+
getContent(wrapper).simulate('keydown', {
64+
keyCode: keyboardKey.Enter,
65+
})
66+
expect(onClick).not.toHaveBeenCalled()
67+
})
68+
})
2469
})

0 commit comments

Comments
 (0)