Commit Graph

587 Commits

Author SHA1 Message Date
Charles de Dreuille 693f1c59d7 Merge pull request #33358 from backstage/charlesdedreuille/bacui-42-code-listboxlistrow-component
feat(ui): add List and ListRow components
2026-03-17 11:01:09 +00:00
Jonathan Roebuck bf41231deb Merge pull request #33387 from backstage/fix/table-complete-mode-loading
Fix Table complete mode loading state for data prop variant
2026-03-17 09:50:48 +00:00
James Brooks 05594087b9 Add virtualized prop to Table component (#33246)
Adding a new virtualized prop to the Table component to better support rendering large numbers of rows
2026-03-17 08:31:43 +00:00
Jonathan Roebuck d06dd51393 Fix effect firing default getData for data prop variant
The effect was calling the default getData = () => [] even when the
consumer used the data prop, immediately clearing the loading state.
Now detects whether getData was explicitly provided and only runs the
async loading logic for that case. Also clears isLoading when data
transitions from undefined to defined.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>
2026-03-17 08:16:50 +00:00
Charles de Dreuille 5096efc276 Merge pull request #33378 from backstage/fix/table-complete-mode-loading
Fix Table loading skeleton not showing for complete mode with getData
2026-03-17 07:18:44 +00:00
Charles de Dreuille 57726bf1c2 Merge pull request #33363 from shivamtiwari3/fix/table-replace-removed-bui-bg-tint-tokens
Fix: replace removed --bui-bg-tint tokens in Table component (fixes #33292)
2026-03-17 07:16:14 +00:00
Patrik Oldsberg 22f101e208 Merge pull request #33368 from backstage/rugvip/add-frontend-dev-utils
frontend-dev-utils: add helper for plugin dev apps
2026-03-16 21:32:15 +01:00
Patrik Oldsberg 1f25382e56 Move table cell requirement docs to docs-ui
Move the cell wrapper requirement documentation from the package
README to the docs-ui table component page where it belongs.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-03-16 20:27:02 +01:00
Patrik Oldsberg 872dc1025e ui: document table cell wrapper requirement
Added TSDoc comments to ColumnConfig.cell, RowRenderFn, CellProps,
CellTextProps, and CellProfileProps making it explicit that cell render
functions must return a cell component (Cell, CellText, or CellProfile)
as the top-level element. Also added a Table Cell Requirement section
to the package README with correct and incorrect usage examples.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-03-16 20:16:25 +01:00
Jonathan Roebuck 9314ff5162 Fix Table loading skeleton not showing for complete mode with getData
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>
2026-03-16 18:06:19 +00:00
Johan Persson 42f8c9b2b8 feat(ui): centralize routing in BUIProvider (#33267)
* feat(ui): centralize routing in BUIProvider

BUIProvider now auto-detects React Router context and provides
client-side navigation for all BUI components. Retired
InternalLinkProvider and added BUIRouterProvider as a public
export for integration use.

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(plugin-app): move BUIProvider inside app router

Moved BUIProvider from wrapping AppRouter to being a child inside
it, so it detects the React Router context and provides client-side
routing for all BUI components.

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(core-app-api): add BUIRouterProvider to legacy app router

Added BUIRouterProvider inside the legacy AppRouter to provide
React Aria routing for all BUI components.

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* docs(ui): update BUIProvider documentation for routing

Updated installation docs to cover BUIProvider's routing role
and the requirement to render it inside a React Router context.

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* refactor(ui): move BUIProvider from analytics to provider directory

BUIProvider now handles both analytics and routing, so it no longer
belongs in the analytics directory.

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* fix(ui): add BUIProvider to storybook stories with MemoryRouter

Added BUIProvider inside MemoryRouter in all stories that use
routing, so client-side navigation works in Storybook.

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* fix(plugin-app): move BUIProvider inside RouterComponent

Moved BUIProvider to wrap all content inside RouterComponent
so that extraElements (like dialogs) also get BUI context.

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* refactor: replace BUIRouterProvider with BUIProvider in legacy app

Use BUIProvider directly inside the legacy AppRouter instead of a
separate BUIRouterProvider export. Removes BUIRouterProvider from
the public API of @backstage/ui.

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* refactor(ui): inline routing logic into BUIProvider

Removed the routing/ directory and inlined the RouterProvider
setup directly into BUIProvider since it's the only consumer.

Signed-off-by: Johan Persson <johanopersson@gmail.com>

---------

Signed-off-by: Johan Persson <johanopersson@gmail.com>
2026-03-16 18:56:24 +01:00
Patrik Oldsberg 2e5c65120a Fix PluginHeader ResizeObserver loop
Defer header height updates to avoid ResizeObserver loop warnings in FullPage layouts and normalize header actions before rendering.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-03-16 16:10:28 +01:00
Charles de Dreuille 2f581de6ba Fixed keyboard navigation
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-16 14:51:49 +00:00
Johan Persson d9d2dd6827 feat(ui): add SearchAutocomplete component
Add SearchAutocomplete and SearchAutocompleteItem components for
building accessible search-with-results patterns. Built on React
Aria's Autocomplete with virtual focus for keyboard navigation
and a non-modal popover for results.

Features:
- Controlled input via inputValue/onInputChange
- Configurable popover width and placement
- Rich content support per result item
- Item selection via onAction
- defaultOpen prop for visual testing
- Close on interact outside and input clear

Includes Storybook stories, docs-ui documentation, changeset,
and API report.

Signed-off-by: Johan Persson <johanopersson@gmail.com>
2026-03-16 15:41:58 +01:00
Charles de Dreuille 985788ff6d Move to GridList
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-16 12:05:48 +00:00
Charles de Dreuille fd1854e3bc Merge pull request #33322 from backstage/jonathanroebuck/bucks-2919-fe-reusable-skeletonloading-state-for-bui-table-components
feat(ui): replace Table loading text with skeleton rows
2026-03-16 11:12:29 +00:00
Charles de Dreuille fdcec89a1a Merge pull request #33354 from backstage/charlesdedreuille/bacui-249-fix-container-bottom-margin-clash-in-bui-oss
fix(ui): fix Container bottom margin clash in Header
2026-03-16 10:28:57 +00:00
Charles de Dreuille d32708ef71 Merge pull request #33353 from backstage/charlesdedreuille/bacui-272-fix-table-row-external-href
fix(ui): open external Table row hrefs in a new tab
2026-03-16 10:16:18 +00:00
Charles de Dreuille af4610d138 Fix types
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-16 09:52:45 +00:00
Charles de Dreuille 0b0e642d88 Update types.ts
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-16 09:44:25 +00:00
shivamtiwari3 bc42b608b1 Fix: replace removed --bui-bg-tint tokens in Table component (fixes #33292)
Root cause: The --bui-bg-tint-* CSS tokens were removed from the design system
in favour of --bui-bg-neutral-* tokens, but Table.module.css was not updated
during the migration, leaving row hover, selected, pressed, and disabled states
with no visual effect.

Fix: Replace --bui-bg-tint-hover/pressed/disabled with the equivalent
--bui-bg-neutral-1-hover/pressed/disabled tokens, matching the migration
mapping documented in the CHANGELOG.

Signed-off-by: shivamtiwari3 <33183708+shivamtiwari3@users.noreply.github.com>
2026-03-16 10:41:06 +05:30
Charles de Dreuille b2110c19c6 Update CardsWithListBox.stories.tsx
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-15 19:10:58 +00:00
Charles de Dreuille 668639722c Cleanups
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-15 08:39:46 +00:00
Charles de Dreuille 9ee2931cc8 Improve styles
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-15 08:32:41 +00:00
Charles de Dreuille 2b1bb9ca3e feat(ui): add customActions prop to ListBoxItem
Adds a `customActions` prop that renders a flex row of React nodes on
the right side of a list item. Click and keyboard events on the actions
area are stopped from propagating to the item's selection handler.

Adds two new stories:
- WithActionsMenu: ButtonIcon (ellipsis) triggering a dropdown Menu
- WithActionsTags: inline TagGroup showing metadata tags per item

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
2026-03-14 18:17:03 +00:00
Charles de Dreuille b7b1b86d8a fix(ui): update ListBox item check and icon design
- Check icon is now only rendered when the item is selected, so it
  takes no space when unselected and pushes content in when selected
- Icon slot is now a fixed 32x32px box to consistently frame any
  React icon component (e.g. from Remix icons)

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
2026-03-14 18:11:39 +00:00
Charles de Dreuille 04d9d8df40 feat(ui): add ListBox and ListBoxItem components
Adds standalone `ListBox` and `ListBoxItem` components to `@backstage/ui`,
built on top of React Aria's ListBox primitives. Items support icons,
descriptions, and single or multiple selection modes.

Includes Storybook stories and docs-ui documentation page.

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
2026-03-14 14:37:33 +00:00
Charles de Dreuille 0733b76b75 Update Row.tsx
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-14 10:44:22 +00:00
Charles de Dreuille 421641b0f5 Update Header.module.css
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-14 10:41:32 +00:00
Charles de Dreuille 612c217c1f fix(ui): open external Table row hrefs in a new tab
Automatically apply `target="_blank"` and `rel="noopener noreferrer"` on
`Row` when `href` is an external link, so external links in default BUI
Table rows open in a new tab instead of navigating the current page.

`rel` tokens are merged rather than replaced, so consumer-provided tokens
(e.g. `rel="nofollow"`) are preserved while `noopener noreferrer` is
always enforced whenever `target="_blank"` is in effect.

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-14 10:37:13 +00:00
Charles de Dreuille 4ebcde9826 Update Header.tsx
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-14 10:31:24 +00:00
Charles de Dreuille 17d6398e22 fix(ui): fix Container bottom margin clash in Header
- Changed Container default bottom spacing from padding-bottom to margin-bottom
- Prevented the Container margin-bottom from applying when used as the Header root element via mb="0"
- Renamed Header CSS classes from bui-HeaderPage* to bui-Header* to match the component name

Fixes https://linear.app/spotify/issue/BACUI-249

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
2026-03-14 10:22:13 +00:00
Charles de Dreuille b99f6d5a93 fix(ui): fix Dialog content overflowing when no height prop is set
Replaces the invalid `min(auto, calc(100vh - 3rem))` CSS pattern with a
flex-based layout. The dialog now grows with its content by default and
scrolls when the content exceeds the viewport height. A fixed height can
still be applied via the `height` prop.

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
2026-03-14 07:20:04 +00:00
Jonathan Roebuck 3ace9c54db feat(ui): add separate loading prop to TableRoot
Use spread for conditional selection props. Add a dedicated loading
prop and data-loading data attribute to TableRoot, distinct from
stale. Both set aria-busy and default to the same opacity, but
consumers can now style them independently.

Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>
2026-03-13 18:29:27 +00:00
Jonathan Roebuck a688c806bc refactor(ui): consolidate live region label logic
Move initial loading label into useLiveRegionLabel so all live
region logic is in one place.

Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>
2026-03-13 18:29:27 +00:00
Jonathan Roebuck ddf90ae1fe chore(ui): remove Table tests and test setup
Removed per reviewer feedback — BUI Table relies on Storybook visual
tests rather than unit tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>
2026-03-13 18:29:26 +00:00
Jonathan Roebuck 6f56a0c0b0 fix(ui): address review feedback for Table skeleton loading
- Add @testing-library/jest-dom and @testing-library/react as explicit
  devDependencies for @backstage/ui
- Disable selection on TableRoot during initial loading to prevent
  interaction with skeleton rows
- Clarify test comment about aria-busy vs data-stale behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>
2026-03-13 18:29:26 +00:00
Jonathan Roebuck 690786f84d feat(ui): replace Table loading text with skeleton rows
Add a skeleton loading state to the BUI Table component that shows the
table header with animated skeleton rows instead of plain "Loading..."
text. Includes accessibility support via aria-busy and live region
announcements.

BUCKS-2919

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>
2026-03-13 18:29:25 +00:00
Charles de Dreuille fcaac3b8bd Fix Card onPress event
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-13 17:07:52 +00:00
Charles de Dreuille 27c2c24a1a Add migration notes
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-12 16:27:40 +00:00
Charles de Dreuille 9d5f3baf1e Update styles and types on Checkbox
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
2026-03-12 16:11:56 +00:00
Fredrik Adelöw a41eff026f Merge pull request #33251 from backstage/renovate/globals-17.x
chore(deps): update dependency globals to v17
2026-03-12 10:25:46 +01:00
github-actions[bot] ed7c4e3bef Version Packages (next) 2026-03-10 17:34:12 +00:00
Johan Persson d4d52fb13c fix(ui): ensure disabled rows override pointer cursor
Move the disabled rule after the pointer cursor rules so that
disabled rows always show cursor: not-allowed, even when they
have data-href or data-selection-mode.

Signed-off-by: Johan Persson <johanopersson@gmail.com>
2026-03-10 17:00:38 +01:00
Johan Persson f42f4cc055 fix(ui): truncate Table column headers with ellipsis on overflow
Wrap column header text in a label span with text-overflow: ellipsis
so that long headers truncate instead of wrapping to multiple lines.

Signed-off-by: Johan Persson <johanopersson@gmail.com>
2026-03-10 17:00:38 +01:00
Johan Persson fbd5c5a93d fix(ui): only show pointer cursor on interactive Table rows
Row always passed onAction to React Aria even when no handler or
href was set, causing all rows to appear interactive. Now onAction
is only passed when there is an actual interaction. CSS explicitly
sets cursor: default on rows and scopes cursor: pointer to rows
with href, selection mode, or pressable state.

Signed-off-by: Johan Persson <johanopersson@gmail.com>
2026-03-10 17:00:38 +01:00
renovate[bot] 9599697048 chore(deps): update dependency globals to v17
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-10 03:44:26 +00:00
renovate[bot] b4e14b6f89 chore(deps): update dependency react-aria-components to v1.16.0 (#32783)
* chore(deps): update dependency react-aria-components to v1.16.0

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* fix(ui): fix selectedKey type mismatch in Tabs component

Change `selectedId` initialization from `null` to `undefined` to
match React Aria's `selectedKey` prop type (`Key | undefined`).

Signed-off-by: Johan Persson <johanopersson@gmail.com>

---------

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Johan Persson <johanopersson@gmail.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Johan Persson <johanopersson@gmail.com>
2026-03-09 15:50:29 +00:00
Patrik Oldsberg ad7c883dee Deprecate HeaderPage in favor of Header in @backstage/ui (#33188)
* Deprecate HeaderPage in favor of Header in @backstage/ui

Rename the HeaderPage component to Header, keeping HeaderPage as a
deprecated alias for backwards compatibility. Also deprecate
HeaderPageProps, HeaderPageOwnProps, HeaderPageBreadcrumb, and
HeaderPageDefinition with new Header* equivalents. Update all internal
usages, stories, and docs-ui documentation to use the new names.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor

* Rename HeaderPage files and directories to Header

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor

* Add changeset for mui-to-bui Header rename

Document the plugin release impact of switching the MUI to BUI theme converter page to the renamed Header component.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor

---------

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
2026-03-09 11:52:19 +01:00
Johan Persson 12d8afe82d feat(ui): add analytics event tracking to BUI navigation components (#33150)
* feat(ui): add analytics types

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(ui): add useAnalytics hook with dev-mode swap guard

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(ui): add AnalyticsProvider, getNodeText, and analytics barrel exports

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(ui): integrate analytics into defineComponent and useDefinition

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(ui): add analytics tracking to Link component

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(ui): add analytics tracking to ButtonLink component

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(ui): add analytics tracking to Tab component

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(ui): add analytics tracking to MenuItem component

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(ui): add analytics tracking to Tag component

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(ui): add analytics tracking to Table Row component

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(ui): widen getNodeText to accept render functions

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* chore(ui): update API reports

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* chore: add changeset for BUI analytics

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* fix(ui): chain MenuItem onAction with user-provided handler instead of overwriting

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* chore(ui): address review feedback — changeset wording and types docs

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(core-app-api): wire AnalyticsProvider from @backstage/ui into app shell

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(plugin-app): add AnalyticsProvider wrapper extension for BUI components

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* chore: update API reports

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* chore: update API reports for core-components and scaffolder

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* docs(ui): add analytics documentation and noTrack prop to component docs

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* chore: update yarn.lock

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* feat(plugin-app): move AnalyticsProvider into AppRoot directly

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* chore: format installation docs

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* fix(ui): call user onPress before analytics in Tag component

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* refactor(ui): replace AnalyticsProvider with generic BUIProvider

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* chore: replace remaining AnalyticsProvider references with BUIProvider

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* fix(plugin-app): import useAnalytics from frontend-plugin-api

Signed-off-by: Johan Persson <johanopersson@gmail.com>

* docs(ui): improve noTrack prop description

Signed-off-by: Johan Persson <johanopersson@gmail.com>

---------

Signed-off-by: Johan Persson <johanopersson@gmail.com>
2026-03-06 14:45:57 +01:00