Skip to content

ui: Alerts page#5031

Draft
sysadmind wants to merge 6 commits intoprometheus:mainfrom
sysadmind:alerts-page
Draft

ui: Alerts page#5031
sysadmind wants to merge 6 commits intoprometheus:mainfrom
sysadmind:alerts-page

Conversation

@sysadmind
Copy link
Copy Markdown
Contributor

@sysadmind sysadmind commented Feb 21, 2026

Builds out the new alerts page in the mantine-ui.

Includes some additional components to support rendering the alerts and groups. This should make the new UI actually useful for something.

image

Reviewer note: I tried to break up commits for this PR. The Accordion is just a copy of the Prometheus Accordion which will be unnecessary in Mantine v9

Pull Request Checklist

Please check all the applicable boxes.

  • Is this a new feature?
    • I have added tests that test the new feature's functionality
  • Is this a breaking change?
    • My changes do not break the existing cluster messages
    • My changes do not break the existing api
  • I have added/updated the required documentation
  • I have signed-off my commits
  • I will follow best practices for contributing to this project

Which user-facing changes does this PR introduce?

[FEATURE] UIv2: Add alerts to the alerts page

Summary by CodeRabbit

  • New Features

    • Added a full Accordion component family, alert filtering UI with label pills, label badges, and an alert group list view.
    • Introduced UTC-aware time utilities for parsing/formatting durations and timestamps.
  • Tests

    • Added unit tests for duration parsing and formatting.
  • Documentation

    • Added a brief README describing the temporary accordion behavior.
  • Dependencies

    • Added runtime dependencies for icons and datetime handling.

This is a more performant version of the upstream component. It will not be necessary as of Mantine v9.

Signed-off-by: Joe Adams <github@joeadams.io>
The LabelBadges component is a pill shaped box that represents a label and value formatted label="value" and has an optional add callback to render a plus icon

The LabelPill component is just a wrapper around the Mantine Pill component with some styles and label formatting in the form label="value"

Signed-off-by: Joe Adams <github@joeadams.io>
Add AlertGroup component to show the list of Alerts in groups provided by the API. The Alert page includes options for showing silenced or inhibited alerts as well as label filters. Adds types around the useGroups data component.

Signed-off-by: Joe Adams <github@joeadams.io>
Signed-off-by: Joe Adams <github@joeadams.io>
Signed-off-by: Joe Adams <github@joeadams.io>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 24, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b7ecdd3d-7a7d-4f4e-bdfb-42cae0e8f0cb

📥 Commits

Reviewing files that changed from the base of the PR and between ba2419f and 36a9fd9.

📒 Files selected for processing (3)
  • ui/mantine-ui/src/lib/time.test.ts
  • ui/mantine-ui/src/pages/Alerts.page.tsx
  • ui/mantine-ui/test-utils/render.tsx
✅ Files skipped from review due to trivial changes (1)
  • ui/mantine-ui/src/lib/time.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • ui/mantine-ui/test-utils/render.tsx
  • ui/mantine-ui/src/pages/Alerts.page.tsx

📝 Walkthrough

Walkthrough

Adds a new Accordion component system with contexts and styles, Day.js-based time utilities and tests, label UI primitives (badges/pills), an alerts grouping UI wired to a refactored groups data hook, test react-query support, and two new runtime dependencies.

Changes

