mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Search: Improvements to design (#23874)
* Search: updated design * Fixed z-index * Fixes * Minor pixel push
This commit is contained in:
parent
21cbcde15f
commit
ef5cbee2b3
@ -98,13 +98,13 @@ export interface GrafanaThemeCommons {
|
||||
panelPadding: number;
|
||||
panelHeaderHeight: number;
|
||||
zIndex: {
|
||||
dropdown: string;
|
||||
navbarFixed: string;
|
||||
sidemenu: string;
|
||||
tooltip: string;
|
||||
modalBackdrop: string;
|
||||
modal: string;
|
||||
typeahead: string;
|
||||
dropdown: number;
|
||||
navbarFixed: number;
|
||||
sidemenu: number;
|
||||
tooltip: number;
|
||||
modalBackdrop: number;
|
||||
modal: number;
|
||||
typeahead: number;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ const getTagStyles = (theme: GrafanaTheme, name: string, colorIndex?: number) =>
|
||||
line-height: ${theme.typography.lineHeight.xs};
|
||||
vertical-align: baseline;
|
||||
background-color: ${colors.color};
|
||||
color: ${theme.colors.textStrong};
|
||||
color: ${theme.palette.gray98};
|
||||
white-space: nowrap;
|
||||
text-shadow: none;
|
||||
padding: 3px 6px;
|
||||
|
@ -122,13 +122,13 @@ const theme: GrafanaThemeCommons = {
|
||||
panelPadding: 8,
|
||||
panelHeaderHeight: 28,
|
||||
zIndex: {
|
||||
navbarFixed: '1000',
|
||||
sidemenu: '1020',
|
||||
dropdown: '1030',
|
||||
typeahead: '1030',
|
||||
tooltip: '1040',
|
||||
modalBackdrop: '1050',
|
||||
modal: '1060',
|
||||
navbarFixed: 1000,
|
||||
sidemenu: 1020,
|
||||
dropdown: 1030,
|
||||
typeahead: 1030,
|
||||
tooltip: 1040,
|
||||
modalBackdrop: 1050,
|
||||
modal: 1060,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -77,11 +77,15 @@ ActionRow.displayName = 'ActionRow';
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
return {
|
||||
actionRow: css`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: ${theme.spacing.md} 0;
|
||||
width: 100%;
|
||||
display: none;
|
||||
|
||||
@media only screen and (min-width: ${theme.breakpoints.md}) {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: ${theme.spacing.md} 0;
|
||||
width: 100%;
|
||||
}
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { FC, memo } from 'react';
|
||||
import { css } from 'emotion';
|
||||
import { useTheme, CustomScrollbar, stylesFactory, Button } from '@grafana/ui';
|
||||
import { useTheme, CustomScrollbar, stylesFactory, IconButton } from '@grafana/ui';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { useSearchQuery } from '../hooks/useSearchQuery';
|
||||
import { useDashboardSearch } from '../hooks/useDashboardSearch';
|
||||
@ -24,11 +24,8 @@ export const DashboardSearch: FC<Props> = memo(({ onCloseSearch, folder }) => {
|
||||
|
||||
// The main search input has own keydown handler, also TagFilter uses input, so
|
||||
// clicking Esc when tagFilter is active shouldn't close the whole search overlay
|
||||
const onClose = (e: React.KeyboardEvent<HTMLElement>) => {
|
||||
const target = e.target as HTMLElement;
|
||||
if ((target.tagName as any) !== 'INPUT' && ['Escape', 'ArrowLeft'].includes(e.key)) {
|
||||
onCloseSearch();
|
||||
}
|
||||
const onClose = () => {
|
||||
onCloseSearch();
|
||||
};
|
||||
|
||||
const onLayoutChange = (layout: string) => {
|
||||
@ -39,59 +36,80 @@ export const DashboardSearch: FC<Props> = memo(({ onCloseSearch, folder }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div tabIndex={0} className="search-container" onKeyDown={onClose}>
|
||||
<SearchField
|
||||
query={query}
|
||||
onChange={onQueryChange}
|
||||
onKeyDown={onKeyDown}
|
||||
autoFocus
|
||||
clearable
|
||||
className={styles.searchField}
|
||||
/>
|
||||
<div className={styles.search}>
|
||||
<ActionRow
|
||||
{...{
|
||||
layout,
|
||||
onLayoutChange,
|
||||
onSortChange,
|
||||
onTagFilterChange,
|
||||
query,
|
||||
}}
|
||||
/>
|
||||
<CustomScrollbar>
|
||||
<SearchResults
|
||||
results={results}
|
||||
loading={loading}
|
||||
onTagSelected={onTagAdd}
|
||||
editable={false}
|
||||
onToggleSection={onToggleSection}
|
||||
layout={layout}
|
||||
<div tabIndex={0} className={styles.overlay}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.searchField}>
|
||||
<SearchField query={query} onChange={onQueryChange} onKeyDown={onKeyDown} autoFocus clearable />
|
||||
<div className={styles.closeBtn}>
|
||||
<IconButton name="times" surface="panel" onClick={onClose} size="xxl" tooltip="Close search" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.search}>
|
||||
<ActionRow
|
||||
{...{
|
||||
layout,
|
||||
onLayoutChange,
|
||||
onSortChange,
|
||||
onTagFilterChange,
|
||||
query,
|
||||
}}
|
||||
/>
|
||||
</CustomScrollbar>
|
||||
<CustomScrollbar>
|
||||
<SearchResults
|
||||
results={results}
|
||||
loading={loading}
|
||||
onTagSelected={onTagAdd}
|
||||
editable={false}
|
||||
onToggleSection={onToggleSection}
|
||||
layout={layout}
|
||||
/>
|
||||
</CustomScrollbar>
|
||||
</div>
|
||||
</div>
|
||||
<Button icon="times" className={styles.closeBtn} onClick={onCloseSearch} variant="secondary">
|
||||
Close
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
return {
|
||||
overlay: css`
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: ${theme.zIndex.sidemenu};
|
||||
position: fixed;
|
||||
background: ${theme.colors.dashboardBg};
|
||||
|
||||
@media only screen and (min-width: ${theme.breakpoints.md}) {
|
||||
left: 60px;
|
||||
z-index: ${theme.zIndex.navbarFixed + 1};
|
||||
}
|
||||
`,
|
||||
container: css`
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: ${theme.spacing.md};
|
||||
|
||||
height: 100%;
|
||||
|
||||
@media only screen and (min-width: ${theme.breakpoints.md}) {
|
||||
padding: 32px;
|
||||
}
|
||||
`,
|
||||
closeBtn: css`
|
||||
top: 10px;
|
||||
right: 8px;
|
||||
right: -5px;
|
||||
top: 2px;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
`,
|
||||
searchField: css`
|
||||
padding-left: ${theme.spacing.md};
|
||||
position: relative;
|
||||
`,
|
||||
search: css`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: ${theme.spacing.xl};
|
||||
height: 100%;
|
||||
max-width: 1400px;
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
@ -11,9 +11,9 @@ import { useManageDashboards } from '../hooks/useManageDashboards';
|
||||
import { SearchResultsFilter } from './SearchResultsFilter';
|
||||
import { SearchResults } from './SearchResults';
|
||||
import { DashboardActions } from './DashboardActions';
|
||||
import { SearchField } from './SearchField';
|
||||
import { useSearchLayout } from '../hooks/useSearchLayout';
|
||||
import { SearchLayout } from '../types';
|
||||
import { FilterInput } from 'app/core/components/FilterInput/FilterInput';
|
||||
|
||||
export interface Props {
|
||||
folderId?: number;
|
||||
@ -93,7 +93,13 @@ export const ManageDashboards: FC<Props> = memo(({ folderId, folderUid }) => {
|
||||
<div className={styles.container}>
|
||||
<div>
|
||||
<HorizontalGroup justify="space-between">
|
||||
<SearchField query={query} onChange={onQueryChange} className={styles.searchField} />
|
||||
<FilterInput
|
||||
labelClassName="gf-form--has-input-icon"
|
||||
inputClassName="gf-form-input width-20"
|
||||
value={query.query}
|
||||
onChange={onQueryChange}
|
||||
placeholder={'Search dashboards by name'}
|
||||
/>
|
||||
<DashboardActions isEditor={isEditor} canEdit={hasEditPermissionInFolders || canSave} folderId={folderId} />
|
||||
</HorizontalGroup>
|
||||
|
||||
@ -193,15 +199,6 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
container: css`
|
||||
height: 100%;
|
||||
`,
|
||||
searchField: css`
|
||||
height: auto;
|
||||
border-bottom: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
input {
|
||||
width: 400px;
|
||||
}
|
||||
`,
|
||||
results: css`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { FC, useContext } from 'react';
|
||||
import { css, cx } from 'emotion';
|
||||
import { ThemeContext, Icon, Input } from '@grafana/ui';
|
||||
import { ThemeContext } from '@grafana/ui';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { DashboardQuery } from '../types';
|
||||
|
||||
@ -17,21 +17,19 @@ interface SearchFieldProps extends Omit<React.InputHTMLAttributes<HTMLInputEleme
|
||||
const getSearchFieldStyles = (theme: GrafanaTheme) => ({
|
||||
wrapper: css`
|
||||
width: 100%;
|
||||
height: 55px; /* this variable is not part of GrafanaTheme yet*/
|
||||
display: flex;
|
||||
background-color: ${theme.colors.panelBg};
|
||||
border-bottom: 1px solid ${theme.colors.panelBorder};
|
||||
position: relative;
|
||||
align-items: center;
|
||||
`,
|
||||
input: css`
|
||||
max-width: 683px;
|
||||
margin-right: 90px;
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
background-color: ${theme.colors.panelBg};
|
||||
background: ${theme.colors.panelBg};
|
||||
flex-grow: 10;
|
||||
background-color: transparent;
|
||||
background: transparent;
|
||||
border-bottom: 2px solid ${theme.colors.border1};
|
||||
font-size: 20px;
|
||||
line-height: 38px;
|
||||
width: 100%;
|
||||
`,
|
||||
spacer: css`
|
||||
flex-grow: 1;
|
||||
@ -60,7 +58,7 @@ export const SearchField: FC<SearchFieldProps> = ({ query, onChange, size, clear
|
||||
|
||||
return (
|
||||
<div className={cx(styles.wrapper, className)}>
|
||||
<Input
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search dashboards by name"
|
||||
value={query.query}
|
||||
@ -70,8 +68,6 @@ export const SearchField: FC<SearchFieldProps> = ({ query, onChange, size, clear
|
||||
tabIndex={1}
|
||||
spellCheck={false}
|
||||
className={styles.input}
|
||||
prefix={<Icon name="search" />}
|
||||
suffix={clearable && <Icon name="times" className={styles.clearButton} onClick={() => onChange('')} />}
|
||||
{...inputProps}
|
||||
/>
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
&--edit {
|
||||
background: $panel-bg;
|
||||
border-bottom: $panel-border;
|
||||
box-shadow: 0 0 10px $dashboard-bg;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,79 +1,3 @@
|
||||
.search-container {
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: ($zindex-modal-backdrop + 10);
|
||||
position: fixed;
|
||||
background: $dashboard-bg;
|
||||
}
|
||||
|
||||
// Search
|
||||
.search-dropdown {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100% - #{$navbarHeight});
|
||||
}
|
||||
|
||||
.search-dropdown__col_1 {
|
||||
padding: $dashboard-padding;
|
||||
max-width: 700px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
height: 100%; // Chrome 74 needs this to make the element scrollable
|
||||
|
||||
.search-item--indent {
|
||||
margin-left: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-dropdown__col_2 {
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
padding-top: 16px;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.search-filter-box {
|
||||
background: $panel-bg;
|
||||
border: $panel-border;
|
||||
border-radius: 3px;
|
||||
padding: $spacer * 1.5;
|
||||
min-width: 340px;
|
||||
margin-bottom: $spacer * 1.5;
|
||||
}
|
||||
|
||||
.search-filter-box__header {
|
||||
border-bottom: 1px solid $hr-border-color;
|
||||
margin-bottom: $spacer * 1.5;
|
||||
}
|
||||
|
||||
.search-filter-box-link {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
i,
|
||||
img {
|
||||
font-size: 20px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-results-scroller {
|
||||
display: flex;
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
background: $panel-bg;
|
||||
border: $panel-border;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.search-results-container {
|
||||
display: block;
|
||||
padding: $spacer;
|
||||
@ -232,10 +156,6 @@
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
.search-container {
|
||||
left: $side-menu-width;
|
||||
}
|
||||
|
||||
.search-item__tags {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
@ -243,38 +163,4 @@
|
||||
justify-content: flex-end;
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
.search-dropdown__col_2 {
|
||||
display: flex;
|
||||
margin-bottom: $space-md;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
.search-dropdown__col_2 {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
max-width: 700px;
|
||||
height: 260px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.search-filter-box {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
.search-dropdown {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.search-dropdown__col_2 {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.search-filter-box {
|
||||
margin-left: $spacer * 1.5;
|
||||
margin-bottom: $spacer * 1.5;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user