feat: Apply component guidelines for @backstage/core-components for src/components

Signed-off-by: Carlos Esteban Lopez <lcarlosesteb@vmware.com>
This commit is contained in:
Carlos Esteban Lopez
2022-11-16 14:12:38 -05:00
committed by Carlos Lopez
parent 80d9674a4a
commit 830687539f
35 changed files with 271 additions and 205 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-components': patch
---
Sync components in @backstage/core-components with the Component Design Guidelines
@@ -13,14 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useEffect, useState } from 'react';
import Snackbar from '@material-ui/core/Snackbar';
import { alertApiRef, AlertMessage, useApi } from '@backstage/core-plugin-api';
import IconButton from '@material-ui/core/IconButton';
import Snackbar from '@material-ui/core/Snackbar';
import Typography from '@material-ui/core/Typography';
import CloseIcon from '@material-ui/icons/Close';
import { Alert } from '@material-ui/lab';
import { AlertMessage, useApi, alertApiRef } from '@backstage/core-plugin-api';
import pluralize from 'pluralize';
import React, { useEffect, useState } from 'react';
// TODO: improve on this and promote to a shared component for use by all apps.
/** @public */
export type AlertDisplayProps = {
anchorOrigin?: {
vertical: 'top' | 'bottom';
horizontal: 'left' | 'center' | 'right';
};
};
/**
* Displays alerts from {@link @backstage/core-plugin-api#AlertApi}
@@ -30,17 +40,6 @@ import pluralize from 'pluralize';
*
* Shown as SnackBar at the center top of the page by default. Configurable with props.
*/
// TODO: improve on this and promote to a shared component for use by all apps.
export type AlertDisplayProps = {
anchorOrigin?: {
vertical: 'top' | 'bottom';
horizontal: 'left' | 'center' | 'right';
};
};
/** @public */
export function AlertDisplay(props: AlertDisplayProps) {
const [messages, setMessages] = useState<Array<AlertMessage>>([]);
const alertApi = useApi(alertApiRef);
@@ -82,7 +81,7 @@ export function AlertDisplay(props: AlertDisplayProps) {
}
severity={firstMessage.severity}
>
<span>
<Typography component="span">
{String(firstMessage.message)}
{messages.length > 1 && (
<em>{` (${messages.length - 1} older ${pluralize(
@@ -90,7 +89,7 @@ export function AlertDisplay(props: AlertDisplayProps) {
messages.length - 1,
)})`}</em>
)}
</span>
</Typography>
</Alert>
</Snackbar>
);
@@ -13,9 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { CSSProperties } from 'react';
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles';
import MaterialAvatar from '@material-ui/core/Avatar';
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import React, { CSSProperties } from 'react';
import { extractInitials, stringToColor } from './utils';
/** @public */
@@ -28,6 +30,8 @@ const useStyles = makeStyles(
width: '4rem',
height: '4rem',
color: '#fff',
},
avatarText: {
fontWeight: theme.typography.fontWeightBold,
letterSpacing: '1px',
textTransform: 'uppercase',
@@ -68,6 +72,11 @@ export function Avatar(props: AvatarProps) {
const { displayName, picture, customStyles } = props;
const classes = useStyles();
let styles = { ...customStyles };
const fontStyles = {
fontFamily: styles.fontFamily,
fontSize: styles.fontSize,
fontWeight: styles.fontWeight,
};
// We only calculate the background color if there's not an avatar
// picture. If there is a picture, it might have a transparent
// background and we don't know whether the calculated background
@@ -85,7 +94,16 @@ export function Avatar(props: AvatarProps) {
className={classes.avatar}
style={styles}
>
{displayName && extractInitials(displayName)}
{displayName && (
<Typography
variant="h6"
component="span"
className={classes.avatarText}
style={fontStyles}
>
{extractInitials(displayName)}
</Typography>
)}
</MaterialAvatar>
);
}
@@ -13,16 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { useTheme } from '@material-ui/core/styles';
import { BackstageTheme } from '@backstage/theme';
import { CopyTextButton } from '../CopyTextButton';
import type {} from 'react-syntax-highlighter';
import { default as LightAsync } from 'react-syntax-highlighter/dist/esm/light-async';
import Box from '@material-ui/core/Box';
import { useTheme } from '@material-ui/core/styles';
import React from 'react';
import LightAsync from 'react-syntax-highlighter/dist/esm/light-async';
import dark from 'react-syntax-highlighter/dist/esm/styles/hljs/dark';
import docco from 'react-syntax-highlighter/dist/esm/styles/hljs/docco';
import { CopyTextButton } from '../CopyTextButton';
import type {} from 'react-syntax-highlighter';
/**
* Properties for {@link CodeSnippet}
*
@@ -87,7 +88,7 @@ export function CodeSnippet(props: CodeSnippetProps) {
const highlightColor = theme.palette.type === 'dark' ? '#256bf3' : '#e6ffed';
return (
<div style={{ position: 'relative' }}>
<Box position="relative">
<LightAsync
customStyle={customStyle}
language={language}
@@ -108,10 +109,10 @@ export function CodeSnippet(props: CodeSnippetProps) {
{text}
</LightAsync>
{showCopyCodeButton && (
<div style={{ position: 'absolute', top: 0, right: 0 }}>
<Box position="absolute" top={0} right={0}>
<CopyTextButton text={text} />
</div>
</Box>
)}
</div>
</Box>
);
}
@@ -58,7 +58,7 @@ const useStyles = makeStyles(
zIndex: 'unset',
},
icon: {
fontSize: 20,
fontSize: theme.typography.h6.fontSize,
},
content: {
width: '100%',
@@ -13,15 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import { BackstageTheme } from '@backstage/theme';
import Box from '@material-ui/core/Box';
import Button from '@material-ui/core/Button';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import React from 'react';
import { CodeSnippet } from '../CodeSnippet';
import { Link } from '../Link';
import { EmptyState } from './EmptyState';
import { CodeSnippet } from '../CodeSnippet';
const COMPONENT_YAML_TEMPLATE = `apiVersion: backstage.io/v1alpha1
kind: Component
@@ -109,7 +110,7 @@ export function MissingAnnotationEmptyState(props: Props) {
Add the annotation to your component YAML as shown in the
highlighted example below:
</Typography>
<div className={classes.code}>
<Box className={classes.code}>
<CodeSnippet
text={generateComponentYaml(annotations)}
language="yaml"
@@ -117,7 +118,7 @@ export function MissingAnnotationEmptyState(props: Props) {
highlightedNumbers={generateLineNumbers(annotations.length)}
customStyle={{ background: 'inherit', fontSize: '115%' }}
/>
</div>
</Box>
<Button color="primary" component={Link} to={url}>
Read more
</Button>
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Box from '@material-ui/core/Box';
import ClickAwayListener from '@material-ui/core/ClickAwayListener';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
@@ -26,6 +26,7 @@ import React, {
useState,
} from 'react';
import { createPortal } from 'react-dom';
import { usePortal } from './lib/usePortal';
import { useShowCallout } from './lib/useShowCallout';
@@ -168,14 +169,14 @@ export function FeatureCalloutCircular(props: PropsWithChildren<Props>) {
return (
<>
<div className={classes.featureWrapper} ref={wrapperRef}>
<Box className={classes.featureWrapper} {...{ ref: wrapperRef }}>
{children}
</div>
</Box>
{createPortal(
<div className={classes.backdrop}>
<Box className={classes.backdrop}>
<ClickAwayListener onClickAway={hide}>
<>
<div
<Box
className={classes.dot}
data-testid="dot"
style={{
@@ -190,9 +191,9 @@ export function FeatureCalloutCircular(props: PropsWithChildren<Props>) {
role="button"
tabIndex={0}
>
<div className={classes.pulseCircle} />
</div>
<div
<Box className={classes.pulseCircle} />
</Box>
<Box
className={classes.text}
data-testid="text"
style={{
@@ -205,10 +206,10 @@ export function FeatureCalloutCircular(props: PropsWithChildren<Props>) {
{title}
</Typography>
<Typography>{description}</Typography>
</div>
</Box>
</>
</ClickAwayListener>
</div>,
</Box>,
portalElement,
)}
</>
@@ -18,6 +18,8 @@ import classnames from 'classnames';
import { makeStyles } from '@material-ui/core/styles';
import LinkIcon from '@material-ui/icons/Link';
import { Link } from '../Link';
import Box from '@material-ui/core/Box';
import Typography from '@material-ui/core/Typography';
export type IconLinkVerticalProps = {
color?: 'primary' | 'secondary';
@@ -56,9 +58,8 @@ const useIconStyles = makeStyles(
color: theme.palette.secondary.main,
},
label: {
fontSize: '0.7rem',
textTransform: 'uppercase',
fontWeight: 600,
fontWeight: theme.typography.fontWeightBold,
letterSpacing: 1.2,
},
}),
@@ -79,10 +80,12 @@ export function IconLinkVertical({
if (disabled) {
return (
<div title={title} className={classnames(classes.link, classes.disabled)}>
<Box title={title} className={classnames(classes.link, classes.disabled)}>
{icon}
<span className={classes.label}>{label}</span>
</div>
<Typography variant="body2" component="span" className={classes.label}>
{label}
</Typography>
</Box>
);
}
@@ -94,7 +97,9 @@ export function IconLinkVertical({
onClick={onClick}
>
{icon}
<span className={classes.label}>{label}</span>
<Typography variant="body2" component="span" className={classes.label}>
{label}
</Typography>
</Link>
);
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Box from '@material-ui/core/Box';
import Grid from '@material-ui/core/Grid';
import IconButton from '@material-ui/core/IconButton';
import { makeStyles, Theme } from '@material-ui/core/styles';
@@ -227,7 +227,7 @@ export function HorizontalScrollGrid(props: PropsWithChildren<Props>) {
};
return (
<div {...otherProps} className={classes.root}>
<Box {...otherProps} className={classes.root}>
<Grid
container
direction="row"
@@ -237,12 +237,12 @@ export function HorizontalScrollGrid(props: PropsWithChildren<Props>) {
>
{children}
</Grid>
<div
<Box
className={classNames(classes.fade, classes.fadeLeft, {
[classes.fadeHidden]: scrollLeft === 0,
})}
/>
<div
<Box
className={classNames(classes.fade, classes.fadeRight, {
[classes.fadeHidden]: scrollRight === 0,
})}
@@ -265,6 +265,6 @@ export function HorizontalScrollGrid(props: PropsWithChildren<Props>) {
<ChevronRightIcon />
</IconButton>
)}
</div>
</Box>
);
}
@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import CSS from 'csstype';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import CSS from 'csstype';
import React from 'react';
type Props = CSS.Properties & {
shorthand?: boolean;
@@ -47,15 +47,16 @@ export function Lifecycle(props: Props) {
const classes = useStyles(props);
const { shorthand, alpha } = props;
return shorthand ? (
<span
<Typography
component="span"
className={classes[alpha ? 'alpha' : 'beta']}
style={{ fontSize: '120%' }}
>
{alpha ? <>&alpha;</> : <>&beta;</>}
</span>
</Typography>
) : (
<span className={classes[alpha ? 'alpha' : 'beta']}>
<Typography component="span" className={classes[alpha ? 'alpha' : 'beta']}>
{alpha ? 'Alpha' : 'Beta'}
</span>
</Typography>
);
}
@@ -13,21 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { configApiRef, useAnalytics, useApi } from '@backstage/core-plugin-api';
import classnames from 'classnames';
// eslint-disable-next-line no-restricted-imports
import MaterialLink, {
LinkProps as MaterialLinkProps,
} from '@material-ui/core/Link';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import classnames from 'classnames';
import { trimEnd } from 'lodash';
import React, { ElementType } from 'react';
import {
createRoutesFromChildren,
Link as RouterLink,
LinkProps as RouterLinkProps,
Route,
} from 'react-router-dom';
import { trimEnd } from 'lodash';
import { createRoutesFromChildren, Route } from 'react-router-dom';
export function isReactRouterBeta(): boolean {
const [obj] = createRoutesFromChildren(<Route index element={<div />} />);
@@ -161,7 +162,9 @@ export const Link = React.forwardRef<any, LinkProps>(
className={classnames(classes.externalLink, props.className)}
>
{props.children}
<span className={classes.visuallyHidden}>, Opens in a new window</span>
<Typography component="span" className={classes.visuallyHidden}>
, Opens in a new window
</Typography>
</MaterialLink>
) : (
// Interact with React Router for internal links
@@ -13,18 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useEffect, useMemo, useRef } from 'react';
import { useLocation } from 'react-router-dom';
import Box from '@material-ui/core/Box';
import IconButton from '@material-ui/core/IconButton';
import CopyIcon from '@material-ui/icons/FileCopy';
import classnames from 'classnames';
import React, { useEffect, useMemo, useRef } from 'react';
import { useLocation } from 'react-router-dom';
import AutoSizer from 'react-virtualized-auto-sizer';
import { FixedSizeList } from 'react-window';
import { AnsiProcessor } from './AnsiProcessor';
import { HEADER_SIZE, useStyles } from './styles';
import classnames from 'classnames';
import { LogLine } from './LogLine';
import { LogViewerControls } from './LogViewerControls';
import { HEADER_SIZE, useStyles } from './styles';
import { useLogViewerSearch } from './useLogViewerSearch';
import { useLogViewerSelection } from './useLogViewerSelection';
@@ -69,10 +70,10 @@ export function RealLogViewer(props: RealLogViewerProps) {
return (
<AutoSizer>
{({ height, width }) => (
<div style={{ width, height }} className={classes.root}>
<div className={classes.header}>
<Box style={{ width, height }} className={classes.root}>
<Box className={classes.header}>
<LogViewerControls {...search} />
</div>
</Box>
<FixedSizeList
ref={listRef}
className={classes.log}
@@ -86,7 +87,7 @@ export function RealLogViewer(props: RealLogViewerProps) {
const line = data[index];
const { lineNumber } = line;
return (
<div
<Box
style={{ ...style }}
className={classnames(classes.line, {
[classes.lineSelected]: selection.isSelected(lineNumber),
@@ -122,11 +123,11 @@ export function RealLogViewer(props: RealLogViewerProps) {
: undefined
}
/>
</div>
</Box>
);
}}
</FixedSizeList>
</div>
</Box>
)}
</AutoSizer>
);
@@ -13,23 +13,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useState, useEffect, PropsWithChildren } from 'react';
import { BackstageTheme } from '@backstage/theme';
import Box from '@material-ui/core/Box';
import LinearProgress, {
LinearProgressProps,
} from '@material-ui/core/LinearProgress';
import { useTheme } from '@material-ui/core/styles';
import React, { PropsWithChildren, useEffect, useState } from 'react';
export function Progress(props: PropsWithChildren<LinearProgressProps>) {
const theme = useTheme<BackstageTheme>();
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
const handle = setTimeout(() => setIsVisible(true), 250);
const handle = setTimeout(
() => setIsVisible(true),
theme.transitions.duration.short,
);
return () => clearTimeout(handle);
}, []);
}, [theme.transitions.duration.short]);
return isVisible ? (
<LinearProgress {...props} data-testid="progress" />
) : (
<div style={{ display: 'none' }} />
<Box display="none" />
);
}
@@ -18,6 +18,7 @@ import { BackstagePalette, BackstageTheme } from '@backstage/theme';
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';
/** @public */
export type GaugeClassKey =
@@ -38,8 +39,8 @@ const useStyles = makeStyles<BackstageTheme>(
top: '50%',
left: '50%',
transform: 'translate(-50%, -60%)',
fontSize: 45,
fontWeight: 'bold',
fontSize: theme.typography.pxToRem(45),
fontWeight: theme.typography.fontWeightBold,
color: theme.palette.textContrast,
},
description: {
@@ -152,7 +153,7 @@ export function Gauge(props: GaugeProps) {
}, [description, hoverRef]);
return (
<div ref={setHoverRef} className={classes.root}>
<Box {...{ ref: setHoverRef }} className={classes.root}>
<Circle
strokeLinecap="butt"
percent={asPercentage}
@@ -162,12 +163,12 @@ export function Gauge(props: GaugeProps) {
className={classes.circle}
/>
{description && isHovering ? (
<div className={classes.description}>{description}</div>
<Box className={classes.description}>{description}</Box>
) : (
<div className={classes.overlay}>
<Box className={classes.overlay}>
{isNaN(value) ? 'N/A' : `${asActual}${unit}`}
</div>
</Box>
)}
</div>
</Box>
);
}
@@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Box from '@material-ui/core/Box';
import { makeStyles } from '@material-ui/core/styles';
import React, { ReactNode } from 'react';
import { BottomLinkProps } from '../../layout/BottomLink';
import { InfoCard, InfoCardVariants } from '../../layout/InfoCard';
import { Gauge, GaugePropsGetColor } from './Gauge';
@@ -74,7 +75,7 @@ export function GaugeCard(props: Props) {
};
return (
<div className={classes.root}>
<Box className={classes.root}>
<InfoCard
title={title}
subheader={subheader}
@@ -84,6 +85,6 @@ export function GaugeCard(props: Props) {
>
<Gauge {...gaugeProps} />
</InfoCard>
</div>
</Box>
);
}
@@ -13,13 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { BackstageTheme } from '@backstage/theme';
import { useTheme } from '@material-ui/core/styles';
import Tooltip from '@material-ui/core/Tooltip';
import Typography from '@material-ui/core/Typography';
import { Line } from 'rc-progress';
import { BackstageTheme } from '@backstage/theme';
import { getProgressColor, GaugePropsGetColor } from './Gauge';
import React from 'react';
import { GaugePropsGetColor, getProgressColor } from './Gauge';
type Props = {
/**
@@ -47,14 +48,14 @@ export function LinearGauge(props: Props) {
});
return (
<Tooltip title={`${percent}%`}>
<span>
<Typography component="span">
<Line
percent={percent}
strokeWidth={4}
trailWidth={4}
strokeColor={strokeColor}
/>
</span>
</Typography>
</Tooltip>
);
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Box from '@material-ui/core/Box';
import Checkbox from '@material-ui/core/Checkbox';
import Chip from '@material-ui/core/Chip';
import ClickAwayListener from '@material-ui/core/ClickAwayListener';
@@ -30,6 +30,7 @@ import {
} from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import React, { useEffect, useState } from 'react';
import ClosedDropdown from './static/ClosedDropdown';
import OpenedDropdown from './static/OpenedDropdown';
@@ -45,17 +46,17 @@ const BootstrapInput = withStyles(
},
},
input: {
borderRadius: 4,
borderRadius: theme.shape.borderRadius,
position: 'relative',
backgroundColor: theme.palette.background.paper,
border: '1px solid #ced4da',
fontSize: 16,
padding: '10px 26px 10px 12px',
fontSize: theme.typography.body1.fontSize,
padding: theme.spacing(1.25, 3.25, 1.25, 1.5),
transition: theme.transitions.create(['border-color', 'box-shadow']),
fontFamily: 'Helvetica Neue',
'&:focus': {
background: theme.palette.background.paper,
borderRadius: 4,
borderRadius: theme.shape.borderRadius,
},
},
}),
@@ -81,7 +82,7 @@ const useStyles = makeStyles(
label: {
transform: 'initial',
fontWeight: 'bold',
fontSize: 14,
fontSize: theme.typography.body2.fontSize,
fontFamily: theme.typography.fontFamily,
color: theme.palette.text.primary,
'&.Mui-focused': {
@@ -91,7 +92,7 @@ const useStyles = makeStyles(
formLabel: {
transform: 'initial',
fontWeight: 'bold',
fontSize: 14,
fontSize: theme.typography.body2.fontSize,
fontFamily: theme.typography.fontFamily,
color: theme.palette.text.primary,
'&.Mui-focused': {
@@ -196,7 +197,7 @@ export function SelectComponent(props: SelectProps) {
};
return (
<div className={classes.root}>
<Box className={classes.root}>
<ClickAwayListener onClickAway={handleClickAway}>
<FormControl className={classes.formControl}>
<InputLabel className={classes.formLabel}>{label}</InputLabel>
@@ -217,7 +218,7 @@ export function SelectComponent(props: SelectProps) {
tabIndex={0}
renderValue={s =>
multiple && (value as any[]).length !== 0 ? (
<div className={classes.chips}>
<Box className={classes.chips}>
{(s as string[]).map(selectedValue => (
<Chip
key={items.find(el => el.value === selectedValue)?.value}
@@ -229,7 +230,7 @@ export function SelectComponent(props: SelectProps) {
className={classes.chip}
/>
))}
</div>
</Box>
) : (
<Typography>
{(value as any[]).length === 0
@@ -279,6 +280,6 @@ export function SelectComponent(props: SelectProps) {
</Select>
</FormControl>
</ClickAwayListener>
</div>
</Box>
);
}
@@ -21,11 +21,11 @@ import SvgIcon from '@material-ui/core/SvgIcon';
export type ClosedDropdownClassKey = 'icon';
const useStyles = makeStyles(
() =>
theme =>
createStyles({
icon: {
position: 'absolute',
right: '4px',
right: theme.spacing(0.5),
pointerEvents: 'none',
},
}),
@@ -20,11 +20,11 @@ import SvgIcon from '@material-ui/core/SvgIcon';
export type OpenedDropdownClassKey = 'icon';
const useStyles = makeStyles(
() =>
theme =>
createStyles({
icon: {
position: 'absolute',
right: '4px',
right: theme.spacing(0.5),
pointerEvents: 'none',
},
}),
@@ -13,11 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useContext, ReactNode, PropsWithChildren } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Box from '@material-ui/core/Box';
import Button from '@material-ui/core/Button';
import { StepActions } from './types';
import { makeStyles } from '@material-ui/core/styles';
import React, { PropsWithChildren, ReactNode, useContext } from 'react';
import { VerticalStepperContext } from './SimpleStepper';
import { StepActions } from './types';
export type SimpleStepperFooterClassKey = 'root';
@@ -145,7 +147,7 @@ export const SimpleStepperFooter = ({
};
return (
<div className={classes.root}>
<Box className={classes.root}>
{[undefined, true].includes(actions.showBack) && stepIndex !== 0 && (
<BackBtn
text={actions.backText}
@@ -184,6 +186,6 @@ export const SimpleStepperFooter = ({
/>
)}
{children}
</div>
</Box>
);
};
@@ -13,12 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { PropsWithChildren } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Box from '@material-ui/core/Box';
import MuiStep from '@material-ui/core/Step';
import StepContent from '@material-ui/core/StepContent';
import StepLabel from '@material-ui/core/StepLabel';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import React, { PropsWithChildren } from 'react';
import { SimpleStepperFooter } from './SimpleStepperFooter';
import { StepProps } from './types';
@@ -40,11 +42,11 @@ export function SimpleStepperStep(props: PropsWithChildren<StepProps>) {
// The end step is not a part of the stepper
// It simply is the final screen with an option to have buttons such as reset or back
return end ? (
<div className={classes.end}>
<Box className={classes.end}>
<Typography variant="h6">{title}</Typography>
{children}
<SimpleStepperFooter actions={{ ...(actions || {}), showNext: false }} />
</div>
</Box>
) : (
<MuiStep {...muiProps}>
<StepLabel>
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { makeStyles } from '@material-ui/core/styles';
import { BackstageTheme } from '@backstage/theme';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import classNames from 'classnames';
import React, { PropsWithChildren } from 'react';
@@ -31,12 +31,12 @@ export type StatusClassKey =
const useStyles = makeStyles<BackstageTheme>(
theme => ({
status: {
fontWeight: 500,
fontWeight: theme.typography.fontWeightMedium,
'&::before': {
width: '0.7em',
height: '0.7em',
display: 'inline-block',
marginRight: 8,
marginRight: theme.spacing(1),
borderRadius: '50%',
content: '""',
},
@@ -78,7 +78,8 @@ const useStyles = makeStyles<BackstageTheme>(
export function StatusOK(props: PropsWithChildren<{}>) {
const classes = useStyles(props);
return (
<span
<Typography
component="span"
className={classNames(classes.status, classes.ok)}
aria-label="Status ok"
aria-hidden="true"
@@ -90,7 +91,8 @@ export function StatusOK(props: PropsWithChildren<{}>) {
export function StatusWarning(props: PropsWithChildren<{}>) {
const classes = useStyles(props);
return (
<span
<Typography
component="span"
className={classNames(classes.status, classes.warning)}
aria-label="Status warning"
aria-hidden="true"
@@ -102,7 +104,8 @@ export function StatusWarning(props: PropsWithChildren<{}>) {
export function StatusError(props: PropsWithChildren<{}>) {
const classes = useStyles(props);
return (
<span
<Typography
component="span"
className={classNames(classes.status, classes.error)}
aria-label="Status error"
aria-hidden="true"
@@ -114,7 +117,8 @@ export function StatusError(props: PropsWithChildren<{}>) {
export function StatusPending(props: PropsWithChildren<{}>) {
const classes = useStyles(props);
return (
<span
<Typography
component="span"
className={classNames(classes.status, classes.pending)}
aria-label="Status pending"
aria-hidden="true"
@@ -126,7 +130,8 @@ export function StatusPending(props: PropsWithChildren<{}>) {
export function StatusRunning(props: PropsWithChildren<{}>) {
const classes = useStyles(props);
return (
<span
<Typography
component="span"
className={classNames(classes.status, classes.running)}
aria-label="Status running"
aria-hidden="true"
@@ -138,7 +143,8 @@ export function StatusRunning(props: PropsWithChildren<{}>) {
export function StatusAborted(props: PropsWithChildren<{}>) {
const classes = useStyles(props);
return (
<span
<Typography
component="span"
className={classNames(classes.status, classes.aborted)}
aria-label="Status aborted"
aria-hidden="true"
@@ -13,25 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import {
withStyles,
createStyles,
WithStyles,
Theme,
WithStyles,
withStyles,
} from '@material-ui/core/styles';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableRow from '@material-ui/core/TableRow';
import React from 'react';
export type MetadataTableTitleCellClassKey = 'root';
const tableTitleCellStyles = (theme: Theme) =>
createStyles({
root: {
fontWeight: 'bolder',
fontWeight: theme.typography.fontWeightBold,
whiteSpace: 'nowrap',
paddingRight: theme.spacing(4),
border: '0',
@@ -53,9 +54,7 @@ export type MetadataTableListClassKey = 'root';
const listStyles = (theme: Theme) =>
createStyles({
root: {
listStyle: 'none',
margin: theme.spacing(0, 0, -1, 0),
padding: '0',
},
});
@@ -64,6 +63,7 @@ export type MetadataTableListItemClassKey = 'root' | 'random';
const listItemStyles = (theme: Theme) =>
createStyles({
root: {
gutters: 0,
padding: theme.spacing(0, 0, 1, 0),
},
random: {},
@@ -111,11 +111,13 @@ interface StyleProps extends WithStyles {
export const MetadataList = withStyles(listStyles, {
name: 'BackstageMetadataTableList',
})(({ classes, children }: StyleProps) => (
<ul className={classes.root}>{children}</ul>
<List disablePadding className={classes.root}>
{children}
</List>
));
export const MetadataListItem = withStyles(listItemStyles, {
name: 'BackstageMetadataTableListItem',
})(({ classes, children }: StyleProps) => (
<li className={classes.root}>{children}</li>
<ListItem className={classes.root}>{children}</ListItem>
));
@@ -22,6 +22,7 @@ import {
Theme,
} from '@material-ui/core/styles';
import startCase from 'lodash/startCase';
import Typography from '@material-ui/core/Typography';
import {
MetadataTable,
@@ -88,7 +89,9 @@ function renderMap(
: startCase(key);
return (
<MetadataListItem key={key}>
{`${fmtKey}: `}
<Typography variant="body2" component="span">
{`${fmtKey}: `}
</Typography>
{value}
</MetadataListItem>
);
@@ -122,7 +125,11 @@ function toValue(
return <Fragment>{value ? '✅' : '❌'}</Fragment>;
}
return <Fragment>{value}</Fragment>;
return (
<Typography variant="body2" component="span">
{value}
</Typography>
);
}
const ItemValue = ({ value, options }: { value: any; options: any }) => (
<Fragment>{toValue(value, options)}</Fragment>
@@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useEffect, useState } from 'react';
import { BackstageTheme } from '@backstage/theme';
import { makeStyles } from '@material-ui/core/styles';
import Box from '@material-ui/core/Box';
import Button from '@material-ui/core/Button';
import { makeStyles } from '@material-ui/core/styles';
import React, { useEffect, useState } from 'react';
import { Select } from '../Select';
import { SelectProps } from '../Select/Select';
@@ -39,7 +40,7 @@ const useFilterStyles = makeStyles<BackstageTheme>(
header: {
display: 'flex',
alignItems: 'center',
height: '60px',
height: theme.spacing(7.5),
justifyContent: 'space-between',
borderBottom: `1px solid ${theme.palette.grey[500]}`,
},
@@ -93,14 +94,14 @@ export const Filters = (props: Props) => {
// As material table doesn't provide a way to add a column filter tab we will make our own filter logic
return (
<div className={classes.root}>
<div className={classes.header}>
<div className={classes.value}>Filters</div>
<Box className={classes.root}>
<Box className={classes.header}>
<Box className={classes.value}>Filters</Box>
<Button color="primary" onClick={handleClick}>
Clear all
</Button>
</div>
<div className={classes.filters}>
</Box>
<Box className={classes.filters}>
{props.filters?.length &&
props.filters.map(filter => (
<Select
@@ -116,7 +117,7 @@ export const Filters = (props: Props) => {
}
/>
))}
</div>
</div>
</Box>
</Box>
);
};
@@ -13,17 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { BackstageTheme } from '@backstage/theme';
import Box from '@material-ui/core/Box';
import { makeStyles } from '@material-ui/core/styles';
import React from 'react';
export type SubvalueCellClassKey = 'value' | 'subvalue';
const useSubvalueCellStyles = makeStyles<BackstageTheme>(
theme => ({
value: {
marginBottom: '6px',
marginBottom: theme.spacing(0.75),
},
subvalue: {
color: theme.palette.textSubtle,
@@ -44,8 +44,8 @@ export function SubvalueCell(props: SubvalueCellProps) {
return (
<>
<div className={classes.value}>{value}</div>
<div className={classes.subvalue}>{subvalue}</div>
<Box className={classes.value}>{value}</Box>
<Box className={classes.subvalue}>{subvalue}</Box>
</>
);
}
@@ -13,12 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { BackstageTheme } from '@backstage/theme';
import { makeStyles, useTheme, withStyles } from '@material-ui/core/styles';
import MTable, {
Column,
Icons,
MaterialTableProps,
MTableBody,
MTableHeader,
MTableToolbar,
Options,
} from '@material-table/core';
import Box from '@material-ui/core/Box';
import IconButton from '@material-ui/core/IconButton';
import { makeStyles, useTheme, withStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
// Material-table is not using the standard icons available in in material-ui. https://github.com/mbrn/material-table/issues/51
import AddBox from '@material-ui/icons/AddBox';
import ArrowUpward from '@material-ui/icons/ArrowUpward';
import Check from '@material-ui/icons/Check';
@@ -34,15 +42,6 @@ import Remove from '@material-ui/icons/Remove';
import SaveAlt from '@material-ui/icons/SaveAlt';
import ViewColumn from '@material-ui/icons/ViewColumn';
import { isEqual, transform } from 'lodash';
import MTable, {
Column,
Icons,
MaterialTableProps,
MTableBody,
MTableHeader,
MTableToolbar,
Options,
} from '@material-table/core';
import React, {
forwardRef,
MutableRefObject,
@@ -51,9 +50,11 @@ import React, {
useEffect,
useState,
} from 'react';
import { SelectProps } from '../Select/Select';
import { Filter, Filters, SelectedFilters, Without } from './Filters';
// Material-table is not using the standard icons available in in material-ui. https://github.com/mbrn/material-table/issues/51
const tableIcons: Icons = {
Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />),
Check: forwardRef((props, ref) => <Check {...props} ref={ref} />),
@@ -122,7 +123,7 @@ const StyledMTableToolbar = withStyles(
},
title: {
'& > h6': {
fontWeight: 'bold',
fontWeight: theme.typography.fontWeightBold,
},
},
searchField: {
@@ -136,14 +137,14 @@ const StyledMTableToolbar = withStyles(
export type FiltersContainerClassKey = 'root' | 'title';
const useFilterStyles = makeStyles<BackstageTheme>(
() => ({
theme => ({
root: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
},
title: {
fontWeight: 'bold',
fontWeight: theme.typography.fontWeightBold,
fontSize: 18,
whiteSpace: 'nowrap',
},
@@ -265,21 +266,21 @@ export function TableToolbar(toolbarProps: {
if (hasFilters) {
return (
<div className={filtersClasses.root}>
<div className={filtersClasses.root}>
<Box className={filtersClasses.root}>
<Box className={filtersClasses.root}>
<IconButton onClick={toggleFilters} aria-label="filter list">
<FilterList />
</IconButton>
<Typography className={filtersClasses.title}>
Filters ({selectedFiltersLength})
</Typography>
</div>
</Box>
<StyledMTableToolbar
{...toolbarProps}
ref={toolbarRef}
onSearchChanged={onSearchChanged}
/>
</div>
</Box>
);
}
@@ -484,7 +485,7 @@ export function Table<T extends object = {}>(props: TableProps<T>) {
);
return (
<div className={tableClasses.root}>
<Box className={tableClasses.root}>
{filtersOpen && data && typeof data !== 'function' && filters?.length && (
<Filters
filters={constructFilters(filters, data as any[])}
@@ -521,7 +522,7 @@ export function Table<T extends object = {}>(props: TableProps<T>) {
}}
{...restProps}
/>
</div>
</Box>
);
}
@@ -33,7 +33,7 @@ const useStyles = makeStyles<BackstageTheme>(
display: 'flex',
justifyContent: 'center',
backgroundColor: theme.palette.tabbar.indicator,
height: '4px',
height: theme.spacing(0.5),
},
flexContainer: {
alignItems: 'center',
@@ -29,16 +29,16 @@ interface StyledIconProps {
export type TabIconClassKey = 'root';
const useStyles = makeStyles<BackstageTheme, StyledIconProps>(
() => ({
theme => ({
root: {
color: '#6E6E6E',
overflow: 'visible',
fontSize: '1.5rem',
fontSize: theme.typography.h5.fontSize,
textAlign: 'center',
borderRadius: '50%',
backgroundColor: '#E6E6E6',
marginLeft: props => (props.isNext ? 'auto' : '0'),
marginRight: props => (props.isNext ? '0' : '10px'),
marginRight: props => (props.isNext ? '0' : theme.spacing(1.25)),
'&:hover': {
backgroundColor: '#E6E6E6',
opacity: '1',
@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { PropsWithChildren } from 'react';
import Box from '@material-ui/core/Box';
import React, { PropsWithChildren } from 'react';
export interface TabPanelProps {
value?: any;
@@ -26,13 +25,13 @@ export const TabPanel = (props: PropsWithChildren<TabPanelProps>) => {
const { children, value, index, ...other } = props;
return (
<div
<Box
role="tabpanel"
hidden={value !== index}
aria-labelledby={`scrollable-auto-tab-${index}`}
{...other}
>
{value === index && <Box p={3}>{children}</Box>}
</div>
</Box>
);
};
@@ -29,6 +29,7 @@ import { TabPanel } from './TabPanel';
import { StyledIcon } from './TabIcon';
import { StyledTab } from './Tab';
import { StyledTabs } from './TabBar';
import Box from '@material-ui/core/Box';
/* Props Types */
@@ -56,8 +57,8 @@ const useStyles = makeStyles<BackstageTheme>(
appbar: {
boxShadow: 'none',
backgroundColor: theme.palette.background.paper,
paddingLeft: '10px',
paddingRight: '10px',
paddingLeft: theme.spacing(1.25),
paddingRight: theme.spacing(1.25),
},
}),
{ name: 'BackstageTabs' },
@@ -110,9 +111,9 @@ export function Tabs(props: TabsProps) {
const currentIndex = navIndex === value[0] ? value[1] : false;
return (
<div className={classes.root}>
<Box className={classes.root}>
<AppBar ref={wrapper} className={classes.appbar} position="static">
<div>
<Box>
<StyledTabs
value={currentIndex}
onChange={handleChange}
@@ -146,7 +147,7 @@ export function Tabs(props: TabsProps) {
</StyledIcon>
)}
</StyledTabs>
</div>
</Box>
</AppBar>
{currentIndex !== false ? (
chunkedTabs[navIndex].map((tab, index) => (
@@ -164,6 +165,6 @@ export function Tabs(props: TabsProps) {
{chunkedTabs[value[0]][value[1]].content}
</TabPanel>
)}
</div>
</Box>
);
}
@@ -92,7 +92,7 @@ const useStyles = makeStyles<BackstageTheme>(
severity as NonNullable<WarningProps['severity']>,
theme,
),
fontWeight: 'bold',
fontWeight: theme.typography.fontWeightBold,
},
message: {
width: '100%',
@@ -46,7 +46,7 @@ const useStyles = makeStyles<BackstageTheme>(
paddingBottom: theme.spacing(5),
[theme.breakpoints.down('xs')]: {
paddingBottom: theme.spacing(4),
fontSize: 32,
fontSize: theme.typography.h3.fontSize,
},
},
subtitle: {
@@ -76,7 +76,7 @@ const useStyles = makeStyles<
},
}),
title: {
fontSize: 24,
fontSize: theme.typography.h5.fontSize,
fontWeight: 500,
color: '#FFF',
padding: 20,
@@ -55,7 +55,7 @@ const useStyles = makeStyles<BackstageTheme>(
label: {
margin: 14,
marginLeft: 7,
fontSize: 14,
fontSize: theme.typography.body2.fontSize,
whiteSpace: 'nowrap',
overflow: 'hidden',
'text-overflow': 'ellipsis',
@@ -88,7 +88,7 @@ const useStyles = makeStyles<BackstageTheme>(
color: theme.palette.navigation.color,
paddingLeft: theme.spacing(4),
paddingRight: theme.spacing(1),
fontSize: '14px',
fontSize: theme.typography.body2.fontSize,
whiteSpace: 'nowrap',
overflow: 'hidden',
'text-overflow': 'ellipsis',