grafana/grafana
Reviewed against Rams quality heuristics: accessibility, color, typography, spacing, components, motion, UX, and craft.
30 files reviewed·August 1, 2026
Low
Design risk in this codebase.
More findings
Verdict
Loading states are an afterthought dressed up as a design pattern, blank boxes and null returns stand in for actual feedback. The biggest risk is trust erosion: users hit these gaps on ordinary transitions, not edge cases, and a stray console.log confirms the rush.
Files Rams reviewed
public/app/features/connections/pages/AddNewConnectionPage.tsx
public/app/features/connections/pages/CacheFeatureHighlightPage.tsx
public/app/features/connections/pages/ConnectionsHomePage.tsx
public/app/features/connections/pages/DataSourceDetailsPage.tsx
public/app/features/connections/pages/DataSourcesListPage.tsx
public/app/features/connections/pages/InsightsFeatureHighlightPage.tsx
public/app/features/connections/pages/NewDataSourcePage.tsx
public/app/features/connections/pages/PermissionsFeatureHighlightPage.tsx
public/app/features/dashboard-scene/pages/DashboardScenePage.tsx
public/app/features/dashboard-scene/pages/PublicDashboardScenePage.tsx
public/app/features/notebook/pages/NotebookScenePage.tsx
public/app/core/components/Login/LoginLayout.tsx
public/app/core/components/Login/LoginPage.tsx
public/app/core/components/NavLandingPage/NavLandingPage.tsx
public/app/core/components/Page/Page.tsx
public/app/core/components/Signup/SignupPage.tsx
public/app/features/alerting/unified/components/contact-points/TemplatesPage.tsx
public/app/features/alerting/unified/components/notification-policies/PolicyPage.tsx
public/app/features/alerting/unified/components/rule-viewer/RuleViewerLayout.tsx
public/app/features/alerting/unified/components/rules/central-state-history/CentralAlertHistoryPage.tsx
public/app/features/alerting/unified/components/rules/deleted-rules/DeletedRulesPage.tsx
public/app/features/alerting/unified/components/silences/SilenceViewPage.tsx
public/app/features/connections/components/FeatureHighlightsTabPage.tsx
public/app/features/datasources/components/DataSourceTabPage.tsx
public/app/features/explore/TraceView/components/scroll-page.tsx
public/app/features/plugins/admin/components/PluginDetailsPage.tsx
public/app/features/plugins/components/AppRootPage.tsx
public/app/features/connections/pages/DataSourceDashboardsPage.tsx
public/app/features/connections/pages/EditDataSourcePage.tsx
public/app/core/components/ForgottenPassword/ChangePasswordPage.tsx
Accessibility
public/app/features/dashboard-scene/pages/DashboardScenePage.tsx:144
Dashboard transition renders a blank page with no loading cue
In DashboardScenePage.tsx, when switching from one dashboard to another and `type !== 'snapshot'` with a mismatched `prevMatch`, the component logs 'skipping rendering' and returns `null`. There is no PageLoader, no spinner, no aria-live announcement during this window, just an unstyled blank viewport.
Why it matters
Users switching dashboards see the page go blank with no feedback that anything is happening, and screen reader users get no announcement of a state change, so a slow transition reads as a broken page rather than a load in progress.
Fix
Render a loading state (PageLoader inside the Page shell) instead of null during in-flight transitions.
if (type !== 'snapshot' && (!prevMatch || uid !== prevMatch?.params.uid)) {
console.log('skipping rendering');
return null;
}if (type !== 'snapshot' && (!prevMatch || uid !== prevMatch?.params.uid)) {
return (
<Page navId="dashboards/browse" layout={PageLayoutType.Canvas}>
<Box paddingY={4} display="flex" direction="column" alignItems="center">
<PageLoader />
</Box>
</Page>
);
}Typography
public/app/features/dashboard-scene/pages/PublicDashboardScenePage.tsx:143
Public dashboard title truncates with no way to recover the full text
The `title` class in PublicDashboardScenePage.tsx applies `overflow: hidden`, `textOverflow: ellipsis`, and `whiteSpace: nowrap` to the dashboard title span, but the span rendering `{title}` carries no `title` attribute or tooltip. Long dashboard names cut off with no way to see the rest.
Why it matters
A user viewing a dashboard with a long name can't tell what it's actually called, and has no way to reveal the truncated portion, which is a real problem on a public-facing page where the title is the primary identifier.
Fix
Add a native title attribute (or tooltip) mirroring the visible text whenever CSS truncation is applied.
<span className={styles.title}>{title}</span><span className={styles.title} title={title}>{title}</span>Get this score on every PR.
Rams reviews each pull request on your repo and posts inline one-click fixes — about a minute per review.
Install Rams freeUX
public/app/features/notebook/pages/NotebookScenePage.tsx:53
Notebook page shows an empty box when the scene never resolves
In NotebookScenePage.tsx, when `notebookScene` is falsy and `loadError` is also falsy, the fallback renders `<Box paddingY={4} display="flex" direction="column" alignItems="center">{isLoading && <PageLoader />}</Box>`. Once `isLoading` flips to false without the scene ever resolving and without an error, the box renders empty with no message or retry action.
Why it matters
A user stuck in this state sees a blank centered box with no indication of what happened or what to do next, which reads as a broken page rather than a recoverable error.
Fix
Render an explicit empty/error state with a retry action when loading finishes without a scene and without a caught error.
<Box paddingY={4} display="flex" direction="column" alignItems="center">
{isLoading && <PageLoader />}
</Box><Box paddingY={4} display="flex" direction="column" alignItems="center">
{isLoading ? <PageLoader /> : <div>Unable to load this notebook. Try again.</div>}
</Box>Craft
public/app/features/dashboard-scene/pages/DashboardScenePage.tsx:143
Debug console.log left in the dashboard render path
DashboardScenePage.tsx contains `console.log('skipping rendering');` directly inside the render function, right before returning null on dashboard transitions. This is debug output shipping straight to production consoles on every dashboard-to-dashboard navigation.
Why it matters
Every user's browser console fills with an internal debug message on normal navigation, which clutters real error output and signals unfinished cleanup to anyone inspecting devtools.
Fix
Remove debug console statements before merge, or gate them behind a dev-only flag.
console.log('skipping rendering');
return null;return null;Color
Spacing
Components
Motion
Working well
- Skipping UrlSyncContextProvider when hideTimeControls is set on the notebook scene is a well-reasoned conditional, backed by an inline comment, that avoids syncing URL state that has no representation.
- Icon resolution in the connections flow falls back cleanly through metadata icon, nav icon (validated with isIconName), then a fixed FALLBACK_ICON, avoiding a broken icon render path.
- Subtitle copy on the datasource details page is correctly branched by isOnPrem with separate Trans i18nKeys, so cloud and on-prem messaging stay independently translatable.
Scored August 1, 2026 with Rams Engine v0.0.3 · Engine changelog
First scored July 9, 2026: 98/100. This rescore on v0.0.3: 91/100.
This page is an automated design review of grafana/grafana’s UI code: 30 files read against 291 versioned rules covering accessibility, color, typography, spacing, components, UX, motion, and craft. The score is out of 100; confirmed criticals cap it — one at 59, two at 49, three or more at 39.
More design scores
Score your own repo.
Free on public repos, no account. The same engine that scored this page reads your UI code and mints a score page like this one.
Public repos only. The full engine reviews the UI code and mints a public score page — we email you the link too. Already-scored repos open instantly.