Skip to content

Commit

Permalink
feat(sn-filter-pane): use selected styles in segment line (#418)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel Sjöstrand <99665802+DanielS-Qlik@users.noreply.github.com>
  • Loading branch information
johanlahti and DanielS-Qlik committed Mar 21, 2024
1 parent 9b6d675 commit 4469bdc
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ export const FoldedListbox = ({
constraints, styles, options, translator, containerSize,
} = stores.store.getState();
const isRtl = options.direction === 'rtl';
const isDrillDown = resource.layout.qListObject.qDimensionInfo.qGrouping === 'H';
const { qDimensionInfo } = resource.layout.qListObject;
const isDrillDown = qDimensionInfo.qGrouping === 'H';
const {
gridHeight, narrowSmall, narrowLarge,
} = getSizes(containerSize, isInPopover);
Expand Down Expand Up @@ -149,7 +150,7 @@ export const FoldedListbox = ({
{!narrowLarge
&& <Grid item width='100%' height={narrowSmall ? '100%' : undefined}>
<SelectionSegmentsIndicator
qDimensionInfo={resource.layout.qListObject.qDimensionInfo} fullHeight={narrowSmall}
qDimensionInfo={qDimensionInfo} fullHeight={narrowSmall} styles={styles}
></SelectionSegmentsIndicator>
</Grid>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,47 @@
import React from 'react';
import { Grid } from '@mui/material';
import { Grid, styled } from '@mui/material';
import getSegmentsSizes from './get-segment-sizes';
import { ISelectionsComponent, IStyles } from '../../hooks/types/components';

interface SelectionSegmentsIndicatorProps {
qDimensionInfo: EngineAPI.INxDimensionInfo,
fullHeight: boolean,
styles?: IStyles,
}

const SelectionSegmentsIndicator = ({ qDimensionInfo, fullHeight }: SelectionSegmentsIndicatorProps) => {
type SelectionState = ('selected' | 'selectedExcluded' | 'possible' | 'alternative' | 'excluded');

interface ISegmentProps {
segmentStyle: object;
}

const StyledSegment = styled(Grid, (({ shouldForwardProp: (p: string) => !['segmentStyle'].includes(p) })))(({ segmentStyle }: ISegmentProps) => ({
...segmentStyle,
}));

const SelectionSegmentsIndicator = ({ qDimensionInfo, fullHeight, styles }: SelectionSegmentsIndicatorProps) => {
if (!qDimensionInfo) {
return null;
}
const ratios = getSegmentsSizes(qDimensionInfo);
const segmentHeight = fullHeight ? '100%' : '4px';
const segments = [
{
key: 'green',
style: {
background: '#009845',
height: segmentHeight,
width: ratios.green,
},
},
{
key: 'white',
style: {
background: '#fff',
height: segmentHeight,
width: ratios.white,
},
},
{
key: 'grey',
style: {
background: '#d2d2d2',
height: segmentHeight,
width: ratios.grey,
},
const { selections = {} as ISelectionsComponent['colors'] } = styles?.listbox || {};

// The keys also determine the order in which the sections will be rendered.
const keys = ['selected', 'selectedExcluded', 'possible', 'alternative', 'excluded'] as const;
const segments = keys.map((key: SelectionState) => ({
key,
style: {
background: selections[key],
height: segmentHeight,
width: ratios[key],
},
];
}));

return (
<Grid container bgcolor='#a9a9a9' borderTop='1px solid #cccccc' height={fullHeight ? '100%' : undefined}>
<Grid container borderTop='1px solid #cccccc' height={fullHeight ? '100%' : undefined}>
{segments.map((s) => (
<Grid item key={s.key} style={s.style} />
<StyledSegment item key={s.key} segmentStyle={s.style} />
))}
</Grid>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ const toPercent = (value: number) => `${Math.min(value * 100, 100)}%`;
const getSegmentsSizes = (qDimensionInfo: EngineAPI.INxDimensionInfo) => {
const counts = qDimensionInfo.qStateCounts;
const total = qDimensionInfo.qCardinal;
const res = { green: '0', white: '0', grey: '0' };
const res = {
selected: '0', possible: '0', alternative: '0', selectedExcluded: '0', excluded: '0',
};

res.green = toPercent((counts.qSelected + counts.qLocked) / total);
res.white = toPercent((counts?.qOption ?? 0) / total);
res.grey = toPercent((counts.qAlternative) / total);
res.selected = toPercent((counts.qSelected + counts.qLocked) / total);
res.selectedExcluded = toPercent((counts?.qSelectedExcluded ?? 0) / total);
res.possible = toPercent((counts?.qOption ?? 0) / total);
res.alternative = toPercent((counts.qAlternative) / total);
res.excluded = toPercent((counts?.qExcluded ?? 0) / total);

return res;
};
Expand Down
7 changes: 7 additions & 0 deletions packages/sn-filter-pane/src/hooks/types/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ export interface IStyles {
opacity?: number;
};
color?: string;
selections: {
selected: string;
alternative: string;
excluded: string;
selectedExcluded: string;
possible: string;
}
}
header: {
color?: string;
Expand Down
4 changes: 2 additions & 2 deletions packages/sn-filter-pane/src/hooks/use-render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default function useRender(stores: IStores) {
const { store, resourceStore } = stores;
const [resourcesReady, setResourcesReady] = useState<boolean>(false);

const { app, fpLayout, env } = store.getState();
const { app, fpLayout } = store.getState();
const containerElement = <IContainerElement>useElement();

if (app && fpLayout) {
Expand All @@ -21,7 +21,7 @@ export default function useRender(stores: IStores) {

// Trigger a re-render only when components have changed in the filterpane layout.
// (Note that useEffect equality check is shallow and therefore requires a hash.)
const componentsHash = env?.flags?.isEnabled('IM_4073_FILTERPANE_STYLING') ? (fpLayout?.components || []).sort().map((c: object) => JSON.stringify(c)).join(',') : undefined;
const componentsHash = (fpLayout?.components || []).sort().map((c: object) => JSON.stringify(c)).join(',');

useEffect(() => {
if (!fpLayout || !app || !resourcesReady) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as stars from '@nebula.js/stardust';
import { IComponent, IThemeComponent } from '../types/components';
import useStyling from '../use-styling';
import { IComponent, IThemeComponent } from '../../types/components';
import useStyling from '..';

jest.mock('@nebula.js/stardust');

Expand Down
3 changes: 3 additions & 0 deletions packages/sn-filter-pane/src/hooks/use-styling/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import useStyling from './use-styling';

export default useStyling;
28 changes: 28 additions & 0 deletions packages/sn-filter-pane/src/hooks/use-styling/selections-style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { stardust } from '@nebula.js/stardust';
import { IComponentOverrides } from './types';
import { ISelectionsComponent } from '../types/components';

interface IGetSelectionStyles {
componentsOverrides: IComponentOverrides;
stardustTheme: stardust.Theme,
}

export default function getSelectionsStyle({ componentsOverrides, stardustTheme }: IGetSelectionStyles) {
const selectionColors = componentsOverrides?.selections?.colors || {} as ISelectionsComponent['colors'];

const getColor = stardustTheme?.getColorPickerColor || (() => false);

const selected = getColor(selectionColors.selected || {}, false) || '#009845';
const alternative = getColor(selectionColors.alternative || {}, false) || '#E4E4E4';
const excluded = getColor(selectionColors.excluded || {}, false) || '#A9A9A9';
const selectedExcluded = getColor(selectionColors.selectedExcluded || {}, false) || '#A9A9A9';
const possible = getColor(selectionColors.possible || {}, false) || '#FFFFFF';

return {
selected,
alternative,
excluded,
selectedExcluded,
possible,
};
}
13 changes: 13 additions & 0 deletions packages/sn-filter-pane/src/hooks/use-styling/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {
IComponent, ISelectionsComponent, IThemeComponent,
} from '../types/components';

export type IComponentOverrides = {
theme?: IThemeComponent;
selections?: ISelectionsComponent;
};

export interface ICreateStylingArgs {
app?: EngineAPI.IApp,
components?: IComponent[];
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
import { useTheme as useStardustTheme } from '@nebula.js/stardust';
import muiTheme from '../theme/theme';
import {
IComponent, ISelectionsComponent, IStyles, IThemeComponent,
} from './types/components';
import { resolveBgColor, resolveBgImage } from './styling-utils';

type IComponentOverrides = {
theme?: IThemeComponent;
selections?: ISelectionsComponent;
};

interface ICreateStylingArgs {
app?: EngineAPI.IApp,
components?: IComponent[];
}
import muiTheme from '../../theme/theme';
import { IComponent, IStyles } from '../types/components';
import { resolveBgColor, resolveBgImage } from '../styling-utils';
import { IComponentOverrides, ICreateStylingArgs } from './types';
import getSelectionsStyle from './selections-style';

const SUPPORTED_COMPONENTS = ['theme', 'selections'];

Expand Down Expand Up @@ -55,6 +45,8 @@ export default function useStyling({ app, components = [] }: ICreateStylingArgs)

const headerFontStyle = componentsOverrides.theme?.header?.fontStyle || {};

const selections = getSelectionsStyle({ componentsOverrides, stardustTheme });

const mergedStyle = {
listbox: {
background: {
Expand All @@ -67,6 +59,7 @@ export default function useStyling({ app, components = [] }: ICreateStylingArgs)
opacity: 1, // to override qlik disabled button style
},
color: componentsOverrides.theme?.header?.fontColor?.color || getListboxStyle('title.main', 'color') || '#404040',
selections,
},
popover: {
// Do not permit transparent or non-colored popovers.
Expand Down
Binary file modified test/rendering/baselines/styling-baseline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 4469bdc

Please sign in to comment.