diff --git a/packages/core-components/src/components/Avatar/Avatar.tsx b/packages/core-components/src/components/Avatar/Avatar.tsx index f694365233..604d093971 100644 --- a/packages/core-components/src/components/Avatar/Avatar.tsx +++ b/packages/core-components/src/components/Avatar/Avatar.tsx @@ -22,17 +22,21 @@ import { } from '@material-ui/core'; import { extractInitials, stringToColor } from './utils'; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - avatar: { - width: '4rem', - height: '4rem', - color: '#fff', - fontWeight: theme.typography.fontWeightBold, - letterSpacing: '1px', - textTransform: 'uppercase', - }, - }), +export type AvatarClassKey = 'avatar'; + +const useStyles = makeStyles( + (theme: Theme) => + createStyles({ + avatar: { + width: '4rem', + height: '4rem', + color: '#fff', + fontWeight: theme.typography.fontWeightBold, + letterSpacing: '1px', + textTransform: 'uppercase', + }, + }), + { name: 'BackstageAvatar' }, ); export type AvatarProps = { diff --git a/packages/core-components/src/components/Avatar/index.ts b/packages/core-components/src/components/Avatar/index.ts index a58b47eba9..4d00450f2d 100644 --- a/packages/core-components/src/components/Avatar/index.ts +++ b/packages/core-components/src/components/Avatar/index.ts @@ -14,3 +14,4 @@ * limitations under the License. */ export { Avatar } from './Avatar'; +export type { AvatarClassKey } from './Avatar'; diff --git a/packages/core-components/src/components/DependencyGraph/DefaultLabel.tsx b/packages/core-components/src/components/DependencyGraph/DefaultLabel.tsx index 74f0a97a2b..7aa245fc1f 100644 --- a/packages/core-components/src/components/DependencyGraph/DefaultLabel.tsx +++ b/packages/core-components/src/components/DependencyGraph/DefaultLabel.tsx @@ -19,11 +19,16 @@ import makeStyles from '@material-ui/core/styles/makeStyles'; import { BackstageTheme } from '@backstage/theme'; import { RenderLabelProps } from './types'; -const useStyles = makeStyles((theme: BackstageTheme) => ({ - text: { - fill: theme.palette.textContrast, - }, -})); +export type DependencyGraphDefaultLabelClassKey = 'text'; + +const useStyles = makeStyles( + (theme: BackstageTheme) => ({ + text: { + fill: theme.palette.textContrast, + }, + }), + { name: 'BackstageDependencyGraphDefaultLabel' }, +); export function DefaultLabel({ edge: { label } }: RenderLabelProps) { const classes = useStyles(); diff --git a/packages/core-components/src/components/DependencyGraph/DefaultNode.tsx b/packages/core-components/src/components/DependencyGraph/DefaultNode.tsx index 8feca43e9a..6e33148aec 100644 --- a/packages/core-components/src/components/DependencyGraph/DefaultNode.tsx +++ b/packages/core-components/src/components/DependencyGraph/DefaultNode.tsx @@ -19,15 +19,20 @@ import { makeStyles } from '@material-ui/core/styles'; import { BackstageTheme } from '@backstage/theme'; import { RenderNodeProps } from './types'; -const useStyles = makeStyles((theme: BackstageTheme) => ({ - node: { - fill: theme.palette.primary.light, - stroke: theme.palette.primary.light, - }, - text: { - fill: theme.palette.primary.contrastText, - }, -})); +export type DependencyGraphDefaultNodeClassKey = 'node' | 'text'; + +const useStyles = makeStyles( + (theme: BackstageTheme) => ({ + node: { + fill: theme.palette.primary.light, + stroke: theme.palette.primary.light, + }, + text: { + fill: theme.palette.primary.contrastText, + }, + }), + { name: 'BackstageDependencyGraphDefaultNode' }, +); export function DefaultNode({ node: { id } }: RenderNodeProps) { const classes = useStyles(); diff --git a/packages/core-components/src/components/DependencyGraph/Edge.tsx b/packages/core-components/src/components/DependencyGraph/Edge.tsx index e0f19d3536..a82c5d4813 100644 --- a/packages/core-components/src/components/DependencyGraph/Edge.tsx +++ b/packages/core-components/src/components/DependencyGraph/Edge.tsx @@ -28,17 +28,22 @@ import { import { ARROW_MARKER_ID, EDGE_TEST_ID, LABEL_TEST_ID } from './constants'; import { DefaultLabel } from './DefaultLabel'; -const useStyles = makeStyles((theme: BackstageTheme) => ({ - path: { - strokeWidth: 2, - stroke: theme.palette.textSubtle, - fill: 'none', - transition: `${theme.transitions.duration.shortest}ms`, - }, - label: { - transition: `${theme.transitions.duration.shortest}ms`, - }, -})); +export type DependencyGraphEdgeClassKey = 'path' | 'label'; + +const useStyles = makeStyles( + (theme: BackstageTheme) => ({ + path: { + strokeWidth: 2, + stroke: theme.palette.textSubtle, + fill: 'none', + transition: `${theme.transitions.duration.shortest}ms`, + }, + label: { + transition: `${theme.transitions.duration.shortest}ms`, + }, + }), + { name: 'BackstageDependencyGraphEdge' }, +); type EdgePoint = dagre.GraphEdge['points'][0]; diff --git a/packages/core-components/src/components/DependencyGraph/Node.tsx b/packages/core-components/src/components/DependencyGraph/Node.tsx index a5e1a62f09..e37f7a6e37 100644 --- a/packages/core-components/src/components/DependencyGraph/Node.tsx +++ b/packages/core-components/src/components/DependencyGraph/Node.tsx @@ -20,11 +20,16 @@ import { DefaultNode } from './DefaultNode'; import { RenderNodeFunction, RenderNodeProps, GraphNode } from './types'; import { NODE_TEST_ID } from './constants'; -const useStyles = makeStyles(theme => ({ - node: { - transition: `${theme.transitions.duration.shortest}ms`, - }, -})); +export type DependencyGraphNodeClassKey = 'node'; + +const useStyles = makeStyles( + theme => ({ + node: { + transition: `${theme.transitions.duration.shortest}ms`, + }, + }), + { name: 'BackstageDependencyGraphNode' }, +); export type NodeComponentProps = { node: GraphNode; diff --git a/packages/core-components/src/components/DependencyGraph/index.ts b/packages/core-components/src/components/DependencyGraph/index.ts index 03a5bfd584..23ab81bab9 100644 --- a/packages/core-components/src/components/DependencyGraph/index.ts +++ b/packages/core-components/src/components/DependencyGraph/index.ts @@ -19,3 +19,8 @@ import * as DependencyGraphTypes from './types'; export { DependencyGraph } from './DependencyGraph'; export type { DependencyGraphProps } from './DependencyGraph'; export { DependencyGraphTypes }; + +export type { DependencyGraphDefaultLabelClassKey } from './DefaultLabel'; +export type { DependencyGraphDefaultNodeClassKey } from './DefaultNode'; +export type { DependencyGraphEdgeClassKey } from './Edge'; +export type { DependencyGraphNodeClassKey } from './Node'; diff --git a/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx b/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx index cc20a49ad6..3d229a5d54 100644 --- a/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx +++ b/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx @@ -25,43 +25,55 @@ import SnackbarContent from '@material-ui/core/SnackbarContent'; import IconButton from '@material-ui/core/IconButton'; import Close from '@material-ui/icons/Close'; -const useStyles = makeStyles((theme: BackstageTheme) => ({ - root: { - padding: theme.spacing(0), - marginBottom: theme.spacing(0), - marginTop: theme.spacing(0), - display: 'flex', - flexFlow: 'row nowrap', - }, - // showing on top - topPosition: { - position: 'relative', - marginBottom: theme.spacing(6), - marginTop: -theme.spacing(3), - zIndex: 'unset', - }, - icon: { - fontSize: 20, - }, - content: { - width: '100%', - maxWidth: 'inherit', - }, - message: { - display: 'flex', - alignItems: 'center', - color: theme.palette.banner.text, - '& a': { - color: theme.palette.banner.link, +export type DismissbleBannerClassKey = + | 'root' + | 'topPosition' + | 'icon' + | 'content' + | 'message' + | 'info' + | 'error'; + +const useStyles = makeStyles( + (theme: BackstageTheme) => ({ + root: { + padding: theme.spacing(0), + marginBottom: theme.spacing(0), + marginTop: theme.spacing(0), + display: 'flex', + flexFlow: 'row nowrap', }, - }, - info: { - backgroundColor: theme.palette.banner.info, - }, - error: { - backgroundColor: theme.palette.banner.error, - }, -})); + // showing on top + topPosition: { + position: 'relative', + marginBottom: theme.spacing(6), + marginTop: -theme.spacing(3), + zIndex: 'unset', + }, + icon: { + fontSize: 20, + }, + content: { + width: '100%', + maxWidth: 'inherit', + }, + message: { + display: 'flex', + alignItems: 'center', + color: theme.palette.banner.text, + '& a': { + color: theme.palette.banner.link, + }, + }, + info: { + backgroundColor: theme.palette.banner.info, + }, + error: { + backgroundColor: theme.palette.banner.error, + }, + }), + { name: 'BackstageDismissableBanner' }, +); type Props = { variant: 'info' | 'error'; diff --git a/packages/core-components/src/components/DismissableBanner/index.ts b/packages/core-components/src/components/DismissableBanner/index.ts index 4390d44903..26bebfed59 100644 --- a/packages/core-components/src/components/DismissableBanner/index.ts +++ b/packages/core-components/src/components/DismissableBanner/index.ts @@ -15,3 +15,4 @@ */ export { DismissableBanner } from './DismissableBanner'; +export type { DismissbleBannerClassKey } from './DismissableBanner'; diff --git a/packages/core-components/src/components/EmptyState/EmptyState.tsx b/packages/core-components/src/components/EmptyState/EmptyState.tsx index b2f5eca65e..f3fc3b2399 100644 --- a/packages/core-components/src/components/EmptyState/EmptyState.tsx +++ b/packages/core-components/src/components/EmptyState/EmptyState.tsx @@ -18,18 +18,23 @@ import React from 'react'; import { makeStyles, Typography, Grid } from '@material-ui/core'; import { EmptyStateImage } from './EmptyStateImage'; -const useStyles = makeStyles(theme => ({ - root: { - backgroundColor: theme.palette.background.default, - padding: theme.spacing(2, 0, 0, 0), - }, - action: { - marginTop: theme.spacing(2), - }, - imageContainer: { - position: 'relative', - }, -})); +export type EmptyStateClassKey = 'root' | 'action' | 'imageContainer'; + +const useStyles = makeStyles( + theme => ({ + root: { + backgroundColor: theme.palette.background.default, + padding: theme.spacing(2, 0, 0, 0), + }, + action: { + marginTop: theme.spacing(2), + }, + imageContainer: { + position: 'relative', + }, + }), + { name: 'BackstageEmptyState' }, +); type Props = { title: string; diff --git a/packages/core-components/src/components/EmptyState/EmptyStateImage.tsx b/packages/core-components/src/components/EmptyState/EmptyStateImage.tsx index 660e7fc947..012fb04e76 100644 --- a/packages/core-components/src/components/EmptyState/EmptyStateImage.tsx +++ b/packages/core-components/src/components/EmptyState/EmptyStateImage.tsx @@ -25,16 +25,21 @@ type Props = { missing: 'field' | 'info' | 'content' | 'data'; }; -const useStyles = makeStyles({ - generalImg: { - width: '95%', - zIndex: 2, - position: 'relative', - left: '50%', - top: '50%', - transform: 'translate(-50%, 15%)', +export type EmptyStateImageClassKey = 'generalImg'; + +const useStyles = makeStyles( + { + generalImg: { + width: '95%', + zIndex: 2, + position: 'relative', + left: '50%', + top: '50%', + transform: 'translate(-50%, 15%)', + }, }, -}); + { name: 'BackstageEmptyStateImage' }, +); export const EmptyStateImage = ({ missing }: Props) => { const classes = useStyles(); diff --git a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx index 17061fa237..6f20f7c8e6 100644 --- a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx +++ b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx @@ -37,13 +37,18 @@ type Props = { annotation: string; }; -const useStyles = makeStyles(theme => ({ - code: { - borderRadius: 6, - margin: `${theme.spacing(2)}px 0px`, - background: theme.palette.type === 'dark' ? '#444' : '#fff', - }, -})); +export type MissingAnnotationEmptyStateClassKey = 'code'; + +const useStyles = makeStyles( + theme => ({ + code: { + borderRadius: 6, + margin: `${theme.spacing(2)}px 0px`, + background: theme.palette.type === 'dark' ? '#444' : '#fff', + }, + }), + { name: 'BackstageMissingAnnotationEmptyState' }, +); export function MissingAnnotationEmptyState(props: Props) { const { annotation } = props; diff --git a/packages/core-components/src/components/EmptyState/index.ts b/packages/core-components/src/components/EmptyState/index.ts index 95e12a014e..2696fba850 100644 --- a/packages/core-components/src/components/EmptyState/index.ts +++ b/packages/core-components/src/components/EmptyState/index.ts @@ -15,4 +15,7 @@ */ export { EmptyState } from './EmptyState'; +export type { EmptyStateClassKey } from './EmptyState'; +export type { EmptyStateImageClassKey } from './EmptyStateImage'; export { MissingAnnotationEmptyState } from './MissingAnnotationEmptyState'; +export type { MissingAnnotationEmptyStateClassKey } from './MissingAnnotationEmptyState'; diff --git a/packages/core-components/src/components/ErrorPanel/ErrorPanel.tsx b/packages/core-components/src/components/ErrorPanel/ErrorPanel.tsx index 309f2b447a..22f28a7a73 100644 --- a/packages/core-components/src/components/ErrorPanel/ErrorPanel.tsx +++ b/packages/core-components/src/components/ErrorPanel/ErrorPanel.tsx @@ -19,17 +19,22 @@ import React, { PropsWithChildren } from 'react'; import { CopyTextButton } from '../CopyTextButton'; import { WarningPanel } from '../WarningPanel'; -const useStyles = makeStyles(theme => ({ - text: { - fontFamily: 'monospace', - whiteSpace: 'pre', - overflowX: 'auto', - marginRight: theme.spacing(2), - }, - divider: { - margin: theme.spacing(2), - }, -})); +export type ErrorPanelClassKey = 'text' | 'divider'; + +const useStyles = makeStyles( + theme => ({ + text: { + fontFamily: 'monospace', + whiteSpace: 'pre', + overflowX: 'auto', + marginRight: theme.spacing(2), + }, + divider: { + margin: theme.spacing(2), + }, + }), + { name: 'BackstageErrorPanel' }, +); type ErrorListProps = { error: string; diff --git a/packages/core-components/src/components/ErrorPanel/index.ts b/packages/core-components/src/components/ErrorPanel/index.ts index 1da4a76959..0ea17486a5 100644 --- a/packages/core-components/src/components/ErrorPanel/index.ts +++ b/packages/core-components/src/components/ErrorPanel/index.ts @@ -15,4 +15,4 @@ */ export { ErrorPanel } from './ErrorPanel'; -export type { ErrorPanelProps } from './ErrorPanel'; +export type { ErrorPanelProps, ErrorPanelClassKey } from './ErrorPanel'; diff --git a/packages/core-components/src/components/FeatureDiscovery/FeatureCalloutCircular.tsx b/packages/core-components/src/components/FeatureDiscovery/FeatureCalloutCircular.tsx index 9459c3cbe0..7c4b9736b7 100644 --- a/packages/core-components/src/components/FeatureDiscovery/FeatureCalloutCircular.tsx +++ b/packages/core-components/src/components/FeatureDiscovery/FeatureCalloutCircular.tsx @@ -27,55 +27,67 @@ import { createPortal } from 'react-dom'; import { usePortal } from './lib/usePortal'; import { useShowCallout } from './lib/useShowCallout'; -const useStyles = makeStyles({ - '@keyframes pulsateSlightly': { - '0%': { transform: 'scale(1.0)' }, - '100%': { transform: 'scale(1.1)' }, +export type FeatureCalloutCircleClassKey = + | '@keyframes pulsateSlightly' + | '@keyframes pulsateAndFade' + | 'featureWrapper' + | 'backdrop' + | 'dot' + | 'pulseCircle' + | 'text'; + +const useStyles = makeStyles( + { + '@keyframes pulsateSlightly': { + '0%': { transform: 'scale(1.0)' }, + '100%': { transform: 'scale(1.1)' }, + }, + '@keyframes pulsateAndFade': { + '0%': { transform: 'scale(1.0)', opacity: 0.9 }, + '100%': { transform: 'scale(1.5)', opacity: 0 }, + }, + featureWrapper: { + position: 'relative', + }, + backdrop: { + zIndex: 2000, + position: 'fixed', + overflow: 'hidden', + left: 0, + right: 0, + top: 0, + bottom: 0, + }, + dot: { + position: 'absolute', + backgroundColor: 'transparent', + borderRadius: '100%', + border: '1px solid rgba(103, 146, 180, 0.98)', + boxShadow: '0px 0px 0px 20000px rgba(0, 0, 0, 0.5)', + zIndex: 2001, + transformOrigin: 'center center', + animation: + '$pulsateSlightly 1744ms 1.2s cubic-bezier(0.4, 0, 0.2, 1) alternate infinite', + }, + pulseCircle: { + width: '100%', + height: '100%', + backgroundColor: 'transparent', + borderRadius: '100%', + border: '2px solid white', + zIndex: 2001, + transformOrigin: 'center center', + animation: + '$pulsateAndFade 872ms 1.2s cubic-bezier(0.4, 0, 0.2, 1) infinite', + }, + text: { + position: 'absolute', + color: 'white', + zIndex: 2003, + }, }, - '@keyframes pulsateAndFade': { - '0%': { transform: 'scale(1.0)', opacity: 0.9 }, - '100%': { transform: 'scale(1.5)', opacity: 0 }, - }, - featureWrapper: { - position: 'relative', - }, - backdrop: { - zIndex: 2000, - position: 'fixed', - overflow: 'hidden', - left: 0, - right: 0, - top: 0, - bottom: 0, - }, - dot: { - position: 'absolute', - backgroundColor: 'transparent', - borderRadius: '100%', - border: '1px solid rgba(103, 146, 180, 0.98)', - boxShadow: '0px 0px 0px 20000px rgba(0, 0, 0, 0.5)', - zIndex: 2001, - transformOrigin: 'center center', - animation: - '$pulsateSlightly 1744ms 1.2s cubic-bezier(0.4, 0, 0.2, 1) alternate infinite', - }, - pulseCircle: { - width: '100%', - height: '100%', - backgroundColor: 'transparent', - borderRadius: '100%', - border: '2px solid white', - zIndex: 2001, - transformOrigin: 'center center', - animation: - '$pulsateAndFade 872ms 1.2s cubic-bezier(0.4, 0, 0.2, 1) infinite', - }, - text: { - position: 'absolute', - color: 'white', - zIndex: 2003, - }, -}); + { name: 'BackstageFeatureCalloutCircular' }, +); export type Props = { featureId: string; diff --git a/packages/core-components/src/components/FeatureDiscovery/index.ts b/packages/core-components/src/components/FeatureDiscovery/index.ts index ed9ab28b17..fb5979d4a9 100644 --- a/packages/core-components/src/components/FeatureDiscovery/index.ts +++ b/packages/core-components/src/components/FeatureDiscovery/index.ts @@ -15,3 +15,4 @@ */ export { FeatureCalloutCircular } from './FeatureCalloutCircular'; +export type { FeatureCalloutCircleClassKey } from './FeatureCalloutCircular'; diff --git a/packages/core-components/src/components/HeaderIconLinkRow/HeaderIconLinkRow.tsx b/packages/core-components/src/components/HeaderIconLinkRow/HeaderIconLinkRow.tsx index 7e49537492..c4508eb9bc 100644 --- a/packages/core-components/src/components/HeaderIconLinkRow/HeaderIconLinkRow.tsx +++ b/packages/core-components/src/components/HeaderIconLinkRow/HeaderIconLinkRow.tsx @@ -17,15 +17,20 @@ import React from 'react'; import { IconLinkVertical, IconLinkVerticalProps } from './IconLinkVertical'; import { makeStyles } from '@material-ui/core'; -const useStyles = makeStyles(theme => ({ - links: { - margin: theme.spacing(2, 0), - display: 'grid', - gridAutoFlow: 'column', - gridAutoColumns: 'min-content', - gridGap: theme.spacing(3), - }, -})); +export type HeaderIconLinkRowClassKey = 'links'; + +const useStyles = makeStyles( + theme => ({ + links: { + margin: theme.spacing(2, 0), + display: 'grid', + gridAutoFlow: 'column', + gridAutoColumns: 'min-content', + gridGap: theme.spacing(3), + }, + }), + { name: 'BackstageHeaderIconLinkRow' }, +); type Props = { links: IconLinkVerticalProps[]; diff --git a/packages/core-components/src/components/HeaderIconLinkRow/IconLinkVertical.tsx b/packages/core-components/src/components/HeaderIconLinkRow/IconLinkVertical.tsx index df26bc07b8..532ba2f959 100644 --- a/packages/core-components/src/components/HeaderIconLinkRow/IconLinkVertical.tsx +++ b/packages/core-components/src/components/HeaderIconLinkRow/IconLinkVertical.tsx @@ -29,30 +29,40 @@ export type IconLinkVerticalProps = { title?: string; }; -const useIconStyles = makeStyles(theme => ({ - link: { - display: 'grid', - justifyItems: 'center', - gridGap: 4, - textAlign: 'center', - }, - disabled: { - color: 'gray', - cursor: 'default', - }, - primary: { - color: theme.palette.primary.main, - }, - secondary: { - color: theme.palette.secondary.main, - }, - label: { - fontSize: '0.7rem', - textTransform: 'uppercase', - fontWeight: 600, - letterSpacing: 1.2, - }, -})); +export type IconLinkVerticalClassKey = + | 'link' + | 'disabled' + | 'primary' + | 'secondary' + | 'label'; + +const useIconStyles = makeStyles( + theme => ({ + link: { + display: 'grid', + justifyItems: 'center', + gridGap: 4, + textAlign: 'center', + }, + disabled: { + color: 'gray', + cursor: 'default', + }, + primary: { + color: theme.palette.primary.main, + }, + secondary: { + color: theme.palette.secondary.main, + }, + label: { + fontSize: '0.7rem', + textTransform: 'uppercase', + fontWeight: 600, + letterSpacing: 1.2, + }, + }), + { name: 'BackstageIconLinkVertical' }, +); export function IconLinkVertical({ color = 'primary', diff --git a/packages/core-components/src/components/HeaderIconLinkRow/index.ts b/packages/core-components/src/components/HeaderIconLinkRow/index.ts index fb732644e4..f2207d32c5 100644 --- a/packages/core-components/src/components/HeaderIconLinkRow/index.ts +++ b/packages/core-components/src/components/HeaderIconLinkRow/index.ts @@ -15,5 +15,8 @@ */ export { HeaderIconLinkRow } from './HeaderIconLinkRow'; - -export type { IconLinkVerticalProps } from './IconLinkVertical'; +export type { HeaderIconLinkRowClassKey } from './HeaderIconLinkRow'; +export type { + IconLinkVerticalProps, + IconLinkVerticalClassKey, +} from './IconLinkVertical'; diff --git a/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.tsx b/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.tsx index a3d16bc4ec..88b61d56bb 100644 --- a/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.tsx +++ b/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.tsx @@ -54,52 +54,66 @@ type Props = { minScrollDistance?: number; // limits how small steps the scroll can take in px }; -const useStyles = makeStyles(theme => ({ - root: { - position: 'relative', - display: 'flex', - flexFlow: 'row nowrap', - alignItems: 'center', - }, - container: { - overflow: 'auto', - scrollbarWidth: 0 as any, // hide in FF - '&::-webkit-scrollbar': { - display: 'none', // hide in Chrome +export type HorizontalScrollGridClassKey = + | 'root' + | 'container' + | 'fade' + | 'fadeLeft' + | 'fadeRight' + | 'fadeHidden' + | 'button' + | 'buttonLeft' + | 'buttonRight'; + +const useStyles = makeStyles( + theme => ({ + root: { + position: 'relative', + display: 'flex', + flexFlow: 'row nowrap', + alignItems: 'center', }, - }, - fade: { - position: 'absolute', - width: fadeSize, - height: `calc(100% + ${fadePadding}px)`, - transition: 'opacity 300ms', - pointerEvents: 'none', - }, - fadeLeft: { - left: -fadePadding, - background: `linear-gradient(90deg, ${generateGradientStops( - theme.palette.type, - )})`, - }, - fadeRight: { - right: -fadePadding, - background: `linear-gradient(270deg, ${generateGradientStops( - theme.palette.type, - )})`, - }, - fadeHidden: { - opacity: 0, - }, - button: { - position: 'absolute', - }, - buttonLeft: { - left: -theme.spacing(2), - }, - buttonRight: { - right: -theme.spacing(2), - }, -})); + container: { + overflow: 'auto', + scrollbarWidth: 0 as any, // hide in FF + '&::-webkit-scrollbar': { + display: 'none', // hide in Chrome + }, + }, + fade: { + position: 'absolute', + width: fadeSize, + height: `calc(100% + ${fadePadding}px)`, + transition: 'opacity 300ms', + pointerEvents: 'none', + }, + fadeLeft: { + left: -fadePadding, + background: `linear-gradient(90deg, ${generateGradientStops( + theme.palette.type, + )})`, + }, + fadeRight: { + right: -fadePadding, + background: `linear-gradient(270deg, ${generateGradientStops( + theme.palette.type, + )})`, + }, + fadeHidden: { + opacity: 0, + }, + button: { + position: 'absolute', + }, + buttonLeft: { + left: -theme.spacing(2), + }, + buttonRight: { + right: -theme.spacing(2), + }, + }), + { name: 'BackstageHorizontalScrollGrid' }, +); // Returns scroll distance from left and right function useScrollDistance( diff --git a/packages/core-components/src/components/HorizontalScrollGrid/index.tsx b/packages/core-components/src/components/HorizontalScrollGrid/index.tsx index bbf545dab3..e126bbf70f 100644 --- a/packages/core-components/src/components/HorizontalScrollGrid/index.tsx +++ b/packages/core-components/src/components/HorizontalScrollGrid/index.tsx @@ -15,3 +15,4 @@ */ export { HorizontalScrollGrid } from './HorizontalScrollGrid'; +export type { HorizontalScrollGridClassKey } from './HorizontalScrollGrid'; diff --git a/packages/core-components/src/components/Lifecycle/Lifecycle.tsx b/packages/core-components/src/components/Lifecycle/Lifecycle.tsx index ef451ac1b0..76e63854f5 100644 --- a/packages/core-components/src/components/Lifecycle/Lifecycle.tsx +++ b/packages/core-components/src/components/Lifecycle/Lifecycle.tsx @@ -23,20 +23,25 @@ type Props = CSS.Properties & { alpha?: boolean; }; -const useStyles = makeStyles({ - alpha: { - color: '#ffffff', - fontFamily: 'serif', - fontWeight: 'normal', - fontStyle: 'italic', +export type LifecycleClassKey = 'alpha' | 'beta'; + +const useStyles = makeStyles( + { + alpha: { + color: '#ffffff', + fontFamily: 'serif', + fontWeight: 'normal', + fontStyle: 'italic', + }, + beta: { + color: '#4d65cc', + fontFamily: 'serif', + fontWeight: 'normal', + fontStyle: 'italic', + }, }, - beta: { - color: '#4d65cc', - fontFamily: 'serif', - fontWeight: 'normal', - fontStyle: 'italic', - }, -}); + { name: 'BackstageLifecycle' }, +); export function Lifecycle(props: Props) { const classes = useStyles(props); diff --git a/packages/core-components/src/components/Lifecycle/index.ts b/packages/core-components/src/components/Lifecycle/index.ts index d52e79e08b..ebf16cb685 100644 --- a/packages/core-components/src/components/Lifecycle/index.ts +++ b/packages/core-components/src/components/Lifecycle/index.ts @@ -15,3 +15,4 @@ */ export { Lifecycle } from './Lifecycle'; +export type { LifecycleClassKey } from './Lifecycle'; diff --git a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx index d2930cbf5d..65be789bb4 100644 --- a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx +++ b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx @@ -21,43 +21,48 @@ import React from 'react'; import { BackstageTheme } from '@backstage/theme'; import { CodeSnippet } from '../CodeSnippet'; -const useStyles = makeStyles(theme => ({ - markdown: { - '& table': { - borderCollapse: 'collapse', - border: `1px solid ${theme.palette.border}`, - }, - '& th, & td': { - border: `1px solid ${theme.palette.border}`, - padding: theme.spacing(1), - }, - '& td': { - wordBreak: 'break-word', - overflow: 'hidden', - verticalAlign: 'middle', - lineHeight: '1', - margin: 0, - padding: theme.spacing(3, 2, 3, 2.5), - borderBottom: 0, - }, - '& th': { - backgroundColor: theme.palette.background.paper, - }, - '& tr': { - backgroundColor: theme.palette.background.paper, - }, - '& tr:nth-child(odd)': { - backgroundColor: theme.palette.background.default, - }, +export type MarkdownContentClassKey = 'markdown'; - '& a': { - color: theme.palette.link, +const useStyles = makeStyles( + theme => ({ + markdown: { + '& table': { + borderCollapse: 'collapse', + border: `1px solid ${theme.palette.border}`, + }, + '& th, & td': { + border: `1px solid ${theme.palette.border}`, + padding: theme.spacing(1), + }, + '& td': { + wordBreak: 'break-word', + overflow: 'hidden', + verticalAlign: 'middle', + lineHeight: '1', + margin: 0, + padding: theme.spacing(3, 2, 3, 2.5), + borderBottom: 0, + }, + '& th': { + backgroundColor: theme.palette.background.paper, + }, + '& tr': { + backgroundColor: theme.palette.background.paper, + }, + '& tr:nth-child(odd)': { + backgroundColor: theme.palette.background.default, + }, + + '& a': { + color: theme.palette.link, + }, + '& img': { + maxWidth: '100%', + }, }, - '& img': { - maxWidth: '100%', - }, - }, -})); + }), + { name: 'BackstageMarkdownContent' }, +); type Props = { content: string; diff --git a/packages/core-components/src/components/MarkdownContent/index.ts b/packages/core-components/src/components/MarkdownContent/index.ts index 9218d9fcde..2e4ef08d3f 100644 --- a/packages/core-components/src/components/MarkdownContent/index.ts +++ b/packages/core-components/src/components/MarkdownContent/index.ts @@ -15,3 +15,4 @@ */ export { MarkdownContent } from './MarkdownContent'; +export type { MarkdownContentClassKey } from './MarkdownContent'; diff --git a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx index f9533d9d03..7f7f51abba 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx +++ b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx @@ -26,11 +26,16 @@ import { import React, { useState } from 'react'; import { PendingAuthRequest } from '@backstage/core-plugin-api'; -const useItemStyles = makeStyles(theme => ({ - root: { - paddingLeft: theme.spacing(3), - }, -})); +export type LoginRequestListItemClassKey = 'root'; + +const useItemStyles = makeStyles( + theme => ({ + root: { + paddingLeft: theme.spacing(3), + }, + }), + { name: 'BackstageLoginRequestListItem' }, +); type RowProps = { request: PendingAuthRequest; diff --git a/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx b/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx index e79d28c470..73e276fce9 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx +++ b/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx @@ -29,20 +29,29 @@ import { useObservable } from 'react-use'; import LoginRequestListItem from './LoginRequestListItem'; import { useApi, oauthRequestApiRef } from '@backstage/core-plugin-api'; -const useStyles = makeStyles(theme => ({ - dialog: { - paddingTop: theme.spacing(1), - }, - title: { - minWidth: 0, - }, - contentList: { - padding: 0, - }, - actionButtons: { - padding: theme.spacing(2, 0), - }, -})); +export type OAuthRequestDialogClassKey = + | 'dialog' + | 'title' + | 'contentList' + | 'actionButtons'; + +const useStyles = makeStyles( + theme => ({ + dialog: { + paddingTop: theme.spacing(1), + }, + title: { + minWidth: 0, + }, + contentList: { + padding: 0, + }, + actionButtons: { + padding: theme.spacing(2, 0), + }, + }), + { name: 'OAuthRequestDialog' }, +); export function OAuthRequestDialog(_props: {}) { const classes = useStyles(); diff --git a/packages/core-components/src/components/OAuthRequestDialog/index.ts b/packages/core-components/src/components/OAuthRequestDialog/index.ts index d2a48eac06..92347e0ed7 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/index.ts +++ b/packages/core-components/src/components/OAuthRequestDialog/index.ts @@ -15,3 +15,5 @@ */ export { OAuthRequestDialog } from './OAuthRequestDialog'; +export type { OAuthRequestDialogClassKey } from './OAuthRequestDialog'; +export type { LoginRequestListItemClassKey } from './LoginRequestListItem'; diff --git a/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx b/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx index fbb1537847..a06930cdfa 100644 --- a/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx +++ b/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx @@ -26,11 +26,16 @@ type Props = { placement?: TooltipProps['placement']; }; -const useStyles = makeStyles({ - container: { - overflow: 'visible !important', +export type OverflowTooltipClassKey = 'container'; + +const useStyles = makeStyles( + { + container: { + overflow: 'visible !important', + }, }, -}); + { name: 'BackstageOverflowTooltip' }, +); export function OverflowTooltip(props: Props) { const [hover, setHover] = useState(false); diff --git a/packages/core-components/src/components/OverflowTooltip/index.ts b/packages/core-components/src/components/OverflowTooltip/index.ts index f7258b5364..af8616d740 100644 --- a/packages/core-components/src/components/OverflowTooltip/index.ts +++ b/packages/core-components/src/components/OverflowTooltip/index.ts @@ -14,3 +14,4 @@ * limitations under the License. */ export { OverflowTooltip } from './OverflowTooltip'; +export type { OverflowTooltipClassKey } from './OverflowTooltip'; diff --git a/packages/core-components/src/components/ProgressBars/Gauge.tsx b/packages/core-components/src/components/ProgressBars/Gauge.tsx index 3b31f64fe7..2699f8a289 100644 --- a/packages/core-components/src/components/ProgressBars/Gauge.tsx +++ b/packages/core-components/src/components/ProgressBars/Gauge.tsx @@ -19,26 +19,31 @@ import { BackstageTheme } from '@backstage/theme'; import { Circle } from 'rc-progress'; import React from 'react'; -const useStyles = makeStyles(theme => ({ - root: { - position: 'relative', - lineHeight: 0, - }, - overlay: { - position: 'absolute', - top: '50%', - left: '50%', - transform: 'translate(-50%, -60%)', - fontSize: 45, - fontWeight: 'bold', - color: theme.palette.textContrast, - }, - circle: { - width: '80%', - transform: 'translate(10%, 0)', - }, - colorUnknown: {}, -})); +export type GaugeClassKey = 'root' | 'overlay' | 'circle' | 'colorUnknown'; + +const useStyles = makeStyles( + theme => ({ + root: { + position: 'relative', + lineHeight: 0, + }, + overlay: { + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -60%)', + fontSize: 45, + fontWeight: 'bold', + color: theme.palette.textContrast, + }, + circle: { + width: '80%', + transform: 'translate(10%, 0)', + }, + colorUnknown: {}, + }), + { name: 'BackstageGauge' }, +); type Props = { value: number; diff --git a/packages/core-components/src/components/ProgressBars/GaugeCard.tsx b/packages/core-components/src/components/ProgressBars/GaugeCard.tsx index 0a603ea991..aec63add11 100644 --- a/packages/core-components/src/components/ProgressBars/GaugeCard.tsx +++ b/packages/core-components/src/components/ProgressBars/GaugeCard.tsx @@ -30,12 +30,17 @@ type Props = { deepLink?: BottomLinkProps; }; -const useStyles = makeStyles({ - root: { - height: '100%', - width: 250, +export type GaugeCardClassKey = 'root'; + +const useStyles = makeStyles( + { + root: { + height: '100%', + width: 250, + }, }, -}); + { name: 'BackstageGaugeCard' }, +); export function GaugeCard(props: Props) { const classes = useStyles(props); diff --git a/packages/core-components/src/components/ProgressBars/index.ts b/packages/core-components/src/components/ProgressBars/index.ts index 01cab20f27..3d821eaac2 100644 --- a/packages/core-components/src/components/ProgressBars/index.ts +++ b/packages/core-components/src/components/ProgressBars/index.ts @@ -15,5 +15,7 @@ */ export { GaugeCard } from './GaugeCard'; +export type { GaugeCardClassKey } from './GaugeCard'; export { Gauge } from './Gauge'; +export type { GaugeClassKey } from './Gauge'; export { LinearGauge } from './LinearGauge'; diff --git a/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx b/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx index 9f25e8290f..37143000a3 100644 --- a/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx +++ b/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx @@ -21,17 +21,22 @@ import { CodeSnippet } from '../CodeSnippet'; import { CopyTextButton } from '../CopyTextButton'; import { ErrorPanel, ErrorPanelProps } from '../ErrorPanel'; -const useStyles = makeStyles(theme => ({ - text: { - fontFamily: 'monospace', - whiteSpace: 'pre', - overflowX: 'auto', - marginRight: theme.spacing(2), - }, - divider: { - margin: theme.spacing(2), - }, -})); +export type ResponseErrorPanelClassKey = 'text' | 'divider'; + +const useStyles = makeStyles( + theme => ({ + text: { + fontFamily: 'monospace', + whiteSpace: 'pre', + overflowX: 'auto', + marginRight: theme.spacing(2), + }, + divider: { + margin: theme.spacing(2), + }, + }), + { name: 'BackstageResponseErrorPanel' }, +); /** * Renders a warning panel as the effect of a failed server request. diff --git a/packages/core-components/src/components/ResponseErrorPanel/index.ts b/packages/core-components/src/components/ResponseErrorPanel/index.ts index c93bd9eade..c29249d01e 100644 --- a/packages/core-components/src/components/ResponseErrorPanel/index.ts +++ b/packages/core-components/src/components/ResponseErrorPanel/index.ts @@ -15,3 +15,4 @@ */ export { ResponseErrorPanel } from './ResponseErrorPanel'; +export type { ResponseErrorPanelClassKey } from './ResponseErrorPanel'; diff --git a/packages/core-components/src/components/Select/Select.tsx b/packages/core-components/src/components/Select/Select.tsx index ae14545b29..23ed2cf62c 100644 --- a/packages/core-components/src/components/Select/Select.tsx +++ b/packages/core-components/src/components/Select/Select.tsx @@ -34,59 +34,73 @@ import React, { useEffect, useState } from 'react'; import ClosedDropdown from './static/ClosedDropdown'; import OpenedDropdown from './static/OpenedDropdown'; -const BootstrapInput = withStyles((theme: Theme) => - createStyles({ - root: { - 'label + &': { - marginTop: theme.spacing(3), +export type SelectInputBaseClassKey = 'root' | 'input'; + +const BootstrapInput = withStyles( + (theme: Theme) => + createStyles({ + root: { + 'label + &': { + marginTop: theme.spacing(3), + }, }, - }, - input: { - borderRadius: 4, - position: 'relative', - backgroundColor: theme.palette.background.paper, - border: '1px solid #ced4da', - fontSize: 16, - padding: '10px 26px 10px 12px', - transition: theme.transitions.create(['border-color', 'box-shadow']), - fontFamily: 'Helvetica Neue', - '&:focus': { - background: theme.palette.background.paper, + input: { borderRadius: 4, + position: 'relative', + backgroundColor: theme.palette.background.paper, + border: '1px solid #ced4da', + fontSize: 16, + padding: '10px 26px 10px 12px', + transition: theme.transitions.create(['border-color', 'box-shadow']), + fontFamily: 'Helvetica Neue', + '&:focus': { + background: theme.palette.background.paper, + borderRadius: 4, + }, }, - }, - }), + }), + { name: 'BackstageSelectInputBase' }, )(InputBase); -const useStyles = makeStyles((theme: Theme) => - createStyles({ - formControl: { - margin: `${theme.spacing(1)} 0px`, - maxWidth: 300, - }, - label: { - transform: 'initial', - fontWeight: 'bold', - fontSize: 14, - fontFamily: theme.typography.fontFamily, - color: theme.palette.text.primary, - '&.Mui-focused': { - color: theme.palette.text.primary, +export type SelectClassKey = + | 'formControl' + | 'label' + | 'chips' + | 'chip' + | 'checkbox' + | 'root'; + +const useStyles = makeStyles( + (theme: Theme) => + createStyles({ + formControl: { + margin: `${theme.spacing(1)} 0px`, + maxWidth: 300, }, - }, - chips: { - display: 'flex', - flexWrap: 'wrap', - }, - chip: { - margin: 2, - }, - checkbox: {}, - root: { - display: 'flex', - flexDirection: 'column', - }, - }), + label: { + transform: 'initial', + fontWeight: 'bold', + fontSize: 14, + fontFamily: theme.typography.fontFamily, + color: theme.palette.text.primary, + '&.Mui-focused': { + color: theme.palette.text.primary, + }, + }, + chips: { + display: 'flex', + flexWrap: 'wrap', + }, + chip: { + margin: 2, + }, + checkbox: {}, + root: { + display: 'flex', + flexDirection: 'column', + }, + }), + { name: 'BackstageSelect' }, ); type Item = { diff --git a/packages/core-components/src/components/Select/index.tsx b/packages/core-components/src/components/Select/index.tsx index 0c35cc1378..0f149f05b5 100644 --- a/packages/core-components/src/components/Select/index.tsx +++ b/packages/core-components/src/components/Select/index.tsx @@ -15,3 +15,6 @@ */ export { SelectComponent as Select } from './Select'; +export type { SelectClassKey, SelectInputBaseClassKey } from './Select'; +export type { ClosedDropdownClassKey } from './static/ClosedDropdown'; +export type { OpenedDropdownClassKey } from './static/OpenedDropdown'; diff --git a/packages/core-components/src/components/Select/static/ClosedDropdown.tsx b/packages/core-components/src/components/Select/static/ClosedDropdown.tsx index 41155bb268..61a24abcef 100644 --- a/packages/core-components/src/components/Select/static/ClosedDropdown.tsx +++ b/packages/core-components/src/components/Select/static/ClosedDropdown.tsx @@ -16,14 +16,18 @@ import React from 'react'; import { SvgIcon, makeStyles, createStyles } from '@material-ui/core'; -const useStyles = makeStyles(() => - createStyles({ - icon: { - position: 'absolute', - right: '4px', - pointerEvents: 'none', - }, - }), +export type ClosedDropdownClassKey = 'icon'; + +const useStyles = makeStyles( + () => + createStyles({ + icon: { + position: 'absolute', + right: '4px', + pointerEvents: 'none', + }, + }), + { name: 'BackstageClosedDropdown' }, ); const ClosedDropdown = () => { diff --git a/packages/core-components/src/components/Select/static/OpenedDropdown.tsx b/packages/core-components/src/components/Select/static/OpenedDropdown.tsx index 2c91dc6989..eb86a34fe0 100644 --- a/packages/core-components/src/components/Select/static/OpenedDropdown.tsx +++ b/packages/core-components/src/components/Select/static/OpenedDropdown.tsx @@ -16,14 +16,18 @@ import React from 'react'; import { SvgIcon, makeStyles, createStyles } from '@material-ui/core'; -const useStyles = makeStyles(() => - createStyles({ - icon: { - position: 'absolute', - right: '4px', - pointerEvents: 'none', - }, - }), +export type OpenedDropdownClassKey = 'icon'; + +const useStyles = makeStyles( + () => + createStyles({ + icon: { + position: 'absolute', + right: '4px', + pointerEvents: 'none', + }, + }), + { name: 'BackstageOpenedDropdown' }, ); const OpenedDropdown = () => { diff --git a/packages/core-components/src/components/SimpleStepper/SimpleStepperFooter.tsx b/packages/core-components/src/components/SimpleStepper/SimpleStepperFooter.tsx index b126b5ba75..270099a104 100644 --- a/packages/core-components/src/components/SimpleStepper/SimpleStepperFooter.tsx +++ b/packages/core-components/src/components/SimpleStepper/SimpleStepperFooter.tsx @@ -18,14 +18,19 @@ import { Button, makeStyles } from '@material-ui/core'; import { StepActions } from './types'; import { VerticalStepperContext } from './SimpleStepper'; -const useStyles = makeStyles(theme => ({ - root: { - marginTop: theme.spacing(3), - '& button': { - marginRight: theme.spacing(1), +export type SimpleStepperFooterClassKey = 'root'; + +const useStyles = makeStyles( + theme => ({ + root: { + marginTop: theme.spacing(3), + '& button': { + marginRight: theme.spacing(1), + }, }, - }, -})); + }), + { name: 'BackstageSimpleStepperFooter' }, +); interface CommonBtnProps { text?: string; diff --git a/packages/core-components/src/components/SimpleStepper/SimpleStepperStep.tsx b/packages/core-components/src/components/SimpleStepper/SimpleStepperStep.tsx index 39383b934b..0696a1256a 100644 --- a/packages/core-components/src/components/SimpleStepper/SimpleStepperStep.tsx +++ b/packages/core-components/src/components/SimpleStepper/SimpleStepperStep.tsx @@ -24,11 +24,16 @@ import { import { SimpleStepperFooter } from './SimpleStepperFooter'; import { StepProps } from './types'; -const useStyles = makeStyles(theme => ({ - end: { - padding: theme.spacing(3), - }, -})); +export type SimpleStepperStepClassKey = 'end'; + +const useStyles = makeStyles( + theme => ({ + end: { + padding: theme.spacing(3), + }, + }), + { name: 'SimpleStepperStep' }, +); export function SimpleStepperStep(props: PropsWithChildren) { const { title, children, end, actions, ...muiProps } = props; diff --git a/packages/core-components/src/components/SimpleStepper/index.ts b/packages/core-components/src/components/SimpleStepper/index.ts index ddb6d2537a..e7f6388e27 100644 --- a/packages/core-components/src/components/SimpleStepper/index.ts +++ b/packages/core-components/src/components/SimpleStepper/index.ts @@ -15,4 +15,6 @@ */ export { SimpleStepper } from './SimpleStepper'; +export type { SimpleStepperFooterClassKey } from './SimpleStepperFooter'; export { SimpleStepperStep } from './SimpleStepperStep'; +export type { SimpleStepperStepClassKey } from './SimpleStepperStep'; diff --git a/packages/core-components/src/components/Status/Status.tsx b/packages/core-components/src/components/Status/Status.tsx index 2b2d40dee3..a6215d6127 100644 --- a/packages/core-components/src/components/Status/Status.tsx +++ b/packages/core-components/src/components/Status/Status.tsx @@ -19,49 +19,61 @@ import { BackstageTheme } from '@backstage/theme'; import classNames from 'classnames'; import React, { PropsWithChildren } from 'react'; -const useStyles = makeStyles(theme => ({ - status: { - fontWeight: 500, - '&::before': { - width: '0.7em', - height: '0.7em', - display: 'inline-block', - marginRight: 8, - borderRadius: '50%', - content: '""', +export type StatusClassKey = + | 'status' + | 'ok' + | 'warning' + | 'error' + | 'pending' + | 'running' + | 'aborted'; + +const useStyles = makeStyles( + theme => ({ + status: { + fontWeight: 500, + '&::before': { + width: '0.7em', + height: '0.7em', + display: 'inline-block', + marginRight: 8, + borderRadius: '50%', + content: '""', + }, }, - }, - ok: { - '&::before': { - backgroundColor: theme.palette.status.ok, + ok: { + '&::before': { + backgroundColor: theme.palette.status.ok, + }, }, - }, - warning: { - '&::before': { - backgroundColor: theme.palette.status.warning, + warning: { + '&::before': { + backgroundColor: theme.palette.status.warning, + }, }, - }, - error: { - '&::before': { - backgroundColor: theme.palette.status.error, + error: { + '&::before': { + backgroundColor: theme.palette.status.error, + }, }, - }, - pending: { - '&::before': { - backgroundColor: theme.palette.status.pending, + pending: { + '&::before': { + backgroundColor: theme.palette.status.pending, + }, }, - }, - running: { - '&::before': { - backgroundColor: theme.palette.status.running, + running: { + '&::before': { + backgroundColor: theme.palette.status.running, + }, }, - }, - aborted: { - '&::before': { - backgroundColor: theme.palette.status.aborted, + aborted: { + '&::before': { + backgroundColor: theme.palette.status.aborted, + }, }, - }, -})); + }), + { name: 'BackstageStatus' }, +); export function StatusOK(props: PropsWithChildren<{}>) { const classes = useStyles(props); diff --git a/packages/core-components/src/components/Status/index.ts b/packages/core-components/src/components/Status/index.ts index 2e34890482..39c4e02c5e 100644 --- a/packages/core-components/src/components/Status/index.ts +++ b/packages/core-components/src/components/Status/index.ts @@ -22,3 +22,5 @@ export { StatusRunning, StatusWarning, } from './Status'; + +export type { StatusClassKey } from './Status'; diff --git a/packages/core-components/src/components/StructuredMetadataTable/MetadataTable.tsx b/packages/core-components/src/components/StructuredMetadataTable/MetadataTable.tsx index 5740ba9500..3c869f88c3 100644 --- a/packages/core-components/src/components/StructuredMetadataTable/MetadataTable.tsx +++ b/packages/core-components/src/components/StructuredMetadataTable/MetadataTable.tsx @@ -26,6 +26,8 @@ import { Theme, } from '@material-ui/core'; +export type MetadataTableTitleCellClassKey = 'root'; + const tableTitleCellStyles = (theme: Theme) => createStyles({ root: { @@ -37,6 +39,8 @@ const tableTitleCellStyles = (theme: Theme) => }, }); +export type MetadataTableCellClassKey = 'root'; + const tableContentCellStyles = { root: { border: '0', @@ -44,6 +48,8 @@ const tableContentCellStyles = { }, }; +export type MetadataTableListClassKey = 'root'; + const listStyles = (theme: Theme) => createStyles({ root: { @@ -53,6 +59,8 @@ const listStyles = (theme: Theme) => }, }); +export type MetadataTableListItemClassKey = 'root' | 'random'; + const listItemStyles = (theme: Theme) => createStyles({ root: { @@ -61,8 +69,12 @@ const listItemStyles = (theme: Theme) => random: {}, }); -const TitleCell = withStyles(tableTitleCellStyles)(TableCell); -const ContentCell = withStyles(tableContentCellStyles)(TableCell); +const TitleCell = withStyles(tableTitleCellStyles, { + name: 'BackstageMetadataTableTitleCell', +})(TableCell); +const ContentCell = withStyles(tableContentCellStyles, { + name: 'BackstageMetadataTableCell', +})(TableCell); export const MetadataTable = ({ dense, @@ -96,14 +108,14 @@ interface StyleProps extends WithStyles { children?: React.ReactNode; } -export const MetadataList = withStyles(listStyles)( - ({ classes, children }: StyleProps) => ( -
    {children}
- ), -); +export const MetadataList = withStyles(listStyles, { + name: 'BackstageMetadataTableList', +})(({ classes, children }: StyleProps) => ( +
    {children}
+)); -export const MetadataListItem = withStyles(listItemStyles)( - ({ classes, children }: StyleProps) => ( -
  • {children}
  • - ), -); +export const MetadataListItem = withStyles(listItemStyles, { + name: 'BackstageMetadataTableListItem', +})(({ classes, children }: StyleProps) => ( +
  • {children}
  • +)); diff --git a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx index 22a1a43b69..abaa662159 100644 --- a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx +++ b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx @@ -25,6 +25,8 @@ import { MetadataListItem, } from './MetadataTable'; +export type StructuredMetadataTableListClassKey = 'root'; + const listStyle = createStyles({ root: { margin: '0 0', @@ -32,6 +34,8 @@ const listStyle = createStyles({ }, }); +export type StructuredMetadataTableNestedListClassKey = 'root'; + const nestedListStyle = (theme: Theme) => createStyles({ root: { @@ -44,16 +48,16 @@ interface StyleProps extends WithStyles { children?: React.ReactNode; } // Sub Components -const StyledList = withStyles(listStyle)( - ({ classes, children }: StyleProps) => ( - {children} - ), -); -const StyledNestedList = withStyles(nestedListStyle)( - ({ classes, children }: StyleProps) => ( - {children} - ), -); +const StyledList = withStyles(listStyle, { + name: 'BackstageStructuredMetadataTableList', +})(({ classes, children }: StyleProps) => ( + {children} +)); +const StyledNestedList = withStyles(nestedListStyle, { + name: 'BackstageStructuredMetadataTableNestedList', +})(({ classes, children }: StyleProps) => ( + {children} +)); function renderList(list: Array, nested?: boolean) { const values = list.map((item: any, index: number) => ( diff --git a/packages/core-components/src/components/StructuredMetadataTable/index.tsx b/packages/core-components/src/components/StructuredMetadataTable/index.tsx index 32ba94edd6..855df31e2f 100644 --- a/packages/core-components/src/components/StructuredMetadataTable/index.tsx +++ b/packages/core-components/src/components/StructuredMetadataTable/index.tsx @@ -14,4 +14,14 @@ * limitations under the License. */ +export type { + MetadataTableCellClassKey, + MetadataTableTitleCellClassKey, + MetadataTableListClassKey, + MetadataTableListItemClassKey, +} from './MetadataTable'; export { StructuredMetadataTable } from './StructuredMetadataTable'; +export type { + StructuredMetadataTableListClassKey, + StructuredMetadataTableNestedListClassKey, +} from './StructuredMetadataTable'; diff --git a/packages/core-components/src/components/SupportButton/SupportButton.tsx b/packages/core-components/src/components/SupportButton/SupportButton.tsx index 62d753e08b..bee2928314 100644 --- a/packages/core-components/src/components/SupportButton/SupportButton.tsx +++ b/packages/core-components/src/components/SupportButton/SupportButton.tsx @@ -40,12 +40,17 @@ type SupportButtonProps = { children?: React.ReactNode; }; -const useStyles = makeStyles({ - popoverList: { - minWidth: 260, - maxWidth: 400, +export type SupportButtonClassKey = 'popoverList'; + +const useStyles = makeStyles( + { + popoverList: { + minWidth: 260, + maxWidth: 400, + }, }, -}); + { name: 'BackstageSupportButton' }, +); const SupportIcon = ({ icon }: { icon: string | undefined }) => { const app = useApp(); diff --git a/packages/core-components/src/components/SupportButton/index.ts b/packages/core-components/src/components/SupportButton/index.ts index 57e6103889..6c5bf6475f 100644 --- a/packages/core-components/src/components/SupportButton/index.ts +++ b/packages/core-components/src/components/SupportButton/index.ts @@ -15,3 +15,4 @@ */ export { SupportButton } from './SupportButton'; +export type { SupportButtonClassKey } from './SupportButton'; diff --git a/packages/core-components/src/components/Table/Filters.tsx b/packages/core-components/src/components/Table/Filters.tsx index bd70e3eb64..7498138751 100644 --- a/packages/core-components/src/components/Table/Filters.tsx +++ b/packages/core-components/src/components/Table/Filters.tsx @@ -20,33 +20,38 @@ import { Button, makeStyles } from '@material-ui/core'; import { Select } from '../Select'; import { SelectProps } from '../Select/Select'; -const useSubvalueCellStyles = makeStyles(theme => ({ - root: { - height: '100%', - width: '315px', - display: 'flex', - flexDirection: 'column', - marginRight: theme.spacing(3), - }, - value: { - fontWeight: 'bold', - fontSize: 18, - }, - header: { - display: 'flex', - alignItems: 'center', - height: '60px', - justifyContent: 'space-between', - borderBottom: `1px solid ${theme.palette.grey[500]}`, - }, - filters: { - display: 'flex', - flexDirection: 'column', - '& > *': { - marginTop: theme.spacing(2), +export type TableFiltersClassKey = 'root' | 'value' | 'heder' | 'filters'; + +const useFilterStyles = makeStyles( + theme => ({ + root: { + height: '100%', + width: '315px', + display: 'flex', + flexDirection: 'column', + marginRight: theme.spacing(3), }, - }, -})); + value: { + fontWeight: 'bold', + fontSize: 18, + }, + header: { + display: 'flex', + alignItems: 'center', + height: '60px', + justifyContent: 'space-between', + borderBottom: `1px solid ${theme.palette.grey[500]}`, + }, + filters: { + display: 'flex', + flexDirection: 'column', + '& > *': { + marginTop: theme.spacing(2), + }, + }, + }), + { name: 'BackstageTableFilters' }, +); export type Without = Pick>; @@ -66,7 +71,7 @@ type Props = { }; export const Filters = (props: Props) => { - const classes = useSubvalueCellStyles(); + const classes = useFilterStyles(); const { onChangeFilters } = props; diff --git a/packages/core-components/src/components/Table/SubvalueCell.tsx b/packages/core-components/src/components/Table/SubvalueCell.tsx index fd7d3fd9fa..43fb54fca8 100644 --- a/packages/core-components/src/components/Table/SubvalueCell.tsx +++ b/packages/core-components/src/components/Table/SubvalueCell.tsx @@ -18,15 +18,20 @@ import React from 'react'; import { BackstageTheme } from '@backstage/theme'; import { makeStyles } from '@material-ui/core'; -const useSubvalueCellStyles = makeStyles(theme => ({ - value: { - marginBottom: '6px', - }, - subvalue: { - color: theme.palette.textSubtle, - fontWeight: 'normal', - }, -})); +export type SubvalueCellClassKey = 'value' | 'subvalue'; + +const useSubvalueCellStyles = makeStyles( + theme => ({ + value: { + marginBottom: '6px', + }, + subvalue: { + color: theme.palette.textSubtle, + fontWeight: 'normal', + }, + }), + { name: 'BackstageSubvalueCell' }, +); type SubvalueCellProps = { value: React.ReactNode; diff --git a/packages/core-components/src/components/Table/Table.tsx b/packages/core-components/src/components/Table/Table.tsx index 627e5b8ccc..61e9cc7969 100644 --- a/packages/core-components/src/components/Table/Table.tsx +++ b/packages/core-components/src/components/Table/Table.tsx @@ -100,52 +100,72 @@ function extractValueByField(data: any, field: string): any | undefined { return value; } -const StyledMTableHeader = withStyles(theme => ({ - header: { - padding: theme.spacing(1, 2, 1, 2.5), - borderTop: `1px solid ${theme.palette.grey.A100}`, - borderBottom: `1px solid ${theme.palette.grey.A100}`, - // withStyles hasn't a generic overload for theme - color: (theme as BackstageTheme).palette.textSubtle, - fontWeight: theme.typography.fontWeightBold, - position: 'static', - wordBreak: 'normal', - }, -}))(MTableHeader); +export type TableHeaderClassKey = 'header'; -const StyledMTableToolbar = withStyles(theme => ({ - root: { - padding: theme.spacing(3, 0, 2.5, 2.5), - }, - title: { - '& > h6': { - fontWeight: 'bold', +const StyledMTableHeader = withStyles( + theme => ({ + header: { + padding: theme.spacing(1, 2, 1, 2.5), + borderTop: `1px solid ${theme.palette.grey.A100}`, + borderBottom: `1px solid ${theme.palette.grey.A100}`, + // withStyles hasn't a generic overload for theme + color: (theme as BackstageTheme).palette.textSubtle, + fontWeight: theme.typography.fontWeightBold, + position: 'static', + wordBreak: 'normal', }, - }, - searchField: { - paddingRight: theme.spacing(2), - }, -}))(MTableToolbar); + }), + { name: 'BackstageTableHeader' }, +)(MTableHeader); -const useFilterStyles = makeStyles(() => ({ - root: { - display: 'flex', - alignItems: 'center', - justifyContent: 'space-between', - }, - title: { - fontWeight: 'bold', - fontSize: 18, - whiteSpace: 'nowrap', - }, -})); +export type TableToolbarClassKey = 'root' | 'title' | 'searchField'; -const useTableStyles = makeStyles(() => ({ - root: { - display: 'flex', - alignItems: 'start', - }, -})); +const StyledMTableToolbar = withStyles( + theme => ({ + root: { + padding: theme.spacing(3, 0, 2.5, 2.5), + }, + title: { + '& > h6': { + fontWeight: 'bold', + }, + }, + searchField: { + paddingRight: theme.spacing(2), + }, + }), + { name: 'BackstageTableToolbar' }, +)(MTableToolbar); + +export type FiltersContainerClassKey = 'root' | 'title'; + +const useFilterStyles = makeStyles( + () => ({ + root: { + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + }, + title: { + fontWeight: 'bold', + fontSize: 18, + whiteSpace: 'nowrap', + }, + }), + { name: 'BackstageTableFiltersContainer' }, +); + +export type TableClassKey = 'root'; + +const useTableStyles = makeStyles( + () => ({ + root: { + display: 'flex', + alignItems: 'start', + }, + }), + { name: 'BackstageTable' }, +); function convertColumns( columns: TableColumn[], diff --git a/packages/core-components/src/components/Table/index.ts b/packages/core-components/src/components/Table/index.ts index f46aab42df..5024d960b8 100644 --- a/packages/core-components/src/components/Table/index.ts +++ b/packages/core-components/src/components/Table/index.ts @@ -14,6 +14,13 @@ * limitations under the License. */ +export type { TableFiltersClassKey } from './Filters'; export { SubvalueCell } from './SubvalueCell'; +export type { SubvalueCellClassKey } from './SubvalueCell'; export { Table } from './Table'; +export type { + TableClassKey, + FiltersContainerClassKey, + TableHeaderClassKey, +} from './Table'; export type { TableColumn, TableFilter, TableProps, TableState } from './Table'; diff --git a/packages/core-components/src/components/Tabs/TabBar.tsx b/packages/core-components/src/components/Tabs/TabBar.tsx index 5fb44d3f09..d0febebc6a 100644 --- a/packages/core-components/src/components/Tabs/TabBar.tsx +++ b/packages/core-components/src/components/Tabs/TabBar.tsx @@ -24,22 +24,27 @@ interface StyledTabsProps { onChange: (event: React.ChangeEvent<{}>, newValue: number) => void; } -const useStyles = makeStyles(theme => ({ - indicator: { - display: 'flex', - justifyContent: 'center', - backgroundColor: theme.palette.tabbar.indicator, - height: '4px', - }, - flexContainer: { - alignItems: 'center', - }, - root: { - '&:last-child': { - marginLeft: 'auto', +export type TabBarClassKey = 'indicator' | 'flexContainer' | 'root'; + +const useStyles = makeStyles( + theme => ({ + indicator: { + display: 'flex', + justifyContent: 'center', + backgroundColor: theme.palette.tabbar.indicator, + height: '4px', }, - }, -})); + flexContainer: { + alignItems: 'center', + }, + root: { + '&:last-child': { + marginLeft: 'auto', + }, + }, + }), + { name: 'BackstageTabBar' }, +); export const StyledTabs = (props: PropsWithChildren) => { const classes = useStyles(props); diff --git a/packages/core-components/src/components/Tabs/TabIcon.tsx b/packages/core-components/src/components/Tabs/TabIcon.tsx index dde01835a3..37b38217a3 100644 --- a/packages/core-components/src/components/Tabs/TabIcon.tsx +++ b/packages/core-components/src/components/Tabs/TabIcon.tsx @@ -25,22 +25,27 @@ interface StyledIconProps { onClick: any; } -const useStyles = makeStyles(() => ({ - root: { - color: '#6E6E6E', - overflow: 'visible', - fontSize: '1.5rem', - textAlign: 'center', - borderRadius: '50%', - backgroundColor: '#E6E6E6', - marginLeft: props => (props.isNext ? 'auto' : '0'), - marginRight: props => (props.isNext ? '0' : '10px'), - '&:hover': { +export type TabIconClassKey = 'root'; + +const useStyles = makeStyles( + () => ({ + root: { + color: '#6E6E6E', + overflow: 'visible', + fontSize: '1.5rem', + textAlign: 'center', + borderRadius: '50%', backgroundColor: '#E6E6E6', - opacity: '1', + marginLeft: props => (props.isNext ? 'auto' : '0'), + marginRight: props => (props.isNext ? '0' : '10px'), + '&:hover': { + backgroundColor: '#E6E6E6', + opacity: '1', + }, }, - }, -})); + }), + { name: 'BackstageTabIcon' }, +); export const StyledIcon = (props: StyledIconProps) => { const classes = useStyles(props); diff --git a/packages/core-components/src/components/Tabs/Tabs.tsx b/packages/core-components/src/components/Tabs/Tabs.tsx index 844f54a543..d60f3ff639 100644 --- a/packages/core-components/src/components/Tabs/Tabs.tsx +++ b/packages/core-components/src/components/Tabs/Tabs.tsx @@ -42,21 +42,26 @@ export interface TabsProps { tabs: TabProps[]; } -const useStyles = makeStyles(theme => ({ - root: { - flexGrow: 1, - width: '100%', - }, - styledTabs: { - backgroundColor: theme.palette.background.paper, - }, - appbar: { - boxShadow: 'none', - backgroundColor: theme.palette.background.paper, - paddingLeft: '10px', - paddingRight: '10px', - }, -})); +export type TabsClassKey = 'root' | 'styledTabs' | 'appbar'; + +const useStyles = makeStyles( + theme => ({ + root: { + flexGrow: 1, + width: '100%', + }, + styledTabs: { + backgroundColor: theme.palette.background.paper, + }, + appbar: { + boxShadow: 'none', + backgroundColor: theme.palette.background.paper, + paddingLeft: '10px', + paddingRight: '10px', + }, + }), + { name: 'BackstageTabs' }, +); export function Tabs(props: TabsProps) { const { tabs } = props; diff --git a/packages/core-components/src/components/Tabs/index.ts b/packages/core-components/src/components/Tabs/index.ts index ae9e0b7486..015118635c 100644 --- a/packages/core-components/src/components/Tabs/index.ts +++ b/packages/core-components/src/components/Tabs/index.ts @@ -15,3 +15,7 @@ */ export { Tabs } from './Tabs'; +export type { TabsClassKey } from './Tabs'; + +export type { TabBarClassKey } from './TabBar'; +export type { TabIconClassKey } from './TabIcon'; diff --git a/packages/core-components/src/components/WarningPanel/WarningPanel.tsx b/packages/core-components/src/components/WarningPanel/WarningPanel.tsx index 536ab066b3..bf845617c9 100644 --- a/packages/core-components/src/components/WarningPanel/WarningPanel.tsx +++ b/packages/core-components/src/components/WarningPanel/WarningPanel.tsx @@ -64,56 +64,66 @@ const ExpandMoreIconStyled = ({ severity }: Pick) => { return ; }; -const useStyles = makeStyles(theme => ({ - panel: { - backgroundColor: ({ severity }: WarningProps) => - getWarningBackgroundColor( - severity as NonNullable, - theme, - ), - color: ({ severity }: WarningProps) => - getWarningTextColor( - severity as NonNullable, - theme, - ), - verticalAlign: 'middle', - }, - summary: { - display: 'flex', - flexDirection: 'row', - }, - summaryText: { - color: ({ severity }: WarningProps) => - getWarningTextColor( - severity as NonNullable, - theme, - ), - fontWeight: 'bold', - }, - message: { - width: '100%', - display: 'block', - color: ({ severity }: WarningProps) => - getWarningTextColor( - severity as NonNullable, - theme, - ), - backgroundColor: ({ severity }: WarningProps) => - getWarningBackgroundColor( - severity as NonNullable, - theme, - ), - }, - details: { - width: '100%', - display: 'block', - color: theme.palette.textContrast, - backgroundColor: theme.palette.background.default, - border: `1px solid ${theme.palette.border}`, - padding: theme.spacing(2.0), - fontFamily: 'sans-serif', - }, -})); +export type WarningPanelClassKey = + | 'panel' + | 'summary' + | 'summaryText' + | 'message' + | 'details'; + +const useStyles = makeStyles( + theme => ({ + panel: { + backgroundColor: ({ severity }: WarningProps) => + getWarningBackgroundColor( + severity as NonNullable, + theme, + ), + color: ({ severity }: WarningProps) => + getWarningTextColor( + severity as NonNullable, + theme, + ), + verticalAlign: 'middle', + }, + summary: { + display: 'flex', + flexDirection: 'row', + }, + summaryText: { + color: ({ severity }: WarningProps) => + getWarningTextColor( + severity as NonNullable, + theme, + ), + fontWeight: 'bold', + }, + message: { + width: '100%', + display: 'block', + color: ({ severity }: WarningProps) => + getWarningTextColor( + severity as NonNullable, + theme, + ), + backgroundColor: ({ severity }: WarningProps) => + getWarningBackgroundColor( + severity as NonNullable, + theme, + ), + }, + details: { + width: '100%', + display: 'block', + color: theme.palette.textContrast, + backgroundColor: theme.palette.background.default, + border: `1px solid ${theme.palette.border}`, + padding: theme.spacing(2.0), + fontFamily: 'sans-serif', + }, + }), + { name: 'BackstageWarningPanel' }, +); export type WarningProps = { title?: string; diff --git a/packages/core-components/src/components/WarningPanel/index.ts b/packages/core-components/src/components/WarningPanel/index.ts index 07f7acca42..866104795f 100644 --- a/packages/core-components/src/components/WarningPanel/index.ts +++ b/packages/core-components/src/components/WarningPanel/index.ts @@ -14,3 +14,4 @@ * limitations under the License. */ export { WarningPanel } from './WarningPanel'; +export type { WarningPanelClassKey } from './WarningPanel';