A frontend library that helps other Backstage plugins interact with the catalog through React components, hooks, and utilities.
—
Core React components for displaying and linking to entities in various formats. These components provide consistent visual representation of entities throughout Backstage interfaces.
A comprehensive table component for displaying multiple entities with customizable columns and options.
/**
* Table component for displaying entities with customizable columns
* @param props - Configuration for the entity table
* @returns Rendered table component
*/
function EntityTable<T extends Entity>(props: EntityTableProps<T>): JSX.Element;
interface EntityTableProps<T extends Entity> {
/** Title displayed above the table */
title: string;
/** Visual variant of the info card containing the table */
variant?: InfoCardVariants;
/** Array of entities to display in the table */
entities: T[];
/** Content shown when no entities are available */
emptyContent?: ReactNode;
/** Column definitions for the table */
columns: TableColumn<T>[];
/** Additional table configuration options */
tableOptions?: TableOptions;
}
/** Factory functions for creating common table columns */
const columnFactories: {
createNameColumn(): TableColumn<Entity>;
createOwnerColumn(): TableColumn<Entity>;
createSpecTargetsColumn(): TableColumn<Entity>;
createMetadataDescriptionColumn(): TableColumn<Entity>;
createTagsColumn(): TableColumn<Entity>;
createTitleColumn(): TableColumn<Entity>;
createLabelColumn(key: string, title?: string): TableColumn<Entity>;
createEntityRefColumn(options: {
title?: string;
field: string;
defaultKind?: string;
}): TableColumn<Entity>;
};Usage Examples:
import { EntityTable, columnFactories } from '@backstage/plugin-catalog-react';
// Basic entity table
<EntityTable
title="Components"
entities={components}
columns={[
columnFactories.createNameColumn(),
columnFactories.createOwnerColumn(),
columnFactories.createMetadataDescriptionColumn(),
columnFactories.createTagsColumn(),
]}
/>
// Custom columns
<EntityTable
title="Services"
entities={services}
columns={[
{ title: 'Name', field: 'metadata.name' },
{ title: 'System', field: 'spec.system' },
{
title: 'Owner',
render: (entity) => entity.spec?.owner || 'Unknown'
}
]}
/>Component for creating clickable links to specific entities with optional icons and custom content.
/**
* Creates a clickable link to an entity with optional icon
* @param props - Link configuration and entity reference
* @returns Rendered link component
*/
function EntityRefLink(props: EntityRefLinkProps): JSX.Element;
interface EntityRefLinkProps {
/** Entity reference (entity object, compound ref, or string) */
entityRef: Entity | CompoundEntityRef | string;
/** Default kind when entityRef is a string without kind */
defaultKind?: string;
/** Default namespace when entityRef doesn't specify namespace */
defaultNamespace?: string;
/** Custom title text (deprecated - use children instead) */
title?: string;
/** Custom content to display instead of entity name */
children?: React.ReactNode;
/** Whether to hide the entity kind icon */
hideIcon?: boolean;
}Usage Examples:
import { EntityRefLink } from '@backstage/plugin-catalog-react';
// Basic entity link
<EntityRefLink entityRef="component:default/my-service" />
// With custom content
<EntityRefLink entityRef={entity}>
<strong>{entity.metadata.name}</strong>
</EntityRefLink>
// Multiple entity links
<EntityRefLinks
entityRefs={[
'component:default/service-a',
'component:default/service-b'
]}
defaultKind="component"
/>Component for displaying multiple entity links in a formatted list.
/**
* Displays multiple entity references as formatted links
* @param props - Configuration for multiple entity links
* @returns Rendered links component
*/
function EntityRefLinks(props: EntityRefLinksProps): JSX.Element;
interface EntityRefLinksProps {
/** Array of entity references to display as links */
entityRefs: (Entity | CompoundEntityRef | string)[];
/** Default kind for string entity refs without kind */
defaultKind?: string;
/** Default namespace for entity refs without namespace */
defaultNamespace?: string;
/** Custom getTitle function for link text */
getTitle?: (entityRef: Entity | CompoundEntityRef | string) => string;
}Component for displaying an entity name with consistent formatting and optional navigation.
/**
* Displays entity name with consistent formatting
* @param props - Display name configuration
* @returns Rendered display name component
*/
function EntityDisplayName(props: EntityDisplayNameProps): JSX.Element;
interface EntityDisplayNameProps {
/** Entity to display name for */
entity: Entity;
/** Whether the name should be a clickable link */
disableUnderline?: boolean;
}
/** Style class keys for EntityDisplayName component */
type CatalogReactEntityDisplayNameClassKey =
| 'root'
| 'title'
| 'subtitle';Usage Examples:
import { EntityDisplayName, useEntity } from '@backstage/plugin-catalog-react';
function EntityHeader() {
const { entity } = useEntity();
return (
<div>
<EntityDisplayName entity={entity} />
<p>{entity.metadata.description}</p>
</div>
);
}Utility functions for working with entity names and references.
/**
* Converts entity reference to human-readable format
* @param entityRef - Entity reference to humanize
* @returns Human-readable entity reference
*/
function humanizeEntityRef(
entityRef: Entity | CompoundEntityRef | string,
options?: {
defaultKind?: string;
defaultNamespace?: string;
}
): string;Component for showing starred status and adding/removing entities from favorites.
/**
* IconButton for showing if a current entity is starred and adding/removing it from favorites
* @param props - MaterialUI IconButton props extended by required entity prop
* @returns Rendered favorite toggle button
*/
function FavoriteEntity(props: FavoriteEntityProps): JSX.Element;
interface FavoriteEntityProps extends ComponentProps<typeof IconButton> {
/** Entity to show favorite status for */
entity: Entity;
}Usage Examples:
import { FavoriteEntity, useEntity } from '@backstage/plugin-catalog-react';
function EntityActionBar() {
const { entity } = useEntity();
return (
<div>
<h2>{entity.metadata.name}</h2>
<FavoriteEntity entity={entity} />
</div>
);
}
// Custom styling
<FavoriteEntity
entity={entity}
size="small"
style={{ marginLeft: 8 }}
/>Popover component that shows entity details on hover or click.
/**
* Popover component that shows entity details on hover
* @param props - Popover configuration and entity reference
* @returns Rendered popover component
*/
function EntityPeekAheadPopover(props: EntityPeekAheadPopoverProps): JSX.Element;
interface EntityPeekAheadPopoverProps {
/** Entity reference to show details for */
entityRef: string | CompoundEntityRef;
/** Child component that triggers the popover */
children: ReactNode;
}Usage Examples:
import { EntityPeekAheadPopover, EntityRefLink } from '@backstage/plugin-catalog-react';
function EntityWithPreview({ entityRef }: { entityRef: string }) {
return (
<EntityPeekAheadPopover entityRef={entityRef}>
<EntityRefLink entityRef={entityRef} />
</EntityPeekAheadPopover>
);
}
// Custom trigger content
<EntityPeekAheadPopover entityRef={entityRef}>
<button>Show Entity Details</button>
</EntityPeekAheadPopover>Dialog component for viewing raw entity data in JSON format.
/**
* Dialog for inspecting raw entity data
* @param props - Dialog configuration and entity
* @returns Rendered inspect dialog component
*/
function InspectEntityDialog(props: InspectEntityDialogProps): JSX.Element;
interface InspectEntityDialogProps {
/** Whether the dialog is open */
open: boolean;
/** Function called when dialog should be closed */
onClose: () => void;
/** Entity to inspect */
entity: Entity;
}Usage Examples:
import { InspectEntityDialog, useEntity } from '@backstage/plugin-catalog-react';
import { useState } from 'react';
function EntityInspectButton() {
const { entity } = useEntity();
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => setOpen(true)}>
Inspect Entity
</button>
<InspectEntityDialog
open={open}
onClose={() => setOpen(false)}
entity={entity}
/>
</>
);
}Dialog component for unregistering entities from the catalog.
/**
* Dialog for unregistering entities from the catalog
* @param props - Dialog configuration and entity
* @returns Rendered unregister dialog component
*/
function UnregisterEntityDialog(props: UnregisterEntityDialogProps): JSX.Element;
interface UnregisterEntityDialogProps {
/** Whether the dialog is open */
open: boolean;
/** Function called when dialog should be closed */
onClose: () => void;
/** Entity to unregister */
entity: Entity;
/** Function called after successful unregistration */
onUnregister?: () => void;
}Usage Examples:
import { UnregisterEntityDialog, useEntity } from '@backstage/plugin-catalog-react';
import { useState } from 'react';
import { catalogApiRef } from '@backstage/plugin-catalog-react';
import { useApi } from '@backstage/core-plugin-api';
function EntityUnregisterButton() {
const { entity } = useEntity();
const [open, setOpen] = useState(false);
const catalogApi = useApi(catalogApiRef);
const handleUnregister = async () => {
// Handle post-unregister actions (redirect, refresh, etc.)
window.location.href = '/catalog';
};
return (
<>
<button onClick={() => setOpen(true)}>
Unregister Entity
</button>
<UnregisterEntityDialog
open={open}
onClose={() => setOpen(false)}
entity={entity}
onUnregister={handleUnregister}
/>
</>
);
}Component for displaying empty state when required annotations are missing.
/**
* Empty state component for missing entity annotations
* @param props - Empty state configuration
* @returns Rendered empty state component
*/
function MissingAnnotationEmptyState(props: MissingAnnotationEmptyStateProps): JSX.Element;
interface MissingAnnotationEmptyStateProps {
/** Annotation key that is missing */
annotation: string;
/** Optional description of what the annotation is used for */
description?: string;
/** Optional link to documentation about the annotation */
readMoreUrl?: string;
}Usage Examples:
import { MissingAnnotationEmptyState } from '@backstage/plugin-catalog-react';
function EntityAnnotationCheck({ entity }: { entity: Entity }) {
const requiredAnnotation = 'backstage.io/source-location';
if (!entity.metadata.annotations?.[requiredAnnotation]) {
return (
<MissingAnnotationEmptyState
annotation={requiredAnnotation}
description="This annotation is required to show source code links"
readMoreUrl="https://backstage.io/docs/features/software-catalog/descriptor-format#metadata"
/>
);
}
return <div>Annotation is present</div>;
}
// Generic missing annotation handler
function RequireAnnotation({
entity,
annotation,
children
}: {
entity: Entity;
annotation: string;
children: ReactNode
}) {
if (!entity.metadata.annotations?.[annotation]) {
return (
<MissingAnnotationEmptyState
annotation={annotation}
description={`The ${annotation} annotation is required for this feature`}
/>
);
}
return <>{children}</>;
}Install with Tessl CLI
npx tessl i tessl/npm-backstage--plugin-catalog-react