Drawer: align component style with PanelInspector (#23694)

* Drawer: add subtitle, expandable button and refactor style

* Drawer: update header style and z-index

* Drawer: refactor Drawer component and PanelInspector

* PanelInspector: add expandable

* Drawer: update stories with new props

* Inspector: rename InspectHeader -> InspectSubtitle

* Inspector: fix tabs spacing

* Drawer: remove z-index

* Update public/app/features/dashboard/components/Inspector/InspectSubtitle.tsx

Co-Authored-By: Dominik Prokop <dominik.prokop@grafana.com>

* Drawer: apply PR feedbacks

Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
This commit is contained in:
Agnès Toulet
2020-04-20 15:27:33 +02:00
committed by GitHub
parent 174ee95153
commit d5f8d976f0
5 changed files with 108 additions and 139 deletions

View File

@@ -33,6 +33,7 @@ export const global = () => {
{state.isOpen && (
<Drawer
title={drawerTitle}
subtitle="This is a subtitle."
onClose={() => {
updateValue({ isOpen: !state.isOpen });
}}
@@ -70,6 +71,7 @@ export const longContent = () => {
{state.isOpen && (
<Drawer
scrollableContent
expandable
title="Drawer with long content"
onClose={() => {
updateValue({ isOpen: !state.isOpen });

View File

@@ -1,21 +1,25 @@
import React, { CSSProperties, FC, ReactNode } from 'react';
import React, { CSSProperties, FC, ReactNode, useState } from 'react';
import { GrafanaTheme } from '@grafana/data';
import RcDrawer from 'rc-drawer';
import { css } from 'emotion';
import CustomScrollbar from '../CustomScrollbar/CustomScrollbar';
import { Icon } from '../Icon/Icon';
import { IconButton } from '../IconButton/IconButton';
import { stylesFactory, useTheme } from '../../themes';
export interface Props {
children: ReactNode;
/** Title shown at the top of the drawer */
title?: JSX.Element | string;
title?: ReactNode;
/** Subtitle shown below the title */
subtitle?: ReactNode;
/** Should the Drawer be closable by clicking on the mask */
closeOnMaskClick?: boolean;
/** Render the drawer inside a container on the page */
inline?: boolean;
/** Either a number in px or a string with unit postfix */
width?: number | string;
/** Should the Drawer be expandable to full width */
expandable?: boolean;
/** Set to true if the component rendered within in drawer content has its own scroll */
scrollableContent?: boolean;
@@ -24,9 +28,6 @@ export interface Props {
}
const getStyles = stylesFactory((theme: GrafanaTheme, scollableContent: boolean) => {
const closeButtonWidth = '50px';
const borderColor = theme.colors.border2;
return {
drawer: css`
.drawer-content {
@@ -36,25 +37,23 @@ const getStyles = stylesFactory((theme: GrafanaTheme, scollableContent: boolean)
overflow: hidden;
}
`,
titleWrapper: css`
font-size: ${theme.typography.size.lg};
display: flex;
align-items: baseline;
justify-content: space-between;
border-bottom: 1px solid ${borderColor};
padding: ${theme.spacing.sm} 0 ${theme.spacing.sm} ${theme.spacing.md};
background-color: ${theme.colors.bodyBg};
top: 0;
header: css`
background-color: ${theme.colors.bg2};
z-index: 1;
flex-grow: 0;
padding-top: ${theme.spacing.xs};
`,
close: css`
cursor: pointer;
width: ${closeButtonWidth};
height: 100%;
actions: css`
display: flex;
flex-shrink: 0;
justify-content: center;
align-items: baseline;
justify-content: flex-end;
`,
titleWrapper: css`
margin-bottom: ${theme.spacing.lg};
padding: 0 ${theme.spacing.sm} 0 ${theme.spacing.lg};
`,
titleSpacing: css`
margin-bottom: ${theme.spacing.md};
`,
content: css`
padding: ${theme.spacing.md};
@@ -72,10 +71,14 @@ export const Drawer: FC<Props> = ({
closeOnMaskClick = false,
scrollableContent = false,
title,
subtitle,
width = '40%',
expandable = false,
}) => {
const theme = useTheme();
const drawerStyles = getStyles(theme, scrollableContent);
const [isExpanded, setIsExpanded] = useState(false);
const currentWidth = isExpanded ? '100%' : width;
return (
<RcDrawer
@@ -85,16 +88,26 @@ export const Drawer: FC<Props> = ({
onClose={onClose}
maskClosable={closeOnMaskClick}
placement="right"
width={width}
width={currentWidth}
getContainer={inline ? false : 'body'}
style={{ position: `${inline && 'absolute'}` } as CSSProperties}
className={drawerStyles.drawer}
>
{typeof title === 'string' && (
<div className={drawerStyles.titleWrapper}>
<div>{title}</div>
<div className={drawerStyles.close} onClick={onClose}>
<Icon name="times" />
<div className={drawerStyles.header}>
<div className={drawerStyles.actions}>
{expandable && !isExpanded && (
<IconButton name="angle-left" size="xl" onClick={() => setIsExpanded(true)} surface="header" />
)}
{expandable && isExpanded && (
<IconButton name="angle-right" size="xl" onClick={() => setIsExpanded(false)} surface="header" />
)}
<IconButton name="times" size="xl" onClick={onClose} surface="header" />
</div>
<div className={drawerStyles.titleWrapper}>
<h3>{title}</h3>
{typeof subtitle === 'string' && <div className="muted">{subtitle}</div>}
{typeof subtitle !== 'string' && subtitle}
</div>
</div>
)}