SearchField.tsx 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import { css, cx } from '@emotion/css';
  2. import React, { FC } from 'react';
  3. import { GrafanaTheme } from '@grafana/data';
  4. import { useStyles } from '@grafana/ui';
  5. import { DashboardQuery } from '../types';
  6. type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
  7. interface SearchFieldProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> {
  8. query: DashboardQuery;
  9. onChange: (query: string) => void;
  10. onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
  11. clearable?: boolean;
  12. width?: number;
  13. }
  14. const getSearchFieldStyles = (theme: GrafanaTheme) => ({
  15. wrapper: css`
  16. width: 100%;
  17. display: flex;
  18. position: relative;
  19. align-items: center;
  20. `,
  21. input: css`
  22. box-sizing: border-box;
  23. outline: none;
  24. background-color: transparent;
  25. background: transparent;
  26. border-bottom: 2px solid ${theme.colors.border1};
  27. font-size: 20px;
  28. line-height: 38px;
  29. width: 100%;
  30. &::placeholder {
  31. color: ${theme.colors.textWeak};
  32. }
  33. `,
  34. spacer: css`
  35. flex-grow: 1;
  36. `,
  37. icon: cx(
  38. css`
  39. color: ${theme.colors.textWeak};
  40. padding: 0 ${theme.spacing.md};
  41. `
  42. ),
  43. clearButton: css`
  44. font-size: ${theme.typography.size.sm};
  45. color: ${theme.colors.textWeak};
  46. text-decoration: underline;
  47. &:hover {
  48. cursor: pointer;
  49. color: ${theme.colors.textStrong};
  50. }
  51. `,
  52. });
  53. export const SearchField: FC<SearchFieldProps> = ({ query, onChange, size, clearable, className, ...inputProps }) => {
  54. const styles = useStyles(getSearchFieldStyles);
  55. return (
  56. <div className={cx(styles.wrapper, className)}>
  57. <input
  58. type="text"
  59. placeholder="Search dashboards by name"
  60. value={query.query}
  61. onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
  62. onChange(event.currentTarget.value);
  63. }}
  64. tabIndex={0}
  65. spellCheck={false}
  66. className={styles.input}
  67. {...inputProps}
  68. />
  69. <div className={styles.spacer} />
  70. </div>
  71. );
  72. };