diff --git a/.betterer.results b/.betterer.results index 48f308f57b5..65afa3201e8 100644 --- a/.betterer.results +++ b/.betterer.results @@ -5834,12 +5834,6 @@ exports[`better eslint`] = { [0, 0, 0, "Styles should be written using objects.", "3"], [0, 0, 0, "Styles should be written using objects.", "4"] ], - "public/app/plugins/panel/gettingstarted/components/Step.tsx:5381": [ - [0, 0, 0, "Styles should be written using objects.", "0"], - [0, 0, 0, "Styles should be written using objects.", "1"], - [0, 0, 0, "Styles should be written using objects.", "2"], - [0, 0, 0, "Styles should be written using objects.", "3"] - ], "public/app/plugins/panel/gettingstarted/components/TutorialCard.tsx:5381": [ [0, 0, 0, "Styles should be written using objects.", "0"], [0, 0, 0, "Styles should be written using objects.", "1"], diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index 556a0ad684b..284141a1035 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -56,6 +56,7 @@ Some features are enabled by default. You can disable these feature by setting t | `lokiQueryHints` | Enables query hints for Loki | Yes | | `alertingPreviewUpgrade` | Show Unified Alerting preview and upgrade page in legacy alerting | Yes | | `alertingQueryOptimization` | Optimizes eligible queries in order to reduce load on datasources | | +| `betterPageScrolling` | Removes CustomScrollbar from the UI, relying on native browser scrollbars | Yes | | `alertingUpgradeDryrunOnStart` | When activated in legacy alerting mode, this initiates a dry-run of the Unified Alerting upgrade during each startup. It logs any issues detected without implementing any actual changes. | Yes | ## Preview feature toggles diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index b2eb5ceabcd..ec9b91f9315 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -178,6 +178,7 @@ export interface FeatureToggles { kubernetesAggregator?: boolean; expressionParser?: boolean; groupByVariable?: boolean; + betterPageScrolling?: boolean; alertingUpgradeDryrunOnStart?: boolean; scopeFilters?: boolean; } diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index 5dc122d423a..a0955fb2d9d 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -1188,6 +1188,14 @@ var ( HideFromDocs: true, HideFromAdminPage: true, }, + { + Name: "betterPageScrolling", + Description: "Removes CustomScrollbar from the UI, relying on native browser scrollbars", + Stage: FeatureStageGeneralAvailability, + FrontendOnly: true, + Owner: grafanaFrontendPlatformSquad, + Expression: "true", // enabled by default + }, { Name: "alertingUpgradeDryrunOnStart", Description: "When activated in legacy alerting mode, this initiates a dry-run of the Unified Alerting upgrade during each startup. It logs any issues detected without implementing any actual changes.", diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index a53756fa9a6..786175591ad 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -159,5 +159,6 @@ newPDFRendering,experimental,@grafana/sharing-squad,false,false,false kubernetesAggregator,experimental,@grafana/grafana-app-platform-squad,false,true,false expressionParser,experimental,@grafana/grafana-app-platform-squad,false,true,false groupByVariable,experimental,@grafana/dashboards-squad,false,false,false +betterPageScrolling,GA,@grafana/grafana-frontend-platform,false,false,true alertingUpgradeDryrunOnStart,GA,@grafana/alerting-squad,false,true,false scopeFilters,experimental,@grafana/dashboards-squad,false,false,false diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index 50410793963..ca3958ffae9 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -647,6 +647,10 @@ const ( // Enable groupBy variable support in scenes dashboards FlagGroupByVariable = "groupByVariable" + // FlagBetterPageScrolling + // Removes CustomScrollbar from the UI, relying on native browser scrollbars + FlagBetterPageScrolling = "betterPageScrolling" + // FlagAlertingUpgradeDryrunOnStart // When activated in legacy alerting mode, this initiates a dry-run of the Unified Alerting upgrade during each startup. It logs any issues detected without implementing any actual changes. FlagAlertingUpgradeDryrunOnStart = "alertingUpgradeDryrunOnStart" diff --git a/pkg/services/featuremgmt/toggles_gen.json b/pkg/services/featuremgmt/toggles_gen.json index 810e3edaba8..df1d76b9e85 100644 --- a/pkg/services/featuremgmt/toggles_gen.json +++ b/pkg/services/featuremgmt/toggles_gen.json @@ -2087,6 +2087,19 @@ "stage": "experimental", "codeowner": "@grafana/grafana-app-platform-squad" } + }, + { + "metadata": { + "name": "betterPageScrolling", + "resourceVersion": "1709583501630", + "creationTimestamp": "2024-03-04T20:18:21Z" + }, + "spec": { + "description": "Removes CustomScrollbar from the UI, relying on native browser scrollbars", + "stage": "GA", + "codeowner": "@grafana/grafana-frontend-platform", + "frontend": true + } } ] } \ No newline at end of file diff --git a/pkg/services/featuremgmt/toggles_gen_test.go b/pkg/services/featuremgmt/toggles_gen_test.go index e1014d79063..6881e21d07b 100644 --- a/pkg/services/featuremgmt/toggles_gen_test.go +++ b/pkg/services/featuremgmt/toggles_gen_test.go @@ -126,7 +126,7 @@ func TestFeatureToggleFiles(t *testing.T) { item.Annotations[utils.AnnoKeyUpdatedTimestamp] = created.String() item.Spec = v // the current value } - } else { + } else if item.DeletionTimestamp == nil { item.DeletionTimestamp = &created fmt.Printf("mark feature as deleted") } diff --git a/public/app/app.ts b/public/app/app.ts index 30229d999cc..0de34f8fe68 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -132,7 +132,11 @@ export class GrafanaApp { initIconCache(); // This needs to be done after the `initEchoSrv` since it is being used under the hood. startMeasure('frontend_app_init'); - addClassIfNoOverlayScrollbar(); + + if (!config.featureToggles.betterPageScrolling) { + addClassIfNoOverlayScrollbar(); + } + setLocale(config.bootData.user.locale); setWeekStart(config.bootData.user.weekStart); setPanelRenderer(PanelRenderer); diff --git a/public/app/core/components/FlaggedScroller.tsx b/public/app/core/components/FlaggedScroller.tsx new file mode 100644 index 00000000000..f7dbdd85dca --- /dev/null +++ b/public/app/core/components/FlaggedScroller.tsx @@ -0,0 +1,54 @@ +import { css, cx } from '@emotion/css'; +import React, { useEffect, useRef } from 'react'; + +import { config } from '@grafana/runtime'; +import { CustomScrollbar, useStyles2 } from '@grafana/ui'; + +type FlaggedScrollerProps = Parameters[0]; + +export default function FlaggedScrollbar(props: FlaggedScrollerProps) { + if (config.featureToggles.betterPageScrolling) { + return {props.children}; + } + + return ; +} + +// Shim to provide API-compatibility for Page's scroll-related props +function NativeScrollbar({ children, scrollRefCallback, scrollTop }: FlaggedScrollerProps) { + const styles = useStyles2(getStyles); + const ref = useRef(null); + + useEffect(() => { + if (ref.current && scrollRefCallback) { + scrollRefCallback(ref.current); + } + }, [ref, scrollRefCallback]); + + useEffect(() => { + if (ref.current && scrollTop != null) { + ref.current?.scrollTo(0, scrollTop); + } + }, [scrollTop]); + + return ( + // Set the .scrollbar-view class to help e2e tests find this, like in CustomScrollbar +
+ {children} +
+ ); +} + +function getStyles() { + return { + nativeScrollbars: css({ + label: 'native-scroll-container', + minHeight: `calc(100% + 0px)`, // I don't know, just copied from custom scrollbars + maxHeight: `calc(100% + 0px)`, // I don't know, just copied from custom scrollbars + display: 'flex', + flexDirection: 'column', + flexGrow: 1, + overflow: 'auto', + }), + }; +} diff --git a/public/app/core/components/Page/Page.tsx b/public/app/core/components/Page/Page.tsx index 5114fc0b4f1..7f017fba487 100644 --- a/public/app/core/components/Page/Page.tsx +++ b/public/app/core/components/Page/Page.tsx @@ -1,11 +1,12 @@ -// Libraries import { css, cx } from '@emotion/css'; import React, { useLayoutEffect } from 'react'; import { GrafanaTheme2, PageLayoutType } from '@grafana/data'; -import { CustomScrollbar, useStyles2 } from '@grafana/ui'; +import { useStyles2 } from '@grafana/ui'; import { useGrafana } from 'app/core/context/GrafanaContext'; +import FlaggedScrollbar from '../FlaggedScroller'; + import { PageContents } from './PageContents'; import { PageHeader } from './PageHeader'; import { PageTabs } from './PageTabs'; @@ -52,7 +53,7 @@ export const Page: PageType = ({ return (
{layout === PageLayoutType.Standard && ( - +
{pageHeaderNav && ( }
{children}
-
+ )} + {layout === PageLayoutType.Canvas && ( - +
{children}
-
+ )} + {layout === PageLayoutType.Custom && children}
); @@ -95,6 +98,9 @@ const getStyles = (theme: GrafanaTheme2) => { label: 'page-content', flexGrow: 1, }), + primaryBg: css({ + background: theme.colors.background.primary, + }), pageInner: css({ label: 'page-inner', padding: theme.spacing(2), diff --git a/public/app/core/components/Page/types.ts b/public/app/core/components/Page/types.ts index aa76f10af73..4705291cbc7 100644 --- a/public/app/core/components/Page/types.ts +++ b/public/app/core/components/Page/types.ts @@ -20,9 +20,15 @@ export interface PageProps extends HTMLAttributes { subTitle?: React.ReactNode; /** Control the page layout. */ layout?: PageLayoutType; - /** Can be used to get the scroll container element to access scroll position */ + /** + * Can be used to get the scroll container element to access scroll position + * */ + // Probably will deprecate this in the future in favor of just scrolling document.body directly scrollRef?: RefCallback; - /** Can be used to update the current scroll position */ + /** + * Can be used to update the current scroll position + * */ + // Probably will deprecate this in the future in favor of just scrolling document.body directly scrollTop?: number; } diff --git a/public/app/plugins/panel/gettingstarted/components/Step.tsx b/public/app/plugins/panel/gettingstarted/components/Step.tsx index a8a15fd7cf0..e76a73e36fa 100644 --- a/public/app/plugins/panel/gettingstarted/components/Step.tsx +++ b/public/app/plugins/panel/gettingstarted/components/Step.tsx @@ -37,30 +37,30 @@ export const Step = ({ step }: Props) => { const getStyles = (theme: GrafanaTheme2) => { return { - setup: css` - display: flex; - width: 95%; - `, - info: css` - width: 172px; - margin-right: 5%; + setup: css({ + display: 'flex', + width: '95%', + }), + info: css({ + width: '172px', + marginRight: '5%', - ${theme.breakpoints.down('xxl')} { - margin-right: ${theme.spacing(4)}; - } - ${theme.breakpoints.down('sm')} { - display: none; - } - `, - title: css` - color: ${theme.v1.palette.blue95}; - `, - cards: css` - overflow-x: scroll; - overflow-y: hidden; - width: 100%; - display: flex; - justify-content: flex-start; - `, + [theme.breakpoints.down('xxl')]: { + marginRight: theme.spacing(4), + }, + [theme.breakpoints.down('sm')]: { + display: 'none', + }, + }), + title: css({ + color: theme.v1.palette.blue95, + }), + cards: css({ + overflowX: 'auto', + overflowY: 'hidden', + width: '100%', + display: 'flex', + justifyContent: 'flex-start', + }), }; }; diff --git a/public/sass/components/_scrollbar.scss b/public/sass/components/_scrollbar.scss index ee242a0d9aa..edb379ae5b6 100644 --- a/public/sass/components/_scrollbar.scss +++ b/public/sass/components/_scrollbar.scss @@ -115,6 +115,7 @@ } // Scrollbars +// Note, this is not applied by default if the `betterPageScrolling` feature flag is applied .no-overlay-scrollbar { ::-webkit-scrollbar { width: 8px;