Skip to content

Commit 30a0166

Browse files
author
Luke Bowerman
authored
DialogHeader now supports detail as alternative to default close UI (#1152)
Also adds in support for fontSize, fontWeight properties Validates functionality with InlineEdit as well
1 parent 8af3bd2 commit 30a0166

File tree

5 files changed

+226
-113
lines changed

5 files changed

+226
-113
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [UNRELEASED]
99

10+
### Added
11+
12+
- `DialogHeader`
13+
- Supports `detail` prop as alternative to default `close` icon
14+
- Supports `fontWeight` & `fontSize` for backwards compatibility
15+
1016
### Changed
1117

1218
- `Fieldset` accordion mode auto-indents elements in the inner `AccordionContent`

packages/components/src/Dialog/Layout/DialogHeader.test.tsx

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,40 +26,40 @@
2626

2727
import 'jest-styled-components'
2828
import React from 'react'
29-
import {
30-
assertSnapshot,
31-
mountWithTheme,
32-
renderWithTheme,
33-
} from '@looker/components-test-utils'
34-
import { IconButton } from '../../Button'
29+
import { assertSnapshot, renderWithTheme } from '@looker/components-test-utils'
30+
import { screen } from '@testing-library/react'
3531
import { DialogHeader } from './DialogHeader'
3632

37-
test('DialogHeader', () => {
38-
assertSnapshot(
39-
<DialogHeader id="test-DialogHeader">The Heading for a Dialog</DialogHeader>
40-
)
41-
})
33+
describe('DialogHeader', () => {
34+
test('Snapshot', () => {
35+
assertSnapshot(
36+
<DialogHeader id="test-DialogHeader">
37+
The Heading for a Dialog
38+
</DialogHeader>
39+
)
40+
})
4241

43-
test('DialogHeader passes through DOM props', () => {
44-
const { findByLabelText } = renderWithTheme(
45-
<DialogHeader aria-label="This is the ARIA label">
46-
The Heading for a Dialog
47-
</DialogHeader>
48-
)
42+
test('Passes through DOM props', () => {
43+
renderWithTheme(
44+
<DialogHeader aria-label="ARIA label">Heading</DialogHeader>
45+
)
4946

50-
expect(findByLabelText('This is the ARIA label')).toBeTruthy()
51-
})
47+
expect(screen.findByLabelText('ARIA label')).toBeTruthy()
48+
})
49+
50+
test('Close visible by default', () => {
51+
renderWithTheme(<DialogHeader>Heading</DialogHeader>)
52+
expect(screen.findByText('Close')).toBeTruthy()
53+
})
5254

53-
test('DialogHeader with hideClose', () => {
54-
const withClose = mountWithTheme(
55-
<DialogHeader id="test-DialogHeader">The Heading for a Dialog</DialogHeader>
56-
)
57-
expect(withClose.find(IconButton).exists()).toBeTruthy()
55+
test(`detail`, () => {
56+
renderWithTheme(<DialogHeader detail="Hello world">Header</DialogHeader>)
57+
expect(screen.findByText('Hello world')).toBeTruthy()
58+
expect(screen.queryByLabelText('Close')).toBeNull()
59+
})
5860

59-
const withoutClose = mountWithTheme(
60-
<DialogHeader id="test-DialogHeader" hideClose>
61-
The Heading for a Dialog
62-
</DialogHeader>
63-
)
64-
expect(withoutClose.find(IconButton).exists()).toBeFalsy()
61+
test('hideClose', () => {
62+
renderWithTheme(<DialogHeader hideClose>Heading</DialogHeader>)
63+
expect(screen.queryByLabelText('Close')).toBeNull()
64+
})
6565
})

packages/components/src/Dialog/Layout/DialogHeader.tsx

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
2525
*/
2626

27-
import React, { FC, useContext } from 'react'
27+
import React, { FC, ReactNode, useContext } from 'react'
2828
import { IconNames } from '@looker/icons'
2929
import styled from 'styled-components'
3030
import {
@@ -33,15 +33,19 @@ import {
3333
SpaceProps,
3434
space,
3535
reset,
36+
FontSizeProps,
37+
FontWeightProps,
3638
} from '@looker/design-tokens'
3739
import { IconButton } from '../../Button'
3840
import { Heading } from '../../Text'
3941
import { DialogContext } from '../DialogContext'
4042

4143
export interface DialogHeaderProps
4244
extends SpaceProps,
43-
CompatibleHTMLProps<HTMLElement> {
44-
children: string | string[]
45+
CompatibleHTMLProps<HTMLElement>,
46+
FontSizeProps,
47+
FontWeightProps {
48+
children: ReactNode
4549
/**
4650
* Don't include the "Close" option
4751
* @default false
@@ -51,12 +55,20 @@ export interface DialogHeaderProps
5155
* Specify an icon to be used for close. Defaults to `Close`
5256
*/
5357
closeIcon?: IconNames
58+
59+
/**
60+
* Replaces the built-in `IconButton` (generally used for close) with an arbitrary ReactNode
61+
*/
62+
detail?: ReactNode
5463
}
5564

5665
const DialogHeaderLayout: FC<DialogHeaderProps> = ({
5766
children,
5867
closeIcon = 'Close',
5968
hideClose,
69+
detail,
70+
fontSize,
71+
fontWeight,
6072
...props
6173
}) => {
6274
const { closeModal } = useContext(DialogContext)
@@ -67,28 +79,38 @@ const DialogHeaderLayout: FC<DialogHeaderProps> = ({
6779
<Heading
6880
as="h3"
6981
mr="xlarge"
70-
fontWeight="semiBold"
82+
fontSize={fontSize || undefined}
83+
fontWeight={fontWeight || 'semiBold'}
7184
style={{ gridArea: 'text' }}
7285
truncate
7386
>
7487
{children}
7588
</Heading>
76-
{!hideClose && (
77-
<IconButton
78-
id={id ? `${id}-iconButton` : undefined}
79-
tabIndex={-1}
80-
color="neutral"
81-
size="small"
82-
onClick={closeModal}
83-
label="Close"
84-
icon={closeIcon}
85-
style={{ gridArea: 'close' }}
86-
/>
89+
{detail ? (
90+
<Detail>{detail}</Detail>
91+
) : (
92+
!hideClose && (
93+
<Detail>
94+
<IconButton
95+
id={id ? `${id}-iconButton` : undefined}
96+
tabIndex={-1}
97+
color="neutral"
98+
size="small"
99+
onClick={closeModal}
100+
label="Close"
101+
icon={closeIcon}
102+
/>
103+
</Detail>
104+
)
87105
)}
88106
</header>
89107
)
90108
}
91109

110+
const Detail = styled.div`
111+
grid-area: close;
112+
`
113+
92114
export const DialogHeader = styled(DialogHeaderLayout)`
93115
${reset}
94116
${space}

0 commit comments

Comments
 (0)