diff --git a/packages/grafana-ui/src/components/Card/Card.tsx b/packages/grafana-ui/src/components/Card/Card.tsx index da5cd338ca5..de7c2a4adb9 100644 --- a/packages/grafana-ui/src/components/Card/Card.tsx +++ b/packages/grafana-ui/src/components/Card/Card.tsx @@ -114,12 +114,14 @@ export const Card: CardInterface = ({ {figure}
-
- {heading} +
+
+ {heading} + {tags} +
+ {meta} + {description &&

{description}

}
- {meta} - {tags} - {description &&

{description}

} {hasActions && (
{actions} @@ -178,20 +180,37 @@ export const getContainerStyles = stylesFactory((theme: GrafanaTheme, disabled = export const getCardStyles = stylesFactory((theme: GrafanaTheme) => { return { inner: css` + display: flex; + justify-content: space-between; + align-items: center; width: 100%; + flex-wrap: wrap; `, heading: css` + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; margin-bottom: 0; font-size: ${theme.typography.size.md}; line-height: ${theme.typography.lineHeight.xs}; `, + info: css` + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + width: 100%; + `, metadata: css` + width: 100%; font-size: ${theme.typography.size.sm}; color: ${theme.colors.textSemiWeak}; - margin: ${theme.spacing.sm} 0 0; + margin: ${theme.spacing.xs} 0 0; line-height: ${theme.typography.lineHeight.xs}; `, description: css` + width: 100%; margin: ${theme.spacing.sm} 0 0; color: ${theme.colors.textSemiWeak}; line-height: ${theme.typography.lineHeight.md}; @@ -202,6 +221,10 @@ export const getCardStyles = stylesFactory((theme: GrafanaTheme) => { & > * { width: 100%; } + + &:empty { + display: none; + } `, actionRow: css` display: flex; @@ -233,7 +256,7 @@ export const getCardStyles = stylesFactory((theme: GrafanaTheme) => { width: 100%; `, tagList: css` - margin-top: ${theme.spacing.sm}; + max-width: 50%; `, }; }); @@ -248,8 +271,21 @@ const Tags: FC = ({ children, styles }) => { }; Tags.displayName = 'Tags'; -const Figure: FC = ({ children, styles }) => { - return
{children}
; +const Figure: FC = ({ children, styles, align = 'top' }) => { + return ( +
+ {children} +
+ ); }; Figure.displayName = 'Figure'; diff --git a/packages/grafana-ui/src/components/Tags/TagList.tsx b/packages/grafana-ui/src/components/Tags/TagList.tsx index c4da2fd6424..bbf684c7b2c 100644 --- a/packages/grafana-ui/src/components/Tags/TagList.tsx +++ b/packages/grafana-ui/src/components/Tags/TagList.tsx @@ -1,5 +1,5 @@ import React, { FC, memo } from 'react'; -import { cx, css } from 'emotion'; +import { css, cx } from 'emotion'; import { OnTagClick, Tag } from './Tag'; export interface Props { @@ -29,11 +29,11 @@ const getStyles = () => { display: flex; flex: 1 1 auto; flex-wrap: wrap; + margin-bottom: -6px; + justify-content: flex-end; `, tag: css` - &:not(:first-child) { - margin-left: 6px; - } + margin: 0 0 6px 6px; `, }; }; diff --git a/public/app/features/search/components/SearchCheckbox.tsx b/public/app/features/search/components/SearchCheckbox.tsx index 1877ac9d2d5..0043b515323 100644 --- a/public/app/features/search/components/SearchCheckbox.tsx +++ b/public/app/features/search/components/SearchCheckbox.tsx @@ -19,12 +19,14 @@ export const SearchCheckbox: FC = memo(({ onClick, checked = false, edita }); const getStyles = stylesFactory(() => ({ - // Vertically align absolutely positioned checkbox element wrapper: css` height: 21px; - margin-right: 12px; & > label { height: 100%; + + & > input { + position: relative; + } } `, })); diff --git a/public/app/features/search/components/SearchItem.tsx b/public/app/features/search/components/SearchItem.tsx index ba9fe06c766..dc9dd742b44 100644 --- a/public/app/features/search/components/SearchItem.tsx +++ b/public/app/features/search/components/SearchItem.tsx @@ -1,26 +1,23 @@ -import React, { FC, useCallback, CSSProperties } from 'react'; -import { css, cx } from 'emotion'; -import { GrafanaTheme } from '@grafana/data'; +import React, { FC, useCallback } from 'react'; +import { css } from 'emotion'; import { selectors as e2eSelectors } from '@grafana/e2e-selectors'; -import { useTheme, TagList, styleMixins, stylesFactory } from '@grafana/ui'; +import { TagList, Card, useStyles } from '@grafana/ui'; +import { GrafanaTheme } from '@grafana/data'; import { DashboardSectionItem, OnToggleChecked } from '../types'; import { SearchCheckbox } from './SearchCheckbox'; -import { SEARCH_ITEM_HEIGHT, SEARCH_ITEM_MARGIN } from '../constants'; +import { SEARCH_ITEM_HEIGHT } from '../constants'; export interface Props { item: DashboardSectionItem; editable?: boolean; onTagSelected: (name: string) => any; onToggleChecked?: OnToggleChecked; - style?: CSSProperties; } const selectors = e2eSelectors.pages.Dashboards; -export const SearchItem: FC = ({ item, editable, onToggleChecked, onTagSelected, style }) => { - const theme = useTheme(); - const styles = getResultsItemStyles(theme); - +export const SearchItem: FC = ({ item, editable, onToggleChecked, onTagSelected }) => { + const styles = useStyles(getStyles); const tagSelected = useCallback((tag: string, event: React.MouseEvent) => { onTagSelected(tag); }, []); @@ -36,71 +33,28 @@ export const SearchItem: FC = ({ item, editable, onToggleChecked, onTagSe ); return ( - + + + + {item.folderTitle && {item.folderTitle}} + + + + ); }; -const getResultsItemStyles = stylesFactory((theme: GrafanaTheme) => ({ - wrapper: css` - ${styleMixins.listItem(theme)}; - display: flex; - align-items: center; - height: ${SEARCH_ITEM_HEIGHT}px; - margin-bottom: ${SEARCH_ITEM_MARGIN}px; - padding: 0 ${theme.spacing.md}; - - &:last-child { - margin-bottom: ${SEARCH_ITEM_MARGIN * 2}px; - } - - :hover { - cursor: pointer; - } - `, - selected: css` - ${styleMixins.listItemSelected(theme)}; - `, - body: css` - display: flex; - flex-direction: column; - justify-content: center; - flex: 1 1 auto; - overflow: hidden; - `, - folderTitle: css` - color: ${theme.colors.textWeak}; - font-size: ${theme.typography.size.sm}; - line-height: ${theme.typography.lineHeight.sm}; - `, - icon: css` - margin-left: 10px; - `, - tags: css` - flex-grow: 0; - justify-content: flex-end; - @media only screen and (max-width: ${theme.breakpoints.md}) { - display: none; - } - `, - link: css` - display: flex; - align-items: center; - flex-shrink: 0; - flex-grow: 1; - height: 100%; - `, -})); +const getStyles = (theme: GrafanaTheme) => { + return { + container: css` + padding: ${theme.spacing.sm} ${theme.spacing.md}; + `, + }; +}; diff --git a/public/app/features/search/constants.ts b/public/app/features/search/constants.ts index 1801eed1f4b..beb2c73f228 100644 --- a/public/app/features/search/constants.ts +++ b/public/app/features/search/constants.ts @@ -1,7 +1,7 @@ export const NO_ID_SECTIONS = ['Recent', 'Starred']; // Height of the search result item -export const SEARCH_ITEM_HEIGHT = 48; -export const SEARCH_ITEM_MARGIN = 4; +export const SEARCH_ITEM_HEIGHT = 62; +export const SEARCH_ITEM_MARGIN = 8; export const DEFAULT_SORT = { label: 'A-Z', value: 'alpha-asc' }; export const SECTION_STORAGE_KEY = 'search.sections'; export const GENERAL_FOLDER_ID = 0;