From 94fa82b741eea20f1935ac6ec8bd7de885bc8f50 Mon Sep 17 00:00:00 2001 From: Marcus Eide Date: Fri, 25 Sep 2020 09:58:18 +0200 Subject: [PATCH] Move variant style handling for Infocard to seperate file and use some of it for TabbedCard --- .../core/src/layout/InfoCard/InfoCard.tsx | 74 +--------------- packages/core/src/layout/InfoCard/variants.ts | 86 +++++++++++++++++++ .../layout/TabbedCard/TabbedCard.stories.tsx | 19 ++++ .../core/src/layout/TabbedCard/TabbedCard.tsx | 62 +++++++++---- 4 files changed, 156 insertions(+), 85 deletions(-) create mode 100644 packages/core/src/layout/InfoCard/variants.ts diff --git a/packages/core/src/layout/InfoCard/InfoCard.tsx b/packages/core/src/layout/InfoCard/InfoCard.tsx index 09d31735cd..6665023b9e 100644 --- a/packages/core/src/layout/InfoCard/InfoCard.tsx +++ b/packages/core/src/layout/InfoCard/InfoCard.tsx @@ -28,6 +28,7 @@ import { import classNames from 'classnames'; import { ErrorBoundary } from '../ErrorBoundary'; import { BottomLink, BottomLinkProps } from '../BottomLink'; +import { getVariantStyles } from './variants'; const useStyles = makeStyles(theme => ({ noPadding: { @@ -59,51 +60,6 @@ const CardActionsTopRight = withStyles(theme => ({ }, }))(CardActions); -const VARIANT_STYLES = { - card: { - flex: { - display: 'flex', - flexDirection: 'column', - }, - fullHeight: { - display: 'flex', - flexDirection: 'column', - height: '100%', - }, - height100: { - display: 'flex', - flexDirection: 'column', - height: 'calc(100% - 10px)', // for pages without content header - marginBottom: '10px', - }, - contentheader: { - height: 'calc(100% - 40px)', // for pages with content header - }, - contentheadertabs: { - height: 'calc(100% - 97px)', // for pages with content header and tabs (Tingle) - }, - noShrink: { - flexShrink: 0, - }, - minheight300: { - minHeight: 300, - overflow: 'initial', - }, - }, - cardContent: { - fullHeight: { - flex: 1, - }, - height100: { - flex: 1, - }, - contentRow: { - display: 'flex', - flexDirection: 'row', - }, - }, -}; - /** * InfoCard is used to display a paper-styled block on the screen, similar to a panel. * @@ -163,32 +119,10 @@ export const InfoCard = ({ noPadding, }: Props): JSX.Element => { const classes = useStyles(); - - /** - * If variant is specified, we build up styles for that particular variant for both - * the Card and the CardContent (since these need to be synced) - */ - let calculatedStyle = {}; - let calculatedCardStyle = {}; - - if (variant) { - const variants = variant.split(/[\s]+/g); - variants.forEach(name => { - calculatedStyle = { - ...calculatedStyle, - ...VARIANT_STYLES.card[name as keyof typeof VARIANT_STYLES['card']], - }; - calculatedCardStyle = { - ...calculatedCardStyle, - ...VARIANT_STYLES.cardContent[ - name as keyof typeof VARIANT_STYLES['cardContent'] - ], - }; - }); - } + const { cardStyle, contentStyle } = getVariantStyles(variant); return ( - + {title && ( <> @@ -217,7 +151,7 @@ export const InfoCard = ({ className={classNames(cardClassName, { [classes.noPadding]: noPadding, })} - style={calculatedCardStyle} + style={contentStyle} > {children} diff --git a/packages/core/src/layout/InfoCard/variants.ts b/packages/core/src/layout/InfoCard/variants.ts new file mode 100644 index 0000000000..cc40bb372f --- /dev/null +++ b/packages/core/src/layout/InfoCard/variants.ts @@ -0,0 +1,86 @@ +/* + * 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. + */ + +const VARIANT_STYLES = { + card: { + flex: { + display: 'flex', + flexDirection: 'column', + }, + fullHeight: { + display: 'flex', + flexDirection: 'column', + height: '100%', + }, + height100: { + display: 'flex', + flexDirection: 'column', + height: 'calc(100% - 10px)', // for pages without content header + marginBottom: '10px', + }, + contentheader: { + height: 'calc(100% - 40px)', // for pages with content header + }, + contentheadertabs: { + height: 'calc(100% - 97px)', // for pages with content header and tabs (Tingle) + }, + noShrink: { + flexShrink: 0, + }, + minheight300: { + minHeight: 300, + overflow: 'initial', + }, + flat: { + boxShadow: 'none', + }, + }, + cardContent: { + fullHeight: { + flex: 1, + }, + height100: { + flex: 1, + }, + contentRow: { + display: 'flex', + flexDirection: 'row', + }, + }, +}; + +export const getVariantStyles = (variant?: string): Record => { + const cardStyle = {}; + const contentStyle = {}; + + if (variant) { + const variants = variant.split(/[\s]+/g); + variants.forEach(name => { + Object.assign( + cardStyle, + VARIANT_STYLES.card[name as keyof typeof VARIANT_STYLES['card']], + ); + Object.assign( + contentStyle, + VARIANT_STYLES.cardContent[ + name as keyof typeof VARIANT_STYLES['cardContent'] + ], + ); + }); + } + + return { cardStyle, contentStyle }; +}; diff --git a/packages/core/src/layout/TabbedCard/TabbedCard.stories.tsx b/packages/core/src/layout/TabbedCard/TabbedCard.stories.tsx index 23c2ab5b49..ba5399dad9 100644 --- a/packages/core/src/layout/TabbedCard/TabbedCard.stories.tsx +++ b/packages/core/src/layout/TabbedCard/TabbedCard.stories.tsx @@ -50,6 +50,25 @@ export const Default = () => { ); }; +export const WithSubheader = () => { + return ( + + +
Some content
+
+ +
Some content 2
+
+ +
Some content 3
+
+ +
Some content 4
+
+
+ ); +}; + const linkInfo = { title: 'Go to XYZ Location', link: '#' }; export const WithFooterLink = () => { diff --git a/packages/core/src/layout/TabbedCard/TabbedCard.tsx b/packages/core/src/layout/TabbedCard/TabbedCard.tsx index e1967b8533..7735d7eb8f 100644 --- a/packages/core/src/layout/TabbedCard/TabbedCard.tsx +++ b/packages/core/src/layout/TabbedCard/TabbedCard.tsx @@ -14,13 +14,12 @@ * limitations under the License. */ -import React, { FC, useState, ReactElement, ReactNode } from 'react'; +import React, { useState, ReactElement, ReactNode } from 'react'; import { Card, CardContent, CardHeader, Divider, - withStyles, makeStyles, Tabs, Tab, @@ -28,6 +27,7 @@ import { } from '@material-ui/core'; import { BottomLink, BottomLinkProps } from '../BottomLink'; import { ErrorBoundary } from '../ErrorBoundary'; +import { getVariantStyles } from '../InfoCard/variants'; const useTabsStyles = makeStyles(theme => ({ root: { @@ -38,31 +38,46 @@ const useTabsStyles = makeStyles(theme => ({ backgroundColor: theme.palette.info.main, height: theme.spacing(0.3), }, + header: { + padding: theme.spacing(2, 2, 2, 2.5), + }, + headerTitle: { + fontWeight: 700, + }, + headerSubheader: { + paddingTop: theme.spacing(1), + }, + noPadding: { + padding: 0, + '&:last-child': { + paddingBottom: 0, + }, + }, })); -const BoldHeader = withStyles(theme => ({ - root: { padding: theme.spacing(2, 2, 2, 2.5), display: 'inline-block' }, - title: { fontWeight: 700 }, - subheader: { paddingTop: theme.spacing(1) }, -}))(CardHeader); - type Props = { slackChannel?: string; children?: ReactElement[]; onChange?: (event: React.ChangeEvent<{}>, value: number | string) => void; title?: string; + subheader?: string; value?: number | string; deepLink?: BottomLinkProps; + variant?: string; + noPadding?: boolean; }; -const TabbedCard: FC = ({ +const TabbedCard = ({ slackChannel = '#backstage', children, title, + subheader, deepLink, value, onChange, -}) => { + variant, + noPadding, +}: Props) => { const tabsClasses = useTabsStyles(); const [selectedIndex, selectIndex] = useState(0); @@ -82,19 +97,36 @@ const TabbedCard: FC = ({ }); } + const { cardStyle, contentStyle } = getVariantStyles(variant); + return ( - + - {title && } + {title && ( + + )} {children} - {selectedTabContent} + + {selectedTabContent} + {deepLink && } @@ -118,7 +150,7 @@ type CardTabProps = TabProps & { children: ReactNode; }; -const CardTab: FC = ({ children, ...props }) => { +const CardTab = ({ children, ...props }: CardTabProps) => { const classes = useCardTabStyles(); return ;