diff --git a/.changeset/calm-buckets-relax.md b/.changeset/calm-buckets-relax.md new file mode 100644 index 0000000000..b950df89b8 --- /dev/null +++ b/.changeset/calm-buckets-relax.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-azure-devops-backend': patch +--- + +Marked all configuration values as required in the schema. diff --git a/.changeset/olive-lamps-deny.md b/.changeset/olive-lamps-deny.md new file mode 100644 index 0000000000..ec6b279d68 --- /dev/null +++ b/.changeset/olive-lamps-deny.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes': patch +--- + +Enhanced deployment accordion to display the namespace of the deployment. diff --git a/.changeset/rotten-dryers-bathe.md b/.changeset/rotten-dryers-bathe.md new file mode 100644 index 0000000000..abded27f06 --- /dev/null +++ b/.changeset/rotten-dryers-bathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes': patch +--- + +Exported `KubernetesApi`, `kubernetesApiRef`, and `KubernetesAuthProvidersApi`. diff --git a/.changeset/spicy-crabs-breathe.md b/.changeset/spicy-crabs-breathe.md new file mode 100644 index 0000000000..2640f0864c --- /dev/null +++ b/.changeset/spicy-crabs-breathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-tech-radar': patch +--- + +Added documentation for exported symbols. diff --git a/.changeset/spicy-pumas-mate.md b/.changeset/spicy-pumas-mate.md new file mode 100644 index 0000000000..7ef8727550 --- /dev/null +++ b/.changeset/spicy-pumas-mate.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Support `material-ui` overrides in Backstage internal components diff --git a/.changeset/techdocs-sad-songs-waltzes.md b/.changeset/techdocs-sad-songs-waltzes.md new file mode 100644 index 0000000000..921939a189 --- /dev/null +++ b/.changeset/techdocs-sad-songs-waltzes.md @@ -0,0 +1,6 @@ +--- +'@backstage/techdocs-common': patch +--- + +Locks the version of the default docker image used to generate TechDocs. As of +this changelog entry, it is v0.3.2! diff --git a/app-config.yaml b/app-config.yaml index 1c0ae98c3e..65761bc07e 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -430,5 +430,5 @@ jenkins: azureDevOps: host: dev.azure.com - token: ${AZURE_TOKEN} + token: my-token organization: my-company diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md index ecd9e4ac21..241ae7ef03 100644 --- a/docs/getting-started/app-custom-theme.md +++ b/docs/getting-started/app-custom-theme.md @@ -37,9 +37,7 @@ exported by [@backstage/theme](https://www.npmjs.com/package/@backstage/theme) in combination with [createTheme](https://material-ui.com/customization/theming/#createmuitheme-options-args-theme) from [@material-ui/core](https://www.npmjs.com/package/@material-ui/core). See -the -[@backstage/theme source](https://github.com/backstage/backstage/tree/master/packages/theme/src) -and the implementation of the `createTheme` function for how this is done. +the "Overriding Backstage and Material UI css rules" section below. You can also create a theme from scratch that matches the `BackstageTheme` type exported by [@backstage/theme](https://www.npmjs.com/package/@backstage/theme). @@ -136,6 +134,79 @@ const themeOptions = createThemeOptions({ }); ``` +## Overriding Backstage and Material UI components styles + +When creating a custom theme you would be applying different values to +component's css rules that use the theme object. For example, a Backstage +component's styles might look like this: + +```ts +const useStyles = makeStyles( + theme => ({ + header: { + padding: theme.spacing(3), + boxShadow: '0 0 8px 3px rgba(20, 20, 20, 0.3)', + backgroundImage: theme.page.backgroundImage, + }, + }), + { name: 'BackstageHeader' }, +); +``` + +Notice how the `padding` is getting its value from `theme.spacing`, that means +that setting a value for spacing in your custom theme would affect this +component padding property and the same goes for `backgroundImage` which uses +`theme.page.backgroundImage`. However, the `boxShadow` property doesn't +reference any value from the theme, that means that creating a custom theme +wouldn't be enough to alter the `box-shadow` property or to add css rules that +aren't already defined like a margin. For these cases you should also create an +override. + +```ts +import { createApp } from '@backstage/core-app-api'; +import { BackstageTheme, lightTheme } from '@backstage/theme'; +/** + * The `@backstage/core-components` package exposes this type that + * contains all Backstage and `material-ui` components that can be + * overridden along with the classes key those components use. + */ +import { BackstageOverrides } from '@backstage/core-components'; + +export const createCustomThemeOverrides = ( + theme: BackstageTheme, +): BackstageOverrides => { + return { + BackstageHeader: { + header: { + width: 'auto', + margin: '20px', + boxShadow: 'none', + borderBottom: `4px solid ${theme.palette.primary.main}`, + }, + }, + }; +}; + +const app = createApp({ + apis: ..., + plugins: ..., + themes: [{ + id: 'my-theme', + title: 'My Custom Theme', + variant: 'light', + theme: { + ...lightTheme, + overrides: { + // These are the overrides that Backstage applies to `material-ui` components + ...lightTheme.overrides, + // These are your custom overrides, either to `material-ui` or Backstage components. + ...createCustomThemeOverrides(lightTheme), + }, + }, + }] +}); +``` + ## Custom Logo In addition to a custom theme, you can also customize the logo displayed at the diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index 78d4f18267..61d9ad5b90 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -26,6 +26,7 @@ import { LinkProps as LinkProps_2 } from '@material-ui/core'; import { LinkProps as LinkProps_3 } from 'react-router-dom'; import { MaterialTableProps } from '@material-table/core'; import { NavLinkProps } from 'react-router-dom'; +import { Overrides } from '@material-ui/core/styles/overrides'; import { ProfileInfoApi } from '@backstage/core-plugin-api'; import { PropsWithChildren } from 'react'; import PropTypes from 'prop-types'; @@ -39,6 +40,7 @@ import { SparklinesLineProps } from 'react-sparklines'; import { SparklinesProps } from 'react-sparklines'; import { StyledComponentProps } from '@material-ui/core'; import { StyleRules } from '@material-ui/styles'; +import { StyleRules as StyleRules_2 } from '@material-ui/core/styles/withStyles'; import { TabProps } from '@material-ui/core'; import { TextTruncateProps } from 'react-text-truncate'; import { Theme } from '@material-ui/core'; @@ -70,12 +72,66 @@ enum Alignment { // @public (undocumented) export function Avatar(props: AvatarProps): JSX.Element; +// Warning: (ae-missing-release-tag) "AvatarClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type AvatarClassKey = 'avatar'; + +// Warning: (ae-missing-release-tag) "BackstageContentClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type BackstageContentClassKey = 'root' | 'stretch' | 'noPadding'; + +// Warning: (ae-forgotten-export) The symbol "BackstageComponentsNameToClassKey" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "BackstageOverrides" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type BackstageOverrides = Overrides & { + [Name in keyof BackstageComponentsNameToClassKey]?: Partial< + StyleRules_2 + >; +}; + +// Warning: (ae-missing-release-tag) "BoldHeaderClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type BoldHeaderClassKey = 'root' | 'title' | 'subheader'; + +// Warning: (ae-missing-release-tag) "BottomLink" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function BottomLink(props: BottomLinkProps): JSX.Element; + +// Warning: (ae-missing-release-tag) "BottomLinkClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type BottomLinkClassKey = 'root' | 'boxTitle' | 'arrow'; + +// Warning: (ae-missing-release-tag) "BottomLinkProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type BottomLinkProps = { + link: string; + title: string; + onClick?: (event: React_2.MouseEvent) => void; +}; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Breadcrumbs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function Breadcrumbs(props: Props_24): JSX.Element; +// Warning: (ae-missing-release-tag) "BreadcrumbsClickableTextClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type BreadcrumbsClickableTextClassKey = 'root'; + +// Warning: (ae-missing-release-tag) "BreadcrumbsStyledBoxClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type BreadcrumbsStyledBoxClassKey = 'root'; + // Warning: (ae-forgotten-export) The symbol "IconComponentProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "BrokenImageIcon" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -88,12 +144,22 @@ export function BrokenImageIcon(props: IconComponentProps): JSX.Element; // @public (undocumented) export function Button(props: Props): JSX.Element; +// Warning: (ae-missing-release-tag) "CardActionsTopRightClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type CardActionsTopRightClassKey = 'root'; + // Warning: (ae-forgotten-export) The symbol "CardTabProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "CardTab" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function CardTab(props: PropsWithChildren): JSX.Element; +// Warning: (ae-missing-release-tag) "CardTabClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type CardTabClassKey = 'root' | 'selected'; + // Warning: (ae-missing-release-tag) "CatalogIcon" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -104,6 +170,11 @@ export function CatalogIcon(props: IconComponentProps): JSX.Element; // @public (undocumented) export function ChatIcon(props: IconComponentProps): JSX.Element; +// Warning: (ae-missing-release-tag) "ClosedDropdownClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ClosedDropdownClassKey = 'icon'; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "CodeSnippet" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -124,6 +195,16 @@ export function ContentHeader( props: PropsWithChildren, ): JSX.Element; +// Warning: (ae-missing-release-tag) "ContentHeaderClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ContentHeaderClassKey = + | 'container' + | 'leftItemsBox' + | 'rightItemsBox' + | 'description' + | 'title'; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "CopyTextButton" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // Warning: (ae-missing-release-tag) "CopyTextButton" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -147,6 +228,11 @@ export namespace CopyTextButton { // @public (undocumented) export function CreateButton(props: CreateButtonProps): JSX.Element | null; +// Warning: (ae-missing-release-tag) "CustomProviderClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type CustomProviderClassKey = 'form' | 'button'; + // Warning: (ae-missing-release-tag) "DashboardIcon" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -167,6 +253,26 @@ type DependencyEdge = T & { // @public (undocumented) export function DependencyGraph(props: DependencyGraphProps): JSX.Element; +// Warning: (ae-missing-release-tag) "DependencyGraphDefaultLabelClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type DependencyGraphDefaultLabelClassKey = 'text'; + +// Warning: (ae-missing-release-tag) "DependencyGraphDefaultNodeClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type DependencyGraphDefaultNodeClassKey = 'node' | 'text'; + +// Warning: (ae-missing-release-tag) "DependencyGraphEdgeClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type DependencyGraphEdgeClassKey = 'path' | 'label'; + +// Warning: (ae-missing-release-tag) "DependencyGraphNodeClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type DependencyGraphNodeClassKey = 'node'; + // Warning: (ae-missing-release-tag) "DependencyGraphProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -238,6 +344,18 @@ enum Direction { // @public (undocumented) export const DismissableBanner: (props: Props_4) => JSX.Element; +// Warning: (ae-missing-release-tag) "DismissbleBannerClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type DismissbleBannerClassKey = + | 'root' + | 'topPosition' + | 'icon' + | 'content' + | 'message' + | 'info' + | 'error'; + // Warning: (ae-missing-release-tag) "DocsIcon" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -268,6 +386,16 @@ export function EmailIcon(props: IconComponentProps): JSX.Element; // @public (undocumented) export function EmptyState(props: Props_5): JSX.Element; +// Warning: (ae-missing-release-tag) "EmptyStateClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type EmptyStateClassKey = 'root' | 'action' | 'imageContainer'; + +// Warning: (ae-missing-release-tag) "EmptyStateImageClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type EmptyStateImageClassKey = 'generalImg'; + // Warning: (ae-forgotten-export) The symbol "State" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ErrorBoundary" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -288,6 +416,11 @@ export type ErrorBoundaryProps = { // @public (undocumented) export function ErrorPage(props: IErrorPageProps): JSX.Element; +// Warning: (ae-missing-release-tag) "ErrorPageClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ErrorPageClassKey = 'container' | 'title' | 'subtitle'; + // Warning: (ae-missing-release-tag) "ErrorPanel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public @@ -295,6 +428,11 @@ export function ErrorPanel( props: PropsWithChildren, ): JSX.Element; +// Warning: (ae-missing-release-tag) "ErrorPanelClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ErrorPanelClassKey = 'text' | 'divider'; + // Warning: (ae-missing-release-tag) "ErrorPanelProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -304,6 +442,18 @@ export type ErrorPanelProps = { title?: string; }; +// Warning: (ae-missing-release-tag) "FeatureCalloutCircleClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type FeatureCalloutCircleClassKey = + | '@keyframes pulsateSlightly' + | '@keyframes pulsateAndFade' + | 'featureWrapper' + | 'backdrop' + | 'dot' + | 'pulseCircle' + | 'text'; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "FeatureCalloutCircular" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -312,6 +462,11 @@ export function FeatureCalloutCircular( props: PropsWithChildren, ): JSX.Element; +// Warning: (ae-missing-release-tag) "FiltersContainerClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type FiltersContainerClassKey = 'root' | 'title'; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Gauge" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -324,6 +479,16 @@ export function Gauge(props: Props_14): JSX.Element; // @public (undocumented) export function GaugeCard(props: Props_13): JSX.Element; +// Warning: (ae-missing-release-tag) "GaugeCardClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type GaugeCardClassKey = 'root'; + +// Warning: (ae-missing-release-tag) "GaugeClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type GaugeClassKey = 'root' | 'overlay' | 'circle' | 'colorUnknown'; + // Warning: (ae-missing-release-tag) "GitHubIcon" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -352,24 +517,57 @@ export function GroupIcon(props: IconComponentProps): JSX.Element; // @public (undocumented) export function Header(props: PropsWithChildren): JSX.Element; +// Warning: (ae-missing-release-tag) "HeaderClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type HeaderClassKey = + | 'header' + | 'leftItemsBox' + | 'rightItemsBox' + | 'title' + | 'subtitle' + | 'type' + | 'breadcrumb' + | 'breadcrumbType' + | 'breadcrumbTitle'; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "HeaderIconLinkRow" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function HeaderIconLinkRow(props: Props_8): JSX.Element; +// Warning: (ae-missing-release-tag) "HeaderIconLinkRowClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type HeaderIconLinkRowClassKey = 'links'; + // Warning: (ae-forgotten-export) The symbol "HeaderLabelProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "HeaderLabel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function HeaderLabel(props: HeaderLabelProps): JSX.Element; +// Warning: (ae-missing-release-tag) "HeaderLabelClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type HeaderLabelClassKey = 'root' | 'label' | 'value'; + // Warning: (ae-forgotten-export) The symbol "HeaderTabsProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "HeaderTabs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function HeaderTabs(props: HeaderTabsProps): JSX.Element; +// Warning: (ae-missing-release-tag) "HeaderTabsClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type HeaderTabsClassKey = + | 'tabsWrapper' + | 'defaultTab' + | 'selected' + | 'tabRoot'; + // Warning: (ae-missing-release-tag) "HelpIcon" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -388,6 +586,30 @@ export function HorizontalScrollGrid( props: PropsWithChildren, ): JSX.Element; +// Warning: (ae-missing-release-tag) "HorizontalScrollGridClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type HorizontalScrollGridClassKey = + | 'root' + | 'container' + | 'fade' + | 'fadeLeft' + | 'fadeRight' + | 'fadeHidden' + | 'button' + | 'buttonLeft' + | 'buttonRight'; + +// Warning: (ae-missing-release-tag) "IconLinkVerticalClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type IconLinkVerticalClassKey = + | 'link' + | 'disabled' + | 'primary' + | 'secondary' + | 'label'; + // Warning: (ae-missing-release-tag) "IconLinkVerticalProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -407,6 +629,18 @@ export type IconLinkVerticalProps = { // @public (undocumented) export function InfoCard(props: Props_19): JSX.Element; +// Warning: (ae-missing-release-tag) "InfoCardClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type InfoCardClassKey = + | 'noPadding' + | 'header' + | 'headerTitle' + | 'headerSubheader' + | 'headerAvatar' + | 'headerAction' + | 'headerContent'; + // Warning: (ae-missing-release-tag) "InfoCardVariants" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -437,6 +671,11 @@ export function ItemCard(props: ItemCardProps): JSX.Element; // @public export function ItemCardGrid(props: ItemCardGridProps): JSX.Element; +// Warning: (ae-missing-release-tag) "ItemCardGridClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ItemCardGridClassKey = 'root'; + // Warning: (ae-forgotten-export) The symbol "styles" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ItemCardGridProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -456,6 +695,11 @@ export type ItemCardGridProps = Partial> & { // @public export function ItemCardHeader(props: ItemCardHeaderProps): JSX.Element; +// Warning: (ae-missing-release-tag) "ItemCardHeaderClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ItemCardHeaderClassKey = 'root'; + // Warning: (ae-forgotten-export) The symbol "styles" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ItemCardHeaderProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -484,6 +728,11 @@ enum LabelPosition { // @public (undocumented) export function Lifecycle(props: Props_10): JSX.Element; +// Warning: (ae-missing-release-tag) "LifecycleClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type LifecycleClassKey = 'alpha' | 'beta'; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "LinearGauge" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -503,35 +752,99 @@ export type LinkProps = LinkProps_2 & component?: ElementType; }; +// Warning: (ae-missing-release-tag) "LoginRequestListItemClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type LoginRequestListItemClassKey = 'root'; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "MarkdownContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public export function MarkdownContent(props: Props_11): JSX.Element; +// Warning: (ae-missing-release-tag) "MarkdownContentClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type MarkdownContentClassKey = 'markdown'; + +// Warning: (ae-missing-release-tag) "MetadataTableCellClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type MetadataTableCellClassKey = 'root'; + +// Warning: (ae-missing-release-tag) "MetadataTableListClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type MetadataTableListClassKey = 'root'; + +// Warning: (ae-missing-release-tag) "MetadataTableListItemClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type MetadataTableListItemClassKey = 'root' | 'random'; + +// Warning: (ae-missing-release-tag) "MetadataTableTitleCellClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type MetadataTableTitleCellClassKey = 'root'; + +// Warning: (ae-missing-release-tag) "MicDropClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type MicDropClassKey = 'micDrop'; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "MissingAnnotationEmptyState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function MissingAnnotationEmptyState(props: Props_6): JSX.Element; +// Warning: (ae-missing-release-tag) "MissingAnnotationEmptyStateClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type MissingAnnotationEmptyStateClassKey = 'code'; + // Warning: (ae-missing-release-tag) "OAuthRequestDialog" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function OAuthRequestDialog(_props: {}): JSX.Element; +// Warning: (ae-missing-release-tag) "OAuthRequestDialogClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type OAuthRequestDialogClassKey = + | 'dialog' + | 'title' + | 'contentList' + | 'actionButtons'; + +// Warning: (ae-missing-release-tag) "OpenedDropdownClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type OpenedDropdownClassKey = 'icon'; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "OverflowTooltip" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function OverflowTooltip(props: Props_12): JSX.Element; +// Warning: (ae-missing-release-tag) "OverflowTooltipClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type OverflowTooltipClassKey = 'container'; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Page" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function Page(props: PropsWithChildren): JSX.Element; +// Warning: (ae-missing-release-tag) "PageClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type PageClassKey = 'root'; + // Warning: (ae-forgotten-export) The symbol "PageWithHeaderProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "PageWithHeader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -588,6 +901,11 @@ type RenderNodeProps = { // @public export function ResponseErrorPanel(props: ErrorPanelProps): JSX.Element; +// Warning: (ae-missing-release-tag) "ResponseErrorPanelClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ResponseErrorPanelClassKey = 'text' | 'divider'; + // Warning: (ae-missing-release-tag) "RoutedTabs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -599,6 +917,22 @@ export function RoutedTabs(props: { routes: SubRoute_2[] }): JSX.Element; // @public (undocumented) export function Select(props: SelectProps): JSX.Element; +// Warning: (ae-missing-release-tag) "SelectClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type SelectClassKey = + | 'formControl' + | 'label' + | 'chips' + | 'chip' + | 'checkbox' + | 'root'; + +// Warning: (ae-missing-release-tag) "SelectInputBaseClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type SelectInputBaseClassKey = 'root' | 'input'; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Sidebar" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -611,6 +945,11 @@ export function Sidebar(props: PropsWithChildren): JSX.Element; export const SIDEBAR_INTRO_LOCAL_STORAGE = '@backstage/core/sidebar-intro-dismissed'; +// Warning: (ae-missing-release-tag) "SidebarClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type SidebarClassKey = 'root' | 'drawer' | 'drawerOpen'; + // Warning: (ae-missing-release-tag) "sidebarConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -915,6 +1254,16 @@ export const SidebarDivider: React_2.ComponentType< // @public (undocumented) export function SidebarIntro(_props: {}): JSX.Element | null; +// Warning: (ae-missing-release-tag) "SidebarIntroClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type SidebarIntroClassKey = + | 'introCard' + | 'introDismiss' + | 'introDismissLink' + | 'introDismissText' + | 'introDismissIcon'; + // Warning: (ae-forgotten-export) The symbol "SidebarItemProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "SidebarItem" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -923,11 +1272,33 @@ export const SidebarItem: React_2.ForwardRefExoticComponent< SidebarItemProps & React_2.RefAttributes >; +// Warning: (ae-missing-release-tag) "SidebarItemClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type SidebarItemClassKey = + | 'root' + | 'buttonItem' + | 'closed' + | 'open' + | 'label' + | 'iconContainer' + | 'searchRoot' + | 'searchField' + | 'searchFieldHTMLInput' + | 'searchContainer' + | 'secondaryAction' + | 'selected'; + // Warning: (ae-missing-release-tag) "SidebarPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function SidebarPage(props: PropsWithChildren<{}>): JSX.Element; +// Warning: (ae-missing-release-tag) "SidebarPageClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type SidebarPageClassKey = 'root'; + // Warning: (ae-missing-release-tag) "SidebarPinStateContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1760,6 +2131,11 @@ export const SidebarSpacer: React_2.ComponentType< // @public (undocumented) export function SignInPage(props: Props_22): JSX.Element; +// Warning: (ae-missing-release-tag) "SignInPageClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type SignInPageClassKey = 'container' | 'item'; + // Warning: (ae-missing-release-tag) "SignInProviderConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1778,6 +2154,11 @@ export function SimpleStepper( props: PropsWithChildren, ): JSX.Element; +// Warning: (ae-missing-release-tag) "SimpleStepperFooterClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type SimpleStepperFooterClassKey = 'root'; + // Warning: (ae-forgotten-export) The symbol "StepProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "SimpleStepperStep" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -1786,11 +2167,28 @@ export function SimpleStepperStep( props: PropsWithChildren, ): JSX.Element; +// Warning: (ae-missing-release-tag) "SimpleStepperStepClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type SimpleStepperStepClassKey = 'end'; + // Warning: (ae-missing-release-tag) "StatusAborted" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function StatusAborted(props: PropsWithChildren<{}>): JSX.Element; +// Warning: (ae-missing-release-tag) "StatusClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type StatusClassKey = + | 'status' + | 'ok' + | 'warning' + | 'error' + | 'pending' + | 'running' + | 'aborted'; + // Warning: (ae-missing-release-tag) "StatusError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1822,18 +2220,38 @@ export function StatusWarning(props: PropsWithChildren<{}>): JSX.Element; // @public (undocumented) export function StructuredMetadataTable(props: Props_16): JSX.Element; +// Warning: (ae-missing-release-tag) "StructuredMetadataTableListClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type StructuredMetadataTableListClassKey = 'root'; + +// Warning: (ae-missing-release-tag) "StructuredMetadataTableNestedListClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type StructuredMetadataTableNestedListClassKey = 'root'; + // Warning: (ae-forgotten-export) The symbol "SubvalueCellProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "SubvalueCell" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function SubvalueCell(props: SubvalueCellProps): JSX.Element; +// Warning: (ae-missing-release-tag) "SubvalueCellClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type SubvalueCellClassKey = 'value' | 'subvalue'; + // Warning: (ae-forgotten-export) The symbol "SupportButtonProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "SupportButton" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function SupportButton(props: SupportButtonProps): JSX.Element; +// Warning: (ae-missing-release-tag) "SupportButtonClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type SupportButtonClassKey = 'popoverList'; + // Warning: (ae-missing-release-tag) "SupportConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1873,12 +2291,22 @@ export type Tab = { >; }; +// Warning: (ae-missing-release-tag) "TabBarClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type TabBarClassKey = 'indicator' | 'flexContainer' | 'root'; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "TabbedCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function TabbedCard(props: PropsWithChildren): JSX.Element; +// Warning: (ae-missing-release-tag) "TabbedCardClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type TabbedCardClassKey = 'root' | 'indicator'; + // Warning: (ae-missing-release-tag) "TabbedLayout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // Warning: (ae-missing-release-tag) "TabbedLayout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -1893,11 +2321,21 @@ export namespace TabbedLayout { Route: (props: SubRoute) => null; } +// Warning: (ae-missing-release-tag) "TabIconClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type TabIconClassKey = 'root'; + // Warning: (ae-missing-release-tag) "Table" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function Table(props: TableProps): JSX.Element; +// Warning: (ae-missing-release-tag) "TableClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type TableClassKey = 'root'; + // Warning: (ae-missing-release-tag) "TableColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1916,6 +2354,16 @@ export type TableFilter = { type: 'select' | 'multiple-select'; }; +// Warning: (ae-missing-release-tag) "TableFiltersClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type TableFiltersClassKey = 'root' | 'value' | 'heder' | 'filters'; + +// Warning: (ae-missing-release-tag) "TableHeaderClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type TableHeaderClassKey = 'header'; + // Warning: (ae-missing-release-tag) "TableProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1944,12 +2392,22 @@ export type TableState = { filters?: SelectedFilters; }; +// Warning: (ae-missing-release-tag) "TableToolbarClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type TableToolbarClassKey = 'root' | 'title' | 'searchField'; + // Warning: (ae-forgotten-export) The symbol "TabsProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Tabs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function Tabs(props: TabsProps): JSX.Element; +// Warning: (ae-missing-release-tag) "TabsClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type TabsClassKey = 'root' | 'styledTabs' | 'appbar'; + // Warning: (ae-missing-release-tag) "TrendLine" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -2002,9 +2460,19 @@ export function WarningIcon(props: IconComponentProps): JSX.Element; // @public export function WarningPanel(props: WarningProps): JSX.Element; +// Warning: (ae-missing-release-tag) "WarningPanelClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type WarningPanelClassKey = + | 'panel' + | 'summary' + | 'summaryText' + | 'message' + | 'details'; + // Warnings were encountered during analysis: // // src/components/TabbedLayout/RoutedTabs.d.ts:9:5 - (ae-forgotten-export) The symbol "SubRoute" needs to be exported by the entry point index.d.ts -// src/components/Table/Table.d.ts:15:5 - (ae-forgotten-export) The symbol "SelectedFilters" needs to be exported by the entry point index.d.ts +// src/components/Table/Table.d.ts:19:5 - (ae-forgotten-export) The symbol "SelectedFilters" needs to be exported by the entry point index.d.ts // src/layout/ErrorBoundary/ErrorBoundary.d.ts:7:5 - (ae-forgotten-export) The symbol "SlackChannel" needs to be exported by the entry point index.d.ts ``` 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..7fc245d6d0 100644 --- a/packages/core-components/src/components/Table/index.ts +++ b/packages/core-components/src/components/Table/index.ts @@ -14,6 +14,17 @@ * limitations under the License. */ +export type { TableFiltersClassKey } from './Filters'; export { SubvalueCell } from './SubvalueCell'; +export type { SubvalueCellClassKey } from './SubvalueCell'; export { Table } from './Table'; -export type { TableColumn, TableFilter, TableProps, TableState } from './Table'; +export type { + TableColumn, + TableFilter, + TableProps, + TableState, + TableClassKey, + FiltersContainerClassKey, + TableHeaderClassKey, + TableToolbarClassKey, +} 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'; diff --git a/packages/core-components/src/index.ts b/packages/core-components/src/index.ts index af577ce79a..3c5e708360 100644 --- a/packages/core-components/src/index.ts +++ b/packages/core-components/src/index.ts @@ -24,3 +24,4 @@ export * from './components'; export * from './hooks'; export * from './icons'; export * from './layout'; +export * from './overridableComponents'; diff --git a/packages/core-components/src/layout/BottomLink/BottomLink.tsx b/packages/core-components/src/layout/BottomLink/BottomLink.tsx index 6d6811cc09..cb168600e5 100644 --- a/packages/core-components/src/layout/BottomLink/BottomLink.tsx +++ b/packages/core-components/src/layout/BottomLink/BottomLink.tsx @@ -21,19 +21,24 @@ import { BackstageTheme } from '@backstage/theme'; import Box from '@material-ui/core/Box'; import { Link } from '../../components/Link'; -const useStyles = makeStyles(theme => ({ - root: { - maxWidth: 'fit-content', - padding: theme.spacing(2, 2, 2, 2.5), - }, - boxTitle: { - margin: 0, - color: theme.palette.textSubtle, - }, - arrow: { - color: theme.palette.textSubtle, - }, -})); +export type BottomLinkClassKey = 'root' | 'boxTitle' | 'arrow'; + +const useStyles = makeStyles( + theme => ({ + root: { + maxWidth: 'fit-content', + padding: theme.spacing(2, 2, 2, 2.5), + }, + boxTitle: { + margin: 0, + color: theme.palette.textSubtle, + }, + arrow: { + color: theme.palette.textSubtle, + }, + }), + { name: 'BackstageBottomLink' }, +); export type BottomLinkProps = { link: string; diff --git a/packages/core-components/src/layout/BottomLink/index.ts b/packages/core-components/src/layout/BottomLink/index.ts index 853c74c880..e0252a5bb4 100644 --- a/packages/core-components/src/layout/BottomLink/index.ts +++ b/packages/core-components/src/layout/BottomLink/index.ts @@ -15,4 +15,4 @@ */ export { BottomLink } from './BottomLink'; -export type { BottomLinkProps } from './BottomLink'; +export type { BottomLinkClassKey, BottomLinkProps } from './BottomLink'; diff --git a/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.tsx b/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.tsx index 28c86d32f0..26304f9e2b 100644 --- a/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.tsx +++ b/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.tsx @@ -27,19 +27,29 @@ import React, { ComponentProps, Fragment } from 'react'; type Props = ComponentProps; -const ClickableText = withStyles({ - root: { - textDecoration: 'underline', - cursor: 'pointer', - }, -})(Typography); +export type BreadcrumbsClickableTextClassKey = 'root'; -const StyledBox = withStyles({ - root: { - textDecoration: 'underline', - color: 'inherit', +const ClickableText = withStyles( + { + root: { + textDecoration: 'underline', + cursor: 'pointer', + }, }, -})(Box); + { name: 'BackstageBreadcrumbsClickableText' }, +)(Typography); + +export type BreadcrumbsStyledBoxClassKey = 'root'; + +const StyledBox = withStyles( + { + root: { + textDecoration: 'underline', + color: 'inherit', + }, + }, + { name: 'BackstageBreadcrumbsStyledBox' }, +)(Box); export function Breadcrumbs(props: Props) { const { children, ...restProps } = props; diff --git a/packages/core-components/src/layout/Breadcrumbs/index.ts b/packages/core-components/src/layout/Breadcrumbs/index.ts index 31bae893a4..3cbce4164a 100644 --- a/packages/core-components/src/layout/Breadcrumbs/index.ts +++ b/packages/core-components/src/layout/Breadcrumbs/index.ts @@ -15,3 +15,7 @@ */ export { Breadcrumbs } from './Breadcrumbs'; +export type { + BreadcrumbsClickableTextClassKey, + BreadcrumbsStyledBoxClassKey, +} from './Breadcrumbs'; diff --git a/packages/core-components/src/layout/Content/Content.tsx b/packages/core-components/src/layout/Content/Content.tsx index a3771dff3f..588c9fd630 100644 --- a/packages/core-components/src/layout/Content/Content.tsx +++ b/packages/core-components/src/layout/Content/Content.tsx @@ -18,28 +18,33 @@ import React, { PropsWithChildren } from 'react'; import classNames from 'classnames'; import { Theme, makeStyles } from '@material-ui/core'; -const useStyles = makeStyles((theme: Theme) => ({ - root: { - gridArea: 'pageContent', - minWidth: 0, - paddingTop: theme.spacing(3), - paddingBottom: theme.spacing(3), - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(2), - [theme.breakpoints.up('sm')]: { - paddingLeft: theme.spacing(3), - paddingRight: theme.spacing(3), +export type BackstageContentClassKey = 'root' | 'stretch' | 'noPadding'; + +const useStyles = makeStyles( + (theme: Theme) => ({ + root: { + gridArea: 'pageContent', + minWidth: 0, + paddingTop: theme.spacing(3), + paddingBottom: theme.spacing(3), + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(2), + [theme.breakpoints.up('sm')]: { + paddingLeft: theme.spacing(3), + paddingRight: theme.spacing(3), + }, }, - }, - stretch: { - display: 'flex', - flexDirection: 'column', - flexGrow: 1, - }, - noPadding: { - padding: 0, - }, -})); + stretch: { + display: 'flex', + flexDirection: 'column', + flexGrow: 1, + }, + noPadding: { + padding: 0, + }, + }), + { name: 'BackstageContent' }, +); type Props = { stretch?: boolean; diff --git a/packages/core-components/src/layout/Content/index.ts b/packages/core-components/src/layout/Content/index.ts index a94ceabdfa..df7bd00b52 100644 --- a/packages/core-components/src/layout/Content/index.ts +++ b/packages/core-components/src/layout/Content/index.ts @@ -15,3 +15,4 @@ */ export { Content } from './Content'; +export type { BackstageContentClassKey } from './Content'; diff --git a/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx b/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx index 76fec703a9..c3faec64a2 100644 --- a/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx +++ b/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx @@ -22,39 +22,49 @@ import React, { PropsWithChildren, ReactNode } from 'react'; import { Typography, makeStyles } from '@material-ui/core'; import { Helmet } from 'react-helmet'; +export type ContentHeaderClassKey = + | 'container' + | 'leftItemsBox' + | 'rightItemsBox' + | 'description' + | 'title'; + const useStyles = (props: ContentHeaderProps) => - makeStyles(theme => ({ - container: { - width: '100%', - display: 'flex', - flexDirection: 'row', - flexWrap: 'wrap', - justifyContent: 'flex-end', - alignItems: 'center', - marginBottom: theme.spacing(2), - textAlign: props.textAlign, - }, - leftItemsBox: { - flex: '1 1 auto', - minWidth: 0, - overflow: 'visible', - }, - rightItemsBox: { - flex: '0 1 auto', - display: 'flex', - flexDirection: 'row', - flexWrap: 'wrap', - alignItems: 'center', - marginLeft: theme.spacing(1), - minWidth: 0, - overflow: 'visible', - }, - description: {}, - title: { - display: 'inline-flex', - marginBottom: 0, - }, - })); + makeStyles( + theme => ({ + container: { + width: '100%', + display: 'flex', + flexDirection: 'row', + flexWrap: 'wrap', + justifyContent: 'flex-end', + alignItems: 'center', + marginBottom: theme.spacing(2), + textAlign: props.textAlign, + }, + leftItemsBox: { + flex: '1 1 auto', + minWidth: 0, + overflow: 'visible', + }, + rightItemsBox: { + flex: '0 1 auto', + display: 'flex', + flexDirection: 'row', + flexWrap: 'wrap', + alignItems: 'center', + marginLeft: theme.spacing(1), + minWidth: 0, + overflow: 'visible', + }, + description: {}, + title: { + display: 'inline-flex', + marginBottom: 0, + }, + }), + { name: 'BackstageContentHeader' }, + ); type ContentHeaderTitleProps = { title?: string; diff --git a/packages/core-components/src/layout/ContentHeader/index.ts b/packages/core-components/src/layout/ContentHeader/index.ts index 537a2b6ed9..3a55db4e22 100644 --- a/packages/core-components/src/layout/ContentHeader/index.ts +++ b/packages/core-components/src/layout/ContentHeader/index.ts @@ -15,3 +15,4 @@ */ export { ContentHeader } from './ContentHeader'; +export type { ContentHeaderClassKey } from './ContentHeader'; diff --git a/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx b/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx index 87eebdb729..79aaaebfc6 100644 --- a/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx +++ b/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx @@ -28,24 +28,29 @@ interface IErrorPageProps { additionalInfo?: string; } -const useStyles = makeStyles(theme => ({ - container: { - padding: theme.spacing(8), - [theme.breakpoints.down('xs')]: { - padding: theme.spacing(2), +export type ErrorPageClassKey = 'container' | 'title' | 'subtitle'; + +const useStyles = makeStyles( + theme => ({ + container: { + padding: theme.spacing(8), + [theme.breakpoints.down('xs')]: { + padding: theme.spacing(2), + }, }, - }, - title: { - paddingBottom: theme.spacing(5), - [theme.breakpoints.down('xs')]: { - paddingBottom: theme.spacing(4), - fontSize: 32, + title: { + paddingBottom: theme.spacing(5), + [theme.breakpoints.down('xs')]: { + paddingBottom: theme.spacing(4), + fontSize: 32, + }, }, - }, - subtitle: { - color: theme.palette.textSubtle, - }, -})); + subtitle: { + color: theme.palette.textSubtle, + }, + }), + { name: 'BackstageErrorPage' }, +); export function ErrorPage(props: IErrorPageProps) { const { status, statusMessage, additionalInfo } = props; diff --git a/packages/core-components/src/layout/ErrorPage/MicDrop.tsx b/packages/core-components/src/layout/ErrorPage/MicDrop.tsx index 666eea4f09..5500994e4f 100644 --- a/packages/core-components/src/layout/ErrorPage/MicDrop.tsx +++ b/packages/core-components/src/layout/ErrorPage/MicDrop.tsx @@ -18,21 +18,26 @@ import React from 'react'; import { makeStyles } from '@material-ui/core'; import MicDropSvgUrl from './mic-drop.svg'; -const useStyles = makeStyles(theme => ({ - micDrop: { - maxWidth: '60%', - position: 'absolute', - bottom: theme.spacing(2), - right: theme.spacing(2), - [theme.breakpoints.down('xs')]: { - maxWidth: '96%', - position: 'relative', - bottom: 'unset', - right: 'unset', - margin: `${theme.spacing(10)}px auto ${theme.spacing(4)}px`, +const useStyles = makeStyles( + theme => ({ + micDrop: { + maxWidth: '60%', + position: 'absolute', + bottom: theme.spacing(2), + right: theme.spacing(2), + [theme.breakpoints.down('xs')]: { + maxWidth: '96%', + position: 'relative', + bottom: 'unset', + right: 'unset', + margin: `${theme.spacing(10)}px auto ${theme.spacing(4)}px`, + }, }, - }, -})); + }), + { name: 'BackstageErrorPageMicDrop' }, +); + +export type MicDropClassKey = 'micDrop'; export const MicDrop = () => { const classes = useStyles(); diff --git a/packages/core-components/src/layout/ErrorPage/index.ts b/packages/core-components/src/layout/ErrorPage/index.ts index a9a5fc9b2a..429b467444 100644 --- a/packages/core-components/src/layout/ErrorPage/index.ts +++ b/packages/core-components/src/layout/ErrorPage/index.ts @@ -15,3 +15,5 @@ */ export { ErrorPage } from './ErrorPage'; +export type { ErrorPageClassKey } from './ErrorPage'; +export type { MicDropClassKey } from './MicDrop'; diff --git a/packages/core-components/src/layout/Header/Header.tsx b/packages/core-components/src/layout/Header/Header.tsx index 3f83bcc843..535e3c4ed8 100644 --- a/packages/core-components/src/layout/Header/Header.tsx +++ b/packages/core-components/src/layout/Header/Header.tsx @@ -22,64 +22,78 @@ import { Helmet } from 'react-helmet'; import { Link } from '../../components/Link'; import { Breadcrumbs } from '../Breadcrumbs'; -const useStyles = makeStyles(theme => ({ - header: { - gridArea: 'pageHeader', - padding: theme.spacing(3), - width: '100%', - boxShadow: '0 0 8px 3px rgba(20, 20, 20, 0.3)', - position: 'relative', - zIndex: 100, - display: 'flex', - flexDirection: 'row', - flexWrap: 'wrap', - alignItems: 'center', - backgroundImage: theme.page.backgroundImage, - backgroundPosition: 'center', - backgroundSize: 'cover', - }, - leftItemsBox: { - maxWidth: '100%', - flexGrow: 1, - }, - rightItemsBox: { - width: 'auto', - }, - title: { - color: theme.palette.bursts.fontColor, - wordBreak: 'break-all', - fontSize: 'calc(24px + 6 * ((100vw - 320px) / 680))', - marginBottom: 0, - }, - subtitle: { - color: 'rgba(255, 255, 255, 0.8)', - lineHeight: '1.0em', - display: 'inline-block', // prevents margin collapse of adjacent siblings - marginTop: theme.spacing(1), - }, - type: { - textTransform: 'uppercase', - fontSize: 11, - opacity: 0.8, - marginBottom: theme.spacing(1), - color: theme.palette.bursts.fontColor, - }, - breadcrumb: { - fontSize: 'calc(15px + 1 * ((100vw - 320px) / 680))', - color: theme.palette.bursts.fontColor, - }, - breadcrumbType: { - fontSize: 'inherit', - opacity: 0.7, - marginRight: -theme.spacing(0.3), - marginBottom: theme.spacing(0.3), - }, - breadcrumbTitle: { - fontSize: 'inherit', - marginLeft: -theme.spacing(0.3), - marginBottom: theme.spacing(0.3), - }, -})); +export type HeaderClassKey = + | 'header' + | 'leftItemsBox' + | 'rightItemsBox' + | 'title' + | 'subtitle' + | 'type' + | 'breadcrumb' + | 'breadcrumbType' + | 'breadcrumbTitle'; + +const useStyles = makeStyles( + theme => ({ + header: { + gridArea: 'pageHeader', + padding: theme.spacing(3), + width: '100%', + boxShadow: '0 0 8px 3px rgba(20, 20, 20, 0.3)', + position: 'relative', + zIndex: 100, + display: 'flex', + flexDirection: 'row', + flexWrap: 'wrap', + alignItems: 'center', + backgroundImage: theme.page.backgroundImage, + backgroundPosition: 'center', + backgroundSize: 'cover', + }, + leftItemsBox: { + maxWidth: '100%', + flexGrow: 1, + }, + rightItemsBox: { + width: 'auto', + }, + title: { + color: theme.palette.bursts.fontColor, + wordBreak: 'break-all', + fontSize: 'calc(24px + 6 * ((100vw - 320px) / 680))', + marginBottom: 0, + }, + subtitle: { + color: 'rgba(255, 255, 255, 0.8)', + lineHeight: '1.0em', + display: 'inline-block', // prevents margin collapse of adjacent siblings + marginTop: theme.spacing(1), + }, + type: { + textTransform: 'uppercase', + fontSize: 11, + opacity: 0.8, + marginBottom: theme.spacing(1), + color: theme.palette.bursts.fontColor, + }, + breadcrumb: { + fontSize: 'calc(15px + 1 * ((100vw - 320px) / 680))', + color: theme.palette.bursts.fontColor, + }, + breadcrumbType: { + fontSize: 'inherit', + opacity: 0.7, + marginRight: -theme.spacing(0.3), + marginBottom: theme.spacing(0.3), + }, + breadcrumbTitle: { + fontSize: 'inherit', + marginLeft: -theme.spacing(0.3), + marginBottom: theme.spacing(0.3), + }, + }), + { name: 'BackstageHeader' }, +); type HeaderStyles = ReturnType; diff --git a/packages/core-components/src/layout/Header/index.ts b/packages/core-components/src/layout/Header/index.ts index 2c322fe9c1..d705b8de74 100644 --- a/packages/core-components/src/layout/Header/index.ts +++ b/packages/core-components/src/layout/Header/index.ts @@ -15,3 +15,4 @@ */ export { Header } from './Header'; +export type { HeaderClassKey } from './Header'; diff --git a/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx b/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx index 88f6e26bf5..5071971f48 100644 --- a/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx +++ b/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx @@ -17,24 +17,29 @@ import { Link, makeStyles, Typography, Grid } from '@material-ui/core'; import React from 'react'; -const useStyles = makeStyles(theme => ({ - root: { - textAlign: 'left', - }, - label: { - color: theme.palette.common.white, - fontWeight: 'bold', - letterSpacing: 0, - fontSize: theme.typography.fontSize, - marginBottom: theme.spacing(1) / 2, - lineHeight: 1, - }, - value: { - color: 'rgba(255, 255, 255, 0.8)', - fontSize: theme.typography.fontSize, - lineHeight: 1, - }, -})); +export type HeaderLabelClassKey = 'root' | 'label' | 'value'; + +const useStyles = makeStyles( + theme => ({ + root: { + textAlign: 'left', + }, + label: { + color: theme.palette.common.white, + fontWeight: 'bold', + letterSpacing: 0, + fontSize: theme.typography.fontSize, + marginBottom: theme.spacing(1) / 2, + lineHeight: 1, + }, + value: { + color: 'rgba(255, 255, 255, 0.8)', + fontSize: theme.typography.fontSize, + lineHeight: 1, + }, + }), + { name: 'BackstageHeaderLabel' }, +); type HeaderLabelContentProps = { value: React.ReactNode; diff --git a/packages/core-components/src/layout/HeaderLabel/index.ts b/packages/core-components/src/layout/HeaderLabel/index.ts index cc803e7fde..df8dcaf84c 100644 --- a/packages/core-components/src/layout/HeaderLabel/index.ts +++ b/packages/core-components/src/layout/HeaderLabel/index.ts @@ -15,3 +15,4 @@ */ export { HeaderLabel } from './HeaderLabel'; +export type { HeaderLabelClassKey } from './HeaderLabel'; diff --git a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx index 3468439ade..b34af3eb83 100644 --- a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx +++ b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx @@ -20,29 +20,38 @@ import React, { useState, useEffect } from 'react'; import { makeStyles, Tabs, Tab as TabUI, TabProps } from '@material-ui/core'; -const useStyles = makeStyles(theme => ({ - tabsWrapper: { - gridArea: 'pageSubheader', - backgroundColor: theme.palette.background.paper, - paddingLeft: theme.spacing(3), - }, - defaultTab: { - padding: theme.spacing(3, 3), - ...theme.typography.caption, - textTransform: 'uppercase', - fontWeight: 'bold', - color: theme.palette.text.secondary, - }, - selected: { - color: theme.palette.text.primary, - }, - tabRoot: { - '&:hover': { - backgroundColor: theme.palette.background.default, +export type HeaderTabsClassKey = + | 'tabsWrapper' + | 'defaultTab' + | 'selected' + | 'tabRoot'; + +const useStyles = makeStyles( + theme => ({ + tabsWrapper: { + gridArea: 'pageSubheader', + backgroundColor: theme.palette.background.paper, + paddingLeft: theme.spacing(3), + }, + defaultTab: { + padding: theme.spacing(3, 3), + ...theme.typography.caption, + textTransform: 'uppercase', + fontWeight: 'bold', + color: theme.palette.text.secondary, + }, + selected: { color: theme.palette.text.primary, }, - }, -})); + tabRoot: { + '&:hover': { + backgroundColor: theme.palette.background.default, + color: theme.palette.text.primary, + }, + }, + }), + { name: 'BackstageHeaderTabs' }, +); export type Tab = { id: string; diff --git a/packages/core-components/src/layout/HeaderTabs/index.tsx b/packages/core-components/src/layout/HeaderTabs/index.tsx index e706f19bf6..477269e7a9 100644 --- a/packages/core-components/src/layout/HeaderTabs/index.tsx +++ b/packages/core-components/src/layout/HeaderTabs/index.tsx @@ -14,5 +14,5 @@ * limitations under the License. */ -export type { Tab } from './HeaderTabs'; +export type { Tab, HeaderTabsClassKey } from './HeaderTabs'; export { HeaderTabs } from './HeaderTabs'; diff --git a/packages/core-components/src/layout/InfoCard/InfoCard.tsx b/packages/core-components/src/layout/InfoCard/InfoCard.tsx index 36205b0dc0..a3094b792e 100644 --- a/packages/core-components/src/layout/InfoCard/InfoCard.tsx +++ b/packages/core-components/src/layout/InfoCard/InfoCard.tsx @@ -29,34 +29,51 @@ import classNames from 'classnames'; import { ErrorBoundary, ErrorBoundaryProps } from '../ErrorBoundary'; import { BottomLink, BottomLinkProps } from '../BottomLink'; -const useStyles = makeStyles(theme => ({ - noPadding: { - padding: 0, - '&:last-child': { - paddingBottom: 0, - }, - }, - header: { - padding: theme.spacing(2, 2, 2, 2.5), - }, - headerTitle: { - fontWeight: 700, - }, - headerSubheader: { - paddingTop: theme.spacing(1), - }, - headerAvatar: {}, - headerAction: {}, - headerContent: {}, -})); +export type InfoCardClassKey = + | 'noPadding' + | 'header' + | 'headerTitle' + | 'headerSubheader' + | 'headerAvatar' + | 'headerAction' + | 'headerContent'; -const CardActionsTopRight = withStyles(theme => ({ - root: { - display: 'inline-block', - padding: theme.spacing(8, 8, 0, 0), - float: 'right', - }, -}))(CardActions); +const useStyles = makeStyles( + theme => ({ + noPadding: { + padding: 0, + '&:last-child': { + paddingBottom: 0, + }, + }, + header: { + padding: theme.spacing(2, 2, 2, 2.5), + }, + headerTitle: { + fontWeight: 700, + }, + headerSubheader: { + paddingTop: theme.spacing(1), + }, + headerAvatar: {}, + headerAction: {}, + headerContent: {}, + }), + { name: 'BackstageInfoCard' }, +); + +export type CardActionsTopRightClassKey = 'root'; + +const CardActionsTopRight = withStyles( + theme => ({ + root: { + display: 'inline-block', + padding: theme.spacing(8, 8, 0, 0), + float: 'right', + }, + }), + { name: 'BackstageInfoCardCardActionsTopRight' }, +)(CardActions); const VARIANT_STYLES = { card: { diff --git a/packages/core-components/src/layout/InfoCard/index.ts b/packages/core-components/src/layout/InfoCard/index.ts index cab443d9b2..1be4c01828 100644 --- a/packages/core-components/src/layout/InfoCard/index.ts +++ b/packages/core-components/src/layout/InfoCard/index.ts @@ -15,4 +15,8 @@ */ export { InfoCard } from './InfoCard'; -export type { InfoCardVariants } from './InfoCard'; +export type { + InfoCardVariants, + InfoCardClassKey, + CardActionsTopRightClassKey, +} from './InfoCard'; diff --git a/packages/core-components/src/layout/ItemCard/ItemCardGrid.tsx b/packages/core-components/src/layout/ItemCard/ItemCardGrid.tsx index 137c48d272..739398252e 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCardGrid.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCardGrid.tsx @@ -17,6 +17,8 @@ import { createStyles, makeStyles, Theme, WithStyles } from '@material-ui/core'; import React from 'react'; +export type ItemCardGridClassKey = 'root'; + const styles = (theme: Theme) => createStyles({ root: { @@ -27,7 +29,7 @@ const styles = (theme: Theme) => }, }); -const useStyles = makeStyles(styles); +const useStyles = makeStyles(styles, { name: 'BackstageItemCardGrid' }); export type ItemCardGridProps = Partial> & { /** diff --git a/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx b/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx index 4dbc5d7c1a..7ad6732e02 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx @@ -23,6 +23,8 @@ import { import React from 'react'; import { BackstageTheme } from '@backstage/theme'; +export type ItemCardHeaderClassKey = 'root'; + const styles = (theme: BackstageTheme) => createStyles({ root: { @@ -34,7 +36,7 @@ const styles = (theme: BackstageTheme) => }, }); -const useStyles = makeStyles(styles); +const useStyles = makeStyles(styles, { name: 'BackstageItemCardHeader' }); export type ItemCardHeaderProps = Partial> & { /** diff --git a/packages/core-components/src/layout/ItemCard/index.ts b/packages/core-components/src/layout/ItemCard/index.ts index 7c4f77f43a..f69374c03d 100644 --- a/packages/core-components/src/layout/ItemCard/index.ts +++ b/packages/core-components/src/layout/ItemCard/index.ts @@ -16,6 +16,9 @@ export { ItemCard } from './ItemCard'; export { ItemCardGrid } from './ItemCardGrid'; -export type { ItemCardGridProps } from './ItemCardGrid'; +export type { ItemCardGridProps, ItemCardGridClassKey } from './ItemCardGrid'; export { ItemCardHeader } from './ItemCardHeader'; -export type { ItemCardHeaderProps } from './ItemCardHeader'; +export type { + ItemCardHeaderProps, + ItemCardHeaderClassKey, +} from './ItemCardHeader'; diff --git a/packages/core-components/src/layout/Page/Page.tsx b/packages/core-components/src/layout/Page/Page.tsx index b838693a3c..37d6c663f2 100644 --- a/packages/core-components/src/layout/Page/Page.tsx +++ b/packages/core-components/src/layout/Page/Page.tsx @@ -18,17 +18,22 @@ import React, { PropsWithChildren } from 'react'; import { BackstageTheme } from '@backstage/theme'; import { makeStyles, ThemeProvider } from '@material-ui/core'; -const useStyles = makeStyles(() => ({ - root: { - display: 'grid', - gridTemplateAreas: - "'pageHeader pageHeader pageHeader' 'pageSubheader pageSubheader pageSubheader' 'pageNav pageContent pageSidebar'", - gridTemplateRows: 'max-content auto 1fr', - gridTemplateColumns: 'auto 1fr auto', - height: '100vh', - overflowY: 'auto', - }, -})); +export type PageClassKey = 'root'; + +const useStyles = makeStyles( + () => ({ + root: { + display: 'grid', + gridTemplateAreas: + "'pageHeader pageHeader pageHeader' 'pageSubheader pageSubheader pageSubheader' 'pageNav pageContent pageSidebar'", + gridTemplateRows: 'max-content auto 1fr', + gridTemplateColumns: 'auto 1fr auto', + height: '100vh', + overflowY: 'auto', + }, + }), + { name: 'BackstagePage' }, +); type Props = { themeId: string; diff --git a/packages/core-components/src/layout/Page/index.ts b/packages/core-components/src/layout/Page/index.ts index 91db73657e..4022075c7b 100644 --- a/packages/core-components/src/layout/Page/index.ts +++ b/packages/core-components/src/layout/Page/index.ts @@ -15,4 +15,5 @@ */ export { Page } from './Page'; +export type { PageClassKey } from './Page'; export { PageWithHeader } from './PageWithHeader'; diff --git a/packages/core-components/src/layout/Sidebar/Bar.tsx b/packages/core-components/src/layout/Sidebar/Bar.tsx index 8855f01104..750ec6bbdc 100644 --- a/packages/core-components/src/layout/Sidebar/Bar.tsx +++ b/packages/core-components/src/layout/Sidebar/Bar.tsx @@ -21,47 +21,52 @@ import { sidebarConfig, SidebarContext } from './config'; import { BackstageTheme } from '@backstage/theme'; import { SidebarPinStateContext } from './Page'; -const useStyles = makeStyles(theme => ({ - root: { - zIndex: 1000, - position: 'relative', - overflow: 'visible', - width: theme.spacing(7) + 1, - }, - drawer: { - display: 'flex', - flexFlow: 'column nowrap', - alignItems: 'flex-start', - position: 'fixed', - left: 0, - top: 0, - bottom: 0, - padding: 0, - background: theme.palette.navigation.background, - overflowX: 'hidden', - msOverflowStyle: 'none', - scrollbarWidth: 'none', - width: sidebarConfig.drawerWidthClosed, - borderRight: `1px solid #383838`, - transition: theme.transitions.create('width', { - easing: theme.transitions.easing.sharp, - duration: theme.transitions.duration.shortest, - }), - '& > *': { - flexShrink: 0, +export type SidebarClassKey = 'root' | 'drawer' | 'drawerOpen'; + +const useStyles = makeStyles( + theme => ({ + root: { + zIndex: 1000, + position: 'relative', + overflow: 'visible', + width: theme.spacing(7) + 1, }, - '&::-webkit-scrollbar': { - display: 'none', + drawer: { + display: 'flex', + flexFlow: 'column nowrap', + alignItems: 'flex-start', + position: 'fixed', + left: 0, + top: 0, + bottom: 0, + padding: 0, + background: theme.palette.navigation.background, + overflowX: 'hidden', + msOverflowStyle: 'none', + scrollbarWidth: 'none', + width: sidebarConfig.drawerWidthClosed, + borderRight: `1px solid #383838`, + transition: theme.transitions.create('width', { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.shortest, + }), + '& > *': { + flexShrink: 0, + }, + '&::-webkit-scrollbar': { + display: 'none', + }, }, - }, - drawerOpen: { - width: sidebarConfig.drawerWidthOpen, - transition: theme.transitions.create('width', { - easing: theme.transitions.easing.sharp, - duration: theme.transitions.duration.shorter, - }), - }, -})); + drawerOpen: { + width: sidebarConfig.drawerWidthOpen, + transition: theme.transitions.create('width', { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.shorter, + }), + }, + }), + { name: 'BackstageSidebar' }, +); enum State { Closed, diff --git a/packages/core-components/src/layout/Sidebar/Intro.tsx b/packages/core-components/src/layout/Sidebar/Intro.tsx index 45098b49e1..70b952588d 100644 --- a/packages/core-components/src/layout/Sidebar/Intro.tsx +++ b/packages/core-components/src/layout/Sidebar/Intro.tsx @@ -26,48 +26,58 @@ import { } from './config'; import { SidebarDivider } from './Items'; -const useStyles = makeStyles(theme => ({ - introCard: { - color: '#b5b5b5', - // XXX (@koroeskohr): should I be using a Mui theme variable? - fontSize: 12, - width: sidebarConfig.drawerWidthOpen, - marginTop: 18, - marginBottom: 12, - paddingLeft: sidebarConfig.iconPadding, - paddingRight: sidebarConfig.iconPadding, - }, - introDismiss: { - display: 'flex', - justifyContent: 'flex-end', - alignItems: 'center', - marginTop: 12, - }, - introDismissLink: { - color: '#dddddd', - display: 'flex', - alignItems: 'center', - marginBottom: 4, - '&:hover': { - color: theme.palette.linkHover, - transition: theme.transitions.create('color', { - easing: theme.transitions.easing.sharp, - duration: theme.transitions.duration.shortest, - }), +export type SidebarIntroClassKey = + | 'introCard' + | 'introDismiss' + | 'introDismissLink' + | 'introDismissText' + | 'introDismissIcon'; + +const useStyles = makeStyles( + theme => ({ + introCard: { + color: '#b5b5b5', + // XXX (@koroeskohr): should I be using a Mui theme variable? + fontSize: 12, + width: sidebarConfig.drawerWidthOpen, + marginTop: 18, + marginBottom: 12, + paddingLeft: sidebarConfig.iconPadding, + paddingRight: sidebarConfig.iconPadding, }, - }, - introDismissText: { - fontSize: '0.7rem', - fontWeight: 'bold', - textTransform: 'uppercase', - letterSpacing: 1, - }, - introDismissIcon: { - width: 18, - height: 18, - marginRight: 12, - }, -})); + introDismiss: { + display: 'flex', + justifyContent: 'flex-end', + alignItems: 'center', + marginTop: 12, + }, + introDismissLink: { + color: '#dddddd', + display: 'flex', + alignItems: 'center', + marginBottom: 4, + '&:hover': { + color: theme.palette.linkHover, + transition: theme.transitions.create('color', { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.shortest, + }), + }, + }, + introDismissText: { + fontSize: '0.7rem', + fontWeight: 'bold', + textTransform: 'uppercase', + letterSpacing: 1, + }, + introDismissIcon: { + width: 18, + height: 18, + marginRight: 12, + }, + }), + { name: 'BackstageSidebarIntro' }, +); type IntroCardProps = { text: string; diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index b3acc36f98..fbe1ffbb82 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -42,90 +42,107 @@ import { } from 'react-router-dom'; import { sidebarConfig, SidebarContext } from './config'; -const useStyles = makeStyles(theme => { - const { - selectedIndicatorWidth, - drawerWidthClosed, - drawerWidthOpen, - iconContainerWidth, - } = sidebarConfig; - return { - root: { - color: theme.palette.navigation.color, - display: 'flex', - flexFlow: 'row nowrap', - alignItems: 'center', - height: 48, - cursor: 'pointer', - }, - buttonItem: { - background: 'none', - border: 'none', - width: 'auto', - margin: 0, - padding: 0, - textAlign: 'inherit', - font: 'inherit', - }, - closed: { - width: drawerWidthClosed, - justifyContent: 'center', - }, - open: { - width: drawerWidthOpen, - }, - label: { - // XXX (@koroeskohr): I can't seem to achieve the desired font-weight from the designs - fontWeight: 'bold', - whiteSpace: 'nowrap', - lineHeight: 'auto', - flex: '3 1 auto', - width: '110px', - overflow: 'hidden', - 'text-overflow': 'ellipsis', - }, - iconContainer: { - boxSizing: 'border-box', - height: '100%', - width: iconContainerWidth, - marginRight: -theme.spacing(2), - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - }, - searchRoot: { - marginBottom: 12, - }, - searchField: { - color: '#b5b5b5', - fontWeight: 'bold', - fontSize: theme.typography.fontSize, - }, - searchFieldHTMLInput: { - padding: `${theme.spacing(2)} 0 ${theme.spacing(2)}`, - }, - searchContainer: { - width: drawerWidthOpen - iconContainerWidth, - }, - secondaryAction: { - width: theme.spacing(6), - textAlign: 'center', - marginRight: theme.spacing(1), - }, - selected: { - '&$root': { - borderLeft: `solid ${selectedIndicatorWidth}px ${theme.palette.navigation.indicator}`, - color: theme.palette.navigation.selectedColor, +export type SidebarItemClassKey = + | 'root' + | 'buttonItem' + | 'closed' + | 'open' + | 'label' + | 'iconContainer' + | 'searchRoot' + | 'searchField' + | 'searchFieldHTMLInput' + | 'searchContainer' + | 'secondaryAction' + | 'selected'; + +const useStyles = makeStyles( + theme => { + const { + selectedIndicatorWidth, + drawerWidthClosed, + drawerWidthOpen, + iconContainerWidth, + } = sidebarConfig; + return { + root: { + color: theme.palette.navigation.color, + display: 'flex', + flexFlow: 'row nowrap', + alignItems: 'center', + height: 48, + cursor: 'pointer', }, - '&$closed': { - width: drawerWidthClosed - selectedIndicatorWidth, + buttonItem: { + background: 'none', + border: 'none', + width: 'auto', + margin: 0, + padding: 0, + textAlign: 'inherit', + font: 'inherit', }, - '& $iconContainer': { - marginLeft: -selectedIndicatorWidth, + closed: { + width: drawerWidthClosed, + justifyContent: 'center', }, - }, - }; -}); + open: { + width: drawerWidthOpen, + }, + label: { + // XXX (@koroeskohr): I can't seem to achieve the desired font-weight from the designs + fontWeight: 'bold', + whiteSpace: 'nowrap', + lineHeight: 'auto', + flex: '3 1 auto', + width: '110px', + overflow: 'hidden', + 'text-overflow': 'ellipsis', + }, + iconContainer: { + boxSizing: 'border-box', + height: '100%', + width: iconContainerWidth, + marginRight: -theme.spacing(2), + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + }, + searchRoot: { + marginBottom: 12, + }, + searchField: { + color: '#b5b5b5', + fontWeight: 'bold', + fontSize: theme.typography.fontSize, + }, + searchFieldHTMLInput: { + padding: `${theme.spacing(2)} 0 ${theme.spacing(2)}`, + }, + searchContainer: { + width: drawerWidthOpen - iconContainerWidth, + }, + secondaryAction: { + width: theme.spacing(6), + textAlign: 'center', + marginRight: theme.spacing(1), + }, + selected: { + '&$root': { + borderLeft: `solid ${selectedIndicatorWidth}px ${theme.palette.navigation.indicator}`, + color: theme.palette.navigation.selectedColor, + }, + '&$closed': { + width: drawerWidthClosed - selectedIndicatorWidth, + }, + '& $iconContainer': { + marginLeft: -selectedIndicatorWidth, + }, + }, + }; + }, + { name: 'BackstageSidebarItem' }, +); type SidebarItemBaseProps = { icon: IconComponent; diff --git a/packages/core-components/src/layout/Sidebar/Page.tsx b/packages/core-components/src/layout/Sidebar/Page.tsx index 47c5878cde..c375112321 100644 --- a/packages/core-components/src/layout/Sidebar/Page.tsx +++ b/packages/core-components/src/layout/Sidebar/Page.tsx @@ -25,17 +25,22 @@ import { sidebarConfig } from './config'; import { BackstageTheme } from '@backstage/theme'; import { LocalStorage } from './localStorage'; -const useStyles = makeStyles({ - root: { - width: '100%', - minHeight: '100%', - transition: 'padding-left 0.1s ease-out', - paddingLeft: ({ isPinned }) => - isPinned - ? sidebarConfig.drawerWidthOpen - : sidebarConfig.drawerWidthClosed, +export type SidebarPageClassKey = 'root'; + +const useStyles = makeStyles( + { + root: { + width: '100%', + minHeight: '100%', + transition: 'padding-left 0.1s ease-out', + paddingLeft: ({ isPinned }) => + isPinned + ? sidebarConfig.drawerWidthOpen + : sidebarConfig.drawerWidthClosed, + }, }, -}); + { name: 'BackstageSidebarPage' }, +); export type SidebarPinStateContextType = { isPinned: boolean; diff --git a/packages/core-components/src/layout/Sidebar/index.ts b/packages/core-components/src/layout/Sidebar/index.ts index 58e193dbaf..067a9bf2eb 100644 --- a/packages/core-components/src/layout/Sidebar/index.ts +++ b/packages/core-components/src/layout/Sidebar/index.ts @@ -15,8 +15,9 @@ */ export { Sidebar } from './Bar'; +export type { SidebarClassKey } from './Bar'; export { SidebarPage, SidebarPinStateContext } from './Page'; -export type { SidebarPinStateContextType } from './Page'; +export type { SidebarPinStateContextType, SidebarPageClassKey } from './Page'; export { SidebarDivider, SidebarItem, @@ -25,7 +26,9 @@ export { SidebarSpacer, SidebarScrollWrapper, } from './Items'; +export type { SidebarItemClassKey } from './Items'; export { IntroCard, SidebarIntro } from './Intro'; +export type { SidebarIntroClassKey } from './Intro'; export { SIDEBAR_INTRO_LOCAL_STORAGE, SidebarContext, diff --git a/packages/core-components/src/layout/SignInPage/customProvider.tsx b/packages/core-components/src/layout/SignInPage/customProvider.tsx index 98753ad444..46fed6b5ae 100644 --- a/packages/core-components/src/layout/SignInPage/customProvider.tsx +++ b/packages/core-components/src/layout/SignInPage/customProvider.tsx @@ -32,16 +32,21 @@ import { GridItem } from './styles'; // accept base64url format according to RFC7515 (https://tools.ietf.org/html/rfc7515#section-3) const ID_TOKEN_REGEX = /^[a-z0-9_\-]+\.[a-z0-9_\-]+\.[a-z0-9_\-]+$/i; -const useFormStyles = makeStyles(theme => ({ - form: { - display: 'flex', - flexFlow: 'column nowrap', - }, - button: { - alignSelf: 'center', - marginTop: theme.spacing(2), - }, -})); +export type CustomProviderClassKey = 'form' | 'button'; + +const useFormStyles = makeStyles( + theme => ({ + form: { + display: 'flex', + flexFlow: 'column nowrap', + }, + button: { + alignSelf: 'center', + marginTop: theme.spacing(2), + }, + }), + { name: 'BackstageCustomProvider' }, +); type Data = { userId: string; diff --git a/packages/core-components/src/layout/SignInPage/index.ts b/packages/core-components/src/layout/SignInPage/index.ts index 2e5502d7ea..caa8506399 100644 --- a/packages/core-components/src/layout/SignInPage/index.ts +++ b/packages/core-components/src/layout/SignInPage/index.ts @@ -16,3 +16,5 @@ export type { SignInProviderConfig } from './types'; export { SignInPage } from './SignInPage'; +export type { SignInPageClassKey } from './styles'; +export type { CustomProviderClassKey } from './customProvider'; diff --git a/packages/core-components/src/layout/SignInPage/styles.tsx b/packages/core-components/src/layout/SignInPage/styles.tsx index 96559a4e78..55db36229b 100644 --- a/packages/core-components/src/layout/SignInPage/styles.tsx +++ b/packages/core-components/src/layout/SignInPage/styles.tsx @@ -16,20 +16,25 @@ import React from 'react'; import { Grid, makeStyles } from '@material-ui/core'; -export const useStyles = makeStyles({ - container: { - padding: 0, - listStyle: 'none', +export type SignInPageClassKey = 'container' | 'item'; + +export const useStyles = makeStyles( + { + container: { + padding: 0, + listStyle: 'none', + }, + item: { + display: 'flex', + flexDirection: 'column', + width: '100%', + maxWidth: '400px', + margin: 0, + padding: 0, + }, }, - item: { - display: 'flex', - flexDirection: 'column', - width: '100%', - maxWidth: '400px', - margin: 0, - padding: 0, - }, -}); + { name: 'BackstageSignInPage' }, +); export const GridItem = ({ children }: { children: JSX.Element }) => { const classes = useStyles(); diff --git a/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx b/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx index f350b24f1d..e9905663b2 100644 --- a/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx +++ b/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx @@ -34,22 +34,32 @@ import { import { BottomLink, BottomLinkProps } from '../BottomLink'; import { ErrorBoundary, ErrorBoundaryProps } from '../ErrorBoundary'; -const useTabsStyles = makeStyles(theme => ({ - root: { - padding: theme.spacing(0, 2, 0, 2.5), - minHeight: theme.spacing(3), - }, - indicator: { - backgroundColor: theme.palette.info.main, - height: theme.spacing(0.3), - }, -})); +export type TabbedCardClassKey = 'root' | 'indicator'; -const BoldHeader = withStyles(theme => ({ - root: { padding: theme.spacing(2, 2, 2, 2.5), display: 'inline-block' }, - title: { fontWeight: 700 }, - subheader: { paddingTop: theme.spacing(1) }, -}))(CardHeader); +const useTabsStyles = makeStyles( + theme => ({ + root: { + padding: theme.spacing(0, 2, 0, 2.5), + minHeight: theme.spacing(3), + }, + indicator: { + backgroundColor: theme.palette.info.main, + height: theme.spacing(0.3), + }, + }), + { name: 'BackstageTabbedCard' }, +); + +export type BoldHeaderClassKey = 'root' | 'title' | 'subheader'; + +const BoldHeader = withStyles( + theme => ({ + root: { padding: theme.spacing(2, 2, 2, 2.5), display: 'inline-block' }, + title: { fontWeight: 700 }, + subheader: { paddingTop: theme.spacing(1) }, + }), + { name: 'BackstageTabbedCardBoldHeader' }, +)(CardHeader); type Props = { /** @deprecated Use errorBoundaryProps instead */ @@ -114,23 +124,28 @@ export function TabbedCard(props: PropsWithChildren) { ); } -const useCardTabStyles = makeStyles(theme => ({ - root: { - minWidth: theme.spacing(6), - minHeight: theme.spacing(3), - margin: theme.spacing(0, 2, 0, 0), - padding: theme.spacing(0.5, 0, 0.5, 0), - textTransform: 'none', - '&:hover': { - opacity: 1, - backgroundColor: 'transparent', - color: theme.palette.text.primary, +export type CardTabClassKey = 'root' | 'selected'; + +const useCardTabStyles = makeStyles( + theme => ({ + root: { + minWidth: theme.spacing(6), + minHeight: theme.spacing(3), + margin: theme.spacing(0, 2, 0, 0), + padding: theme.spacing(0.5, 0, 0.5, 0), + textTransform: 'none', + '&:hover': { + opacity: 1, + backgroundColor: 'transparent', + color: theme.palette.text.primary, + }, }, - }, - selected: { - fontWeight: 'bold', - }, -})); + selected: { + fontWeight: 'bold', + }, + }), + { name: 'BackstageCardTab' }, +); type CardTabProps = TabProps & { children: ReactNode; diff --git a/packages/core-components/src/layout/TabbedCard/index.ts b/packages/core-components/src/layout/TabbedCard/index.ts index f3e32be054..2f31163beb 100644 --- a/packages/core-components/src/layout/TabbedCard/index.ts +++ b/packages/core-components/src/layout/TabbedCard/index.ts @@ -15,3 +15,8 @@ */ export { CardTab, TabbedCard } from './TabbedCard'; +export type { + CardTabClassKey, + TabbedCardClassKey, + BoldHeaderClassKey, +} from './TabbedCard'; diff --git a/packages/core-components/src/layout/index.ts b/packages/core-components/src/layout/index.ts index 4abde642dc..19cd6dfb78 100644 --- a/packages/core-components/src/layout/index.ts +++ b/packages/core-components/src/layout/index.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +export * from './BottomLink'; export * from './Content'; export * from './ContentHeader'; export * from './ErrorBoundary'; diff --git a/packages/core-components/src/overridableComponents.ts b/packages/core-components/src/overridableComponents.ts new file mode 100644 index 0000000000..b3186ae48d --- /dev/null +++ b/packages/core-components/src/overridableComponents.ts @@ -0,0 +1,172 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Overrides } from '@material-ui/core/styles/overrides'; +import { StyleRules } from '@material-ui/core/styles/withStyles'; + +import { + AvatarClassKey, + DependencyGraphDefaultLabelClassKey, + DependencyGraphDefaultNodeClassKey, + DependencyGraphEdgeClassKey, + DependencyGraphNodeClassKey, + DismissbleBannerClassKey, + EmptyStateClassKey, + EmptyStateImageClassKey, + MissingAnnotationEmptyStateClassKey, + ErrorPanelClassKey, + FeatureCalloutCircleClassKey, + HeaderIconLinkRowClassKey, + IconLinkVerticalClassKey, + HorizontalScrollGridClassKey, + LifecycleClassKey, + MarkdownContentClassKey, + LoginRequestListItemClassKey, + OAuthRequestDialogClassKey, + OverflowTooltipClassKey, + GaugeClassKey, + GaugeCardClassKey, + ResponseErrorPanelClassKey, + SelectInputBaseClassKey, + SelectClassKey, + ClosedDropdownClassKey, + OpenedDropdownClassKey, + SimpleStepperFooterClassKey, + SimpleStepperStepClassKey, + StatusClassKey, + MetadataTableTitleCellClassKey, + MetadataTableCellClassKey, + MetadataTableListClassKey, + MetadataTableListItemClassKey, + StructuredMetadataTableListClassKey, + StructuredMetadataTableNestedListClassKey, + SupportButtonClassKey, + TableFiltersClassKey, + SubvalueCellClassKey, + TableHeaderClassKey, + TableToolbarClassKey, + FiltersContainerClassKey, + TableClassKey, + TabBarClassKey, + TabIconClassKey, + TabsClassKey, + WarningPanelClassKey, +} from './components'; + +import { + BottomLinkClassKey, + BreadcrumbsClickableTextClassKey, + BreadcrumbsStyledBoxClassKey, + BackstageContentClassKey, + ContentHeaderClassKey, + ErrorPageClassKey, + MicDropClassKey, + HeaderClassKey, + HeaderLabelClassKey, + HeaderTabsClassKey, + InfoCardClassKey, + CardActionsTopRightClassKey, + ItemCardGridClassKey, + ItemCardHeaderClassKey, + PageClassKey, + SidebarClassKey, + SidebarIntroClassKey, + SidebarItemClassKey, + SidebarPageClassKey, + CustomProviderClassKey, + SignInPageClassKey, + TabbedCardClassKey, + BoldHeaderClassKey, + CardTabClassKey, +} from './layout'; + +type BackstageComponentsNameToClassKey = { + BackstageAvatar: AvatarClassKey; + BackstageDependencyGraphDefaultLabel: DependencyGraphDefaultLabelClassKey; + BackstageDependencyGraphDefaultNode: DependencyGraphDefaultNodeClassKey; + BackstageDependencyGraphEdge: DependencyGraphEdgeClassKey; + BackstageDependencyGraphNode: DependencyGraphNodeClassKey; + BackstageDismissableBanner: DismissbleBannerClassKey; + BackstageEmptyState: EmptyStateClassKey; + BackstageEmptyStateImage: EmptyStateImageClassKey; + BackstageMissingAnnotationEmptyState: MissingAnnotationEmptyStateClassKey; + BackstageErrorPanel: ErrorPanelClassKey; + BackstageFeatureCalloutCircular: FeatureCalloutCircleClassKey; + BackstageHeaderIconLinkRow: HeaderIconLinkRowClassKey; + BackstageIconLinkVertical: IconLinkVerticalClassKey; + BackstageHorizontalScrollGrid: HorizontalScrollGridClassKey; + BackstageLifecycle: LifecycleClassKey; + BackstageMarkdownContent: MarkdownContentClassKey; + BackstageLoginRequestListItem: LoginRequestListItemClassKey; + OAuthRequestDialog: OAuthRequestDialogClassKey; + BackstageOverflowTooltip: OverflowTooltipClassKey; + BackstageGauge: GaugeClassKey; + BackstageGaugeCard: GaugeCardClassKey; + BackstageResponseErrorPanel: ResponseErrorPanelClassKey; + BackstageSelectInputBase: SelectInputBaseClassKey; + BackstageSelect: SelectClassKey; + BackstageClosedDropdown: ClosedDropdownClassKey; + BackstageOpenedDropdown: OpenedDropdownClassKey; + BackstageSimpleStepperFooter: SimpleStepperFooterClassKey; + SimpleStepperStep: SimpleStepperStepClassKey; + BackstageStatus: StatusClassKey; + BackstageMetadataTableTitleCell: MetadataTableTitleCellClassKey; + BackstageMetadataTableCell: MetadataTableCellClassKey; + BackstageMetadataTableList: MetadataTableListClassKey; + BackstageMetadataTableListItem: MetadataTableListItemClassKey; + BackstageStructuredMetadataTableList: StructuredMetadataTableListClassKey; + BackstageStructuredMetadataTableNestedList: StructuredMetadataTableNestedListClassKey; + BackstageSupportButton: SupportButtonClassKey; + BackstageTableFilters: TableFiltersClassKey; + BackstageSubvalueCell: SubvalueCellClassKey; + BackstageTableHeader: TableHeaderClassKey; + BackstageTableToolbar: TableToolbarClassKey; + BackstageTableFiltersContainer: FiltersContainerClassKey; + BackstageTable: TableClassKey; + BackstageTabBar: TabBarClassKey; + BackstageTabIcon: TabIconClassKey; + BackstageTabs: TabsClassKey; + BackstageWarningPanel: WarningPanelClassKey; + BackstageBottomLink: BottomLinkClassKey; + BackstageBreadcrumbsClickableText: BreadcrumbsClickableTextClassKey; + BackstageBreadcrumbsStyledBox: BreadcrumbsStyledBoxClassKey; + BackstageContent: BackstageContentClassKey; + BackstageContentHeader: ContentHeaderClassKey; + BackstageErrorPage: ErrorPageClassKey; + BackstageErrorPageMicDrop: MicDropClassKey; + BackstageHeader: HeaderClassKey; + BackstageHeaderLabel: HeaderLabelClassKey; + BackstageHeaderTabs: HeaderTabsClassKey; + BackstageInfoCard: InfoCardClassKey; + BackstageInfoCardCardActionsTopRight: CardActionsTopRightClassKey; + BackstageItemCardGrid: ItemCardGridClassKey; + BackstageItemCardHeader: ItemCardHeaderClassKey; + BackstagePage: PageClassKey; + BackstageSidebar: SidebarClassKey; + BackstageSidebarIntro: SidebarIntroClassKey; + BackstageSidebarItem: SidebarItemClassKey; + BackstageSidebarPage: SidebarPageClassKey; + BackstageCustomProvider: CustomProviderClassKey; + BackstageSignInPage: SignInPageClassKey; + BackstageTabbedCard: TabbedCardClassKey; + BackstageTabbedCardBoldHeader: BoldHeaderClassKey; + BackstageCardTab: CardTabClassKey; +}; + +export type BackstageOverrides = Overrides & { + [Name in keyof BackstageComponentsNameToClassKey]?: Partial< + StyleRules + >; +}; diff --git a/packages/techdocs-common/api-report.md b/packages/techdocs-common/api-report.md index 2f6d2a6f89..38f4a9aec3 100644 --- a/packages/techdocs-common/api-report.md +++ b/packages/techdocs-common/api-report.md @@ -256,6 +256,7 @@ export class TechdocsGenerator implements GeneratorBase { config: Config; scmIntegrations: ScmIntegrationRegistry; }); + static readonly defaultDockerImage = 'spotify/techdocs:v0.3.2'; // (undocumented) static fromConfig( config: Config, diff --git a/packages/techdocs-common/src/stages/generate/techdocs.ts b/packages/techdocs-common/src/stages/generate/techdocs.ts index c3d48507ce..5814fecea3 100644 --- a/packages/techdocs-common/src/stages/generate/techdocs.ts +++ b/packages/techdocs-common/src/stages/generate/techdocs.ts @@ -37,9 +37,12 @@ import { GeneratorRunOptions, } from './types'; -const defaultDockerImage = 'spotify/techdocs'; - export class TechdocsGenerator implements GeneratorBase { + /** + * The default docker image (and version) used to generate content. Public + * and static so that techdocs-common consumers can use the same version. + */ + public static readonly defaultDockerImage = 'spotify/techdocs:v0.3.2'; private readonly logger: Logger; private readonly containerRunner: ContainerRunner; private readonly options: GeneratorConfig; @@ -124,7 +127,8 @@ export class TechdocsGenerator implements GeneratorBase { break; case 'docker': await this.containerRunner.runContainer({ - imageName: this.options.dockerImage ?? defaultDockerImage, + imageName: + this.options.dockerImage ?? TechdocsGenerator.defaultDockerImage, args: ['build', '-d', '/output'], logStream, mountDirs, diff --git a/plugins/azure-devops-backend/config.d.ts b/plugins/azure-devops-backend/config.d.ts index 9d4e896a89..433e4df22f 100644 --- a/plugins/azure-devops-backend/config.d.ts +++ b/plugins/azure-devops-backend/config.d.ts @@ -16,7 +16,7 @@ export interface Config { /** Configuration options for the azure-devops-backend plugin */ - azureDevOps?: { + azureDevOps: { /** * The hostname of the given Azure instance */ @@ -25,7 +25,7 @@ export interface Config { * Token used to authenticate requests. * @visibility secret */ - token?: string; + token: string; /** * The organization of the given Azure instance */ diff --git a/plugins/azure-devops-backend/src/service/router.test.ts b/plugins/azure-devops-backend/src/service/router.test.ts index 08d86c5cc8..a66b86f418 100644 --- a/plugins/azure-devops-backend/src/service/router.test.ts +++ b/plugins/azure-devops-backend/src/service/router.test.ts @@ -62,10 +62,7 @@ describe('createRouter', () => { const response = await request(app).get('/health'); expect(response.status).toEqual(200); - expect(response.body).toEqual({ - status: 'Healthy', - details: 'All required config has been provided', - }); + expect(response.body).toEqual({ status: 'ok' }); }); }); diff --git a/plugins/azure-devops-backend/src/service/router.ts b/plugins/azure-devops-backend/src/service/router.ts index c223926848..1fc86128e6 100644 --- a/plugins/azure-devops-backend/src/service/router.ts +++ b/plugins/azure-devops-backend/src/service/router.ts @@ -36,9 +36,9 @@ export async function createRouter( const { logger } = options; const config = options.config.getConfig('azureDevOps'); - const token: string = config.getString('token'); - const host: string = config.getString('host'); - const organization: string = config.getString('organization'); + const token = config.getString('token'); + const host = config.getString('host'); + const organization = config.getString('organization'); const authHandler = getPersonalAccessTokenHandler(token); const webApi = new WebApi(`https://${host}/${organization}`, authHandler); @@ -49,36 +49,8 @@ export async function createRouter( const router = Router(); router.use(express.json()); - router.get('/health', (_, response) => { - let code: number = 200; - let status: string = ''; - let details: string = ''; - - if (token && host && organization) { - code = 200; - status = 'Healthy'; - details = 'All required config has been provided'; - } - - if (!token) { - code = 500; - status = 'Unhealthy'; - details = 'Token is missing'; - } - - if (!host) { - code = 500; - status = 'Unhealthy'; - details = 'Host is missing'; - } - - if (!organization) { - code = 500; - status = 'Unhealthy'; - details = 'Organization is missing'; - } - - response.status(code).json({ status: status, details: details }); + router.get('/health', (_req, res) => { + res.status(200).json({ status: 'ok' }); }); router.get('/repository/:projectName/:repoName', async (req, res) => { diff --git a/plugins/kubernetes/api-report.md b/plugins/kubernetes/api-report.md index fcbf349d7e..f7afc7af9d 100644 --- a/plugins/kubernetes/api-report.md +++ b/plugins/kubernetes/api-report.md @@ -10,6 +10,7 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { OAuthApi } from '@backstage/core-plugin-api'; +import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common'; import { RouteRef } from '@backstage/core-plugin-api'; // Warning: (ae-forgotten-export) The symbol "ClusterLinksFormatter" needs to be exported by the entry point index.d.ts @@ -38,7 +39,28 @@ export function formatClusterLink( // @public (undocumented) export const isKubernetesAvailable: (entity: Entity) => boolean; -// Warning: (ae-forgotten-export) The symbol "KubernetesAuthProvidersApi" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "KubernetesApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface KubernetesApi { + // (undocumented) + getClusters(): Promise< + { + name: string; + authProvider: string; + }[] + >; + // (undocumented) + getObjectsByEntity( + requestBody: KubernetesRequestBody, + ): Promise; +} + +// Warning: (ae-missing-release-tag) "kubernetesApiRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const kubernetesApiRef: ApiRef; + // Warning: (ae-missing-release-tag) "KubernetesAuthProviders" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -51,6 +73,17 @@ export class KubernetesAuthProviders implements KubernetesAuthProvidersApi { ): Promise; } +// Warning: (ae-missing-release-tag) "KubernetesAuthProvidersApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface KubernetesAuthProvidersApi { + // (undocumented) + decorateRequestBodyForAuth( + authProvider: string, + requestBody: KubernetesRequestBody, + ): Promise; +} + // Warning: (ae-missing-release-tag) "kubernetesAuthProvidersApiRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/plugins/kubernetes/dev/index.tsx b/plugins/kubernetes/dev/index.tsx index 77907a4ffd..a2c1114c2d 100644 --- a/plugins/kubernetes/dev/index.tsx +++ b/plugins/kubernetes/dev/index.tsx @@ -13,7 +13,100 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import React from 'react'; +import { Entity } from '@backstage/catalog-model'; import { createDevApp } from '@backstage/dev-utils'; -import { kubernetesPlugin } from '../src'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { + EntityKubernetesContent, + kubernetesPlugin, + kubernetesApiRef, + KubernetesApi, +} from '../src'; +import { + FetchResponse, + ObjectsByEntityResponse, +} from '@backstage/plugin-kubernetes-common'; +import fixture1 from '../src/__fixtures__/1-deployments.json'; +import fixture2 from '../src/__fixtures__/2-deployments.json'; +import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; -createDevApp().registerPlugin(kubernetesPlugin).render(); +const mockEntity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'backstage', + description: 'backstage.io', + annotations: { + 'backstage.io/kubernetes-id': 'dice-roller', + }, + }, + spec: { + lifecycle: 'production', + type: 'service', + owner: 'user:guest', + }, +}; + +class MockKubernetesClient implements KubernetesApi { + readonly resources: FetchResponse[]; + + constructor(fixtureData: { [resourceType: string]: any[] }) { + this.resources = Object.entries(fixtureData).flatMap( + ([type, resources]) => + ({ type: type.toLocaleLowerCase('en-US'), resources } as FetchResponse), + ); + } + + async getObjectsByEntity(): Promise { + return { + items: [ + { + cluster: { name: 'mock-cluster' }, + resources: this.resources, + errors: [], + }, + ], + }; + } + + async getClusters(): Promise<{ name: string; authProvider: string }[]> { + return [{ name: 'mock-cluster', authProvider: 'serviceAccount' }]; + } +} + +createDevApp() + .addPage({ + path: '/fixture-1', + title: 'Fixture 1', + element: ( + + + + + + ), + }) + .addPage({ + path: '/fixture-2', + title: 'Fixture 2', + element: ( + + + + + + ), + }) + .registerPlugin(kubernetesPlugin) + .render(); diff --git a/plugins/kubernetes/src/api/index.ts b/plugins/kubernetes/src/api/index.ts new file mode 100644 index 0000000000..33c49db099 --- /dev/null +++ b/plugins/kubernetes/src/api/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { kubernetesApiRef } from './types'; +export type { KubernetesApi } from './types'; diff --git a/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx b/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx index 7fc3a317da..da53db687b 100644 --- a/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx +++ b/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx @@ -15,20 +15,17 @@ */ import React from 'react'; -import { render } from '@testing-library/react'; import * as deployments from '../../__fixtures__/2-deployments.json'; -import { wrapInTestApp } from '@backstage/test-utils'; +import { renderInTestApp } from '@backstage/test-utils'; import { DeploymentDrawer } from './DeploymentDrawer'; describe('DeploymentDrawer', () => { it('should render deployment drawer', async () => { - const { getByText, getAllByText } = render( - wrapInTestApp( - , - ), + const { getByText, getAllByText } = await renderInTestApp( + , ); expect(getAllByText('dice-roller')).toHaveLength(2); @@ -45,6 +42,22 @@ describe('DeploymentDrawer', () => { expect(getByText('600')).toBeInTheDocument(); expect(getByText('Progressing')).toBeInTheDocument(); expect(getByText('Available')).toBeInTheDocument(); + expect(getByText('namespace: default')).toBeInTheDocument(); expect(getAllByText('True')).toHaveLength(2); }); + + it('should render deployment drawer without namespace', async () => { + const deployment = (deployments as any).deployments[0]; + const { queryByText } = await renderInTestApp( + , + ); + + expect(queryByText('namespace: default')).not.toBeInTheDocument(); + }); }); diff --git a/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentDrawer.tsx b/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentDrawer.tsx index 2d22caec7c..6d25702d70 100644 --- a/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentDrawer.tsx +++ b/plugins/kubernetes/src/components/DeploymentsAccordions/DeploymentDrawer.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { V1Deployment } from '@kubernetes/client-node'; import { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer'; import { renderCondition } from '../../utils/pod'; -import { Typography, Grid } from '@material-ui/core'; +import { Typography, Grid, Chip } from '@material-ui/core'; export const DeploymentDrawer = ({ deployment, @@ -27,6 +27,7 @@ export const DeploymentDrawer = ({ deployment: V1Deployment; expanded?: boolean; }) => { + const namespace = deployment.metadata?.namespace; return ( + {namespace && ( + + + + )} ); diff --git a/plugins/kubernetes/src/index.ts b/plugins/kubernetes/src/index.ts index 08af757d47..71e1779c84 100644 --- a/plugins/kubernetes/src/index.ts +++ b/plugins/kubernetes/src/index.ts @@ -26,5 +26,6 @@ export { EntityKubernetesContent, } from './plugin'; export { Router, isKubernetesAvailable } from './Router'; +export * from './api'; export * from './kubernetes-auth-provider'; export * from './utils/clusterLinks'; diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/index.ts b/plugins/kubernetes/src/kubernetes-auth-provider/index.ts index 4edb9c19e0..f6a07d44a9 100644 --- a/plugins/kubernetes/src/kubernetes-auth-provider/index.ts +++ b/plugins/kubernetes/src/kubernetes-auth-provider/index.ts @@ -15,4 +15,5 @@ */ export { kubernetesAuthProvidersApiRef } from './types'; +export type { KubernetesAuthProvidersApi } from './types'; export { KubernetesAuthProviders } from './KubernetesAuthProviders';