Skip to content

Commit

Permalink
feat: Make filters and dividers display horizontally in horizontal na…
Browse files Browse the repository at this point in the history
…tive filters filter bar (#22169)

Co-authored-by: Michael S. Molina <michael.s.molina@gmail.com>
  • Loading branch information
codyml and michael-s-molina committed Nov 25, 2022
1 parent b2fcdc5 commit 64939f2
Show file tree
Hide file tree
Showing 22 changed files with 1,130 additions and 228 deletions.
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
6 changes: 3 additions & 3 deletions superset-frontend/src/components/DropdownContainer/index.tsx
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'
: '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

0 comments on commit 64939f2

Please sign in to comment.