Skip to content

Commit b513781

Browse files
authored
Merge pull request #483 from mashmatrix/support-slds-2-page-header
Update `PageHeader` for SLDS2
2 parents 4edd315 + 42a8b4c commit b513781

File tree

2 files changed

+210
-170
lines changed

2 files changed

+210
-170
lines changed

src/scripts/PageHeader.tsx

Lines changed: 148 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import React, { FC } from 'react';
22
import classNames from 'classnames';
3-
4-
import { MediaObject } from './MediaObject';
5-
import { Text, TextProps } from './Text';
6-
import { Grid, Row, Col, GridProps } from './Grid';
7-
import { BreadCrumbs, Crumb } from './BreadCrumbs';
3+
import { TextProps } from './Text';
84

95
/**
106
*
@@ -16,9 +12,9 @@ export const PageHeaderDetailBody: FC<PageHeaderDetailBodyProps> = ({
1612
...props
1713
}) =>
1814
typeof children === 'string' ? (
19-
<Text category='body' type='regular' truncate {...props}>
15+
<div className='slds-truncate' title={children} {...props}>
2016
{children}
21-
</Text>
17+
</div>
2218
) : (
2319
<>{children}</>
2420
);
@@ -33,14 +29,9 @@ export const PageHeaderDetailLabel: FC<PageHeaderDetailLabelProps> = ({
3329
...props
3430
}) =>
3531
typeof children === 'string' ? (
36-
<Text
37-
category='title'
38-
truncate
39-
className='slds-m-bottom_xx-small'
40-
{...props}
41-
>
32+
<div className='slds-text-title slds-truncate' title={children} {...props}>
4233
{children}
43-
</Text>
34+
</div>
4435
) : (
4536
<>{children}</>
4637
);
@@ -70,17 +61,20 @@ export const PageHeaderDetailItem: FC<PageHeaderDetailItemProps> = (props) => {
7061
/**
7162
*
7263
*/
73-
export type PageHeaderDetailProps = GridProps;
64+
export type PageHeaderDetailProps = React.HTMLAttributes<HTMLDivElement>;
7465

