Skip to content

Commit

Permalink
[EuiCallOut] Add onDismiss prop (#7156)
Browse files Browse the repository at this point in the history
Co-authored-by: Bree Hall <[email protected]>
Co-authored-by: Cee Chen <[email protected]>
  • Loading branch information
3 people authored Sep 25, 2023
1 parent 4dcb28e commit 4a83e0e
Show file tree
Hide file tree
Showing 9 changed files with 259 additions and 56 deletions.
27 changes: 27 additions & 0 deletions src-docs/src/views/call_out/call_out_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ const dangerSnippet = [
`,
];

import OnDismiss from './on_dismiss';
const onDismissSource = require('!!raw-loader!./on_dismiss');
const onDismissSnippet = [
`<EuiCallOut onDismiss={onDismiss}>
<p><!-- Content --></p>
</EuiCallOut>
`,
];

export const CallOutExample = {
title: 'Callout',
intro: (
Expand Down Expand Up @@ -164,5 +173,23 @@ export const CallOutExample = {
snippet: dangerSnippet,
demo: <Danger />,
},
{
title: 'Dismissible callouts',
source: [
{
type: GuideSectionTypes.TSX,
code: onDismissSource,
},
],
text: (
<p>
To render a cross icon in the top right hand corner, pass an{' '}
<EuiCode>onDismiss</EuiCode> callback that handles conditionally
rendering your callout.
</p>
),
snippet: onDismissSnippet,
demo: <OnDismiss />,
},
],
};
86 changes: 86 additions & 0 deletions src-docs/src/views/call_out/on_dismiss.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React, { useState } from 'react';

import {
EuiFlexGroup,
EuiSwitch,
EuiSpacer,
EuiButtonEmpty,
EuiCallOut,
} from '../../../../src';

export default () => {
const [showCallOut, setShowCallOut] = useState(
!localStorage.getItem('EuiCallOutOnDismissDemo')
);
const onDismiss = () => {
setShowCallOut(false);
localStorage.setItem('EuiCallOutOnDismissDemo', 'hidden');
};
const resetDemo = () => {
setShowCallOut(true);
localStorage.setItem('EuiCallOutOnDismissDemo', '');
};

// UI toggles
const [showTitle, setShowTitle] = useState(true);
const [showChildren, setShowChildren] = useState(true);
const [smallSize, setSmallSize] = useState(false);

return (
<div css={{ maxInlineSize: 500 }}>
<EuiFlexGroup>
<EuiSwitch
label="Show title"
checked={showTitle}
onChange={(e) => setShowTitle(e.target.checked)}
compressed
/>
<EuiSwitch
label="Show children"
checked={showChildren}
onChange={(e) => setShowChildren(e.target.checked)}
compressed
/>
<EuiSwitch
label="Small size"
checked={smallSize}
onChange={(e) => setSmallSize(e.target.checked)}
compressed
/>
</EuiFlexGroup>
<EuiSpacer />
{showCallOut ? (
<EuiCallOut
onDismiss={onDismiss}
iconType="iInCircle"
title={
showTitle
? 'You can dismiss this callout by clicking the Close button in the top right corner'
: ''
}
size={smallSize ? 's' : 'm'}
>
{showChildren && (
<>
<p>
Here’s more some stuff users need to know. But maybe users don't
need to know it on every page refresh, so you could remember
whether or not to display this callout in local storage.
</p>
{!showTitle && (
<p>
This second paragraph is here to demonstrate that only the
first one needs to account for the dismiss button in width.
</p>
)}
</>
)}
</EuiCallOut>
) : (
<EuiButtonEmpty onClick={resetDemo}>
The callout has been dismissed. Click to reset the demo
</EuiButtonEmpty>
)}
</div>
);
};
7 changes: 7 additions & 0 deletions src-docs/src/views/call_out/playground.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { EuiCallOut, EuiText } from '../../../../src/components/';
import {
propUtilityForPlayground,
iconValidator,
simulateFunction,
dummyFunction,
} from '../../services/playground';

export default () => {
Expand All @@ -29,6 +31,8 @@ export default () => {
hidden: false,
};

propsToUse.onDismiss = simulateFunction(propsToUse.onDismiss);

return {
config: {
componentName: 'EuiCallOut',
Expand All @@ -42,6 +46,9 @@ export default () => {
named: ['EuiCallOut', 'EuiText'],
},
},
customProps: {
onDismiss: dummyFunction,
},
},
};
};
7 changes: 5 additions & 2 deletions src/components/call_out/__snapshots__/call_out.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ exports[`EuiCallOut is rendered 1`] = `
data-test-subj="test subject string"
>
<div
class="euiText emotion-euiText-s-euiTextColor-default-euiCallOut__description"
class="euiText emotion-euiText-s-euiTextColor-default"
>
Content
</div>
Expand Down Expand Up @@ -96,7 +96,10 @@ exports[`EuiCallOut props title is rendered 1`] = `
Title
</p>
<div
class="euiText emotion-euiText-s-euiTextColor-default-euiCallOut__description"
class="euiSpacer euiSpacer--s emotion-euiSpacer-s"
/>
<div
class="euiText emotion-euiText-s-euiTextColor-default"
>
Content
</div>
Expand Down
40 changes: 33 additions & 7 deletions src/components/call_out/call_out.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,44 @@ import { UseEuiTheme } from '../../services';

export const euiCallOutStyles = ({ euiTheme }: UseEuiTheme) => {
return {
euiCallOut: css``,
euiCallOut: css`
position: relative;
`,
hasDismissButton: {
// Ensure that only the top-most (first-child) title or child text
// has a padding-right on it (to account for the dismiss button)
hasDimissButton: css`
& > :first-child:is(.euiTitle),
& > :first-child:is(.euiText) > :first-child {
${logicalCSS('padding-right', euiTheme.size.base)}
}
`,
// Ensure the callout always has enough height for the button
s: css`
${logicalCSS('min-height', euiTheme.size.xl)}
`,
m: css`
${logicalCSS('min-height', euiTheme.size.xxl)}
`,
},
dismissButton: {
euiCallOut__dismissButton: css`
position: absolute;
`,
s: css`
${logicalCSS('top', euiTheme.size.xs)}
${logicalCSS('right', euiTheme.size.xs)}
`,
m: css`
${logicalCSS('top', euiTheme.size.s)}
${logicalCSS('right', euiTheme.size.s)}
`,
},
euiCallOut__icon: css`
position: relative;
${logicalCSS('top', '-1px')}
${logicalCSS('margin-right', euiTheme.size.s)}
`,
euiCallOut__description: css`
:not(:only-child) {
${logicalCSS('margin-top', euiTheme.size.s)}
}
`,
};
};

Expand All @@ -36,7 +63,6 @@ export const euiCallOutHeadingStyles = ({ euiTheme }: UseEuiTheme) => {
// In case it's nested inside EuiText
)}
`,

primary: css`
color: ${euiTheme.colors.primaryText};
`,
Expand Down
11 changes: 11 additions & 0 deletions src/components/call_out/call_out.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import React from 'react';
import { fireEvent } from '@testing-library/react';
import { requiredProps } from '../../test/required_props';
import { render } from '../../test/rtl';

Expand Down Expand Up @@ -59,5 +60,15 @@ describe('EuiCallOut', () => {
});
});
});

test('onDismiss', () => {
const onDismiss = jest.fn();
const { getByTestSubject } = render(
<EuiCallOut onDismiss={onDismiss}>Content</EuiCallOut>
);

fireEvent.click(getByTestSubject('euiDismissCalloutButton'));
expect(onDismiss).toHaveBeenCalledTimes(1);
});
});
});
Loading

0 comments on commit 4a83e0e

Please sign in to comment.