Cohort / File(s) Summary
Accordion component family
ui/mantine-ui/src/components/Accordion/Accordion.tsx, ui/mantine-ui/src/components/Accordion/Accordion.context.ts, ui/mantine-ui/src/components/Accordion/Accordion.types.ts, ui/mantine-ui/src/components/Accordion/Accordion.module.css, ui/mantine-ui/src/components/Accordion/AccordionChevron.tsx, ui/mantine-ui/src/components/Accordion/AccordionControl/AccordionControl.tsx, ui/mantine-ui/src/components/Accordion/AccordionItem/..., ui/mantine-ui/src/components/Accordion/AccordionPanel/..., ui/mantine-ui/src/components/Accordion/index.ts, ui/mantine-ui/src/components/Accordion/README-PROMETHEUS.md
New, full Accordion implementation (components, contexts, types, CSS). Supports controlled/uncontrolled modes, keyboard navigation, chevron positioning/rotation, multiple variants, and unmounting collapsed panel children (Prometheus-specific note).
Label UI
ui/mantine-ui/src/components/LabelBadges.tsx, ui/mantine-ui/src/components/LabelBadges.module.css, ui/mantine-ui/src/components/LabelPill.tsx, ui/mantine-ui/src/components/LabelPill.module.css
New LabelBadges and LabelPill components + styles for rendering label key/value badges and removable pills with optional callbacks and keyboard accessibility.
Alert grouping UI
ui/mantine-ui/src/components/AlertGroupList.tsx, ui/mantine-ui/src/pages/Alerts.page.tsx
New AlertGroupList component rendering grouped alerts inside the Accordion; Alerts page updated to an interactive filtering UI with label filter input, pills, and silenced/inhibited toggles wired to useGroups.
Time utilities & tests
ui/mantine-ui/src/lib/time.ts, ui/mantine-ui/src/lib/time.test.ts
Adds Day.js setup (utc, duration, relativeTime) and utilities: UTC now, ISO8601 parsing, parseDuration, formatDurationMs; includes comprehensive parsing/formatting tests.
Data hook changes
ui/mantine-ui/src/data/groups.ts
Refactors useGroups from suspense to standard query (useAPIQuery), adds optional useGroupParams (silenced/inhibited/filter), converts internal types to exported types (Group, Receiver, AlertStatus, Alert).
Test utils
ui/mantine-ui/test-utils/render.tsx
Test render helper now wraps UI with a React Query QueryClientProvider using a test QueryClient (no retries).
Dependencies
ui/mantine-ui/package.json
Added runtime dependencies: @tabler/icons-react and dayjs.
sequenceDiagram
  participant Page as AlertsPage
  participant Hook as useGroups
  participant UI as AlertGroupList
  participant Accordion as Accordion (Context + Items)
  participant Time as time.ts
  Page->>Hook: call useGroups(filterParams)
  Hook-->>Page: returns groups data
  Page->>UI: render AlertGroupList(groups)
  UI->>Accordion: render Accordion with items
  Accordion->>Accordion: manage active state (context)
  Accordion->>Time: format endsAt with parseISO8601/fromNow
  Note over Page,Accordion: user interacts (add/remove filters, toggle switches) -> re-call useGroups
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through code and found a fold,

panels hide where secrets are told.
Badges gleam and timestamps chime,
filters dance in perfect time.
A tiny hop for UI kind—accordion pockets for the mind.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title "ui: Alerts page" is concise and directly describes the main change—building out a new alerts page in the mantine-ui. It follows the specified format and clearly summarizes the primary objective.
Description check ✅ Passed The PR description includes a clear explanation of the changes, provides context about the Accordion being a temporary fork, includes a screenshot demonstrating the feature, and documents the release notes. However, it does not explicitly list linked issues or provide detailed testing information as suggested by the template.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (8)
ui/mantine-ui/src/components/Accordion/README-PROMETHEUS.md (1)

5-7: Use a durable public reference for the fork rationale.

Line 6 points to a Discord thread, which is often inaccessible to contributors and can rot. Please prefer a public Mantine issue/changelog/release note URL so future cleanup is verifiable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/mantine-ui/src/components/Accordion/README-PROMETHEUS.md` around lines 5 -
7, Replace the ephemeral Discord thread reference in the sentence starting
"According to Mantine author Vitaly..." with a durable public Mantine URL
(issue, changelog, or release notes) that documents the feature backport to
Mantine 9.0.0; update the README-PROMETHEUS.md text to quote or link that public
URL (or an archived permalink) so the rationale is verifiable and won’t rot.
ui/mantine-ui/src/components/AlertGroupList.tsx (2)

44-46: Avoid duplicate parseISO8601 calls.

parseISO8601(alert.endsAt) is called twice—once for the tooltip label and once for the relative time. This parses the same ISO string twice unnecessarily.

Proposed fix
+                  <Table.Tr>
+                    <Table.Td w="15%">Ends</Table.Td>
+                    <Table.Td>
+                      {(() => {
+                        const endsAt = parseISO8601(alert.endsAt);
+                        return (
+                          <Tooltip label={endsAt.format()}>
+                            <Box>{endsAt.fromNow()}</Box>
+                          </Tooltip>
+                        );
+                      })()}
+                    </Table.Td>
+                  </Table.Tr>
-                  <Table.Tr>
-                    <Table.Td w="15%">Ends</Table.Td>
-                    <Table.Td>
-                      <Tooltip label={parseISO8601(alert.endsAt).format()}>
-                        <Box>{parseISO8601(alert.endsAt).fromNow()}</Box>
-                      </Tooltip>
-                    </Table.Td>
-                  </Table.Tr>

Alternatively, extract it into a small inner component or compute it once per alert in the map callback.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/mantine-ui/src/components/AlertGroupList.tsx` around lines 44 - 46,
Compute parseISO8601(alert.endsAt) once and reuse it instead of calling it
twice; inside the map callback in AlertGroupList (where Tooltip and Box are
rendered) assign the result to a local const (e.g., endsAtDate) and pass
endsAtDate.format() to Tooltip and endsAtDate.fromNow() to Box (or extract into
a small inner component that accepts the parsed date) so you avoid duplicate
parsing and improve performance.

