From d5fd652f839b61120b005bdf99bc9dea551a6d3a Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Fri, 12 May 2023 17:01:41 +0100 Subject: [PATCH] [v10.0.x] Drawer: Introduce a size property that set's width percentage and minWidth (#68128) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drawer: Introduce a size property that set's width percentage and minWidth (#67809) * Drawer: Introduce drawer size that sets width and min-width * media queries * Change large drawer to 75% * Change news drawer to medium as the news items have better layout then with images on the side * Tweaks and fixed inline drawer issue * review fixes * Deprecate inline, update mdx docs * remove inline var (cherry picked from commit 20217db100983303588ffbebca68fd023c80f490) Co-authored-by: Torkel Ödegaard --- .../src/components/Drawer/Drawer.mdx | 12 ++- .../src/components/Drawer/Drawer.story.tsx | 38 +------- .../src/components/Drawer/Drawer.tsx | 91 +++++++++++++------ .../AppChrome/News/NewsContainer.tsx | 7 +- .../components/HelpWizard/HelpWizard.tsx | 2 +- .../components/Inspector/InspectContent.tsx | 1 - .../SaveDashboard/SaveDashboardDrawer.tsx | 1 - 7 files changed, 82 insertions(+), 70 deletions(-) diff --git a/packages/grafana-ui/src/components/Drawer/Drawer.mdx b/packages/grafana-ui/src/components/Drawer/Drawer.mdx index f8afb9b5c3d..26a2358e217 100644 --- a/packages/grafana-ui/src/components/Drawer/Drawer.mdx +++ b/packages/grafana-ui/src/components/Drawer/Drawer.mdx @@ -21,10 +21,20 @@ onClose = () => { }; return ( - +
Put your Drawer content here
); ``` +## Sizes + +The Drawer supports 3 sizes: `sm`, `md`, and `lg`. This option defines a width in percentage and as well as a min-width. + +- sm: width = 25vh and min-width = 384px +- md: width = 50vh and min-width = 568px +- lg: width = 75vh and min-width = 744px + +## Props + diff --git a/packages/grafana-ui/src/components/Drawer/Drawer.story.tsx b/packages/grafana-ui/src/components/Drawer/Drawer.story.tsx index 9ffec537740..d762336e438 100644 --- a/packages/grafana-ui/src/components/Drawer/Drawer.story.tsx +++ b/packages/grafana-ui/src/components/Drawer/Drawer.story.tsx @@ -22,7 +22,6 @@ const meta: ComponentMeta = { args: { closeOnMaskClick: true, scrollableContent: false, - width: '40%', expandable: false, subtitle: 'This is a subtitle.', }, @@ -142,42 +141,6 @@ LongContent.args = { title: 'Drawer title with long content', }; -export const InLine: ComponentStory = (args) => { - const [isOpen, setIsOpen] = useState(false); - return ( - <> -
- - {isOpen && ( - setIsOpen(false)}> -
    -
  • this
  • -
  • is
  • -
  • a
  • -
  • list
  • -
  • of
  • -
  • menu
  • -
  • items
  • -
-
- )} -
- - ); -}; -InLine.args = { - title: 'Drawer title inline', - inline: true, -}; - export const WithTabs: ComponentStory = (args) => { const [isOpen, setIsOpen] = useState(false); const [activeTab, setActiveTab] = useState('options'); @@ -206,6 +169,7 @@ export const WithTabs: ComponentStory = (args) => { ); }; + WithTabs.args = { title: 'Drawer title with tabs', }; diff --git a/packages/grafana-ui/src/components/Drawer/Drawer.tsx b/packages/grafana-ui/src/components/Drawer/Drawer.tsx index 7c5efda7ba7..1aad5038d33 100644 --- a/packages/grafana-ui/src/components/Drawer/Drawer.tsx +++ b/packages/grafana-ui/src/components/Drawer/Drawer.tsx @@ -1,9 +1,9 @@ -import { css } from '@emotion/css'; +import { css, cx } from '@emotion/css'; import { useDialog } from '@react-aria/dialog'; import { FocusScope } from '@react-aria/focus'; import { useOverlay } from '@react-aria/overlays'; import RcDrawer from 'rc-drawer'; -import React, { CSSProperties, ReactNode, useState, useEffect } from 'react'; +import React, { ReactNode, useState, useEffect } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; @@ -20,12 +20,21 @@ export interface Props { subtitle?: ReactNode; /** Should the Drawer be closable by clicking on the mask, defaults to true */ closeOnMaskClick?: boolean; - /** Render the drawer inside a container on the page */ + /** @deprecated */ inline?: boolean; - /** Either a number in px or a string with unit postfix */ + /** + * @deprecated use the size property instead + **/ width?: number | string; /** Should the Drawer be expandable to full width */ expandable?: boolean; + /** + * Specifies the width and min-width. + * sm = width 25vw & min-width 384px + * md = width 50vw & min-width 568px + * lg = width 75vw & min-width 744px + **/ + size?: 'sm' | 'md' | 'lg'; /** Tabs */ tabs?: React.ReactNode; /** Set to true if the component rendered within in drawer content has its own scroll */ @@ -36,20 +45,19 @@ export interface Props { export function Drawer({ children, - inline = false, onClose, closeOnMaskClick = true, scrollableContent = false, title, subtitle, - width = '40%', + width, + size = 'md', expandable = false, tabs, }: Props) { - const drawerStyles = useStyles2(getStyles); + const styles = useStyles2(getStyles); const [isExpanded, setIsExpanded] = useState(false); const [isOpen, setIsOpen] = useState(false); - const currentWidth = isExpanded ? '100%' : width; const overlayRef = React.useRef(null); const { dialogProps, titleProps } = useDialog({}, overlayRef); const { overlayProps } = useOverlay( @@ -66,31 +74,29 @@ export function Drawer({ setIsOpen(true); }, []); - const content =
{children}
; - const style: CSSProperties = {}; - if (inline) { - style.position = 'absolute'; - } + // deprecated width prop now defaults to empty string which make the size prop take over + const fixedWidth = isExpanded ? '100%' : width ?? ''; + const rootClass = cx(styles.drawer, !fixedWidth && styles.sizes[size]); + const content =
{children}
; return ( @@ -100,14 +106,14 @@ export function Drawer({ ? selectors.components.Drawer.General.title(title) : selectors.components.Drawer.General.title('no title') } - className={drawerStyles.container} + className={styles.container} {...overlayProps} {...dialogProps} ref={overlayRef} > {typeof title === 'string' && ( -
-
+
+
{expandable && !isExpanded && (
-
+

{title}

{typeof subtitle === 'string' &&
{subtitle}
} {typeof subtitle !== 'string' && subtitle} - {tabs &&
{tabs}
} + {tabs &&
{tabs}
}
)} {typeof title !== 'string' && title} -
+
{!scrollableContent ? content : {content}}
@@ -162,10 +168,39 @@ const getStyles = (theme: GrafanaTheme2) => { box-shadow: ${theme.shadows.z3}; ${theme.breakpoints.down('sm')} { - width: 100% !important; + width: calc(100% - ${theme.spacing(2)}) !important; + min-width: 0 !important; } } `, + sizes: { + sm: css({ + '.rc-drawer-content-wrapper': { + label: 'drawer-sm', + width: '25vw', + minWidth: theme.spacing(48), + }, + }), + md: css({ + '.rc-drawer-content-wrapper': { + label: 'drawer-md', + width: '50vw', + minWidth: theme.spacing(66), + }, + }), + lg: css({ + '.rc-drawer-content-wrapper': { + label: 'drawer-lg', + width: '75vw', + minWidth: theme.spacing(93), + + [theme.breakpoints.down('md')]: { + width: `calc(100% - ${theme.spacing(2)}) !important`, + minWidth: 0, + }, + }, + }), + }, drawerContent: css` background-color: ${theme.colors.background.primary} !important; display: flex; diff --git a/public/app/core/components/AppChrome/News/NewsContainer.tsx b/public/app/core/components/AppChrome/News/NewsContainer.tsx index 727e4122570..80c6a2099f0 100644 --- a/public/app/core/components/AppChrome/News/NewsContainer.tsx +++ b/public/app/core/components/AppChrome/News/NewsContainer.tsx @@ -22,7 +22,12 @@ export function NewsContainer({ className }: NewsContainerProps) { <> {showNewsDrawer && ( - + )} diff --git a/public/app/features/dashboard/components/HelpWizard/HelpWizard.tsx b/public/app/features/dashboard/components/HelpWizard/HelpWizard.tsx index f2af5932fbf..541dc7bba11 100644 --- a/public/app/features/dashboard/components/HelpWizard/HelpWizard.tsx +++ b/public/app/features/dashboard/components/HelpWizard/HelpWizard.tsx @@ -72,7 +72,7 @@ export function HelpWizard({ panel, plugin, onClose }: Props) { return (