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

feat: Make filters and dividers display horizontally in horizontal native filters filter bar #22169

Merged
merged 7 commits into from
Nov 25, 2022
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
4 changes: 2 additions & 2 deletions superset-frontend/.storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ module.exports = {
builder: 'webpack5',
},
stories: [
'../src/@(components|common|filters|explore|views)/**/*.stories.@(tsx|jsx)',
'../src/@(components|common|filters|explore|views)/**/*.*.@(mdx)',
'../src/@(components|common|filters|explore|views|dashboard)/**/*.stories.@(tsx|jsx)',
'../src/@(components|common|filters|explore|views|dashboard)/**/*.*.@(mdx)',
],
addons: [
'@storybook/addon-essentials',
Expand Down
5 changes: 5 additions & 0 deletions superset-frontend/spec/fixtures/mockStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';

import { rootReducer } from 'src/views/store';
import { FilterBarOrientation } from 'src/dashboard/types';

import mockState from './mockState';
import {
Expand Down Expand Up @@ -125,6 +126,9 @@ export const stateWithNativeFilters = {
},
},
},
dashboardInfo: {
filterBarOrientation: FilterBarOrientation.VERTICAL,
},
};

export const getMockStoreWithNativeFilters = () =>
Expand Down Expand Up @@ -153,6 +157,7 @@ export const stateWithoutNativeFilters = {
},
dashboardInfo: {
dash_edit_perm: true,
filterBarOrientation: FilterBarOrientation.VERTICAL,
metadata: {
native_filter_configuration: [],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ const DropdownContainer = forwardRef(
css={css`
display: flex;
flex-direction: column;
gap: ${theme.gridUnit * 3}px;
gap: ${theme.gridUnit * 4}px;
`}
data-test="dropdown-content"
style={popoverStyle}
Expand Down Expand Up @@ -252,14 +252,14 @@ const DropdownContainer = forwardRef(
ref={ref}
css={css`
display: flex;
align-items: flex-end;
align-items: center;
`}
>
<div
css={css`
display: flex;
align-items: center;
gap: ${theme.gridUnit * 3}px;
gap: ${theme.gridUnit * 4}px;
margin-right: ${theme.gridUnit * 3}px;
min-width: 100px;
`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const verticalStyle = (theme: SupersetTheme, width: number) => css`
`;

const horizontalStyle = (theme: SupersetTheme) => css`
margin: 0 ${theme.gridUnit * 2}px;
margin: 0 ${theme.gridUnit * 4}px;
&& > .filter-clear-all-button {
text-transform: capitalize;
font-weight: ${theme.typography.weights.normal};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,59 @@ import React, { useContext, useMemo, useState } from 'react';
import { styled, SupersetTheme } from '@superset-ui/core';
import { FormItem as StyledFormItem, Form } from 'src/components/Form';
import { Tooltip } from 'src/components/Tooltip';
import { FilterBarOrientation } from 'src/dashboard/types';
import { truncationCSS } from 'src/hooks/useTruncation';
import { checkIsMissingRequiredValue } from '../utils';
import FilterValue from './FilterValue';
import { FilterProps } from './types';
import { FilterCard } from '../../FilterCard';
import { FilterBarScrollContext } from '../Vertical';
import { FilterControlProps } from './types';
import { FilterCardPlacement } from '../../FilterCard/types';

const StyledIcon = styled.div`
position: absolute;
right: 0;
`;

const StyledFilterControlTitle = styled.h4`
const VerticalFilterControlTitle = styled.h4`
font-size: ${({ theme }) => theme.typography.sizes.s}px;
color: ${({ theme }) => theme.colors.grayscale.dark1};
margin: 0;
overflow-wrap: break-word;
`;

const StyledFilterControlTitleBox = styled.div`
const HorizontalFilterControlTitle = styled(VerticalFilterControlTitle)`
font-weight: ${({ theme }) => theme.typography.weights.normal};
color: ${({ theme }) => theme.colors.grayscale.base};
${truncationCSS}
`;

const HorizontalOverflowFilterControlTitle = styled(
HorizontalFilterControlTitle,
)`
max-width: none;
`;

const VerticalFilterControlTitleBox = styled.div`
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
margin-bottom: ${({ theme }) => theme.gridUnit}px;
`;

const StyledFilterControlContainer = styled(Form)`
const HorizontalFilterControlTitleBox = styled(VerticalFilterControlTitleBox)`
margin-bottom: unset;
max-width: ${({ theme }) => theme.gridUnit * 15}px;
`;

const HorizontalOverflowFilterControlTitleBox = styled(
VerticalFilterControlTitleBox,
)`
width: 100%;
`;

const VerticalFilterControlContainer = styled(Form)`
width: 100%;
&& .ant-form-item-label > label {
text-transform: none;
Expand All @@ -58,7 +84,25 @@ const StyledFilterControlContainer = styled(Form)`
}
`;

const FormItem = styled(StyledFormItem)`
const HorizontalFilterControlContainer = styled(Form)`
&& .ant-form-item-label > label {
margin-bottom: 0;
text-transform: none;
}
.ant-form-item-tooltip {
margin-bottom: ${({ theme }) => theme.gridUnit}px;
}
`;

const HorizontalOverflowFilterControlContainer = styled(
VerticalFilterControlContainer,
)`
&& .ant-form-item-label > label {
padding-right: unset;
}
`;

const VerticalFormItem = styled(StyledFormItem)`
.ant-form-item-label {
label.ant-form-item-required:not(.ant-form-item-required-mark-optional) {
&::after {
Expand All @@ -68,6 +112,62 @@ const FormItem = styled(StyledFormItem)`
}
`;

const HorizontalFormItem = styled(StyledFormItem)`
&& {
margin-bottom: 0;
align-items: center;
}
.ant-form-item-label {
padding-bottom: 0;
margin-right: ${({ theme }) => theme.gridUnit * 2}px;
label.ant-form-item-required:not(.ant-form-item-required-mark-optional) {
&::after {
display: none;
}
}
& > label::after {
display: none;
}
}
.ant-form-item-control {
width: ${({ theme }) => theme.gridUnit * 40}px;
}
`;

const HorizontalOverflowFormItem = VerticalFormItem;

const useFilterControlDisplay = (
orientation: FilterBarOrientation,
overflow: boolean,
) =>
useMemo(() => {
if (orientation === FilterBarOrientation.HORIZONTAL) {
if (overflow) {
return {
FilterControlContainer: HorizontalOverflowFilterControlContainer,
FormItem: HorizontalOverflowFormItem,
FilterControlTitleBox: HorizontalOverflowFilterControlTitleBox,
FilterControlTitle: HorizontalOverflowFilterControlTitle,
};
}
return {
FilterControlContainer: HorizontalFilterControlContainer,
FormItem: HorizontalFormItem,
FilterControlTitleBox: HorizontalFilterControlTitleBox,
FilterControlTitle: HorizontalFilterControlTitle,
};
}
return {
FilterControlContainer: VerticalFilterControlContainer,
FormItem: VerticalFormItem,
FilterControlTitleBox: VerticalFilterControlTitleBox,
FilterControlTitle: VerticalFilterControlTitle,
};
}, [orientation, overflow]);

const ToolTipContainer = styled.div`
font-size: ${({ theme }) => theme.typography.sizes.m}px;
display: flex;
Expand Down Expand Up @@ -109,7 +209,7 @@ const DescriptionToolTip = ({ description }: { description: string }) => (
</ToolTipContainer>
);

const FilterControl: React.FC<FilterProps> = ({
const FilterControl = ({
dataMaskSelected,
filter,
icon,
Expand All @@ -118,7 +218,9 @@ const FilterControl: React.FC<FilterProps> = ({
inView,
showOverflow,
parentRef,
}) => {
orientation = FilterBarOrientation.VERTICAL,
overflow = false,
}: FilterControlProps) => {
const [isFilterActive, setIsFilterActive] = useState(false);

const { name = '<undefined>' } = filter;
Expand All @@ -129,27 +231,60 @@ const FilterControl: React.FC<FilterProps> = ({
);
const isRequired = !!filter.controlValues?.enableEmptyFilter;

const {
FilterControlContainer,
FormItem,
FilterControlTitleBox,
FilterControlTitle,
} = useFilterControlDisplay(orientation, overflow);

const label = useMemo(
() => (
<StyledFilterControlTitleBox>
<StyledFilterControlTitle data-test="filter-control-name">
<FilterControlTitleBox>
<FilterControlTitle data-test="filter-control-name">
{name}
</StyledFilterControlTitle>
</FilterControlTitle>
{isRequired && <RequiredFieldIndicator />}
{filter.description?.trim() && (
<DescriptionToolTip description={filter.description} />
)}
<StyledIcon data-test="filter-icon">{icon}</StyledIcon>
</StyledFilterControlTitleBox>
</FilterControlTitleBox>
),
[name, isRequired, filter.description, icon],
[
FilterControlTitleBox,
FilterControlTitle,
name,
isRequired,
filter.description,
icon,
],
);

const isScrolling = useContext(FilterBarScrollContext);
const filterCardPlacement = useMemo(() => {
if (orientation === FilterBarOrientation.HORIZONTAL) {
if (overflow) {
return FilterCardPlacement.Left;
}
return FilterCardPlacement.Bottom;
}
return FilterCardPlacement.Right;
}, [orientation, overflow]);

return (
<StyledFilterControlContainer layout="vertical">
<FilterCard filter={filter} isVisible={!isFilterActive && !isScrolling}>
<FilterControlContainer
layout={
orientation === FilterBarOrientation.HORIZONTAL && !overflow
? 'horizontal'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should we use an enum for horizontal and vertical layout? Maybe we could even simply use FilterBarOrientation for that?

: 'vertical'
}
>
<FilterCard
filter={filter}
isVisible={!isFilterActive && !isScrolling}
placement={filterCardPlacement}
>
<div>
<FormItem
label={label}
Expand All @@ -165,11 +300,13 @@ const FilterControl: React.FC<FilterProps> = ({
inView={inView}
parentRef={parentRef}
setFilterActive={setIsFilterActive}
orientation={orientation}
overflow={overflow}
/>
</FormItem>
</div>
</FilterCard>
</StyledFilterControlContainer>
</FilterControlContainer>
);
};

Expand Down
Loading