13-14: Consider using stable keys instead of array indices.

Using array indices as keys (key={i}, key={j}) can cause React reconciliation issues if items are reordered, inserted, or removed. If the API provides unique identifiers for groups or alerts (e.g., alert.fingerprint or similar), prefer using those.

Also applies to: 29-30

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/mantine-ui/src/components/AlertGroupList.tsx` around lines 13 - 14,
Replace the unstable array-index keys in AlertGroupList.tsx (the groups?.map
rendering Card with key={i} and the nested alerts.map with key={j}) with stable
unique identifiers from the data model (e.g., use group.id, group.groupId, or
another unique group property for the Card key, and use alert.fingerprint or
alert.id for each alert key); update the JSX in the AlertGroupList component to
reference those unique fields instead of i/j so React can reconcile items
correctly when reordering or mutating the lists.
ui/mantine-ui/src/components/LabelPill.tsx (1)

11-23: Consider making the remove button conditional on onRemove prop.

The remove button is always rendered (withRemoveButton is hardcoded to true), but onRemove is optional. If onRemove is not provided, the button appears but does nothing when clicked.

Proposed fix
     <Pill
       className={classes.label}
       classNames={{ remove: classes.remove }}
       size="lg"
-      withRemoveButton
+      withRemoveButton={!!onRemove}
       onRemove={onRemove}
       {...others}
     >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/mantine-ui/src/components/LabelPill.tsx` around lines 11 - 23, The
LabelPill component currently always shows the remove button by passing
withRemoveButton unconditionally; make the remove button conditional by only
setting withRemoveButton when onRemove is provided. Update the LabelPill
function (component) to compute or pass withRemoveButton={Boolean(onRemove)} (or
omit the prop when onRemove is undefined) and ensure onRemove is still forwarded
to the underlying Pill so clicks work when present; reference LabelPill, the
onRemove prop, and the Pill component/classNames props when making the change.
ui/mantine-ui/src/pages/Alerts.page.tsx (1)

157-157: Consider adding loading and error state feedback.

Currently, when isLoading is true or error exists, nothing is displayed. Users won't know if data is loading or if an error occurred.

Suggested improvement
+import { ActionIcon, Alert, Group, Loader, Stack, Switch, TextInput } from '@mantine/core';
-import { ActionIcon, Group, Stack, Switch, TextInput } from '@mantine/core';
...
-      {!isLoading && !error && groupList}
+      {isLoading && <Loader />}
+      {error && <Alert color="red" title="Error">{error.message || 'Failed to load alerts'}</Alert>}
+      {!isLoading && !error && groupList}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/mantine-ui/src/pages/Alerts.page.tsx` at line 157, The UI currently
renders nothing when isLoading is true or error is present for the Alerts page;
update the render logic around the existing {!isLoading && !error && groupList}
to show explicit feedback: when isLoading is true render a loading indicator
(e.g., Mantine Loader or "Loading..." text) and when error exists render a
user-friendly error message with optional retry action (e.g., a Retry button
that calls the same fetch or refresh function). Locate the conditional around
groupList in Alerts.page.tsx and replace the empty branches with appropriate
loading and error UI, reusing existing state variables isLoading, error and the
fetch/retry handler function.
ui/mantine-ui/src/components/Accordion/AccordionPanel/AccordionPanel.tsx (2)

46-50: Unused onTransitionEnd prop declared in interface.

The onTransitionEnd prop is defined in the interface but never used in the component implementation. Either remove it from the interface or wire it to the Collapse component's onTransitionEnd handler.

🔧 Option 1: Remove unused prop
 export interface AccordionPanelProps
   extends BoxProps, CompoundStylesApiProps<AccordionPanelFactory>, ElementProps<'div'> {
-  /** Called when the panel animation completes */
-  onTransitionEnd?: () => void;
 }
🔧 Option 2: Wire the prop to Collapse
   const { classNames, className, style, styles, vars, children, ...others } = useProps(
+  const { classNames, className, style, styles, vars, children, onTransitionEnd, ...others } = useProps(
     'AccordionPanel',
     null,
     props
   );

Then pass it to <Collapse onTransitionEnd={onTransitionEnd} ...>.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/mantine-ui/src/components/Accordion/AccordionPanel/AccordionPanel.tsx`
around lines 46 - 50, The interface AccordionPanelProps declares an unused
onTransitionEnd prop; fix by wiring it through the AccordionPanel component to
the Collapse component (pass onTransitionEnd to <Collapse
onTransitionEnd={onTransitionEnd} ...>) so the handler is invoked when the panel
animation completes, or if you prefer to remove the unused API, delete
onTransitionEnd from AccordionPanelProps and any related exports; locate
AccordionPanelProps and the AccordionPanel component (and the nested Collapse
usage) to apply the change.

