From 1336a57e99788e267e1ff882a33b005d66ad8b21 Mon Sep 17 00:00:00 2001 From: Alex Khomenko Date: Wed, 28 Apr 2021 13:41:20 +0300 Subject: [PATCH] Grafana-UI: Export Card container styles (#33386) * Export Card container styles * Export CardContainer as a separate component * Update story * Remove tooltip --- .../src/components/Card/Card.story.tsx | 21 +--- .../grafana-ui/src/components/Card/Card.tsx | 115 ++++-------------- .../src/components/Card/CardContainer.tsx | 84 +++++++++++++ packages/grafana-ui/src/components/index.ts | 3 +- 4 files changed, 112 insertions(+), 111 deletions(-) create mode 100644 packages/grafana-ui/src/components/Card/CardContainer.tsx diff --git a/packages/grafana-ui/src/components/Card/Card.story.tsx b/packages/grafana-ui/src/components/Card/Card.story.tsx index 404e0b79a5b..2ac3adce400 100644 --- a/packages/grafana-ui/src/components/Card/Card.story.tsx +++ b/packages/grafana-ui/src/components/Card/Card.story.tsx @@ -21,13 +21,9 @@ export default { knobs: { disable: true, }, - }, - argTypes: { - heading: { control: { disable: true } }, - description: { control: { disable: true } }, - href: { control: { disable: true } }, - tooltip: { control: { disable: true } }, - onClick: { control: { disable: true } }, + controls: { + exclude: ['onClick', 'href', 'heading', 'description', 'className'], + }, }, }; @@ -63,17 +59,6 @@ export const AsLink: Story = ({ disabled }) => { ); }; -export const WithTooltip: Story = ({ disabled }) => { - return ( - - ); -}; - export const WithTags: Story = ({ disabled }) => { return ( diff --git a/packages/grafana-ui/src/components/Card/Card.tsx b/packages/grafana-ui/src/components/Card/Card.tsx index 4cf6106a337..3338f94d155 100644 --- a/packages/grafana-ui/src/components/Card/Card.tsx +++ b/packages/grafana-ui/src/components/Card/Card.tsx @@ -1,50 +1,13 @@ -import React, { memo, cloneElement, FC, HTMLAttributes, ReactNode, useCallback } from 'react'; +import React, { memo, cloneElement, FC, ReactNode, useCallback } from 'react'; import { css, cx } from '@emotion/css'; import { GrafanaThemeV2 } from '@grafana/data'; -import { useTheme2, styleMixins, stylesFactory } from '../../themes'; -import { Tooltip, PopoverContent } from '../Tooltip/Tooltip'; +import { useTheme2, stylesFactory } from '../../themes'; +import { CardContainer, CardContainerProps } from './CardContainer'; /** * @public */ -export interface ContainerProps extends HTMLAttributes { - /** Content for the card's tooltip */ - tooltip?: PopoverContent; -} - -const CardContainer: FC = ({ children, tooltip, ...props }) => { - return tooltip ? ( - -
{children}
-
- ) : ( -
{children}
- ); -}; - -/** - * @public - */ -export interface CardInnerProps { - href?: string; -} - -const CardInner: FC = ({ children, href }) => { - const theme = useTheme2(); - const styles = getCardStyles(theme); - return href ? ( - - {children} - - ) : ( -
{children}
- ); -}; - -/** - * @public - */ -export interface Props extends ContainerProps { +export interface Props extends Omit { /** Main heading for the Card **/ heading: ReactNode; /** Card description text */ @@ -74,7 +37,6 @@ export const Card: CardInterface = ({ heading, description, disabled, - tooltip, href, onClick, className, @@ -100,66 +62,40 @@ export const Card: CardInterface = ({ const disableHover = disabled || (!onClick && !href); const disableEvents = disabled && !actions; - const containerStyles = getContainerStyles(theme, disableEvents, disableHover); const onCardClick = useCallback(() => (disableHover ? () => {} : onClick?.()), [disableHover, onClick]); return ( - - {figure} -
-
-
-
- {heading} -
- {meta} - {description &&

{description}

} + {figure} +
+
+
+
+ {heading}
- {tags} + {meta} + {description &&

{description}

}
- {hasActions && ( -
- {actions} - {secondaryActions} -
- )} + {tags}
- + {hasActions && ( +
+ {actions} + {secondaryActions} +
+ )} +
); }; -const getContainerStyles = stylesFactory((theme: GrafanaThemeV2, disabled = false, disableHover = false) => { - return css({ - display: 'flex', - width: '100%', - background: theme.colors.background.secondary, - borderRadius: theme.shape.borderRadius(), - position: 'relative', - pointerEvents: disabled ? 'none' : 'auto', - marginBottom: theme.spacing(1), - transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], { - duration: theme.transitions.duration.short, - }), - - ...(!disableHover && { - '&:hover': { - background: theme.colors.emphasize(theme.colors.background.secondary, 0.03), - cursor: 'pointer', - zIndex: 1, - }, - '&:focus': styleMixins.getFocusStyles(theme), - }), - }); -}); - /** * @public */ @@ -245,11 +181,6 @@ export const getCardStyles = stylesFactory((theme: GrafanaThemeV2) => { separator: css` margin: 0 ${theme.spacing(1)}; `, - innerLink: css` - display: flex; - width: 100%; - padding: ${theme.spacing(2)}; - `, tagList: css` max-width: 50%; `, diff --git a/packages/grafana-ui/src/components/Card/CardContainer.tsx b/packages/grafana-ui/src/components/Card/CardContainer.tsx new file mode 100644 index 00000000000..0cfbba39358 --- /dev/null +++ b/packages/grafana-ui/src/components/Card/CardContainer.tsx @@ -0,0 +1,84 @@ +import React, { HTMLAttributes, ReactNode } from 'react'; +import { css, cx } from '@emotion/css'; +import { GrafanaThemeV2 } from '@grafana/data'; +import { styleMixins, stylesFactory, useTheme2 } from '../../themes'; + +/** + * @public + */ +export interface CardInnerProps { + href?: string; + children?: ReactNode; +} + +const CardInner = ({ children, href }: CardInnerProps) => { + const theme = useTheme2(); + const { inner } = getCardContainerStyles(theme); + return href ? ( + + {children} + + ) : ( +
{children}
+ ); +}; + +/** + * @public + */ +export interface CardContainerProps extends HTMLAttributes, CardInnerProps { + /** Disable pointer events for the Card, e.g. click events */ + disableEvents?: boolean; + /** No style change on hover */ + disableHover?: boolean; + /** Custom container styles */ + className?: string; +} + +export const CardContainer = ({ + href, + children, + disableEvents, + disableHover, + className, + ...props +}: CardContainerProps) => { + const theme = useTheme2(); + const { container } = getCardContainerStyles(theme, disableEvents, disableHover); + return ( +
+ {children} +
+ ); +}; + +const getCardContainerStyles = stylesFactory((theme: GrafanaThemeV2, disabled = false, disableHover = false) => { + return { + container: css({ + display: 'flex', + width: '100%', + background: theme.colors.background.secondary, + borderRadius: theme.shape.borderRadius(), + position: 'relative', + pointerEvents: disabled ? 'none' : 'auto', + marginBottom: theme.spacing(1), + transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], { + duration: theme.transitions.duration.short, + }), + + ...(!disableHover && { + '&:hover': { + background: theme.colors.emphasize(theme.colors.background.secondary, 0.03), + cursor: 'pointer', + zIndex: 1, + }, + '&:focus': styleMixins.getFocusStyles(theme), + }), + }), + inner: css({ + display: 'flex', + width: '100%', + padding: theme.spacing(2), + }), + }; +}); diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index bc8588057ed..14461458342 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -189,7 +189,8 @@ export { Checkbox } from './Forms/Checkbox'; export { TextArea } from './TextArea/TextArea'; export { FileUpload } from './FileUpload/FileUpload'; export { TimeRangeInput } from './TimePicker/TimeRangeInput'; -export { Card, Props as CardProps, ContainerProps, CardInnerProps, getCardStyles } from './Card/Card'; +export { Card, Props as CardProps, getCardStyles } from './Card/Card'; +export { CardContainer, CardContainerProps } from './Card/CardContainer'; export { FormattedValueDisplay } from './FormattedValueDisplay/FormattedValueDisplay'; export { ButtonSelect } from './Dropdown/ButtonSelect';