diff --git a/packages/grafana-ui/src/components/FilterInput/FilterInput.tsx b/packages/grafana-ui/src/components/FilterInput/FilterInput.tsx index 93a238e7d97..08f0ce6234f 100644 --- a/packages/grafana-ui/src/components/FilterInput/FilterInput.tsx +++ b/packages/grafana-ui/src/components/FilterInput/FilterInput.tsx @@ -6,35 +6,40 @@ import { Trans } from '@grafana/i18n'; import { useCombinedRefs } from '../../utils/useCombinedRefs'; import { Button } from '../Button/Button'; import { Icon } from '../Icon/Icon'; -import { Input } from '../Input/Input'; +import { Input, Props as InputProps } from '../Input/Input'; export interface Props extends Omit, 'onChange'> { value: string | undefined; width?: number; onChange: (value: string) => void; escapeRegex?: boolean; + suffix?: InputProps['suffix']; } export const FilterInput = forwardRef( - ({ value, width, onChange, escapeRegex = true, ...restProps }, ref) => { + ({ value, width, onChange, escapeRegex = true, suffix: _suffix, ...restProps }, ref) => { const innerRef = useRef(null); const combinedRef = useCombinedRefs(ref, innerRef); - const suffix = - value !== '' ? ( - - ) : null; + const suffix = ( + <> + {value !== '' && ( + + )} + {_suffix} + + ); return ( selectedItems.length > 0 && items.length > selectedItems.length, [items, selectedItems] ); - const selectCheckLabel = useMemo( - () => (selectedItems.length ? `${selectedItems.length} selected` : `Select all`), - [selectedItems] - ); + const selectCheckLabel = useMemo(() => { + if (!values.length) { + return t('grafana-ui.table.filter.select-all', 'Select all'); + } + if (values.length !== selectedItems.length) { + return t('grafana-ui.table.filter.selected-some-hidden', '{{ numSelected }} selected ({{ numHidden }} hidden)', { + numSelected: values.length, + numHidden: values.length - selectedItems.length, + }); + } + return t('grafana-ui.table.filter.selected', '{{ numSelected }} selected', { + numSelected: values.length, + }); + }, [selectedItems.length, values.length]); const selectCheckDescription = useMemo( () => items.length !== selectedItems.length - ? 'Add all displayed values to the filter' - : 'Remove all displayed values from the filter', + ? t('grafana-ui.table.filter.add-all', 'Add all displayed values to the filter') + : t('grafana-ui.table.filter.remove-all', 'Remove all displayed values from the filter'), [items, selectedItems] ); const styles = useStyles2(getStyles); const theme = useTheme2(); - const gutter = theme.spacing.gridSize; + const gutter = theme.spacing.gridSize / 2; const height = useMemo(() => Math.min(items.length * ITEM_HEIGHT, MIN_HEIGHT) + gutter, [gutter, items.length]); const onCheckedChanged = useCallback( @@ -207,9 +217,8 @@ function ItemRenderer({ index, style, data: { onCheckedChanged, items, values, c const getStyles = (theme: GrafanaTheme2) => ({ filterList: css({ label: 'filterList', - backgroundColor: theme.components.input.background, - border: `1px solid ${theme.colors.border.medium}`, - borderRadius: theme.shape.radius.default, + marginBottom: theme.spacing(0.5), + borderBottom: `1px solid ${theme.colors.border.weak}`, }), filterListRow: css({ label: 'filterListRow', @@ -223,12 +232,6 @@ const getStyles = (theme: GrafanaTheme2) => ({ backgroundColor: theme.colors.action.hover, }, }), - selectDivider: css({ - label: 'selectDivider', - width: '100%', - borderTop: `1px solid ${theme.colors.border.medium}`, - padding: theme.spacing(0.5, 2), - }), noValuesLabel: css({ paddingTop: theme.spacing(1), }), diff --git a/packages/grafana-ui/src/components/Table/TableNG/Filter/FilterPopup.tsx b/packages/grafana-ui/src/components/Table/TableNG/Filter/FilterPopup.tsx index de258a44815..40c96d83cb9 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Filter/FilterPopup.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Filter/FilterPopup.tsx @@ -118,27 +118,28 @@ export const FilterPopup = ({ ref={containerRef} > - - {field && } - - - -
+ {field && } - +
+ + } + /> +
- -
+ + + {clearFilterVisible && ( - - - + )} @@ -186,7 +183,7 @@ const getStyles = (theme: GrafanaTheme2) => ({ filterContainer: css({ label: 'filterContainer', width: '100%', - minWidth: '250px', + minWidth: '320px', height: '100%', backgroundColor: theme.colors.background.primary, border: `1px solid ${theme.colors.border.weak}`, @@ -194,14 +191,19 @@ const getStyles = (theme: GrafanaTheme2) => ({ boxShadow: theme.shadows.z3, borderRadius: theme.shape.radius.default, }), - listDivider: css({ - label: 'listDivider', - width: '100%', - borderTop: `1px solid ${theme.colors.border.medium}`, - }), label: css({ marginBottom: 0, }), + inputContainer: css({ + width: 300, + }), + buttonSelectOverrides: css({ + fontSize: 12, + '&:hover, &:focus, &:active': { + color: theme.colors.text.primary, + background: 'transparent', + }, + }), }); const stopPropagation = (event: React.MouseEvent) => { diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index f690c04b70a..e2efd17b56c 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -9002,6 +9002,13 @@ "copy": "Copy to Clipboard", "csv-counts": "Rows:{{rows}}, Columns:{{columns}}", "csv-placeholder": "Enter CSV here...", + "filter": { + "add-all": "Add all displayed values to the filter", + "remove-all": "Remove all displayed values from the filter", + "select-all": "Select all", + "selected": "{{ numSelected }} selected", + "selected-some-hidden": "{{ numSelected }} selected ({{ numHidden }} hidden)" + }, "filter-placeholder": "Filter values", "filter-popup-apply": "Ok", "filter-popup-aria-label-match-case": "Match case",