Utilisation des couches UI dans ce dépôt

Comment choisir entre @backstage/ui (bui), @backstage/core-components et Material UI v4 pour construire des composants UI. Couvre les règles d'utilisation, la configuration et les composants courants.

Spar Skills Guide Bot
DeveloppementIntermédiaire
0023/07/2026
#ui#backstage#components#migration#design-system

Recommandé pour


name: ui description: How to build UI in this repo — the bui (@backstage/ui) design system vs legacy @backstage/core-components + MUI v4, which to reach for, and how to read Backstage Storybook component/story source. Use when creating or changing pages, cards, layouts, buttons, or any frontend component.

The three UI layers in this repo

| Layer | Import from | Status | | --- | --- | --- | | bui — the new Backstage design system | @backstage/ui (aka "Backstage UI", "BUI") | Preferred for new work. The direction we're migrating toward. | | core-components — classic Backstage components | @backstage/core-components | Legacy but still required where bui has no equivalent (e.g. feature-rich Table, Page/Header/Content scaffolding, Link with route refs). | | Material UI v4 | @material-ui/core | Legacy primitives + makeStyles. Used for styling and gaps bui doesn't cover. MUI v4 docs. |

Rule of thumb: reach for bui first. Fall back to core-components / MUI v4 only when bui lacks the piece you need. Mixing all three in one file is normal and expected during the migration — see ClusterAboutCard.tsx, which imports Grid from bui, Link from core-components, and Box/Tooltip from MUI v4 together.

@backstage/ui is currently 0.16.0 — a young, fast-moving package. APIs change between releases and it is not a full replacement for core-components yet. When unsure whether a bui component exists or what props it takes, check the Storybook source (see below) rather than guessing.

bui setup (already done)

  • The plugin's package.json must declare "@backstage/ui": "backstage:^" (already present in gs, ui-react, ai-chat, and app).
  • The global stylesheet is imported once in packages/app/src/index.tsx: import '@backstage/ui/css/styles.css';. Don't re-import it per component.
  • We do not wrap the app in BUIProvider — bui components render against the existing app theme + the global CSS. (Storybook recipes use BUIProvider because they render in isolation; the real app doesn't need it.)

bui components we actually use

Common primitives already in the codebase (import from @backstage/ui):

  • Layout: Flex, Grid, Box, Container
  • Surfaces: Card, CardHeader, CardBody, CardFooter
  • Typography: Text (e.g. <Text as="h3" variant="title-x-small" weight="bold">)
  • Controls: Button, ButtonIcon, Switch, Link
  • Overlay/menu: Tooltip, TooltipTrigger, MenuTrigger, Menu, MenuItem
  • Data display: Table + Cell / CellText / ColumnConfig, List, ListRow, Avatar
  • Page chrome: PluginHeader, Header (the two-tier header pattern — plugin-level PluginHeader above an entity-level Header). NFS page headers and SubPageBlueprint tabs are rendered by the custom GSPageLayout swappable component, not directly — see "Page headers and tabs" in docs/ui.md before building a tabbed page.

Cards: use the shared InfoCard wrapper

@giantswarm/backstage-plugin-ui-react exports an InfoCard built on bui's Card/CardHeader/CardBody/CardFooter with our standard title styling and header/footer action slots. Prefer it over hand-rolling a bui Card or the core-components InfoCard for new cards. Source: plugins/ui-react/src/components/InfoCard/InfoCard.tsx.

Tables: see the tables skill

The bui Table (data-driven columnConfig + data, cells must return Cell/CellText) and the feature-rich core-components Table are both documented in depth in the tables skill, including the choice matrix and gotchas (loading skeleton needs data={undefined}). Read that skill for anything table-related; don't duplicate it here.

Reading Backstage Storybook source

The Backstage Storybook renders components from the upstream backstage/backstage monorepo — stories are .stories.tsx files colocated with their components. There is no separate storybook repo, and we do not run a local storybook. To learn a pattern (how a page/card is composed, what props a bui component takes), read the story + component source directly.

The reliable technique: index.jsonimportPath → GitHub raw

Every Storybook deployment publishes a machine-readable index at https://backstage.io/storybook/index.json. Each entry carries the exact source paths:

{
  "id": "recipes-pluginheader-and-header--with-tabs",
  "title": "Recipes/PluginHeader and Header",
  "importPath": "./packages/ui/src/recipes/PluginHeaderAndHeader.stories.tsx",
  "componentPath": "./packages/ui/src/components/PluginHeader/PluginHeader.tsx"
}

Then fetch the raw source from GitHub (strip the leading ./):

BASE=https://raw.githubusercontent.com/backstage/backstage/master
curl -sfL "$BASE/packages/ui/src/recipes/PluginHeaderAndHeader.stories.tsx"
curl -sfL "$BASE/packages/ui/src/components/PluginHeader/PluginHeader.tsx"

To find the story ID for a Storybook URL: the ?path=/story/<id> query param is the entry id. Story IDs can drift between releases (the "Recipes/..." example also now exists as "Backstage UI/PluginHeader") — search index.json by title or a keyword rather than trusting an old URL. Quick lookup:

curl -sfL https://backstage.io/storybook/index.json \
  | jq '.entries | to_entries[] | select(.value.title|test("PluginHeader";"i")) | .value | {id,importPath,componentPath}'

Live inspection with Chrome DevTools

Use the chrome-devtools MCP when you want to inspect the rendered result (DOM, computed styles, a11y tree) or grab index.json without CORS friction:

  • new_page / navigate_page to https://backstage.io/storybook/
  • evaluate_script running fetch('https://backstage.io/storybook/index.json') (same-origin, so no CORS block) to pull the index or any raw story text
  • take_snapshot for the a11y tree of a rendered story

Note: the chrome-devtools MCP has its own filesystem roots — it can't write into the session scratchpad. Fetch text via evaluate_script and return it inline, or just curl the GitHub raw URL from Bash instead.

Related skills

  • tables — bui Table vs core-components Table, columns, filtering, faceted sidebars.
  • components — component directory structure, named exports, barrel files.
  • upstream-search — searching a local clone of backstage/backstage (needs BACKSTAGE_UPSTREAM_DIR set; the Storybook technique above needs no clone).
Skills similaires