Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EuiModalHeaderTitle] Remove automatic detection of title contents in favor of always wrapping a h1, configurable via new component prop #6530

Merged
merged 5 commits into from
Jan 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`EuiModalHeaderTitle component 1`] = `
<div
class="euiTitle euiModalHeader__title emotion-euiTitle-m"
>
children
</div>
`;

exports[`EuiModalHeaderTitle is rendered 1`] = `
<h1
aria-label="aria-label"
Expand Down
18 changes: 17 additions & 1 deletion src/components/modal/confirm_modal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import React from 'react';
import { mount } from 'enzyme';
import { render } from '../../test/rtl';

import {
findTestSubject,
Expand All @@ -33,7 +34,10 @@ beforeEach(() => {

describe('EuiConfirmModal', () => {
shouldRenderCustomStyles(
<EuiConfirmModal onCancel={() => {}}>children</EuiConfirmModal>
<EuiConfirmModal title="Test" onCancel={() => {}}>
children
</EuiConfirmModal>,
{ childProps: ['titleProps'] }
);

test('renders EuiConfirmModal', () => {
Expand Down Expand Up @@ -196,4 +200,16 @@ describe('EuiConfirmModal', () => {
});
});
});

test('titleProps', () => {
const { baseElement } = render(
<EuiConfirmModal
title="A confirmation modal"
titleProps={{ component: 'div', className: 'titlePropsTest' }}
onCancel={() => {}}
/>
);
const title = baseElement.querySelector('.titlePropsTest');
expect(title?.tagName.toLowerCase()).toEqual('div');
});
});
13 changes: 11 additions & 2 deletions src/components/modal/confirm_modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import React, {
FunctionComponent,
ComponentProps,
ReactNode,
useEffect,
useState,
Expand All @@ -17,7 +18,10 @@ import classnames from 'classnames';
import { EuiModal, EuiModalProps } from './modal';
import { EuiModalFooter } from './modal_footer';
import { EuiModalHeader } from './modal_header';
import { EuiModalHeaderTitle } from './modal_header_title';
import {
EuiModalHeaderTitle,
EuiModalHeaderTitleProps,
} from './modal_header_title';
import { EuiModalBody } from './modal_body';

import { useEuiTheme } from '../../services';
Expand All @@ -34,6 +38,7 @@ export interface EuiConfirmModalProps
*/
children?: ReactNode;
title?: ReactNode;
titleProps?: ComponentProps<EuiModalHeaderTitleProps>;
cancelButtonText?: ReactNode;
confirmButtonText?: ReactNode;
onCancel: (
Expand Down Expand Up @@ -71,6 +76,7 @@ export const CANCEL_BUTTON = 'cancel';
export const EuiConfirmModal: FunctionComponent<EuiConfirmModalProps> = ({
children,
title,
titleProps,
onCancel,
onConfirm,
cancelButtonText,
Expand Down Expand Up @@ -118,7 +124,10 @@ export const EuiConfirmModal: FunctionComponent<EuiConfirmModalProps> = ({
if (title) {
modalTitle = (
<EuiModalHeader>
<EuiModalHeaderTitle data-test-subj="confirmModalTitleText">
<EuiModalHeaderTitle
data-test-subj="confirmModalTitleText"
{...titleProps}
>
{title}
</EuiModalHeaderTitle>
</EuiModalHeader>
Expand Down
13 changes: 10 additions & 3 deletions src/components/modal/modal_header_title.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import React from 'react';
import { render } from 'enzyme';
import { render } from '../../test/rtl';
import { requiredProps } from '../../test/required_props';
import { shouldRenderCustomStyles } from '../../test/internal';

Expand All @@ -17,9 +17,16 @@ describe('EuiModalHeaderTitle', () => {
shouldRenderCustomStyles(<EuiModalHeaderTitle>children</EuiModalHeaderTitle>);

test('is rendered', () => {
const component = (
const { container } = render(
<EuiModalHeaderTitle {...requiredProps}>children</EuiModalHeaderTitle>
);
expect(render(component)).toMatchSnapshot();
expect(container.firstChild).toMatchSnapshot();
});

test('component', () => {
const { container } = render(
<EuiModalHeaderTitle component="div">children</EuiModalHeaderTitle>
);
expect(container.firstChild).toMatchSnapshot();
});
});
14 changes: 11 additions & 3 deletions src/components/modal/modal_header_title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,34 @@
* Side Public License, v 1.
*/

import React, { FunctionComponent, HTMLAttributes } from 'react';
import React, { FunctionComponent, HTMLAttributes, ElementType } from 'react';
import classnames from 'classnames';
import { CommonProps } from '../common';

import { EuiTitle } from '../title';

export type EuiModalHeaderTitleProps = FunctionComponent<
HTMLAttributes<HTMLDivElement> & CommonProps
HTMLAttributes<HTMLHeadingElement> &
CommonProps & {
/**
* The tag to render
* @default h1
*/
component?: ElementType;
}
>;

export const EuiModalHeaderTitle: EuiModalHeaderTitleProps = ({
className,
children,
component: Component = 'h1',
...rest
}) => {
const classes = classnames('euiModalHeader__title', className);

return (
<EuiTitle size="m" className={classes} {...rest}>
{React.isValidElement(children) ? children : <h1>{children}</h1>}
<Component>{children}</Component>
</EuiTitle>
);
};
6 changes: 6 additions & 0 deletions upcoming_changelogs/6530.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- Added the `component` prop to `EuiModalHeaderTitle`, which allows overriding the default `h1` tag
- Added the `titleProps` prop to `EuiConfirmModal`, which allows overriding the default `h1` tag

**Breaking changes**

- `EuiModalHeaderTitle` now **always** wraps its children in a `h1` tag (previously attempted to conditionally detect whether its children were raw strings or not). To change this tag type to, e.g. a more generic `div`, use the new `component` prop.