diff --git a/examples/unified_field_list_examples/public/field_list_sidebar.tsx b/examples/unified_field_list_examples/public/field_list_sidebar.tsx index 121132e89b810..9e71071d327ce 100644 --- a/examples/unified_field_list_examples/public/field_list_sidebar.tsx +++ b/examples/unified_field_list_examples/public/field_list_sidebar.tsx @@ -33,6 +33,8 @@ const getCreationOptions: UnifiedFieldListSidebarContainerProps['getCreationOpti originatingApp: PLUGIN_ID, localStorageKeyPrefix: 'examples', timeRangeUpdatesType: 'timefilter', + compressed: true, + showSidebarToggleButton: true, disablePopularFields: true, }; }; diff --git a/packages/kbn-dom-drag-drop/src/drag_drop.test.tsx b/packages/kbn-dom-drag-drop/src/drag_drop.test.tsx index 54965548aa264..09de21fbe3dc9 100644 --- a/packages/kbn-dom-drag-drop/src/drag_drop.test.tsx +++ b/packages/kbn-dom-drag-drop/src/drag_drop.test.tsx @@ -119,6 +119,28 @@ describe('DragDrop', () => { }); }); + test('dragstart sets dragClassName as expected', async () => { + const dndDispatch = jest.fn(); + const component = mount( + + + + + + ); + const dragDrop = component.find('[data-test-subj="testDragDrop"]').at(0); + + expect(dragDrop.getDOMNode().querySelector('.dragTest')).toBeNull(); + dragDrop.simulate('dragstart', { dataTransfer }); + expect(dragDrop.getDOMNode().querySelector('.dragTest')).toBeDefined(); + + act(() => { + jest.runAllTimers(); + }); + + expect(dragDrop.getDOMNode().querySelector('.dragTest')).toBeNull(); + }); + test('drop resets all the things', async () => { const preventDefault = jest.fn(); const stopPropagation = jest.fn(); diff --git a/packages/kbn-dom-drag-drop/src/drag_drop.tsx b/packages/kbn-dom-drag-drop/src/drag_drop.tsx index ab4158ad31543..b20570ee6969c 100644 --- a/packages/kbn-dom-drag-drop/src/drag_drop.tsx +++ b/packages/kbn-dom-drag-drop/src/drag_drop.tsx @@ -42,6 +42,10 @@ interface BaseProps { * The CSS class(es) for the root element. */ className?: string; + /** + * CSS class to apply when the item is being dragged + */ + dragClassName?: string; /** * The event handler that fires when an item @@ -212,6 +216,7 @@ const removeSelection = () => { const DragInner = memo(function DragInner({ dataTestSubj, className, + dragClassName, value, children, dndDispatch, @@ -305,6 +310,18 @@ const DragInner = memo(function DragInner({ // so we know we have DraggableProps if we reach this code. if (e && 'dataTransfer' in e) { e.dataTransfer.setData('text', value.humanData.label); + + // Apply an optional class to the element being dragged so the ghost + // can be styled. We must add it to the actual element for a single + // frame before removing it so the ghost picks up the styling. + const current = e.currentTarget; + + if (dragClassName && !current.classList.contains(dragClassName)) { + current.classList.add(dragClassName); + requestAnimationFrame(() => { + current.classList.remove(dragClassName); + }); + } } // Chrome causes issues if you try to render from within a diff --git a/packages/kbn-unified-data-table/src/components/data_table.scss b/packages/kbn-unified-data-table/src/components/data_table.scss index 8b0f8719a450f..048a641cf7562 100644 --- a/packages/kbn-unified-data-table/src/components/data_table.scss +++ b/packages/kbn-unified-data-table/src/components/data_table.scss @@ -3,32 +3,6 @@ max-width: 100%; height: 100%; overflow: hidden; - border-radius: $euiBorderRadius; - - .euiDataGrid__controls { - border: none; - border-bottom: $euiBorderThin; - } - - .euiDataGridRowCell.euiDataGridRowCell--firstColumn { - border-left: none; - padding: 0; - } - - .euiDataGridRowCell.euiDataGridRowCell--lastColumn { - border-right: none; - } - - .unifiedDataTable__table .euiDataGridRowCell:first-of-type, - .unifiedDataTable__table .euiDataGrid--headerShade.euiDataGrid--bordersAll .euiDataGridHeaderCell:first-of-type { - border-left: none; - border-right: none; - } - - .euiDataGridRowCell:last-of-type, - .euiDataGridHeaderCell:last-of-type { - border-right: none; - } } .unifiedDataTable__cellValue { @@ -57,6 +31,29 @@ flex-direction: column; flex-wrap: nowrap; height: 100%; + + .euiDataGrid__content { + background: transparent; + } + + .euiDataGrid__controls { + border-top: $euiBorderThin; + } + + .euiDataGrid--headerUnderline .euiDataGridHeaderCell { + border-bottom: $euiBorderThin; + } + + .euiDataGridRowCell.euiDataGridRowCell--controlColumn[data-gridcell-column-id='openDetails'], + .euiDataGridRowCell.euiDataGridRowCell--controlColumn[data-gridcell-column-id='select'] { + padding-left: 0; + padding-right: 0; + } + + .euiDataGrid--rowHoverHighlight .euiDataGridRow:hover, + .euiDataGrid--rowHoverHighlight .euiDataGridRow:hover .euiDataGridRowCell__contentByHeight + .euiDataGridRowCell__expandActions { + background-color: tintOrShade($euiColorLightShade, 50%, 0); + } } .unifiedDataTable__table { @@ -65,14 +62,6 @@ min-height: 0; } -.unifiedDataTable__footer { - flex-shrink: 0; - background-color: $euiColorLightShade; - padding: $euiSize / 2 $euiSize; - margin-top: $euiSize / 4; - text-align: center; -} - .unifiedDataTable__flyoutHeader { white-space: nowrap; } @@ -118,7 +107,35 @@ @include euiTextTruncate; } +.unifiedDataTable__rowControl { + // fine-tuning the vertical alignment with the text for any row height setting + margin-top: -3px; + .euiDataGridRowCell__truncate & { // "Single line" row height setting + margin-top: 0; + } +} + +.unifiedDataTable__descriptionList { + // force the content truncation when "Single line" row height setting is active + .euiDataGridRowCell__truncate & { + -webkit-line-clamp: 1; + display: -webkit-box; + -webkit-box-orient: vertical; + height: 100%; + overflow: hidden; + } +} + +.unifiedDataTable__descriptionListTitle { + margin-inline: 0 0; + padding-inline: 0; + background: transparent; + font-weight: $euiFontWeightBold; +} + .unifiedDataTable__descriptionListDescription { + margin-inline: $euiSizeS $euiSizeS; + padding-inline: 0; word-break: break-all; white-space: normal; diff --git a/packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx b/packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx index 01246603643fd..7eceeda173809 100644 --- a/packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx @@ -218,7 +218,7 @@ describe('Data table columns', function () { , "displayAsText": "timestamp", "id": "timestamp", - "initialWidth": 210, + "initialWidth": 212, "isSortable": true, "schema": "datetime", "visibleCellActions": undefined, @@ -406,7 +406,7 @@ describe('Data table columns', function () { , "displayAsText": "timestamp", "id": "timestamp", - "initialWidth": 210, + "initialWidth": 212, "isSortable": true, "schema": "datetime", "visibleCellActions": undefined, diff --git a/packages/kbn-unified-data-table/src/components/data_table_columns.tsx b/packages/kbn-unified-data-table/src/components/data_table_columns.tsx index 4b66f2a2bd6cf..4b4ac622e78f6 100644 --- a/packages/kbn-unified-data-table/src/components/data_table_columns.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_columns.tsx @@ -30,7 +30,7 @@ import { buildEditFieldButton } from './build_edit_field_button'; const openDetails = { id: 'openDetails', - width: 24, + width: 26, headerCellRender: () => ( diff --git a/packages/kbn-unified-data-table/src/components/data_table_document_selection.tsx b/packages/kbn-unified-data-table/src/components/data_table_document_selection.tsx index 213e24790e840..bb0a0dc2b775a 100644 --- a/packages/kbn-unified-data-table/src/components/data_table_document_selection.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_document_selection.tsx @@ -15,14 +15,19 @@ import { EuiCopy, EuiDataGridCellValueElementProps, EuiPopover, + EuiFlexGroup, + EuiFlexItem, + useEuiTheme, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { euiDarkVars as themeDark, euiLightVars as themeLight } from '@kbn/ui-theme'; import { i18n } from '@kbn/i18n'; +import { css } from '@emotion/react'; import type { DataTableRecord } from '@kbn/discover-utils/types'; import { UnifiedDataTableContext } from '../table_context'; export const SelectButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueElementProps) => { + const { euiTheme } = useEuiTheme(); const { selectedDocs, expanded, rows, isDarkMode, setSelectedDocs } = useContext(UnifiedDataTableContext); const doc = useMemo(() => rows[rowIndex], [rows, rowIndex]); @@ -46,20 +51,33 @@ export const SelectButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueEle }, [expanded, doc, setCellProps, isDarkMode]); return ( - { - if (checked) { - const newSelection = selectedDocs.filter((docId) => docId !== doc.id); - setSelectedDocs(newSelection); - } else { - setSelectedDocs([...selectedDocs, doc.id]); - } - }} - /> + + + { + if (checked) { + const newSelection = selectedDocs.filter((docId) => docId !== doc.id); + setSelectedDocs(newSelection); + } else { + setSelectedDocs([...selectedDocs, doc.id]); + } + }} + /> + + ); }; diff --git a/packages/kbn-unified-data-table/src/components/data_table_expand_button.tsx b/packages/kbn-unified-data-table/src/components/data_table_expand_button.tsx index 108ffaa4ec5fe..c44ea74791b33 100644 --- a/packages/kbn-unified-data-table/src/components/data_table_expand_button.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_expand_button.tsx @@ -62,23 +62,25 @@ export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueEle } return ( - - { - const nextHit = isCurrentRowExpanded ? undefined : current; - toolTipRef.current?.hideToolTip(); - setPressed(Boolean(nextHit)); - setExpanded?.(nextHit); - }} - color={isCurrentRowExpanded ? 'primary' : 'text'} - iconType={isCurrentRowExpanded ? 'minimize' : 'expand'} - isSelected={isCurrentRowExpanded} - /> - +
+ + { + const nextHit = isCurrentRowExpanded ? undefined : current; + toolTipRef.current?.hideToolTip(); + setPressed(Boolean(nextHit)); + setExpanded?.(nextHit); + }} + color={isCurrentRowExpanded ? 'primary' : 'text'} + iconType={isCurrentRowExpanded ? 'minimize' : 'expand'} + isSelected={isCurrentRowExpanded} + /> + +
); }; diff --git a/packages/kbn-unified-data-table/src/constants.ts b/packages/kbn-unified-data-table/src/constants.ts index 1fb391ddc7f70..c85751756cefd 100644 --- a/packages/kbn-unified-data-table/src/constants.ts +++ b/packages/kbn-unified-data-table/src/constants.ts @@ -13,15 +13,17 @@ export const MAX_LOADED_GRID_ROWS = 10000; export const ROWS_PER_PAGE_OPTIONS = [10, 25, 50, DEFAULT_ROWS_PER_PAGE, 250, 500]; export const defaultMonacoEditorWidth = 370; -export const defaultTimeColumnWidth = 210; +export const defaultTimeColumnWidth = 212; export const kibanaJSON = 'kibana-json'; -export const GRID_STYLE = { - border: 'all', +export const GRID_STYLE: EuiDataGridStyle = { + border: 'horizontal', fontSize: 's', - cellPadding: 's', - rowHover: 'none', -} as EuiDataGridStyle; + cellPadding: 'l', + rowHover: 'highlight', + header: 'underline', + stripes: true, +}; export const toolbarVisibility = { showColumnSelector: { diff --git a/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx b/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx index 941dccabf2474..0f6624a120b9c 100644 --- a/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx +++ b/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx @@ -212,7 +212,9 @@ describe('Unified data table cell rendering', function () { compressed={true} type="inline" > - + extension - + bytesDisplayName - + _index - + _score - + extension - + bytesDisplayName - + _index - + _score - + extension - + bytesDisplayName - + _index - + _score - + object.value - + object.value {pairs.map(([key, value]) => ( - {key} + + {key} + renders properly with a drag handl "aria-label": "Preview bytes: number", } } - className="unifiedFieldListItemButton unifiedFieldListItemButton--number unifiedFieldListItemButton--exists custom" + className="unifiedFieldListItemButton unifiedFieldListItemButton--number unifiedFieldListItemButton--exists unifiedFieldListItemButton--withDragHandle custom" dataTestSubj="test-subj" dragHandle={ diff --git a/packages/kbn-unified-field-list/src/components/field_item_button/field_item_button.tsx b/packages/kbn-unified-field-list/src/components/field_item_button/field_item_button.tsx index 13860a0e4f155..c9be7af08638c 100644 --- a/packages/kbn-unified-field-list/src/components/field_item_button/field_item_button.tsx +++ b/packages/kbn-unified-field-list/src/components/field_item_button/field_item_button.tsx @@ -105,6 +105,7 @@ export function FieldItemButton({ [`unifiedFieldListItemButton--${type}`]: type, [`unifiedFieldListItemButton--exists`]: !isEmpty, [`unifiedFieldListItemButton--missing`]: isEmpty, + [`unifiedFieldListItemButton--withDragHandle`]: Boolean(otherProps.dragHandle), }, className ); diff --git a/packages/kbn-unified-field-list/src/components/field_list_filters/field_list_filters.tsx b/packages/kbn-unified-field-list/src/components/field_list_filters/field_list_filters.tsx index e1834dd8fd5f0..4410bc82eeef8 100644 --- a/packages/kbn-unified-field-list/src/components/field_list_filters/field_list_filters.tsx +++ b/packages/kbn-unified-field-list/src/components/field_list_filters/field_list_filters.tsx @@ -23,6 +23,7 @@ export interface FieldListFiltersProps { getCustomFieldType?: FieldTypeFilterProps['getCustomFieldType']; onSupportedFieldFilter?: FieldTypeFilterProps['onSupportedFieldFilter']; onChangeFieldTypes: FieldTypeFilterProps['onChange']; + compressed?: FieldNameSearchProps['compressed']; nameFilter: FieldNameSearchProps['nameFilter']; screenReaderDescriptionId?: FieldNameSearchProps['screenReaderDescriptionId']; onChangeNameFilter: FieldNameSearchProps['onChange']; @@ -38,6 +39,7 @@ export interface FieldListFiltersProps { * @param getCustomFieldType * @param onSupportedFieldFilter * @param onChangeFieldTypes + * @param compressed * @param nameFilter * @param screenReaderDescriptionId * @param onChangeNameFilter @@ -52,6 +54,7 @@ function InnerFieldListFilters({ getCustomFieldType, onSupportedFieldFilter, onChangeFieldTypes, + compressed, nameFilter, screenReaderDescriptionId, onChangeNameFilter, @@ -72,6 +75,7 @@ function InnerFieldListFilters({ /> ) : undefined } + compressed={compressed} nameFilter={nameFilter} screenReaderDescriptionId={screenReaderDescriptionId} onChange={onChangeNameFilter} diff --git a/packages/kbn-unified-field-list/src/components/field_list_filters/field_name_search.tsx b/packages/kbn-unified-field-list/src/components/field_list_filters/field_name_search.tsx index 91d78850e4453..faf146adfd831 100644 --- a/packages/kbn-unified-field-list/src/components/field_list_filters/field_name_search.tsx +++ b/packages/kbn-unified-field-list/src/components/field_list_filters/field_name_search.tsx @@ -16,6 +16,7 @@ import { EuiFieldSearch, type EuiFieldSearchProps } from '@elastic/eui'; export interface FieldNameSearchProps { 'data-test-subj': string; append?: EuiFieldSearchProps['append']; + compressed?: EuiFieldSearchProps['compressed']; nameFilter: string; screenReaderDescriptionId?: string; onChange: (nameFilter: string) => unknown; @@ -25,6 +26,7 @@ export interface FieldNameSearchProps { * Search input for fields list * @param dataTestSubject * @param append + * @param compressed * @param nameFilter * @param screenReaderDescriptionId * @param onChange @@ -33,6 +35,7 @@ export interface FieldNameSearchProps { export const FieldNameSearch: React.FC = ({ 'data-test-subj': dataTestSubject, append, + compressed, nameFilter, screenReaderDescriptionId, onChange, @@ -52,6 +55,7 @@ export const FieldNameSearch: React.FC = ({ placeholder={searchPlaceholder} value={nameFilter} append={append} + compressed={compressed} /> ); }; diff --git a/packages/kbn-unified-field-list/src/containers/unified_field_list_item/field_list_item.test.tsx b/packages/kbn-unified-field-list/src/containers/unified_field_list_item/field_list_item.test.tsx index 6ccbf54516995..4feeb9b1be23e 100644 --- a/packages/kbn-unified-field-list/src/containers/unified_field_list_item/field_list_item.test.tsx +++ b/packages/kbn-unified-field-list/src/containers/unified_field_list_item/field_list_item.test.tsx @@ -82,6 +82,7 @@ async function getComponent({ isEmpty: false, groupIndex: 1, itemIndex: 0, + size: 'xs', workspaceSelectedFieldNames: [], }; const comp = await mountWithIntl(); diff --git a/packages/kbn-unified-field-list/src/containers/unified_field_list_item/field_list_item.tsx b/packages/kbn-unified-field-list/src/containers/unified_field_list_item/field_list_item.tsx index 837818399eccf..745d463b28386 100644 --- a/packages/kbn-unified-field-list/src/containers/unified_field_list_item/field_list_item.tsx +++ b/packages/kbn-unified-field-list/src/containers/unified_field_list_item/field_list_item.tsx @@ -33,6 +33,7 @@ import type { interface GetCommonFieldItemButtonPropsParams { stateService: UnifiedFieldListSidebarContainerStateService; field: DataViewField; + size: FieldItemButtonProps['size']; isSelected: boolean; toggleDisplay: (field: DataViewField, isSelected?: boolean) => void; } @@ -40,10 +41,12 @@ interface GetCommonFieldItemButtonPropsParams { function getCommonFieldItemButtonProps({ stateService, field, + size, isSelected, toggleDisplay, }: GetCommonFieldItemButtonPropsParams): { field: FieldItemButtonProps['field']; + size: FieldItemButtonProps['size']; isSelected: FieldItemButtonProps['isSelected']; buttonAddFieldToWorkspaceProps?: FieldItemButtonProps['buttonAddFieldToWorkspaceProps']; buttonRemoveFieldFromWorkspaceProps?: FieldItemButtonProps['buttonRemoveFieldFromWorkspaceProps']; @@ -54,6 +57,7 @@ function getCommonFieldItemButtonProps({ field.name === '_source' ? undefined : (f: DataViewField) => toggleDisplay(f, isSelected); return { field, + size, isSelected, buttonAddFieldToWorkspaceProps: stateService.creationOptions.buttonAddFieldToWorkspaceProps, buttonRemoveFieldFromWorkspaceProps: @@ -68,10 +72,11 @@ interface MultiFieldsProps { multiFields: NonNullable; toggleDisplay: (field: DataViewField) => void; alwaysShowActionButton: boolean; + size: FieldItemButtonProps['size']; } const MultiFields: React.FC = memo( - ({ stateService, multiFields, toggleDisplay, alwaysShowActionButton }) => ( + ({ stateService, multiFields, toggleDisplay, alwaysShowActionButton, size }) => (
@@ -84,7 +89,6 @@ const MultiFields: React.FC = memo( {multiFields.map((entry) => ( = memo( field: entry.field, isSelected: entry.isSelected, toggleDisplay, + size, })} /> ))} @@ -187,6 +192,10 @@ export interface UnifiedFieldListItemProps { * Item index in the field list */ itemIndex: number; + /** + * Item size + */ + size: FieldItemButtonProps['size']; } function UnifiedFieldListItemComponent({ @@ -209,6 +218,7 @@ function UnifiedFieldListItemComponent({ workspaceSelectedFieldNames, groupIndex, itemIndex, + size, }: UnifiedFieldListItemProps) { const [infoIsOpen, setOpen] = useState(false); @@ -284,6 +294,7 @@ function UnifiedFieldListItemComponent({ multiFields={multiFields} alwaysShowActionButton={alwaysShowActionButton} toggleDisplay={toggleDisplay} + size={size} /> )} @@ -315,6 +326,8 @@ function UnifiedFieldListItemComponent({ [field, itemIndex] ); const order = useMemo(() => [0, groupIndex, itemIndex], [groupIndex, itemIndex]); + const isDragDisabled = + alwaysShowActionButton || stateService.creationOptions.disableFieldListItemDragAndDrop; return ( } diff --git a/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/field_list_sidebar.scss b/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/field_list_sidebar.scss index d01d93c345ef9..b646d60ec3b0f 100644 --- a/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/field_list_sidebar.scss +++ b/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/field_list_sidebar.scss @@ -6,6 +6,11 @@ width: $euiSize * 19; height: 100%; + &--collapsed { + width: auto; + padding: $euiSizeS $euiSizeS 0; + } + @include euiBreakpoint('xs', 's') { width: 100%; padding: $euiSize; @@ -14,7 +19,7 @@ } .unifiedFieldListSidebar__list { - padding: $euiSizeS 0 $euiSizeS $euiSizeS; + padding: $euiSizeS $euiSizeS 0; @include euiBreakpoint('xs', 's') { padding: $euiSizeS 0 0 0; @@ -38,3 +43,18 @@ .unifiedFieldListSidebar__flyoutHeader { align-items: center; } + +.unifiedFieldListSidebar .unifiedFieldListItemButton { + &.kbnFieldButton { + margin-bottom: $euiSizeXS / 2; + } + + &.domDragDrop-isDraggable { + box-shadow: none; + } + + &:not(.unifiedFieldListItemButton__dragging) { + padding: 0; + background: none; + } +} diff --git a/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/field_list_sidebar.tsx b/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/field_list_sidebar.tsx index 12eb7209cd05a..fb90e2b36d39e 100644 --- a/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/field_list_sidebar.tsx +++ b/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/field_list_sidebar.tsx @@ -9,16 +9,29 @@ import './field_list_sidebar.scss'; import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiPageSidebar } from '@elastic/eui'; +import { css } from '@emotion/react'; +import classnames from 'classnames'; +import { + EuiButton, + EuiButtonProps, + EuiFlexGroup, + EuiFlexItem, + EuiHideFor, + EuiPageSidebar, + EuiPageSidebarProps, + useEuiTheme, +} from '@elastic/eui'; +import { ToolbarButton } from '@kbn/shared-ux-button-toolbar'; import { type DataViewField } from '@kbn/data-views-plugin/public'; import { getDataViewFieldSubtypeMulti } from '@kbn/es-query/src/utils'; import { FIELDS_LIMIT_SETTING, SEARCH_FIELDS_FROM_SOURCE } from '@kbn/discover-utils'; import { FieldList } from '../../components/field_list'; import { FieldListFilters } from '../../components/field_list_filters'; import { FieldListGrouped, type FieldListGroupedProps } from '../../components/field_list_grouped'; -import { FieldsGroupNames } from '../../types'; +import { FieldsGroupNames, type ButtonAddFieldVariant } from '../../types'; import { GroupedFieldsParams, useGroupedFields } from '../../hooks/use_grouped_fields'; import { UnifiedFieldListItem, type UnifiedFieldListItemProps } from '../unified_field_list_item'; +import { SidebarToggleButton, type SidebarToggleButtonProps } from './sidebar_toggle_button'; import { getSelectedFields, shouldShowField, @@ -46,6 +59,11 @@ export type UnifiedFieldListSidebarCustomizableProps = Pick< */ showFieldList?: boolean; + /** + * Compressed view + */ + compressed?: boolean; + /** * Custom logic for determining which field is selected */ @@ -83,6 +101,22 @@ interface UnifiedFieldListSidebarInternalProps { */ alwaysShowActionButton?: UnifiedFieldListItemProps['alwaysShowActionButton']; + /** + * What button style type to use + */ + buttonAddFieldVariant: ButtonAddFieldVariant; + + /** + * In case if sidebar is collapsible by default + * Pass `undefined` to hide the collapse/expand buttons from the sidebar + */ + isSidebarCollapsed?: boolean; + + /** + * A handler to toggle the sidebar + */ + onToggleSidebar?: SidebarToggleButtonProps['onChange']; + /** * Trigger a field editing */ @@ -104,10 +138,13 @@ export const UnifiedFieldListSidebarComponent: React.FC { const { dataViews, core } = services; const useNewFieldsApi = useMemo( @@ -210,6 +248,7 @@ export const UnifiedFieldListSidebarComponent: React.FC + ) : null; + + const pageSidebarProps: Partial = { + className: classnames('unifiedFieldListSidebar', { + 'unifiedFieldListSidebar--collapsed': isSidebarCollapsed, + }), + 'aria-label': i18n.translate( + 'unifiedFieldList.fieldListSidebar.indexAndFieldsSectionAriaLabel', + { + defaultMessage: 'Index and fields', } - > + ), + id: + stateService.creationOptions.dataTestSubj?.fieldListSidebarDataTestSubj ?? + 'unifiedFieldListSidebarId', + 'data-test-subj': + stateService.creationOptions.dataTestSubj?.fieldListSidebarDataTestSubj ?? + 'unifiedFieldListSidebarId', + }; + + if (isSidebarCollapsed && sidebarToggleButton) { + return ( + +
{sidebarToggleButton}
+
+ ); + } + + const hasButtonAddFieldToolbarStyle = buttonAddFieldVariant === 'toolbar'; + const buttonAddFieldCommonProps: Partial = { + size: 's', + iconType: 'indexOpen', + 'data-test-subj': + stateService.creationOptions.dataTestSubj?.fieldListAddFieldButtonTestSubj ?? + 'unifiedFieldListAddField', + }; + const buttonAddFieldLabel = i18n.translate( + 'unifiedFieldList.fieldListSidebar.addFieldButtonLabel', + { + defaultMessage: 'Add a field', + } + ); + + return ( + - {Boolean(prepend) && {prepend}} + {Boolean(prepend) && ( + + {prepend} + + )} } + prepend={ + + {sidebarToggleButton && ( + {sidebarToggleButton} + )} + + + + + } className="unifiedFieldListSidebar__list" > {showFieldList ? ( @@ -293,25 +387,33 @@ export const UnifiedFieldListSidebarComponent: React.FC )} - {!!onEditField && ( - - onEditField()} - size="s" - > - {i18n.translate('unifiedFieldList.fieldListSidebar.addFieldButtonLabel', { - defaultMessage: 'Add a field', - })} - - - )} + {!!onEditField && ( + + {hasButtonAddFieldToolbarStyle ? ( + onEditField()} + /> + ) : ( + onEditField()}> + {buttonAddFieldLabel} + + )} + + )} ); diff --git a/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/field_list_sidebar_container.tsx b/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/field_list_sidebar_container.tsx index 4765280b4ef68..520a64f8d69b0 100644 --- a/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/field_list_sidebar_container.tsx +++ b/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/field_list_sidebar_container.tsx @@ -35,6 +35,7 @@ import { type ExistingFieldsFetcher, } from '../../hooks/use_existing_fields'; import { useQuerySubscriber } from '../../hooks/use_query_subscriber'; +import { useSidebarToggle } from '../../hooks/use_sidebar_toggle'; import { UnifiedFieldListSidebar, type UnifiedFieldListSidebarCustomizableProps, @@ -72,11 +73,6 @@ export type UnifiedFieldListSidebarContainerProps = Omit< */ getCreationOptions: () => UnifiedFieldListSidebarContainerCreationOptions; - /** - * In case if you have a sidebar toggle button - */ - isSidebarCollapsed?: boolean; - /** * Custom content to render at the top of field list in the flyout (for example a data view picker) */ @@ -115,7 +111,6 @@ const UnifiedFieldListSidebarContainer = forwardRef< services, dataView, workspaceSelectedFieldNames, - isSidebarCollapsed, // TODO later: pull the logic of collapsing the sidebar to this component prependInFlyout, variant = 'responsive', onFieldEdited, @@ -125,6 +120,7 @@ const UnifiedFieldListSidebarContainer = forwardRef< ); const { data, dataViewFieldEditor } = services; const [isFieldListFlyoutVisible, setIsFieldListFlyoutVisible] = useState(false); + const { isSidebarCollapsed, onToggleSidebar } = useSidebarToggle({ stateService }); const canEditDataView = Boolean(dataViewFieldEditor?.userPermissions.editIndexPattern()) || @@ -250,8 +246,15 @@ const UnifiedFieldListSidebarContainer = forwardRef< isAffectedByGlobalFilter, onEditField: editField, onDeleteField: deleteField, + compressed: stateService.creationOptions.compressed ?? false, + buttonAddFieldVariant: stateService.creationOptions.buttonAddFieldVariant ?? 'primary', }; + if (stateService.creationOptions.showSidebarToggleButton) { + commonSidebarProps.isSidebarCollapsed = isSidebarCollapsed; + commonSidebarProps.onToggleSidebar = onToggleSidebar; + } + const buttonPropsToTriggerFlyout = stateService.creationOptions.buttonPropsToTriggerFlyout; const renderListVariant = () => { @@ -319,6 +322,8 @@ const UnifiedFieldListSidebarContainer = forwardRef< @@ -333,12 +338,12 @@ const UnifiedFieldListSidebarContainer = forwardRef< } if (variant === 'list-always') { - return (!isSidebarCollapsed && renderListVariant()) || null; + return renderListVariant(); } return ( <> - {!isSidebarCollapsed && {renderListVariant()}} + {renderListVariant()} {renderButtonVariant()} ); diff --git a/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/sidebar_toggle_button/index.ts b/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/sidebar_toggle_button/index.ts new file mode 100644 index 0000000000000..f3dd50b48c968 --- /dev/null +++ b/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/sidebar_toggle_button/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { SidebarToggleButton, type SidebarToggleButtonProps } from './sidebar_toggle_button'; diff --git a/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/sidebar_toggle_button/sidebar_toggle_button.tsx b/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/sidebar_toggle_button/sidebar_toggle_button.tsx new file mode 100644 index 0000000000000..1bf8f62b2cced --- /dev/null +++ b/packages/kbn-unified-field-list/src/containers/unified_field_list_sidebar/sidebar_toggle_button/sidebar_toggle_button.tsx @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { IconButtonGroup, type IconButtonGroupProps } from '@kbn/shared-ux-button-toolbar'; + +/** + * Toggle button props + */ +export interface SidebarToggleButtonProps { + 'data-test-subj'?: string; + isSidebarCollapsed: boolean; + buttonSize: IconButtonGroupProps['buttonSize']; + onChange: (isSidebarCollapsed: boolean) => void; +} + +/** + * A toggle button for the fields sidebar + * @param data-test-subj + * @param isSidebarCollapsed + * @param onChange + * @constructor + */ +export const SidebarToggleButton: React.FC = ({ + 'data-test-subj': dataTestSubj = 'unifiedFieldListSidebar__toggle', + isSidebarCollapsed, + buttonSize, + onChange, +}) => { + // TODO: replace with new Eui icons once available + return ( +
+ onChange(false), + }, + ] + : [ + { + label: i18n.translate('unifiedFieldList.fieldListSidebar.collapseSidebarButton', { + defaultMessage: 'Hide sidebar', + }), + iconType: 'menuLeft', + 'data-test-subj': `${dataTestSubj}-collapse`, + onClick: () => onChange(true), + }, + ]), + ]} + /> +
+ ); +}; diff --git a/packages/kbn-unified-field-list/src/hooks/use_sidebar_toggle.test.tsx b/packages/kbn-unified-field-list/src/hooks/use_sidebar_toggle.test.tsx new file mode 100644 index 0000000000000..16ee451400c6c --- /dev/null +++ b/packages/kbn-unified-field-list/src/hooks/use_sidebar_toggle.test.tsx @@ -0,0 +1,104 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { renderHook, act } from '@testing-library/react-hooks'; +import { useSidebarToggle } from './use_sidebar_toggle'; +import * as localStorageModule from 'react-use/lib/useLocalStorage'; + +jest.spyOn(localStorageModule, 'default'); + +describe('UnifiedFieldList useSidebarToggle', () => { + const stateService = { + creationOptions: { + originatingApp: 'test', + localStorageKeyPrefix: 'this', + }, + }; + + beforeEach(() => { + (localStorageModule.default as jest.Mock).mockClear(); + }); + + it('should toggle correctly', async () => { + const storeMock = jest.fn(); + (localStorageModule.default as jest.Mock).mockImplementation(() => { + return [false, storeMock]; + }); + + const { result } = renderHook(useSidebarToggle, { + initialProps: { + stateService, + }, + }); + + expect(result.current.isSidebarCollapsed).toBe(false); + + act(() => { + result.current.onToggleSidebar(true); + }); + + expect(result.current.isSidebarCollapsed).toBe(true); + expect(storeMock).toHaveBeenCalledWith(true); + + act(() => { + result.current.onToggleSidebar(false); + }); + + expect(result.current.isSidebarCollapsed).toBe(false); + expect(storeMock).toHaveBeenLastCalledWith(false); + }); + + it('should restore collapsed state and expand from it', async () => { + const storeMock = jest.fn(); + (localStorageModule.default as jest.Mock).mockImplementation(() => { + return [true, storeMock]; + }); + + const { result } = renderHook(useSidebarToggle, { + initialProps: { + stateService, + }, + }); + + expect(result.current.isSidebarCollapsed).toBe(true); + + act(() => { + result.current.onToggleSidebar(false); + }); + + expect(result.current.isSidebarCollapsed).toBe(false); + expect(storeMock).toHaveBeenCalledWith(false); + }); + + it('should not persist if local storage key is not defined', async () => { + const storeMock = jest.fn(); + (localStorageModule.default as jest.Mock).mockImplementation(() => { + return [false, storeMock]; + }); + + const { result } = renderHook(useSidebarToggle, { + initialProps: { + stateService: { + creationOptions: { + originatingApp: 'test', + localStorageKeyPrefix: undefined, + }, + }, + }, + }); + + expect(result.current.isSidebarCollapsed).toBe(false); + + act(() => { + result.current.onToggleSidebar(true); + }); + + expect(result.current.isSidebarCollapsed).toBe(true); + expect(storeMock).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/kbn-unified-field-list/src/hooks/use_sidebar_toggle.ts b/packages/kbn-unified-field-list/src/hooks/use_sidebar_toggle.ts new file mode 100644 index 0000000000000..b12c7dc7dae95 --- /dev/null +++ b/packages/kbn-unified-field-list/src/hooks/use_sidebar_toggle.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { useCallback, useState, useMemo } from 'react'; +import useLocalStorage from 'react-use/lib/useLocalStorage'; +import type { UnifiedFieldListSidebarContainerStateService } from '../types'; + +/** + * Hook params + */ +export interface UseSidebarToggleParams { + /** + * Service for managing the state + */ + stateService: UnifiedFieldListSidebarContainerStateService; +} + +/** + * Hook result type + */ +export interface UseSidebarToggleResult { + isSidebarCollapsed: boolean; + onToggleSidebar: (isSidebarCollapsed: boolean) => void; +} + +/** + * Hook for managing sidebar toggle state + * @param stateService + */ +export const useSidebarToggle = ({ + stateService, +}: UseSidebarToggleParams): UseSidebarToggleResult => { + const [initialIsSidebarCollapsed, storeIsSidebarCollapsed] = useLocalStorage( + `${stateService.creationOptions.localStorageKeyPrefix ?? 'unifiedFieldList'}:sidebarClosed`, // as legacy `discover:sidebarClosed` key + false + ); + const [isSidebarCollapsed, setIsSidebarCollapsed] = useState( + initialIsSidebarCollapsed ?? false + ); + + const onToggleSidebar = useCallback( + (isCollapsed) => { + setIsSidebarCollapsed(isCollapsed); + if (stateService.creationOptions.localStorageKeyPrefix) { + storeIsSidebarCollapsed(isCollapsed); + } + }, + [ + storeIsSidebarCollapsed, + setIsSidebarCollapsed, + stateService.creationOptions.localStorageKeyPrefix, + ] + ); + + return useMemo( + () => ({ isSidebarCollapsed, onToggleSidebar }), + [isSidebarCollapsed, onToggleSidebar] + ); +}; diff --git a/packages/kbn-unified-field-list/src/types.ts b/packages/kbn-unified-field-list/src/types.ts index 76997c73176b3..dad321dbe56b3 100755 --- a/packages/kbn-unified-field-list/src/types.ts +++ b/packages/kbn-unified-field-list/src/types.ts @@ -107,6 +107,8 @@ export type OverrideFieldGroupDetails = ( export type TimeRangeUpdatesType = 'search-session' | 'timefilter'; +export type ButtonAddFieldVariant = 'primary' | 'toolbar'; + export type SearchMode = 'documents' | 'text-based'; export interface UnifiedFieldListSidebarContainerCreationOptions { @@ -116,7 +118,12 @@ export interface UnifiedFieldListSidebarContainerCreationOptions { originatingApp: string; /** - * Your app name: "discover", "lens", etc. If not provided, sections state would not be persisted. + * Pass `true` to enable the compressed view + */ + compressed?: boolean; + + /** + * Your app name: "discover", "lens", etc. If not provided, sections and sidebar toggle states would not be persisted. */ localStorageKeyPrefix?: string; @@ -125,6 +132,16 @@ export interface UnifiedFieldListSidebarContainerCreationOptions { */ timeRangeUpdatesType?: TimeRangeUpdatesType; + /** + * Choose how the bottom "Add a field" button should look like. Default `primary`. + */ + buttonAddFieldVariant?: ButtonAddFieldVariant; + + /** + * Pass `true` to make the sidebar collapsible. Additionally, define `localStorageKeyPrefix` to persist toggle state. + */ + showSidebarToggleButton?: boolean; + /** * Pass `true` to skip auto fetching of fields existence info */ diff --git a/packages/kbn-unified-field-list/tsconfig.json b/packages/kbn-unified-field-list/tsconfig.json index 78ea71ca44344..f60d203786439 100644 --- a/packages/kbn-unified-field-list/tsconfig.json +++ b/packages/kbn-unified-field-list/tsconfig.json @@ -29,6 +29,7 @@ "@kbn/shared-ux-utility", "@kbn/discover-utils", "@kbn/ebt-tools", + "@kbn/shared-ux-button-toolbar", ], "exclude": ["target/**/*"] } diff --git a/src/plugins/discover/public/__mocks__/__storybook_mocks__/with_discover_services.tsx b/src/plugins/discover/public/__mocks__/__storybook_mocks__/with_discover_services.tsx index 62b04533c2a41..cf280767e0d4b 100644 --- a/src/plugins/discover/public/__mocks__/__storybook_mocks__/with_discover_services.tsx +++ b/src/plugins/discover/public/__mocks__/__storybook_mocks__/with_discover_services.tsx @@ -21,7 +21,6 @@ import { SEARCH_FIELDS_FROM_SOURCE, SHOW_MULTIFIELDS, } from '@kbn/discover-utils'; -import { SIDEBAR_CLOSED_KEY } from '../../application/main/components/layout/discover_layout'; import { LocalStorageMock } from '../local_storage_mock'; import { DiscoverServices } from '../../build_services'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; @@ -73,9 +72,7 @@ export const services = { docLinks: { links: { discover: {} } }, theme, }, - storage: new LocalStorageMock({ - [SIDEBAR_CLOSED_KEY]: false, - }) as unknown as Storage, + storage: new LocalStorageMock({}) as unknown as Storage, data: { query: { timefilter: { diff --git a/src/plugins/discover/public/application/context/components/action_bar/action_bar.tsx b/src/plugins/discover/public/application/context/components/action_bar/action_bar.tsx index 5cbb72f0602ee..747cd68837545 100644 --- a/src/plugins/discover/public/application/context/components/action_bar/action_bar.tsx +++ b/src/plugins/discover/public/application/context/components/action_bar/action_bar.tsx @@ -156,7 +156,7 @@ export function ActionBar({ {!isSuccessor && showWarning && } {!isSuccessor && showWarning && } - {!isSuccessor && } + ); } diff --git a/src/plugins/discover/public/application/context/context_app.scss b/src/plugins/discover/public/application/context/context_app.scss index 13593a7ed32dd..19ae9a7471302 100644 --- a/src/plugins/discover/public/application/context/context_app.scss +++ b/src/plugins/discover/public/application/context/context_app.scss @@ -17,8 +17,4 @@ &__cell--highlight { background-color: tintOrShade($euiColorPrimary, 90%, 70%); } - - .euiDataGridRowCell.euiDataGridRowCell--firstColumn { - padding: 0; - } } diff --git a/src/plugins/discover/public/application/context/context_app.tsx b/src/plugins/discover/public/application/context/context_app.tsx index 19a5058638392..355c82417f632 100644 --- a/src/plugins/discover/public/application/context/context_app.tsx +++ b/src/plugins/discover/public/application/context/context_app.tsx @@ -10,7 +10,8 @@ import React, { Fragment, memo, useEffect, useRef, useMemo, useCallback } from ' import './context_app.scss'; import classNames from 'classnames'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiText, EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui'; +import { EuiText, EuiPage, EuiPageBody, EuiSpacer, useEuiPaddingSize } from '@elastic/eui'; +import { css } from '@emotion/react'; import { cloneDeep } from 'lodash'; import { DataView, DataViewField } from '@kbn/data-views-plugin/public'; import { useExecutionContext } from '@kbn/kibana-react-plugin/public'; @@ -215,6 +216,8 @@ export const ContextApp = ({ dataView, anchorId, referrer }: ContextAppProps) => }; }; + const titlePadding = useEuiPaddingSize('m'); + return ( {fetchedState.anchorStatus.value === LoadingStatus.FAILED ? ( @@ -235,12 +238,16 @@ export const ContextApp = ({ dataView, anchorId, referrer }: ContextAppProps) => - - + - {!!interceptedWarnings?.length && ( - <> - - - - )} - - {loadingFeedback()} - + + {!!interceptedWarnings?.length && ( + <> + + + + )} + + {loadingFeedback()} + {isLegacy && rows && rows.length !== 0 && ( )} - - + + + ); } + +const WrapperWithPadding: React.FC = ({ children }) => { + const padding = useEuiPaddingSize('s'); + + return ( +
+ {children} +
+ ); +}; diff --git a/src/plugins/discover/public/application/doc/components/doc.tsx b/src/plugins/discover/public/application/doc/components/doc.tsx index 83c2c08eafa2e..5bf79863ecfbe 100644 --- a/src/plugins/discover/public/application/doc/components/doc.tsx +++ b/src/plugins/discover/public/application/doc/components/doc.tsx @@ -50,7 +50,7 @@ export function Doc(props: DocProps) { values: { id: props.id }, })}
- + {reqState === ElasticRequestState.NotFoundDataView && ( time; (services.data.query.queryString.getDefaultQuery as jest.Mock).mockReturnValue({ @@ -77,6 +73,9 @@ async function mountComponent( (searchSourceInstanceMock.fetch$ as jest.Mock).mockImplementation( jest.fn().mockReturnValue(of({ rawResponse: { hits: { total: 2 } } })) ); + (localStorageModule.default as jest.Mock).mockImplementation( + jest.fn(() => [prevSidebarClosed, jest.fn()]) + ); const stateContainer = getDiscoverStateMock({ isTimeBased: true }); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx index 58c23aa561e12..3402bfbce1bcc 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx @@ -6,17 +6,18 @@ * Side Public License, v 1. */ import './discover_layout.scss'; -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import { - EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiHideFor, EuiPage, EuiPageBody, EuiPanel, - EuiSpacer, + useEuiBackgroundColor, + useEuiTheme, } from '@elastic/eui'; +import { css } from '@emotion/react'; import { i18n } from '@kbn/i18n'; import { METRIC_TYPE } from '@kbn/analytics'; import classNames from 'classnames'; @@ -52,11 +53,6 @@ import { DiscoverHistogramLayout } from './discover_histogram_layout'; import { ErrorCallout } from '../../../../components/common/error_callout'; import { addLog } from '../../../../utils/add_log'; -/** - * Local storage key for sidebar persistence state - */ -export const SIDEBAR_CLOSED_KEY = 'discover:sidebarClosed'; - const SidebarMemoized = React.memo(DiscoverSidebarResponsive); const TopNavMemoized = React.memo(DiscoverTopNav); @@ -72,11 +68,12 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) { data, uiSettings, filterManager, - storage, history, spaces, inspector, } = useDiscoverServices(); + const { euiTheme } = useEuiTheme(); + const pageBackgroundColor = useEuiBackgroundColor('plain'); const globalQueryState = data.query.getState(); const { main$ } = stateContainer.dataState.data$; const [query, savedQuery, columns, sort] = useAppStateSelector((state) => [ @@ -109,8 +106,6 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) { return dataView.type !== DataViewType.ROLLUP && dataView.isTimeBased(); }, [dataView]); - const initialSidebarClosed = Boolean(storage.get(SIDEBAR_CLOSED_KEY)); - const [isSidebarClosed, setIsSidebarClosed] = useState(initialSidebarClosed); const useNewFieldsApi = useMemo(() => !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE), [uiSettings]); const isPlainRecord = useMemo(() => getRawRecordType(query) === RecordRawType.PLAIN, [query]); @@ -172,11 +167,6 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) { filterManager.setFilters(disabledFilters); }, [filterManager]); - const toggleSidebarCollapse = useCallback(() => { - storage.set(SIDEBAR_CLOSED_KEY, !isSidebarClosed); - setIsSidebarClosed(!isSidebarClosed); - }, [isSidebarClosed, storage]); - const contentCentered = resultState === 'uninitialized' || resultState === 'none'; const documentState = useDataState(stateContainer.dataState.data$.documents$); @@ -240,7 +230,13 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) { ]); return ( - +

- + - -
- - -
-
+
{resultState === 'none' ? ( @@ -335,7 +319,10 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) { role="main" panelRef={resizeRef} paddingSize="none" + borderRadius="none" hasShadow={false} + hasBorder={false} + color="transparent" className={classNames('dscPageContent', { 'dscPageContent--centered': contentCentered, })} diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx index d7d90ff6b517e..e241a52b1d259 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { DragDrop, type DropType, DropOverlayWrapper } from '@kbn/dom-drag-drop'; import useObservable from 'react-use/lib/useObservable'; import React, { useCallback } from 'react'; @@ -97,7 +97,6 @@ export const DiscoverMainContent = ({ data-test-subj="dscMainContent" > - {!isPlainRecord && ( = ({ return ( } - hasBorder + hasBorder={false} title={

void; }) => { + const { euiTheme } = useEuiTheme(); const { uiSettings } = useDiscoverServices(); const tabsCss = css` padding: 0 ${useEuiPaddingSize('s')}; - background-color: ${euiThemeVars.euiPageBackgroundColor}; + border-bottom: ${viewMode === VIEW_MODE.AGGREGATED_LEVEL ? euiTheme.border.thin : 'none'}; `; const showViewModeToggle = uiSettings.get(SHOW_FIELD_STATISTICS) ?? false; @@ -36,7 +36,7 @@ export const DocumentViewModeToggle = ({ } return ( - + setDiscoverViewMode(VIEW_MODE.DOCUMENT_LEVEL)} diff --git a/src/plugins/unified_histogram/public/layout/layout.tsx b/src/plugins/unified_histogram/public/layout/layout.tsx index d2088d4776445..95661ed9b3f2f 100644 --- a/src/plugins/unified_histogram/public/layout/layout.tsx +++ b/src/plugins/unified_histogram/public/layout/layout.tsx @@ -275,7 +275,7 @@ export const UnifiedHistogramLayout = ({ chart={chart} breakdown={breakdown} appendHitsCounter={appendHitsCounter} - appendHistogram={showFixedPanels ? : } + appendHistogram={} disableAutoFetching={disableAutoFetching} disableTriggers={disableTriggers} disabledActions={disabledActions} diff --git a/src/plugins/unified_histogram/public/panels/panels_resizable.tsx b/src/plugins/unified_histogram/public/panels/panels_resizable.tsx index 773ebe172b25e..9f8fd5338a38f 100644 --- a/src/plugins/unified_histogram/public/panels/panels_resizable.tsx +++ b/src/plugins/unified_histogram/public/panels/panels_resizable.tsx @@ -6,12 +6,7 @@ * Side Public License, v 1. */ -import { - EuiResizableContainer, - useEuiTheme, - useGeneratedHtmlId, - useResizeObserver, -} from '@elastic/eui'; +import { EuiResizableContainer, useGeneratedHtmlId, useResizeObserver } from '@elastic/eui'; import type { ResizeTrigger } from '@elastic/eui/src/components/resizable_container/types'; import { css } from '@emotion/react'; import { isEqual, round } from 'lodash'; @@ -162,12 +157,6 @@ export const PanelsResizable = ({ disableResizeWithPortalsHack(); }, [disableResizeWithPortalsHack, resizeWithPortalsHackIsResizing]); - const { euiTheme } = useEuiTheme(); - const buttonCss = css` - margin-top: -${euiTheme.size.base}; - margin-bottom: 0; - `; - return ( { const rowData = await PageObjects.discover.getDocTableField(1); diff --git a/test/functional/apps/discover/group3/_sidebar.ts b/test/functional/apps/discover/group3/_sidebar.ts index eefda4891390b..6a09524777487 100644 --- a/test/functional/apps/discover/group3/_sidebar.ts +++ b/test/functional/apps/discover/group3/_sidebar.ts @@ -214,16 +214,19 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('collapse expand', function () { it('should initially be expanded', async function () { await testSubjects.existOrFail('discover-sidebar'); + await testSubjects.existOrFail('fieldList'); }); it('should collapse when clicked', async function () { await PageObjects.discover.toggleSidebarCollapse(); - await testSubjects.missingOrFail('discover-sidebar'); + await testSubjects.existOrFail('discover-sidebar'); + await testSubjects.missingOrFail('fieldList'); }); it('should expand when clicked', async function () { await PageObjects.discover.toggleSidebarCollapse(); await testSubjects.existOrFail('discover-sidebar'); + await testSubjects.existOrFail('fieldList'); }); }); diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index 1545975667c60..d36cd4b56b129 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -370,13 +370,14 @@ export class DiscoverPageObject extends FtrService { } public async toggleSidebarCollapse() { - return await this.testSubjects.click('collapseSideBarButton'); + return await this.testSubjects.click('unifiedFieldListSidebar__toggle'); } public async closeSidebar() { await this.retry.tryForTime(2 * 1000, async () => { - await this.toggleSidebarCollapse(); - await this.testSubjects.missingOrFail('discover-sidebar'); + await this.testSubjects.click('unifiedFieldListSidebar__toggle-collapse'); + await this.testSubjects.missingOrFail('unifiedFieldListSidebar__toggle-collapse'); + await this.testSubjects.missingOrFail('fieldList'); }); } diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 29c9b379fc04b..2f8a2bad9d57b 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -2395,7 +2395,6 @@ "discover.serverLocatorExtension.titleFromLocatorUnknown": "Recherche inconnue", "discover.singleDocRoute.errorTitle": "Une erreur s'est produite", "discover.skipToBottomButtonLabel": "Atteindre la fin du tableau", - "discover.toggleSidebarAriaLabel": "Activer/Désactiver la barre latérale", "discover.topNav.openSearchPanel.manageSearchesButtonLabel": "Gérer les recherches", "discover.topNav.openSearchPanel.noSearchesFoundDescription": "Aucune recherche correspondante trouvée.", "discover.topNav.openSearchPanel.openSearchTitle": "Ouvrir une recherche", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index eaa6b47105103..f9656c1178806 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -2410,7 +2410,6 @@ "discover.serverLocatorExtension.titleFromLocatorUnknown": "不明な検索", "discover.singleDocRoute.errorTitle": "エラーが発生しました", "discover.skipToBottomButtonLabel": "テーブルの最後に移動", - "discover.toggleSidebarAriaLabel": "サイドバーを切り替える", "discover.topNav.openSearchPanel.manageSearchesButtonLabel": "検索の管理", "discover.topNav.openSearchPanel.noSearchesFoundDescription": "一致する検索が見つかりませんでした。", "discover.topNav.openSearchPanel.openSearchTitle": "検索を開く", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index a0fe7e9e05650..3d1ae2ad2bcca 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -2410,7 +2410,6 @@ "discover.serverLocatorExtension.titleFromLocatorUnknown": "未知搜索", "discover.singleDocRoute.errorTitle": "发生错误", "discover.skipToBottomButtonLabel": "转到表尾", - "discover.toggleSidebarAriaLabel": "切换侧边栏", "discover.topNav.openSearchPanel.manageSearchesButtonLabel": "管理搜索", "discover.topNav.openSearchPanel.noSearchesFoundDescription": "未找到匹配的搜索。", "discover.topNav.openSearchPanel.openSearchTitle": "打开搜索",