Route the EXISTS-based filters through final_entities (one row per
entity) instead of correlating against the search table directly.
This avoids the pathological case where correlated subqueries scan
the much larger search table for every row in the outer facets query.
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
- Add `href` to `HeaderMetadataUser`: avatar becomes a link and name renders as a primary `Link` with `standalone` (no underline at rest)
- Add `WithMetadataUsersNoLinks` story alongside `WithMetadataUsers` to cover both link and non-link variants
- Remove `strong`/`em` from ReactMarkdown `allowedElements` in Header description — only plain text and inline links are now supported
- Replace `<Container>` root with a plain `<div>` so the Header spans its full parent width
- Add `HeaderMetadataStatus` component and CSS (new files)
- Update docs: fixtures, snippets, props-definition, and page.mdx to reflect all changes
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
- Add HeaderMetadataUsers component: single user shows avatar + name,
multiple users show avatar stack with tooltip on hover
- Use Pressable from react-aria for tooltip trigger compatibility
- Switch tags and metadata text to body-medium variant
- Fix metadata item styling: secondary color label, no bold, no colon,
flex row with gap-2 between label and value
- Update Header gap to space-3
- Update docs with HeaderMetadataUsers example, correct prop types,
and synced default snippet
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
Add new props to the Header API reference and examples on ui.backstage.io.
Also adds deprecated badge support to the shared PropsTable component so
the breadcrumbs prop is visually marked as deprecated.
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
Add three new props to the Header component:
- `tags`: renders a row of text/link items above the title, separated by
3×3px circle dividers
- `description`: renders a markdown string below the title with inline
link support via react-markdown
- `metadata`: renders key-value pairs below the description with 20px gaps
Also deprecates the `breadcrumbs` prop for future removal.
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
- Add aria-label="Open calendar" and aria-hidden on icon for the calendar trigger button
- Add aria-hidden on nav button icons (React Aria provides built-in labels for prev/next slots)
- Update React Aria docs link to react-aria.adobe.com format
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
- Fixed size: 1.5rem (small), 2rem (medium) in rem units
- No padding, flex-centered icon
- Inset focus ring using 1px box-shadow with --bui-ring token
- Border radius bumped to radius-2
- Medium size padding-inline-end reduced to space-1
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
- Switch DateRangePicker to use the BUI Popover component (with hideArrow)
instead of the raw react-aria-components Popover
- Add WithUnavailableDates story showing isDateUnavailable with weekends
blocked and non-contiguous ranges disallowed (default behaviour)
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
Adds a new DateRangePicker component to @backstage/ui built on React Aria,
featuring a custom field group with two DateInput fields and a calendar
trigger, a RangeCalendar popover with proper range selection visuals
(solid circles for start/end, transparent solid fill for in-range cells
with row-boundary rounding), and full BUI token usage including bg
consumer auto-increment. Includes Storybook stories and a docs-ui page.
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
Update assertions to expect the entity presentation short ref (e.g.
'foo') instead of the old catalog-resolved display name (e.g.
'BackUser'), and remove now-unused entity fixtures and catalog API
mocking.
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Remove the catalog API lookup and manual title resolution. The
EntityRefLink already uses the entity presentation API to resolve
display names, so the component only needs the entity ref string.
This removes unused imports of useApi, useAsync, catalogApiRef,
parseEntityRef, and UserEntity.
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Node.js setTimeout uses a 32-bit signed integer for the delay, so
values larger than 2^31-1 ms (~24.8 days) cause the callback to fire
immediately. Fix by chunking the wait into segments of at most 2^30 ms.
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
React Aria's `CollectionBuilder` renders `TabList`'s children into both a
hidden collection-building tree and the real DOM. The hidden instance of
`TabsIndicators` sits outside the `TabListStateContext` provider, so its
`state` is `null` — causing its `updateCSSVariables` effect to hit the
`else` branch and write `--active-tab-opacity: 0` to the `tabsRef` DOM
element that the real instance also writes to. Under the right render
ordering, this hidden write lands after the real instance's `opacity: 1`
and makes the active indicator disappear on uncontrolled Tabs.
Guard `updateCSSVariables` with an early return when `state == null` so
the hidden instance never writes to the shared DOM element.
Signed-off-by: Johan Persson <johanopersson@gmail.com>