Search: use Card component (#29892)

* Search: Use Card component for search items

* Search: Set min height of search item

* Search: Adjust item height

* Search: Move tags to the right

* Search: Center item content

* Search: Align tags

* Search: Adjust Card spacing

* Search: Adjust dimensions
This commit is contained in:
Alex Khomenko
2021-01-19 13:42:59 +02:00
committed by GitHub
parent 77ef9abeed
commit 0fceca5f73
5 changed files with 82 additions and 90 deletions

View File

@@ -19,12 +19,14 @@ export const SearchCheckbox: FC<Props> = 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;
}
}
`,
}));

View File

@@ -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<Props> = ({ item, editable, onToggleChecked, onTagSelected, style }) => {
const theme = useTheme();
const styles = getResultsItemStyles(theme);
export const SearchItem: FC<Props> = ({ item, editable, onToggleChecked, onTagSelected }) => {
const styles = useStyles(getStyles);
const tagSelected = useCallback((tag: string, event: React.MouseEvent<HTMLElement>) => {
onTagSelected(tag);
}, []);
@@ -36,71 +33,28 @@ export const SearchItem: FC<Props> = ({ item, editable, onToggleChecked, onTagSe
);
return (
<div
style={style}
<Card
aria-label={selectors.dashboards(item.title)}
className={cx(styles.wrapper, { [styles.selected]: item.selected })}
heading={item.title}
href={item.url}
style={{ minHeight: SEARCH_ITEM_HEIGHT }}
className={styles.container}
>
<SearchCheckbox editable={editable} checked={item.checked} onClick={toggleItem} />
<a href={item.url} className={styles.link}>
<div className={styles.body}>
<span>{item.title}</span>
<span className={styles.folderTitle}>{item.folderTitle}</span>
</div>
</a>
<TagList tags={item.tags} onClick={tagSelected} className={styles.tags} />
</div>
<Card.Figure align={'center'}>
<SearchCheckbox editable={editable} checked={item.checked} onClick={toggleItem} />
</Card.Figure>
{item.folderTitle && <Card.Meta>{item.folderTitle}</Card.Meta>}
<Card.Tags>
<TagList tags={item.tags} onClick={tagSelected} />
</Card.Tags>
</Card>
);
};
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};
`,
};
};

View File

@@ -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;