diff --git a/packages/grafana-ui/src/components/PageLayout/PageToolbar.test.tsx b/packages/grafana-ui/src/components/PageLayout/PageToolbar.test.tsx index 6fa71287d09..bfba98620ea 100644 --- a/packages/grafana-ui/src/components/PageLayout/PageToolbar.test.tsx +++ b/packages/grafana-ui/src/components/PageLayout/PageToolbar.test.tsx @@ -3,6 +3,12 @@ import React from 'react'; import { PageToolbar } from '..'; +const resizeWindow = (x: number, y: number) => { + global.innerWidth = x; + global.innerHeight = y; + global.dispatchEvent(new Event('resize')); +}; + describe('PageToolbar', () => { it('renders left items when title is not set', () => { const leftItemContent = 'Left Item!'; @@ -10,4 +16,31 @@ describe('PageToolbar', () => { expect(screen.getByText(leftItemContent)).toBeInTheDocument(); }); + + describe('On small screens', () => { + const windowWidth = global.innerWidth, + windowHeight = global.innerHeight; + + beforeAll(() => { + resizeWindow(500, 500); + }); + + afterAll(() => { + resizeWindow(windowWidth, windowHeight); + }); + + it('left items are not visible', () => { + const leftItemContent = 'Left Item!'; + render({leftItemContent}]} />); + + expect(screen.getByText(leftItemContent)).not.toBeVisible(); + }); + + it('left items are visible when forceShowLeftItems is true', () => { + const leftItemContent = 'Left Item!'; + render({leftItemContent}]} />); + + expect(screen.getByText(leftItemContent)).toBeVisible(); + }); + }); }); diff --git a/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx b/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx index 49508b3e2e5..c46a7aeadc4 100644 --- a/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx +++ b/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx @@ -25,6 +25,11 @@ export interface Props { isFullscreen?: boolean; 'aria-label'?: string; buttonOverflowAlignment?: 'left' | 'right'; + /** + * Forces left items to be visible on small screens. + * By default left items are hidden on small screens. + */ + forceShowLeftItems?: boolean; } /** @alpha */ @@ -44,13 +49,14 @@ export const PageToolbar = React.memo( /** main nav-container aria-label **/ 'aria-label': ariaLabel, buttonOverflowAlignment = 'right', + forceShowLeftItems = false, }: Props) => { const styles = useStyles2(getStyles); /** * .page-toolbar css class is used for some legacy css view modes (TV/Kiosk) and * media queries for mobile view when toolbar needs left padding to make room - * for mobile menu icon. This logic hopefylly can be changed when we move to a full react + * for mobile menu icon. This logic hopefully can be changed when we move to a full react * app and change how the app side menu & mobile menu is rendered. */ const mainStyle = cx( @@ -127,7 +133,10 @@ export const PageToolbar = React.memo( )} {leftItems?.map((child, index) => ( -
+
{child}
))} @@ -236,11 +245,14 @@ const getStyles = (theme: GrafanaTheme2) => { `, leftActionItem: css` display: none; + align-items: center; + padding-right: ${spacing(0.5)}; ${theme.breakpoints.up('md')} { - align-items: center; display: flex; - padding-right: ${spacing(0.5)}; } `, + forceShowLeftActionItems: css` + display: flex; + `, }; }; diff --git a/public/app/features/explore/Explore.test.tsx b/public/app/features/explore/Explore.test.tsx index 38a4f2d4c3a..3007377ff7e 100644 --- a/public/app/features/explore/Explore.test.tsx +++ b/public/app/features/explore/Explore.test.tsx @@ -11,6 +11,12 @@ import { Explore, Props } from './Explore'; import { scanStopAction } from './state/query'; import { createEmptyQueryResponse } from './state/utils'; +const resizeWindow = (x: number, y: number) => { + global.innerWidth = x; + global.innerHeight = y; + global.dispatchEvent(new Event('resize')); +}; + const makeEmptyQueryResponse = (loadingState: LoadingState) => { const baseEmptyResponse = createEmptyQueryResponse(); @@ -143,4 +149,25 @@ describe('Explore', () => { expect(screen.getByTestId('explore-no-data')).toBeInTheDocument(); }); + + describe('On small screens', () => { + const windowWidth = global.innerWidth, + windowHeight = global.innerHeight; + + beforeAll(() => { + resizeWindow(500, 500); + }); + + afterAll(() => { + resizeWindow(windowWidth, windowHeight); + }); + + it('should render data source picker', async () => { + setup(); + + const dataSourcePicker = await screen.findByLabelText('Data source picker select container'); + + expect(dataSourcePicker).toBeInTheDocument(); + }); + }); }); diff --git a/public/app/features/explore/ExploreToolbar.tsx b/public/app/features/explore/ExploreToolbar.tsx index ed4ebe7e427..6e1806b2f40 100644 --- a/public/app/features/explore/ExploreToolbar.tsx +++ b/public/app/features/explore/ExploreToolbar.tsx @@ -286,6 +286,7 @@ class UnConnectedExploreToolbar extends PureComponent { title={exploreId === ExploreId.left && !isTopnav ? 'Explore' : undefined} pageIcon={exploreId === ExploreId.left && !isTopnav ? 'compass' : undefined} leftItems={toolbarLeftItems} + forceShowLeftItems > {this.renderActions()}