Skip to content

Commit bd3cc8a

Browse files
author
Luke Bowerman
authored
Improvements to Modal layout helpers (#1025)
* Improvements to Modal layout helpers
1 parent 756ff15 commit bd3cc8a

File tree

7 files changed

+126
-53
lines changed

7 files changed

+126
-53
lines changed

CHANGELOG.md

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

1414
### Changed
1515

16+
- `ModalContent`
17+
- Tweaked the presentation of overflow state (simple border on top, more subtle shadow + border at bottom)
18+
- now supports `borderBottom` that will always display a border at the bottom of the content area regardless of whether the content overflows the container.
19+
- `ModalFooter` now leverages `Space` components internally
20+
- `ModalHeader` refactored to invert Styled Components usage
1621
- `SpaceVertical` now has `align=stretch` by default
1722

1823
### Fixed

packages/components/src/Modal/Layout/ModalContent.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export interface ModalContentProps
4646
* touch the container edges.
4747
*/
4848
innerProps?: SpaceProps
49+
50+
borderBottom?: boolean
4951
}
5052

5153
interface ContentState {
@@ -77,14 +79,21 @@ class Internal extends Component<InternalContentProps, ContentState> {
7779
}
7880

7981
public render() {
80-
const { children, className, innerProps, ...props } = this.props
82+
const {
83+
borderBottom,
84+
children,
85+
className,
86+
innerProps,
87+
...props
88+
} = this.props
8189

8290
if (innerProps && innerProps.p && !innerProps.px) {
8391
innerProps.px = innerProps.p
8492
}
8593

8694
return (
8795
<Outer
96+
borderBottom={borderBottom}
8897
className={`${className} ${this.state.overflow && 'overflow'}`}
8998
ref={this.ref}
9099
{...omit(props, ['renderedHeight'])}
@@ -103,16 +112,19 @@ export const ModalContent = (props: ModalContentProps) => {
103112
)
104113
}
105114

106-
const Outer = styled.div`
115+
const Outer = styled.div<{ borderBottom?: boolean }>`
107116
${reset}
108117
${layout}
109118
110119
overflow: auto;
111120
flex: 8;
121+
${({ borderBottom, theme: { colors } }) =>
122+
borderBottom && `border-bottom: 1px solid ${colors.ui2}`};
112123
113124
&.overflow {
114-
box-shadow: inset 0 -16px 16px -16px ${({ theme }) => theme.colors.ui2},
115-
inset 0 16px 16px -16px ${({ theme }) => theme.colors.ui2};
125+
border-bottom: 1px solid ${({ theme }) => theme.colors.ui2};
126+
border-top: 1px solid ${({ theme }) => theme.colors.ui2};
127+
box-shadow: inset 0 -4px 4px -4px ${({ theme }) => theme.colors.ui2};
116128
}
117129
`
118130

packages/components/src/Modal/Layout/ModalFooter.tsx

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,42 +27,33 @@
2727
import React, { FC, ReactNode } from 'react'
2828
import styled from 'styled-components'
2929
import { CompatibleHTMLProps } from '@looker/design-tokens'
30-
import { SpaceProps, space } from 'styled-system'
30+
import { Space, SpaceHelperProps } from '../../Layout/Space'
3131

32-
export interface ModalFooterProps extends CompatibleHTMLProps<HTMLDivElement> {
32+
export interface ModalFooterProps
33+
extends CompatibleHTMLProps<HTMLDivElement>,
34+
SpaceHelperProps {
3335
/**
3436
* Secondary content to place in the footer
3537
*/
3638
secondary?: ReactNode
3739
}
3840

39-
export const ModalFooter: FC<ModalFooterProps> = ({
41+
export const ModalFooterLayout: FC<ModalFooterProps> = ({
4042
children,
4143
secondary,
4244
...props
4345
}) => {
4446
return (
45-
<Layout {...props}>
46-
<SpaceChildren>{children}</SpaceChildren>
47-
{secondary && <SpaceChildren mr="auto">{secondary}</SpaceChildren>}
48-
</Layout>
47+
<Space as="footer" reverse between {...props}>
48+
<Space reverse>{children}</Space>
49+
{secondary && <Space>{secondary}</Space>}
50+
</Space>
4951
)
5052
}
5153

52-
const Layout = styled.footer`
53-
align-items: center;
54-
display: flex;
55-
flex-direction: row-reverse;
56-
padding: ${({ theme }) => `${theme.space.large} ${theme.space.xlarge}`};
57-
`
54+
export const ModalFooter = styled(ModalFooterLayout)``
5855

59-
const SpaceChildren = styled.div<SpaceProps>`
60-
${space};
61-
display: grid;
62-
grid-gap: ${({ theme }) => theme.space.medium};
63-
grid-auto-flow: column;
64-
direction: rtl; /* Grid equivalent to flex-direction: row-reverse */
65-
* {
66-
direction: ltr;
67-
}
68-
`
56+
ModalFooter.defaultProps = {
57+
px: 'xlarge',
58+
py: 'large',
59+
}

packages/components/src/Modal/Layout/ModalHeader.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,22 @@ export interface ModalHeaderProps
5656
* Render an icon next to the title text
5757
*/
5858
headerIcon?: ReactElement<IconProps>
59+
60+
className?: string
5961
}
6062

61-
export const ModalHeader: FC<ModalHeaderProps> = ({
63+
const ModalHeaderLayout: FC<ModalHeaderProps> = ({
64+
className,
6265
children,
6366
closeIcon = 'Close',
6467
hideClose,
6568
headerIcon,
6669
id,
67-
...props
6870
}) => {
6971
const { closeModal } = useContext(ModalContext)
7072

7173
return (
72-
<Header {...props}>
74+
<header className={className}>
7375
{headerIcon && <HeaderIconWrapper>{headerIcon}</HeaderIconWrapper>}
7476
<Heading
7577
as="h3"
@@ -92,19 +94,19 @@ export const ModalHeader: FC<ModalHeaderProps> = ({
9294
style={{ gridArea: 'close' }}
9395
/>
9496
)}
95-
</Header>
97+
</header>
9698
)
9799
}
98100

99-
const Header = styled.header<SpaceProps>`
101+
export const ModalHeader = styled(ModalHeaderLayout)`
100102
${reset}
101103
${space}
102104
display: grid;
103105
grid-template-columns: [icon] auto [text] 1fr [close] auto;
104106
align-items: center;
105107
`
106108

107-
Header.defaultProps = {
109+
ModalHeader.defaultProps = {
108110
p: 'large',
109111
pr: 'medium',
110112
px: 'xlarge',

packages/components/src/Modal/Layout/__snapshots__/ModalContent.test.tsx.snap

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ exports[`ModalContent - no overflow 1`] = `
99
}
1010
1111
.c0.overflow {
12-
box-shadow: inset 0 -16px 16px -16px #DEE1E5, inset 0 16px 16px -16px #DEE1E5;
12+
border-bottom: 1px solid #DEE1E5;
13+
border-top: 1px solid #DEE1E5;
14+
box-shadow: inset 0 -4px 4px -4px #DEE1E5;
1315
}
1416
1517
.c1 {
@@ -39,7 +41,9 @@ exports[`ModalContent - no overflow 2`] = `
3941
}
4042
4143
.c0.overflow {
42-
box-shadow: inset 0 -16px 16px -16px #DEE1E5, inset 0 16px 16px -16px #DEE1E5;
44+
border-bottom: 1px solid #DEE1E5;
45+
border-top: 1px solid #DEE1E5;
46+
box-shadow: inset 0 -4px 4px -4px #DEE1E5;
4347
}
4448
4549
.c1 {

packages/components/src/Modal/Layout/__snapshots__/ModalFooter.test.tsx.snap

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
exports[`ModalFooter with Button 1`] = `
44
.c0 {
5+
width: 100%;
6+
padding-left: 2rem;
7+
padding-right: 2rem;
8+
padding-top: 1.25rem;
9+
padding-bottom: 1.25rem;
510
-webkit-align-items: center;
611
-webkit-box-align: center;
712
-ms-flex-align: center;
@@ -13,25 +18,42 @@ exports[`ModalFooter with Button 1`] = `
1318
-webkit-flex-direction: row-reverse;
1419
-ms-flex-direction: row-reverse;
1520
flex-direction: row-reverse;
16-
padding: 1.25rem 2rem;
21+
-webkit-box-pack: justify;
22+
-webkit-justify-content: space-between;
23+
-ms-flex-pack: justify;
24+
justify-content: space-between;
1725
}
1826
1927
.c1 {
20-
display: grid;
21-
grid-gap: 1rem;
22-
grid-auto-flow: column;
23-
direction: rtl;
28+
width: 100%;
29+
-webkit-align-items: center;
30+
-webkit-box-align: center;
31+
-ms-flex-align: center;
32+
align-items: center;
33+
display: -webkit-box;
34+
display: -webkit-flex;
35+
display: -ms-flexbox;
36+
display: flex;
37+
-webkit-flex-direction: row-reverse;
38+
-ms-flex-direction: row-reverse;
39+
flex-direction: row-reverse;
40+
}
41+
42+
.c1.c1 > * {
43+
margin-left: 1rem;
2444
}
2545
26-
.c1 * {
27-
direction: ltr;
46+
.c1.c1 > *:last-child {
47+
margin-left: 0rem;
2848
}
2949
3050
<footer
31-
className="c0"
51+
className="c0 "
52+
width="100%"
3253
>
3354
<div
3455
className="c1"
56+
width="100%"
3557
>
3658
<button>
3759
Cancel
@@ -42,6 +64,11 @@ exports[`ModalFooter with Button 1`] = `
4264

4365
exports[`ModalFooter with ModalContext 1`] = `
4466
.c0 {
67+
width: 100%;
68+
padding-left: 2rem;
69+
padding-right: 2rem;
70+
padding-top: 1.25rem;
71+
padding-bottom: 1.25rem;
4572
-webkit-align-items: center;
4673
-webkit-box-align: center;
4774
-ms-flex-align: center;
@@ -53,25 +80,42 @@ exports[`ModalFooter with ModalContext 1`] = `
5380
-webkit-flex-direction: row-reverse;
5481
-ms-flex-direction: row-reverse;
5582
flex-direction: row-reverse;
56-
padding: 1.25rem 2rem;
83+
-webkit-box-pack: justify;
84+
-webkit-justify-content: space-between;
85+
-ms-flex-pack: justify;
86+
justify-content: space-between;
5787
}
5888
5989
.c1 {
60-
display: grid;
61-
grid-gap: 1rem;
62-
grid-auto-flow: column;
63-
direction: rtl;
90+
width: 100%;
91+
-webkit-align-items: center;
92+
-webkit-box-align: center;
93+
-ms-flex-align: center;
94+
align-items: center;
95+
display: -webkit-box;
96+
display: -webkit-flex;
97+
display: -ms-flexbox;
98+
display: flex;
99+
-webkit-flex-direction: row-reverse;
100+
-ms-flex-direction: row-reverse;
101+
flex-direction: row-reverse;
102+
}
103+
104+
.c1.c1 > * {
105+
margin-left: 1rem;
64106
}
65107
66-
.c1 * {
67-
direction: ltr;
108+
.c1.c1 > *:last-child {
109+
margin-left: 0rem;
68110
}
69111
70112
<footer
71-
className="c0"
113+
className="c0 "
114+
width="100%"
72115
>
73116
<div
74117
className="c1"
118+
width="100%"
75119
>
76120
<button>
77121
Cancel

packages/www/src/documentation/components/modals/dialog.mdx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,25 @@ Dialogs break out of the standard application flow and UI to present new informa
2424
return (
2525
<div>
2626
<Dialog isOpen={value} onClose={() => setOff()}>
27+
<ModalHeader>A Dialog Example</ModalHeader>
2728
<ModalContent>
28-
<Paragraph>Some content inside the Dialog</Paragraph>
29-
<Button>A button too!</Button>
29+
<SpaceVertical>
30+
<Paragraph>
31+
{`Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin pellentesque dui sodales efficitur vehicula. Praesent at aliquet nisi. Fusce risus quam, scelerisque non lacus mollis, feugiat molestie sem. Praesent augue erat, molestie id sem quis, fermentum venenatis lacus. Morbi vehicula lacus id fringilla scelerisque. Nulla dignissim nisi nisl, ac porttitor orci accumsan nec. Vestibulum pulvinar risus felis, vel bibendum odio luctus a. Morbi pharetra, ipsum sit amet vehicula malesuada, lacus quam viverra sapien, eget malesuada sem risus quis ligula. Vestibulum non laoreet est. Nullam blandit sollicitudin cursus. Nam cursus nisl id ipsum ullamcorper consequat.`}
32+
</Paragraph>
33+
<Paragraph>
34+
{`Aenean consectetur volutpat dolor id varius. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nam mollis, sapien sit amet suscipit consectetur, odio metus malesuada arcu, et eleifend nisi lorem eu diam. Praesent malesuada finibus finibus. Suspendisse eu lobortis ante, sed gravida odio. Nam auctor eros nulla. Praesent maximus ligula quam, et pretium lacus vulputate non. Donec condimentum turpis vitae mi volutpat malesuada. Nam sagittis non metus in efficitur. Vestibulum commodo nibh velit, sed luctus felis condimentum non.`}
35+
`
36+
</Paragraph>
37+
<Paragraph>
38+
{`Aenean consectetur volutpat dolor id varius. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nam mollis, sapien sit amet suscipit consectetur, odio metus malesuada arcu, et eleifend nisi lorem eu diam. Praesent malesuada finibus finibus. Suspendisse eu lobortis ante, sed gravida odio. Nam auctor eros nulla. Praesent maximus ligula quam, et pretium lacus vulputate non. Donec condimentum turpis vitae mi volutpat malesuada. Nam sagittis non metus in efficitur. Vestibulum commodo nibh velit, sed luctus felis condimentum non.`}
39+
</Paragraph>
40+
</SpaceVertical>
3041
</ModalContent>
42+
<ModalFooter>
43+
<Button>Close Example Dialog</Button>
44+
<ButtonTransparent color="neutral">Cancel</ButtonTransparent>
45+
</ModalFooter>
3146
</Dialog>
3247
<Button onClick={() => setOn()}>Open Dialog</Button>
3348
</div>

0 commit comments

Comments
 (0)