feat: Allow GaugeCard to handle multi-line titles
By adding a fullHeightFixedContent variant. Also, add support for a small version. Signed-off-by: Gustaf Räntilä <g.rantila@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Add a fullHeightFixedContent variant of the GaugeCard, and a small size version. Fixed content will vertically align the gauge in the cards, even when the card titles span across multiple lines.
|
||||
@@ -448,6 +448,7 @@ export type GaugeProps = {
|
||||
inverse?: boolean;
|
||||
unit?: string;
|
||||
max?: number;
|
||||
size?: 'normal' | 'small';
|
||||
description?: ReactNode;
|
||||
getColor?: GaugePropsGetColor;
|
||||
};
|
||||
@@ -609,7 +610,11 @@ export type InfoCardClassKey =
|
||||
| 'headerContent';
|
||||
|
||||
// @public (undocumented)
|
||||
export type InfoCardVariants = 'flex' | 'fullHeight' | 'gridItem';
|
||||
export type InfoCardVariants =
|
||||
| 'flex'
|
||||
| 'fullHeight'
|
||||
| 'fullHeightFixedContent'
|
||||
| 'gridItem';
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "ItemCardProps" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "ItemCard" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
|
||||
@@ -19,6 +19,7 @@ import { makeStyles, useTheme } from '@material-ui/core/styles';
|
||||
import { Circle } from 'rc-progress';
|
||||
import React, { ReactNode, useEffect, useState } from 'react';
|
||||
import Box from '@material-ui/core/Box';
|
||||
import classNames from 'classnames';
|
||||
|
||||
/** @public */
|
||||
export type GaugeClassKey =
|
||||
@@ -43,6 +44,9 @@ const useStyles = makeStyles(
|
||||
fontWeight: theme.typography.fontWeightBold,
|
||||
color: theme.palette.textContrast,
|
||||
},
|
||||
overlaySmall: {
|
||||
fontSize: theme.typography.pxToRem(25),
|
||||
},
|
||||
description: {
|
||||
fontSize: '100%',
|
||||
top: '50%',
|
||||
@@ -68,6 +72,7 @@ export type GaugeProps = {
|
||||
inverse?: boolean;
|
||||
unit?: string;
|
||||
max?: number;
|
||||
size?: 'normal' | 'small';
|
||||
description?: ReactNode;
|
||||
getColor?: GaugePropsGetColor;
|
||||
};
|
||||
@@ -121,7 +126,7 @@ export const getProgressColor: GaugePropsGetColor = ({
|
||||
|
||||
export function Gauge(props: GaugeProps) {
|
||||
const [hoverRef, setHoverRef] = useState<HTMLDivElement | null>(null);
|
||||
const { getColor = getProgressColor } = props;
|
||||
const { getColor = getProgressColor, size = 'normal' } = props;
|
||||
const classes = useStyles(props);
|
||||
const { palette } = useTheme();
|
||||
const { value, fractional, inverse, unit, max, description } = {
|
||||
@@ -165,7 +170,12 @@ export function Gauge(props: GaugeProps) {
|
||||
{description && isHovering ? (
|
||||
<Box className={classes.description}>{description}</Box>
|
||||
) : (
|
||||
<Box className={classes.overlay}>
|
||||
<Box
|
||||
className={classNames(
|
||||
classes.overlay,
|
||||
size === 'small' ? classes.overlaySmall : undefined,
|
||||
)}
|
||||
>
|
||||
{isNaN(value) ? 'N/A' : `${asActual}${unit}`}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
@@ -175,6 +175,82 @@ export const InfoMessage = () => (
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
export const AlignedBottom = () => (
|
||||
<Wrapper>
|
||||
<Grid item>
|
||||
<GaugeCard
|
||||
variant="fullHeightFixedContent"
|
||||
title="Progress"
|
||||
subheader="With a subheader"
|
||||
progress={0.3}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<GaugeCard
|
||||
variant="fullHeightFixedContent"
|
||||
title="Progress"
|
||||
subheader="With a subheader"
|
||||
progress={0.57}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<GaugeCard
|
||||
variant="fullHeightFixedContent"
|
||||
title="Progress with longer title"
|
||||
subheader="With a subheader"
|
||||
progress={0.89}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<GaugeCard
|
||||
variant="fullHeightFixedContent"
|
||||
title="Progress"
|
||||
subheader="With a subheader"
|
||||
inverse
|
||||
progress={0.2}
|
||||
/>
|
||||
</Grid>
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
export const Small = () => (
|
||||
<Wrapper>
|
||||
<Grid item>
|
||||
<GaugeCard
|
||||
variant="fullHeightFixedContent"
|
||||
size="small"
|
||||
title="Progress"
|
||||
progress={0.3}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<GaugeCard
|
||||
variant="fullHeightFixedContent"
|
||||
size="small"
|
||||
title="Progress"
|
||||
progress={0.57}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<GaugeCard
|
||||
variant="fullHeightFixedContent"
|
||||
size="small"
|
||||
title="Progress, longer title"
|
||||
progress={0.89}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<GaugeCard
|
||||
variant="fullHeightFixedContent"
|
||||
size="small"
|
||||
title="Progress"
|
||||
inverse
|
||||
progress={0.2}
|
||||
/>
|
||||
</Grid>
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
export const HoverMessage = () => (
|
||||
<Wrapper>
|
||||
<Grid item>
|
||||
|
||||
@@ -27,6 +27,7 @@ type Props = {
|
||||
variant?: InfoCardVariants;
|
||||
/** Progress in % specified as decimal, e.g. "0.23" */
|
||||
progress: number;
|
||||
size?: 'normal' | 'small';
|
||||
description?: ReactNode;
|
||||
icon?: ReactNode;
|
||||
inverse?: boolean;
|
||||
@@ -43,6 +44,10 @@ const useStyles = makeStyles(
|
||||
height: '100%',
|
||||
width: 250,
|
||||
},
|
||||
rootSmall: {
|
||||
height: '100%',
|
||||
width: 160,
|
||||
},
|
||||
},
|
||||
{ name: 'BackstageGaugeCard' },
|
||||
);
|
||||
@@ -64,6 +69,7 @@ export function GaugeCard(props: Props) {
|
||||
description,
|
||||
icon,
|
||||
variant,
|
||||
size = 'normal',
|
||||
getColor,
|
||||
} = props;
|
||||
|
||||
@@ -75,15 +81,22 @@ export function GaugeCard(props: Props) {
|
||||
};
|
||||
|
||||
return (
|
||||
<Box className={classes.root}>
|
||||
<Box className={size === 'small' ? classes.rootSmall : classes.root}>
|
||||
<InfoCard
|
||||
title={title}
|
||||
subheader={subheader}
|
||||
deepLink={deepLink}
|
||||
variant={variant}
|
||||
icon={icon}
|
||||
titleTypographyProps={
|
||||
size === 'small'
|
||||
? {
|
||||
variant: 'h6',
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<Gauge {...gaugeProps} />
|
||||
<Gauge {...gaugeProps} size={size} />
|
||||
</InfoCard>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -46,6 +46,10 @@ const useStyles = makeStyles(
|
||||
header: {
|
||||
padding: theme.spacing(2, 2, 2, 2.5),
|
||||
},
|
||||
headerFixedContent: {
|
||||
flexGrow: 1,
|
||||
alignItems: 'flex-start',
|
||||
},
|
||||
headerTitle: {
|
||||
fontWeight: theme.typography.fontWeightBold,
|
||||
},
|
||||
@@ -87,6 +91,11 @@ const VARIANT_STYLES = {
|
||||
flexDirection: 'column',
|
||||
height: '100%',
|
||||
},
|
||||
fullHeightFixedContent: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100%',
|
||||
},
|
||||
gridItem: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
@@ -102,6 +111,9 @@ const VARIANT_STYLES = {
|
||||
fullHeight: {
|
||||
flex: 1,
|
||||
},
|
||||
fullHeightFixedContent: {
|
||||
flex: '0 1 0%',
|
||||
},
|
||||
gridItem: {
|
||||
flex: 1,
|
||||
},
|
||||
@@ -109,7 +121,11 @@ const VARIANT_STYLES = {
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type InfoCardVariants = 'flex' | 'fullHeight' | 'gridItem';
|
||||
export type InfoCardVariants =
|
||||
| 'flex'
|
||||
| 'fullHeight'
|
||||
| 'fullHeightFixedContent'
|
||||
| 'gridItem';
|
||||
|
||||
/**
|
||||
* InfoCard is used to display a paper-styled block on the screen, similar to a panel.
|
||||
@@ -228,7 +244,12 @@ export function InfoCard(props: Props): JSX.Element {
|
||||
{title && (
|
||||
<CardHeader
|
||||
classes={{
|
||||
root: classes.header,
|
||||
root: classNames(
|
||||
classes.header,
|
||||
variant === 'fullHeightFixedContent'
|
||||
? classes.headerFixedContent
|
||||
: undefined,
|
||||
),
|
||||
title: classes.headerTitle,
|
||||
subheader: classes.headerSubheader,
|
||||
avatar: classes.headerAvatar,
|
||||
|
||||
Reference in New Issue
Block a user