Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Total hits and histogram control touchups #9

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ describe('<ToolbarButton />', () => {
component.find('button').simulate('click');
expect(mockHandler).toHaveBeenCalled();
});

test('accepts an onBlur handler', () => {
const mockHandler = jest.fn();
const component = mountWithIntl(<ToolbarButton label="Create chart" onBlur={mockHandler} />);
component.find('button').simulate('blur');
expect(mockHandler).toHaveBeenCalled();
});
});

describe('iconButton', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type ButtonRenderStyle = 'standard' | 'iconButton';
interface ToolbarButtonCommonProps
extends Pick<
EuiButtonPropsForButton,
'onClick' | 'iconType' | 'size' | 'data-test-subj' | 'isDisabled' | 'aria-label'
'onClick' | 'onBlur' | 'iconType' | 'size' | 'data-test-subj' | 'isDisabled' | 'aria-label'
> {
/**
* Render style of the toolbar button
Expand Down
6 changes: 5 additions & 1 deletion src/core/public/styles/_base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
// focus states in Kibana.
:focus {
&:not([class^='eui']):not(.kbn-resetFocusState) {
@include euiFocusRing;
// The focus policy causes double focus rings to appear on EuiSelectableList
// since the focusable element does not contain a class starting with "eui".
&:not(.euiSelectableList__list > ul) {
@include euiFocusRing;
}
}
}

Expand Down
110 changes: 60 additions & 50 deletions src/plugins/unified_histogram/public/chart/chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -277,58 +277,68 @@ export function Chart({
responsive={false}
>
<EuiFlexItem grow={false} css={chartToolbarCss}>
<EuiFlexGroup direction="row" gutterSize="s" responsive={false} alignItems="center">
<EuiFlexItem grow={false}>
{renderCustomChartToggleActions ? (
renderCustomChartToggleActions()
) : (
<IconButtonGroup
legend={i18n.translate('unifiedHistogram.hideChartButtongroupLegend', {
defaultMessage: 'Chart visibility',
})}
buttonSize="s"
buttons={[
{
label: chartVisible
? i18n.translate('unifiedHistogram.hideChartButton', {
defaultMessage: 'Hide chart',
})
: i18n.translate('unifiedHistogram.showChartButton', {
defaultMessage: 'Show chart',
}),
iconType: chartVisible ? 'transitionTopOut' : 'transitionTopIn',
'data-test-subj': 'unifiedHistogramToggleChartButton',
onClick: toggleHideChart,
},
]}
/>
)}
</EuiFlexItem>
{chartVisible && !isPlainRecord && !!onTimeIntervalChange && (
<EuiFlexItem grow={false}>
<TimeIntervalSelector chart={chart} onTimeIntervalChange={onTimeIntervalChange} />
</EuiFlexItem>
)}
<EuiFlexItem>
<div>
{chartVisible && breakdown && (
<BreakdownFieldSelector
dataView={dataView}
breakdown={breakdown}
onBreakdownFieldChange={onBreakdownFieldChange}
/>
)}
{chartVisible &&
currentSuggestion &&
allSuggestions &&
allSuggestions?.length > 1 && (
<SuggestionSelector
suggestions={allSuggestions}
activeSuggestion={currentSuggestion}
onSuggestionChange={onSuggestionSelectorChange}
<EuiFlexGroup
direction="row"
gutterSize="s"
responsive={false}
alignItems="center"
justifyContent="spaceBetween"
>
<EuiFlexItem grow={false} css={{ minWidth: 0 }}>
<EuiFlexGroup direction="row" gutterSize="s" responsive={false} alignItems="center">
<EuiFlexItem grow={false}>
{renderCustomChartToggleActions ? (
renderCustomChartToggleActions()
) : (
<IconButtonGroup
legend={i18n.translate('unifiedHistogram.hideChartButtongroupLegend', {
defaultMessage: 'Chart visibility',
})}
buttonSize="s"
buttons={[
{
label: chartVisible
? i18n.translate('unifiedHistogram.hideChartButton', {
defaultMessage: 'Hide chart',
})
: i18n.translate('unifiedHistogram.showChartButton', {
defaultMessage: 'Show chart',
}),
iconType: chartVisible ? 'transitionTopOut' : 'transitionTopIn',
'data-test-subj': 'unifiedHistogramToggleChartButton',
onClick: toggleHideChart,
},
]}
/>
)}
</div>
</EuiFlexItem>
{chartVisible && !isPlainRecord && !!onTimeIntervalChange && (
<EuiFlexItem grow={false} css={{ minWidth: 0 }}>
<TimeIntervalSelector chart={chart} onTimeIntervalChange={onTimeIntervalChange} />
</EuiFlexItem>
)}
<EuiFlexItem grow={false} css={{ minWidth: 0 }}>
<div>
{chartVisible && breakdown && (
<BreakdownFieldSelector
dataView={dataView}
breakdown={breakdown}
onBreakdownFieldChange={onBreakdownFieldChange}
/>
)}
{chartVisible &&
currentSuggestion &&
allSuggestions &&
allSuggestions?.length > 1 && (
<SuggestionSelector
suggestions={allSuggestions}
activeSuggestion={currentSuggestion}
onSuggestionChange={onSuggestionSelectorChange}
/>
)}
</div>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
{chartVisible && actions.length > 0 && (
<EuiFlexItem grow={false}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ export const SuggestionSelector = ({
position="top"
content={suggestionsPopoverDisabled ? undefined : activeSuggestion?.title}
anchorProps={{ css: suggestionComboCss }}
display="block"
delay="long"
>
<EuiComboBox
data-test-subj="unifiedHistogramSuggestionSelector"
Expand Down
103 changes: 69 additions & 34 deletions src/plugins/unified_histogram/public/chart/toolbar_selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,20 @@

import React, { useCallback, ReactElement, useState, useMemo } from 'react';
import {
EuiFlexGroup,
EuiFlexItem,
EuiPopover,
EuiPopoverTitle,
EuiSelectable,
EuiSelectableProps,
EuiSelectableOption,
useEuiTheme,
EuiPanel,
EuiToolTip,
} from '@elastic/eui';
import { ToolbarButton } from '@kbn/shared-ux-button-toolbar';
import { FormattedMessage } from '@kbn/i18n-react';
import { css } from '@emotion/react';
import { calculateWidthFromEntries } from '@kbn/calculate-width-from-char-count';
import { i18n } from '@kbn/i18n';

export const EMPTY_OPTION = '__EMPTY_SELECTOR_OPTION__';

Expand Down Expand Up @@ -48,6 +49,14 @@ export const ToolbarSelector: React.FC<ToolbarSelectorProps> = ({
const { euiTheme } = useEuiTheme();
const [isOpen, setIsOpen] = useState<boolean>(false);
const [searchTerm, setSearchTerm] = useState<string>();
const [labelPopoverDisabled, setLabelPopoverDisabled] = useState(false);

const disableLabelPopover = useCallback(() => setLabelPopoverDisabled(true), []);

const enableLabelPopover = useCallback(
() => setTimeout(() => setLabelPopoverDisabled(false)),
[]
);

const onSelectionChange = useCallback(
(newOptions) => {
Expand All @@ -57,15 +66,24 @@ export const ToolbarSelector: React.FC<ToolbarSelectorProps> = ({
chosenOption?.value && chosenOption?.value !== EMPTY_OPTION ? chosenOption : undefined
);
setIsOpen(false);
disableLabelPopover();
},
[onChange, setIsOpen]
[disableLabelPopover, onChange]
);

const searchProps: EuiSelectableProps['searchProps'] = useMemo(
() =>
searchable
? {
id: `${dataTestSubj}SelectableInput`,
'data-test-subj': `${dataTestSubj}SelectorSearch`,
compressed: true,
placeholder: i18n.translate(
'unifiedHistogram.toolbarSelectorPopover.searchPlaceholder',
{
defaultMessage: 'Search',
}
),
onChange: (value) => setSearchTerm(value),
}
: undefined,
Expand All @@ -78,62 +96,79 @@ export const ToolbarSelector: React.FC<ToolbarSelectorProps> = ({
<EuiPopover
id={dataTestSubj}
ownFocus
initialFocus={`.${dataTestSubj}__popoverPanel`}
panelClassName={`${dataTestSubj}__popoverPanel`}
initialFocus={
searchable ? `#${dataTestSubj}SelectableInput` : `#${dataTestSubj}Selectable_listbox`
}
panelProps={{
css: css`
min-width: ${panelMinWidth}px;
`,
css: searchable
? css`
min-width: ${panelMinWidth}px;
`
: css`
width: ${panelMinWidth}px;
`,
}}
panelPaddingSize="s"
panelPaddingSize="none"
button={
<ToolbarButton
size="s"
css={css`
font-weight: ${euiTheme.font.weight.medium};
max-width: ${euiTheme.base * 20}px;
`}
data-test-subj={`${dataTestSubj}Button`}
data-selected-value={dataSelectedValue}
aria-label={popoverTitle}
label={buttonLabel}
onClick={() => setIsOpen(!isOpen)}
/>
<EuiToolTip content={labelPopoverDisabled ? undefined : buttonLabel} delay="long">
<ToolbarButton
size="s"
css={css`
font-weight: ${euiTheme.font.weight.medium};
width: 100%;
min-width: 0;
max-width: ${euiTheme.base * 20}px;
`}
data-test-subj={`${dataTestSubj}Button`}
data-selected-value={dataSelectedValue}
aria-label={popoverTitle}
label={buttonLabel}
onClick={() => setIsOpen(!isOpen)}
onBlur={enableLabelPopover}
/>
</EuiToolTip>
}
isOpen={isOpen}
closePopover={() => setIsOpen(false)}
anchorPosition="downLeft"
>
<EuiPopoverTitle>
<EuiFlexGroup alignItems="center" responsive={false}>
<EuiFlexItem>{popoverTitle}</EuiFlexItem>
</EuiFlexGroup>
</EuiPopoverTitle>
<EuiPopoverTitle paddingSize="s">{popoverTitle}</EuiPopoverTitle>
<EuiSelectable
id={`${dataTestSubj}Selectable`}
singleSelection
aria-label={popoverTitle}
data-test-subj={`${dataTestSubj}Selectable`}
options={options}
onChange={onSelectionChange}
listProps={{
truncationProps: { truncation: 'middle' },
isVirtualized: searchable,
}}
{...(searchable
? {
searchable,
searchProps,
noMatchesMessage: (
<FormattedMessage
id="unifiedHistogram.toolbarSelectorPopover.noResults"
defaultMessage="No results found for {term}"
values={{
term: <strong>{searchTerm}</strong>,
}}
/>
<p>
<FormattedMessage
id="unifiedHistogram.toolbarSelectorPopover.noResults"
defaultMessage="No results found for {term}"
values={{
term: <strong>{searchTerm}</strong>,
}}
/>
</p>
),
}
: {})}
>
{(list, search) => (
<>
{search}
{search && (
<EuiPanel paddingSize="s" hasShadow={false} css={{ paddingBottom: 0 }}>
{search}
</EuiPanel>
)}
{list}
</>
)}
Expand Down
Loading