75-
export const PageHeaderDetail: FC<GridProps> = ({ children, ...props }) => (
76-
<Grid
77-
tag='ul'
78-
vertical={false}
79-
className='slds-page-header__detail-row'
66+
export const PageHeaderDetail: FC<PageHeaderDetailProps> = ({
67+
children,
68+
...props
69+
}) => (
70+
<div
71+
className='slds-page-header__row slds-page-header__row_gutters'
8072
{...props}
8173
>
82-
{children}
83-
</Grid>
74+
<div className='slds-page-header__col-details'>
75+
<ul className='slds-page-header__detail-row'>{children}</ul>
76+
</div>
77+
</div>
8478
);
8579

8680
/**
@@ -133,82 +127,161 @@ export const PageHeaderHeading: FC<PageHeaderHeadingProps> = (props) => {
133127
} = props;
134128

135129
const infoPart = info ? (
136-
<Text category='body' type='small'>
137-
{info}
138-
</Text>
130+
<p className='slds-page-header__name-meta'>{info}</p>
139131
) : null;
140132

141133
const titlePart =
142134
typeof title === 'string' ? (
143-
<PageHeaderHeadingTitle className='slds-m-right_small'>
144-
{title}
145-
</PageHeaderHeadingTitle>
135+
<div className='slds-page-header__name-title'>
136+
<h1>
137+
{legend && <span>{legend}</span>}
138+
<span className='slds-page-header__title slds-truncate' title={title}>
139+
{title}
140+
</span>
141+
</h1>
142+
</div>
146143
) : (
147-
title
144+
<div className='slds-page-header__name-title'>
145+
<h1>{title}</h1>
146+
</div>
148147
);
149148

150149
let breadCrumbsPart = null;
151150
if (breadCrumbs) {
152-
breadCrumbsPart =
153-
breadCrumbs.length && breadCrumbs[0].type === Crumb ? (
154-
<BreadCrumbs>{breadCrumbs}</BreadCrumbs>
155-
) : (
156-
breadCrumbs
157-
);
151+
breadCrumbsPart = (
152+
<nav role='navigation' aria-label='Breadcrumbs'>
153+
<ol className='slds-breadcrumb slds-list_horizontal slds-wrap'>
154+
{breadCrumbs}
155+
</ol>
156+
</nav>
157+
);
158158
}
159159

160-
const content_ = (
161-
<div>
162-
{breadCrumbsPart}
163-
{legend ? (
164-
<Text category='title' type='caps' className='slds-line-height_reset'>
165-
{legend}
166-
</Text>
167-
) : null}
168-
{leftActions ? (
169-
<Grid vertical={false}>
170-
{titlePart}
171-
<Col className='slds-shrink-none'>{leftActions}</Col>
172-
</Grid>
173-
) : (
174-
titlePart
175-
)}
176-
{!breadCrumbs && !legend && !rightActions ? infoPart : null}
160+
const mediaContent = (
161+
<div className='slds-media__body'>
162+
<div className='slds-page-header__name'>
163+
{titlePart}
164+
{leftActions && (
165+
<div className='slds-page-header__name-switcher slds-is-relative'>
166+
{leftActions}
167+
</div>
168+
)}
169+
</div>
170+
{!breadCrumbs && infoPart}
177171
</div>
178172
);
179-
const content = figure ? (
180-
<MediaObject figureLeft={figure}>{content_}</MediaObject>
181-
) : (
182-
content_
183-
);
184173

185-
return rightActions ? (
186-
<div>
187-
<Grid vertical={false}>
188-
<Col className='slds-has-flexi-truncate'>{content}</Col>
189-
<Col align='top' noFlex>
190-
<Grid>
191-
<Row cols={1}>{rightActions}</Row>
192-
</Grid>
193-
</Col>
194-
</Grid>
195-
{breadCrumbs || legend || rightActions ? infoPart : null}
174+
const mediaObject = figure ? (
175+
<div className='slds-media'>
176+
<div className='slds-media__figure'>
177+
{React.cloneElement(figure, {
178+
className: classNames(
179+
(() => {
180+
const props: unknown = figure.props;
181+
const isPropsObject = typeof props === 'object' && props !== null;
182+
183+
if (
184+
isPropsObject &&
185+
'className' in props &&
186+
typeof props.className === 'string'
187+
) {
188+
return props.className;
189+
} else {
190+
return null;
191+
}
192+
})(),
193+
'slds-page-header__icon'
194+
),
195+
'aria-hidden': 'true',
196+
})}
197+
</div>
198+
{mediaContent}
196199
</div>
197200
) : (
198-
<div>
199-
{content}
200-
{breadCrumbs || legend || rightActions ? infoPart : null}
201+
<div className='slds-media'>{mediaContent}</div>
202+
);
203+
204+
return (
205+
<div className='slds-page-header__row'>
206+
<div className='slds-page-header__col-title'>
207+
{breadCrumbsPart}
208+
{mediaObject}
209+
</div>
210+
{rightActions && (
211+
<div className='slds-page-header__col-actions'>
212+
<div className='slds-page-header__controls'>
213+
{Array.isArray(rightActions) ? (
214+
rightActions.map((action, index) => (
215+
<div key={index} className='slds-page-header__control'>
216+
{action}
217+
</div>
218+
))
219+
) : (
220+
<div className='slds-page-header__control'>{rightActions}</div>
221+
)}
222+
</div>
223+
</div>
224+
)}
201225
</div>
202226
);
203227
};
204228

205229
/**
206230
*
207231
*/
208-
export type PageHeaderProps = React.HTMLAttributes<HTMLDivElement>;
232+
export type PageHeaderMetaProps = {
233+
info?: string;
234+
rightActions?: JSX.Element | Array<JSX.Element>;
235+
} & React.HTMLAttributes<HTMLDivElement>;
209236

210-
export const PageHeader: FC<PageHeaderProps> = (props) => (
211-
<div className='slds-page-header' role='banner' {...props}>
212-
{props.children}
237+
export const PageHeaderMeta: FC<PageHeaderMetaProps> = ({
238+
info,
239+
rightActions,
240+
...props
241+
}) => (
242+
<div className='slds-page-header__row' {...props}>
243+
<div className='slds-page-header__col-meta'>
244+
{info && <p className='slds-page-header__meta-text'>{info}</p>}
245+
</div>
246+
{rightActions && (
247+
<div className='slds-page-header__col-controls'>
248+
<div className='slds-page-header__controls'>
249+
{Array.isArray(rightActions) ? (
250+
rightActions.map((action, index) => (
251+
<div key={index} className='slds-page-header__control'>
252+
{action}
253+
</div>
254+
))
255+
) : (
256+
<div className='slds-page-header__control'>{rightActions}</div>
257+
)}
258+
</div>
259+
</div>
260+
)}
213261
</div>
214262
);
263+
264+
/**
265+
*
266+
*/
267+
export type PageHeaderProps = {
268+
variant?: 'record-home' | 'related-list';
269+
} & React.HTMLAttributes<HTMLDivElement>;
270+
271+
export const PageHeader: FC<PageHeaderProps> = ({
272+
variant,
273+
className,
274+
...props
275+
}) => {
276+
const pageHeaderClassNames = classNames(
277+
'slds-page-header',
278+
variant ? `slds-page-header_${variant}` : null,
279+
className
280+
);
281+
282+
return (
283+
<div className={pageHeaderClassNames} role='banner' {...props}>
284+
{props.children}
285+
</div>
286+
);
287+
};

0 commit comments

Comments
 (0)