diff --git a/src-docs/src/views/accordion/accordion_disabled.tsx b/src-docs/src/views/accordion/accordion_disabled.tsx
new file mode 100644
index 00000000000..11c4fa20266
--- /dev/null
+++ b/src-docs/src/views/accordion/accordion_disabled.tsx
@@ -0,0 +1,41 @@
+import React, { useState } from 'react';
+
+import {
+ EuiAccordion,
+ EuiFieldPassword,
+ EuiFormRow,
+ EuiPanel,
+ useGeneratedHtmlId,
+} from '../../../../src';
+
+export default () => {
+ const [passwordValue, setPasswordValue] = useState('');
+ const disabledAccordionId = useGeneratedHtmlId({
+ prefix: 'disabledAccordion',
+ });
+
+ const isInvalid = passwordValue === '';
+
+ return (
+
+
+
+ setPasswordValue(v.currentTarget.value)}
+ />
+
+
+
+ );
+};
diff --git a/src-docs/src/views/accordion/accordion_example.js b/src-docs/src/views/accordion/accordion_example.js
index ff28c277b0a..b48f115c2cd 100644
--- a/src-docs/src/views/accordion/accordion_example.js
+++ b/src-docs/src/views/accordion/accordion_example.js
@@ -89,6 +89,9 @@ const accordionIsLoadingSnippet = [
import AccordionButtonElement from './accordion_buttonElement';
const accordionButtonElementSource = require('!!raw-loader!./accordion_buttonElement');
+import AccordionDisabled from './accordion_disabled';
+const accordionDisabledSource = require('!!raw-loader!./accordion_disabled');
+
export const AccordionExample = {
title: 'Accordion',
intro: (
@@ -314,6 +317,53 @@ export const AccordionExample = {
snippet: accordionIsLoadingSnippet,
demo: ,
},
+ {
+ title: 'Disabled state',
+ source: [
+ {
+ type: GuideSectionTypes.JS,
+ code: accordionDisabledSource,
+ },
+ ],
+ text: (
+ <>
+
+ In some cases you might want to prevent the user from closing the{' '}
+ EuiAccordion . For example, if a form field is
+ displaying an error, opening the accordion and preventing its
+ closure until the error has been addressed will help the user find
+ and fix the error.
+
+
+ The isDisabled prop will disable interaction on
+ the button and the arrow. Use it in conjunction with{' '}
+ initialIsOpen to achieve the desired effect.
+
+
+ When disabling the interaction of accordions based on user
+ input, it's advisable to ensure there is further
+ explanation through the use of help or error text.
+ >
+ }
+ />
+ >
+ ),
+ demo: ,
+ props: { EuiAccordion },
+ snippet: `
+
+
+`,
+ },
{
title: 'When content changes dynamically',
source: [
diff --git a/src-docs/src/views/accordion/playground.js b/src-docs/src/views/accordion/playground.js
index 260c231db53..4dfc963ce87 100644
--- a/src-docs/src/views/accordion/playground.js
+++ b/src-docs/src/views/accordion/playground.js
@@ -21,6 +21,11 @@ export const accordionConfig = () => {
type: PropTypes.String,
};
+ propsToUse.buttonElement = {
+ ...propsToUse.buttonElement,
+ defaultValue: 'button',
+ };
+
propsToUse.id = {
...propsToUse.id,
value: htmlIdGenerator('generated')(),
diff --git a/src/components/accordion/__snapshots__/accordion.test.tsx.snap b/src/components/accordion/__snapshots__/accordion.test.tsx.snap
index e3f1e27bef9..c837f863ea6 100644
--- a/src/components/accordion/__snapshots__/accordion.test.tsx.snap
+++ b/src/components/accordion/__snapshots__/accordion.test.tsx.snap
@@ -8,7 +8,7 @@ exports[`EuiAccordion behavior closes when clicked twice 1`] = `
class="euiAccordion__triggerWrapper emotion-euiAccordion__triggerWrapper"
>
@@ -54,6 +54,62 @@ exports[`EuiAccordion behavior closes when clicked twice 1`] = `
`;
+exports[`EuiAccordion behavior does not open when isDisabled 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+ You cannot see me.
+
+
+
+
+
+`;
+
exports[`EuiAccordion behavior opens when clicked once 1`] = `
@@ -116,7 +172,7 @@ exports[`EuiAccordion behavior opens when div is clicked if element is a div 1`]
class="euiAccordion__triggerWrapper emotion-euiAccordion__triggerWrapper"
>
@@ -214,6 +270,58 @@ exports[`EuiAccordion is rendered 1`] = `
`;
+exports[`EuiAccordion isDisabled is rendered 1`] = `
+
+`;
+
exports[`EuiAccordion props arrowDisplay none is rendered 1`] = `
{
text-decoration: underline;
}
`,
+
+ // Triggering button needs separate `disabled` key because the element that renders may not support `:disabled`;
+ // Hover pseudo selector for specificity
+ disabled: css`
+ &,
+ &:hover {
+ cursor: not-allowed;
+ color: ${euiTheme.colors.disabledText};
+ text-decoration: none;
+ }
+ `,
};
};
diff --git a/src/components/accordion/accordion.test.tsx b/src/components/accordion/accordion.test.tsx
index d8be9c9a74a..6cc19cf896c 100644
--- a/src/components/accordion/accordion.test.tsx
+++ b/src/components/accordion/accordion.test.tsx
@@ -188,6 +188,14 @@ describe('EuiAccordion', () => {
});
});
+ describe('isDisabled', () => {
+ it('is rendered', () => {
+ const component = render(
);
+
+ expect(component).toMatchSnapshot();
+ });
+ });
+
describe('behavior', () => {
it('opens when clicked once', () => {
const component = mount(
@@ -201,6 +209,18 @@ describe('EuiAccordion', () => {
expect(component.render()).toMatchSnapshot();
});
+ it('does not open when isDisabled', () => {
+ const component = mount(
+
+ You cannot see me.
+
+ );
+
+ component.find('button').at(0).simulate('click');
+
+ expect(component.render()).toMatchSnapshot();
+ });
+
it('opens when div is clicked if element is a div', () => {
const component = mount(
diff --git a/src/components/accordion/accordion.tsx b/src/components/accordion/accordion.tsx
index a6aaef40aa5..7b12d2bd34d 100644
--- a/src/components/accordion/accordion.tsx
+++ b/src/components/accordion/accordion.tsx
@@ -110,6 +110,10 @@ export type EuiAccordionProps = CommonProps &
* Choose whether the loading message replaces the content. Customize the message by passing a node
*/
isLoadingMessage?: boolean | ReactNode;
+ /**
+ * Disable the open/close interaction and visually subdues the trigger
+ */
+ isDisabled?: boolean;
};
export class EuiAccordionClass extends Component<
@@ -121,6 +125,7 @@ export class EuiAccordionClass extends Component<
paddingSize: 'none' as const,
arrowDisplay: 'left' as const,
isLoading: false,
+ isDisabled: false,
isLoadingMessage: false,
element: 'div' as const,
buttonElement: 'button' as const,
@@ -206,6 +211,7 @@ export class EuiAccordionClass extends Component<
forceState,
isLoading,
isLoadingMessage,
+ isDisabled,
buttonProps,
buttonElement: _ButtonElement = 'button',
arrowProps,
@@ -263,7 +269,10 @@ export class EuiAccordionClass extends Component<
// Emotion styles
const buttonStyles = euiAccordionButtonStyles(theme);
- const cssButtonStyles = [buttonStyles.euiAccordion__button];
+ const cssButtonStyles = [
+ buttonStyles.euiAccordion__button,
+ isDisabled && buttonStyles.disabled,
+ ];
const childrenStyles = euiAccordionChildrenStyles(theme);
const cssChildrenStyles = [
@@ -313,6 +322,7 @@ export class EuiAccordionClass extends Component<
aria-expanded={isOpen}
aria-labelledby={buttonId}
tabIndex={buttonElementIsFocusable ? -1 : 0}
+ isDisabled={isDisabled}
/>
);
}
@@ -361,8 +371,9 @@ export class EuiAccordionClass extends Component<
css={cssButtonStyles}
aria-controls={id}
aria-expanded={isOpen}
- onClick={this.onToggle}
+ onClick={isDisabled ? undefined : this.onToggle}
type={ButtonElement === 'button' ? 'button' : undefined}
+ disabled={ButtonElement === 'button' ? isDisabled : undefined}
>
{buttonContent}
diff --git a/upcoming_changelogs/6095.md b/upcoming_changelogs/6095.md
new file mode 100644
index 00000000000..b6b4bc593b0
--- /dev/null
+++ b/upcoming_changelogs/6095.md
@@ -0,0 +1 @@
+- Added `isDisabled` prop to `EuiAccordion`