75-85: Hardcoded 200ms timeout may desync from custom transitionDuration.

The timeout for unmounting children is hardcoded to 200ms, but ctx.transitionDuration can be customized. If a longer transition duration is configured, children will unmount before the animation completes.

Consider using the context's transition duration:

♻️ Proposed fix
   useEffect(() => {
     let timeout: ReturnType<typeof setTimeout>;
+    const duration = ctx.transitionDuration ?? 200;

     if (isActive) {
       setShowChildren(true);
     } else {
-      timeout = setTimeout(() => setShowChildren(false), 200);
+      timeout = setTimeout(() => setShowChildren(false), duration);
     }

     return () => clearTimeout(timeout);
-  }, [isActive]);
+  }, [isActive, ctx.transitionDuration]);

Also applies to: 93-93

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/mantine-ui/src/components/Accordion/AccordionPanel/AccordionPanel.tsx`
around lines 75 - 85, The unmount delay is hardcoded to 200ms and can desync
from customized durations; update the unmount timeout to use the context
transition duration (ctx.transitionDuration) wherever the 200ms literal is used
(inside the useEffect controlling setShowChildren when isActive changes and the
similar occurrence around the other block at ~93), e.g., derive the timeout
value from ctx.transitionDuration (fallback to a sensible default if undefined),
store it in the same timeout variable, and ensure clearTimeout(timeout) still
correctly clears that timer in the cleanup.
ui/mantine-ui/src/lib/time.ts (1)

20-26: parseISO8601 and parseTime are functionally identical.

Both functions call dayjs.utc(value). Consider removing one or documenting the semantic difference if intended.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/mantine-ui/src/lib/time.ts` around lines 20 - 26, parseISO8601 and
parseTime are duplicates; either remove the redundant function or
implement/document a distinct semantic for parseTime. Fix by choosing one
approach: 1) Remove parseTime and update all callers to use parseISO8601 (keep
dayjs.utc(value) in parseISO8601), or 2) Give parseTime a clear different
behavior (e.g., parse time-only strings with a specific format/assume local date
or attach today's date) and update its implementation and JSDoc accordingly.
Reference the functions parseISO8601 and parseTime when making the change so
callers and tests can be updated consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/mantine-ui/src/components/Accordion/Accordion.tsx`:
- Around line 89-90: The JSDoc says the Accordion prop "loop" defaults to true
but Accordion.defaultProps does not set it, so add loop: true to the Accordion
component's defaultProps (update the defaultProps object defined for Accordion)
to ensure runtime behavior matches the documentation; also scan the nearby
documented props block (the JSDoc block around lines 125-132) and add any other
props that declare `@default` to Accordion.defaultProps so documented defaults and
runtime defaults stay in sync.

In `@ui/mantine-ui/src/data/groups.ts`:
- Around line 38-40: The current construction of filterEntries uses raw
interpolation of params.filter values which can break matcher strings if values
contain quotes or backslashes; update the map for filterEntries to escape
problematic characters (at minimum backslashes and both single/double quotes)
before embedding value into the `${key}="${value}"` string so the resulting
matcher is syntactically valid. Locate the filterEntries creation (uses
params?.filter and Object.entries(params.filter)) and replace the direct
interpolation with a sanitizedValue computed from value by escaping backslashes
and quotes (or use a safe serializer) and then build the matcher as
`${key}="${sanitizedValue}"`. Ensure this change handles undefined/null values
consistently and preserves existing behavior when values contain no special
characters.

In `@ui/mantine-ui/src/lib/time.ts`:
- Around line 33-39: The duration regex (durationRE) fails for millisecond-only
strings like "100ms" because the minute group (?<min>[0-9]+)m appears before
(?<ms>[0-9]+)ms and greedily consumes the "m"; update the durationRE declaration
in the time parsing code to either place the ms pattern before the min pattern
(move ((?<ms>[0-9]+)ms)? to appear before ((?<min>[0-9]+)m)?), or change the
minutes group to use a negative lookahead like (?<min>[0-9]+)m(?!s) so "ms" is
correctly parsed, ensuring the rest of the matching logic using matches and
matches.groups remains unchanged.

In `@ui/mantine-ui/src/pages/Alerts.page.tsx`:
- Around line 28-33: The memoized groupList currently has a stale closure and
inconsistent return types: wrap handleSubAdd in useCallback (e.g., const
handleSubAdd = useCallback(..., [...relevant deps...])) so it is stable, then
update the useMemo to consistently return a JSX element or null (not an array)
and include handleSubAdd and data in the dependency array (e.g., useMemo(() =>
data ? <AlertGroupList groups={data} addCallback={handleSubAdd} /> : null,
[data, handleSubAdd])). Ensure the referenced symbols are handleSubAdd,
useMemo/groupList, and AlertGroupList.

In `@ui/mantine-ui/test-utils/render.tsx`:
- Around line 6-12: Move the module-level QueryClient creation into a factory
function (e.g., createTestQueryClient) so each test gets a fresh instance;
replace the existing const queryClient = new QueryClient(...) with a function
that returns new QueryClient({ defaultOptions: { queries: { retry: false } } })
and update any callers in this file (such as the render wrapper or
renderWithProviders) to call createTestQueryClient() per-render instead of using
the shared queryClient variable to avoid shared cache/observers between tests.

---

Nitpick comments:
In `@ui/mantine-ui/src/components/Accordion/AccordionPanel/AccordionPanel.tsx`:
- Around line 46-50: The interface AccordionPanelProps declares an unused
onTransitionEnd prop; fix by wiring it through the AccordionPanel component to
the Collapse component (pass onTransitionEnd to <Collapse
onTransitionEnd={onTransitionEnd} ...>) so the handler is invoked when the panel
animation completes, or if you prefer to remove the unused API, delete
onTransitionEnd from AccordionPanelProps and any related exports; locate
AccordionPanelProps and the AccordionPanel component (and the nested Collapse
usage) to apply the change.
- Around line 75-85: The unmount delay is hardcoded to 200ms and can desync from
customized durations; update the unmount timeout to use the context transition
duration (ctx.transitionDuration) wherever the 200ms literal is used (inside the
useEffect controlling setShowChildren when isActive changes and the similar
occurrence around the other block at ~93), e.g., derive the timeout value from
ctx.transitionDuration (fallback to a sensible default if undefined), store it
in the same timeout variable, and ensure clearTimeout(timeout) still correctly
clears that timer in the cleanup.

In `@ui/mantine-ui/src/components/Accordion/README-PROMETHEUS.md`:
- Around line 5-7: Replace the ephemeral Discord thread reference in the
sentence starting "According to Mantine author Vitaly..." with a durable public
Mantine URL (issue, changelog, or release notes) that documents the feature
backport to Mantine 9.0.0; update the README-PROMETHEUS.md text to quote or link
that public URL (or an archived permalink) so the rationale is verifiable and
won’t rot.

In `@ui/mantine-ui/src/components/AlertGroupList.tsx`:
- Around line 44-46: Compute parseISO8601(alert.endsAt) once and reuse it
instead of calling it twice; inside the map callback in AlertGroupList (where
Tooltip and Box are rendered) assign the result to a local const (e.g.,
endsAtDate) and pass endsAtDate.format() to Tooltip and endsAtDate.fromNow() to
Box (or extract into a small inner component that accepts the parsed date) so
you avoid duplicate parsing and improve performance.
- Around line 13-14: Replace the unstable array-index keys in AlertGroupList.tsx
(the groups?.map rendering Card with key={i} and the nested alerts.map with
key={j}) with stable unique identifiers from the data model (e.g., use group.id,
group.groupId, or another unique group property for the Card key, and use
alert.fingerprint or alert.id for each alert key); update the JSX in the
AlertGroupList component to reference those unique fields instead of i/j so
React can reconcile items correctly when reordering or mutating the lists.

In `@ui/mantine-ui/src/components/LabelPill.tsx`:
- Around line 11-23: The LabelPill component currently always shows the remove
button by passing withRemoveButton unconditionally; make the remove button
conditional by only setting withRemoveButton when onRemove is provided. Update
the LabelPill function (component) to compute or pass
withRemoveButton={Boolean(onRemove)} (or omit the prop when onRemove is
undefined) and ensure onRemove is still forwarded to the underlying Pill so
clicks work when present; reference LabelPill, the onRemove prop, and the Pill
component/classNames props when making the change.

In `@ui/mantine-ui/src/lib/time.ts`:
- Around line 20-26: parseISO8601 and parseTime are duplicates; either remove
the redundant function or implement/document a distinct semantic for parseTime.
Fix by choosing one approach: 1) Remove parseTime and update all callers to use
parseISO8601 (keep dayjs.utc(value) in parseISO8601), or 2) Give parseTime a
clear different behavior (e.g., parse time-only strings with a specific
format/assume local date or attach today's date) and update its implementation
and JSDoc accordingly. Reference the functions parseISO8601 and parseTime when
making the change so callers and tests can be updated consistently.

In `@ui/mantine-ui/src/pages/Alerts.page.tsx`:
- Line 157: The UI currently renders nothing when isLoading is true or error is
present for the Alerts page; update the render logic around the existing
{!isLoading && !error && groupList} to show explicit feedback: when isLoading is
true render a loading indicator (e.g., Mantine Loader or "Loading..." text) and
when error exists render a user-friendly error message with optional retry
action (e.g., a Retry button that calls the same fetch or refresh function).
Locate the conditional around groupList in Alerts.page.tsx and replace the empty
branches with appropriate loading and error UI, reusing existing state variables
isLoading, error and the fetch/retry handler function.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fd3f7372-3c16-4288-acf9-e8f708686ca2

📥 Commits

Reviewing files that changed from the base of the PR and between 7aa1b9f and ba2419f.

⛔ Files ignored due to path filters (1)
  • ui/mantine-ui/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (22)
  • ui/mantine-ui/package.json
  • ui/mantine-ui/src/components/Accordion/Accordion.context.ts
  • ui/mantine-ui/src/components/Accordion/Accordion.module.css
  • ui/mantine-ui/src/components/Accordion/Accordion.tsx
  • ui/mantine-ui/src/components/Accordion/Accordion.types.ts
  • ui/mantine-ui/src/components/Accordion/AccordionChevron.tsx
  • ui/mantine-ui/src/components/Accordion/AccordionControl/AccordionControl.tsx
  • ui/mantine-ui/src/components/Accordion/AccordionItem.context.ts
  • ui/mantine-ui/src/components/Accordion/AccordionItem/AccordionItem.tsx
  • ui/mantine-ui/src/components/Accordion/AccordionPanel/AccordionPanel.tsx
  • ui/mantine-ui/src/components/Accordion/README-PROMETHEUS.md
  • ui/mantine-ui/src/components/Accordion/index.ts
  • ui/mantine-ui/src/components/AlertGroupList.tsx
  • ui/mantine-ui/src/components/LabelBadges.module.css
  • ui/mantine-ui/src/components/LabelBadges.tsx
  • ui/mantine-ui/src/components/LabelPill.module.css
  • ui/mantine-ui/src/components/LabelPill.tsx
  • ui/mantine-ui/src/data/groups.ts
  • ui/mantine-ui/src/lib/time.test.ts
  • ui/mantine-ui/src/lib/time.ts
  • ui/mantine-ui/src/pages/Alerts.page.tsx
  • ui/mantine-ui/test-utils/render.tsx

Signed-off-by: Joe Adams <github@joeadams.io>
@sysadmind sysadmind marked this pull request as draft March 31, 2026 21:06
@sysadmind
Copy link
Copy Markdown
Contributor Author

Moving to draft. Mantine v9 was released, so we can pull the Accordion out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant