diff --git a/packages/core/src/layout/Header/Header.js b/packages/core/src/layout/Header/Header.js deleted file mode 100644 index f58dce21f7..0000000000 --- a/packages/core/src/layout/Header/Header.js +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import React, { Component, Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { Typography, withStyles, Tooltip } from '@material-ui/core'; -import { Theme } from '../Page/Page'; -// import { Link } from 'shared/components'; -import Waves from './Waves'; -import Helmet from 'react-helmet'; - -class Header extends Component { - static propTypes = { - type: PropTypes.string, - typeLink: PropTypes.string, - title: PropTypes.node.isRequired, - tooltip: PropTypes.string, - subtitle: PropTypes.node, - pageTitleOverride: PropTypes.string, - style: PropTypes.object, - component: PropTypes.object, - }; - - typeFragment() { - const { type, typeLink, classes } = this.props; - if (!type) { - return null; - } - - return typeLink ? ( - // - {type} - ) : ( - // - {type} - ); - } - - titleFragment() { - const { title, pageTitleOverride, classes, tooltip } = this.props; - const FinalTitle = ( - - {title || pageTitleOverride} - - ); - if (tooltip) { - return ( - - {FinalTitle} - - ); - } - return FinalTitle; - } - - subtitleFragment() { - const { subtitle, classes } = this.props; - if (!subtitle) { - return null; - } else if (typeof subtitle !== 'string') { - return subtitle; - } - - return ( - - {subtitle} - - ); - } - - render() { - const { title, pageTitleOverride, children, style, classes } = this.props; - const pageTitle = pageTitleOverride || title; - return ( - - - - {theme => ( -
- -
- {this.typeFragment()} - {this.titleFragment()} - {this.subtitleFragment()} -
-
{children}
-
- )} -
-
- ); - } -} - -const styles = theme => ({ - header: { - gridArea: 'pageHeader', - padding: theme.spacing(3), - minHeight: 118, - width: '100%', - boxShadow: '0 0 8px 3px rgba(20, 20, 20, 0.3)', - position: 'relative', - zIndex: 100, - display: 'flex', - flexDirection: 'row', - flexWrap: 'wrap', - justifyContent: 'flex-end', - alignItems: 'center', - }, - leftItemsBox: { - flex: '1 1 auto', - }, - rightItemsBox: { - flex: '0 1 auto', - display: 'flex', - flexDirection: 'row', - flexWrap: 'wrap', - alignItems: 'center', - marginRight: theme.spacing(6), - }, - title: { - color: theme.palette.bursts.fontColor, - lineHeight: '1.0em', - wordBreak: 'break-all', - fontSize: 'calc(24px + 6 * ((100vw - 320px) / 680))', - marginBottom: theme.spacing(1), - }, - subtitle: { - color: 'rgba(255, 255, 255, 0.8)', - lineHeight: '1.0em', - }, - type: { - textTransform: 'uppercase', - fontSize: 9, - opacity: 0.8, - marginBottom: 10, - color: theme.palette.bursts.fontColor, - }, -}); - -export default withStyles(styles)(Header); diff --git a/packages/core/src/layout/Header/Header.test.js b/packages/core/src/layout/Header/Header.test.tsx similarity index 82% rename from packages/core/src/layout/Header/Header.test.js rename to packages/core/src/layout/Header/Header.test.tsx index 0c30f82aee..5213fe1ac3 100644 --- a/packages/core/src/layout/Header/Header.test.js +++ b/packages/core/src/layout/Header/Header.test.tsx @@ -36,18 +36,24 @@ describe('
', () => { }); it('should override document title', () => { - const rendered = render(wrapInThemedTestApp(
)); + const rendered = render( + wrapInThemedTestApp(
), + ); rendered.getByText('Title1'); rendered.getByText('defaultTitle: Title2 | Backstage'); }); it('should have subtitle', () => { - const rendered = render(wrapInThemedTestApp(
)); + const rendered = render( + wrapInThemedTestApp(
), + ); rendered.getByText('Subtitle'); }); it('should have type rendered', () => { - const rendered = render(wrapInThemedTestApp(
)); + const rendered = render( + wrapInThemedTestApp(
), + ); rendered.getByText('tool'); }); }); diff --git a/packages/core/src/layout/Header/Header.tsx b/packages/core/src/layout/Header/Header.tsx new file mode 100644 index 0000000000..5b3bb7ee60 --- /dev/null +++ b/packages/core/src/layout/Header/Header.tsx @@ -0,0 +1,197 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { Fragment, ReactNode, CSSProperties, FC } from 'react'; +import Helmet from 'react-helmet'; +import { Typography, Tooltip, makeStyles } from '@material-ui/core'; +import { Theme } from '../Page/Page'; +// import { Link } from 'shared/components'; +import { BackstageTheme } from '../../theme/theme'; +import Waves from './Waves'; + +const useStyles = makeStyles(theme => ({ + header: { + gridArea: 'pageHeader', + padding: theme.spacing(3), + minHeight: 118, + width: '100%', + boxShadow: '0 0 8px 3px rgba(20, 20, 20, 0.3)', + position: 'relative', + zIndex: 100, + display: 'flex', + flexDirection: 'row', + flexWrap: 'wrap', + justifyContent: 'flex-end', + alignItems: 'center', + }, + leftItemsBox: { + flex: '1 1 auto', + }, + rightItemsBox: { + flex: '0 1 auto', + display: 'flex', + flexDirection: 'row', + flexWrap: 'wrap', + alignItems: 'center', + marginRight: theme.spacing(6), + }, + title: { + color: theme.palette.bursts.fontColor, + lineHeight: '1.0em', + wordBreak: 'break-all', + fontSize: 'calc(24px + 6 * ((100vw - 320px) / 680))', + marginBottom: theme.spacing(1), + }, + subtitle: { + color: 'rgba(255, 255, 255, 0.8)', + lineHeight: '1.0em', + }, + type: { + textTransform: 'uppercase', + fontSize: 9, + opacity: 0.8, + marginBottom: 10, + color: theme.palette.bursts.fontColor, + }, +})); + +type HeaderStyles = ReturnType; + +type Props = { + component?: ReactNode; + pageTitleOverride?: string; + style?: CSSProperties; + subtitle?: ReactNode; + title: ReactNode; + tooltip?: string; + type?: string; + typeLink?: string; +}; + +type TypeFragmentProps = { + classes: HeaderStyles; + type?: Props['title']; + typeLink?: Props['typeLink']; +}; + +type TitleFragmentProps = { + classes: HeaderStyles; + pageTitle: string | ReactNode; + tooltip?: Props['tooltip']; +}; + +type SubtitleFragmentProps = { + classes: HeaderStyles; + subtitle?: Props['subtitle']; +}; + +const TypeFragment: FC = ({ type, typeLink, classes }) => { + if (!type) { + return null; + } + + if (!typeLink) { + return ( + // + {type} + ); + } + + return ( + // + {type} + ); +}; + +const TitleFragment: FC = ({ + pageTitle, + classes, + tooltip, +}) => { + const FinalTitle = ( + + {pageTitle} + + ); + + if (!tooltip) { + return FinalTitle; + } + + return ( + + {FinalTitle} + + ); +}; + +const SubtitleFragment: FC = ({ classes, subtitle }) => { + if (!subtitle) { + return null; + } + + if (typeof subtitle !== 'string') { + return <>{subtitle}; + } + + return ( + + {subtitle} + + ); +}; + +export const Header: FC = ({ + children, + pageTitleOverride, + style, + subtitle, + title, + tooltip, + type, + typeLink, +}) => { + const classes = useStyles(); + const documentTitle = pageTitleOverride || title; + const pageTitle = title || pageTitleOverride; + const titleTemplate = `${documentTitle} | %s | Backstage`; + const defaultTitle = `${documentTitle} | Backstage`; + + return ( + + + + {theme => ( +
+ +
+ + + +
+
{children}
+
+ )} +
+
+ ); +}; + +export default Header; diff --git a/packages/core/src/theme/theme.d.ts b/packages/core/src/theme/theme.d.ts index db4dfe5e86..7c9f552310 100644 --- a/packages/core/src/theme/theme.d.ts +++ b/packages/core/src/theme/theme.d.ts @@ -39,5 +39,12 @@ export type BackstageTheme = Theme & { linkHover: string; link: string; gold: string; + bursts: { + fontColor: string; + slackChannelText: string; + backgroundColor: { + default: string; + }; + }; }; };