Skip to content
This repository has been archived by the owner on Jul 28, 2024. It is now read-only.

[FRNT-565] Implement priorities fabric #166

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
Draft
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
131 changes: 37 additions & 94 deletions src/dev/global.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import styled from 'styled-components';
import { WolyGlobalStyles } from 'ui/woly-global-styles';
import { createPalette } from 'lib/palette';
import { createPriority } from 'lib/priority';

import { systemUi } from './font-stacks';

Expand All @@ -12,8 +13,8 @@ export const Global = styled(WolyGlobalStyles)`
}

/* base colors */
--bw-0: 0, 0%, 0%;
--bw-1000: 0, 0%, 100%;
--bw-0: 0, 0%, 100%;
--bw-1000: 0, 0%, 0%;

/* bw palette */
${createPalette('247, 7%, 48%', 'bw')}
Expand Down Expand Up @@ -52,113 +53,55 @@ export const Global = styled(WolyGlobalStyles)`
--woly-backdrop: hsla(var(--bw-0), 0.3);
--woly-shadow: 3px 3px 9px hsla(0, 0%, 22%, 12%);

[data-priority='default'] {
--woly-shape-default: hsla(var(--bw-500), 1);
--woly-shape-disabled: hsla(var(--bw-200), 1);
--woly-shape-hover: hsla(var(--bw-600), 1);
--woly-shape-active: hsla(var(--bw-700), 1);

--woly-shape-text-default: hsla(var(--bw-1000), 1);
--woly-shape-text-disabled: hsla(var(--bw-300), 1);
--woly-shape-text-hover: hsla(var(--bw-1000), 1);
--woly-shape-text-active: hsla(var(--bw-1000), 1);

--woly-canvas-default: transparent;
--woly-canvas-disabled: hsla(var(--bw-200), 1);
--woly-canvas-hover: hsla(var(--bw-600), 1);
--woly-canvas-active: hsla(var(--bw-700), 1);

--woly-canvas-text-default: hsla(var(--bw-0), 1);
--woly-canvas-text-disabled: hsla(var(--bw-300), 1);
--woly-canvas-text-hover: hsla(var(--bw-0), 1);
--woly-canvas-text-active: hsla(var(--bw-0), 1);
}

[data-priority='primary'] {
--woly-shape-default: hsla(var(--primary-500), 1);
--woly-shape-disabled: hsla(var(--primary-200), 1);
--woly-shape-hover: hsla(var(--primary-600), 1);
--woly-shape-active: hsla(var(--primary-700), 1);

--woly-shape-text-default: hsla(var(--bw-1000), 1);
--woly-shape-text-disabled: hsla(var(--bw-300), 1);
--woly-shape-text-hover: hsla(var(--bw-1000), 1);
--woly-shape-text-active: hsla(var(--bw-1000), 1);

--woly-canvas-default: transparent;
--woly-canvas-disabled: hsla(var(--bw-200), 1);
--woly-canvas-hover: hsla(var(--primary-600), 1);
--woly-canvas-active: hsla(var(--primary-700), 1);

--woly-canvas-text-default: hsla(var(--bw-0), 1);
--woly-canvas-text-disabled: hsla(var(--bw-300), 1);
--woly-canvas-text-hover: hsla(var(--bw-0), 1);
--woly-canvas-text-active: hsla(var(--bw-0), 1);
}

[data-priority='secondary'] {
--woly-shape-default: hsla(var(--secondary-500), 1);
--woly-shape-disabled: hsla(var(--secondary-200), 1);
--woly-shape-hover: hsla(var(--secondary-600), 1);
--woly-shape-active: hsla(var(--secondary-700), 1);

--woly-shape-text-default: hsla(var(--bw-1000), 1);
--woly-canvas-text-disabled: hsla(var(--bw-300), 1);
--woly-shape-text-hover: hsla(var(--bw-1000), 1);
--woly-shape-text-active: hsla(var(--bw-1000), 1);

--woly-canvas-default: transparent;
--woly-canvas-disabled: hsla(var(--bw-200), 1);
--woly-canvas-hover: hsla(var(--secondary-600), 1);
--woly-canvas-active: hsla(var(--secondary-700), 1);

--woly-canvas-text-default: hsla(var(--bw-0), 1);
--woly-canvas-text-disabled: hsla(var(--bw-300), 1);
--woly-canvas-text-hover: hsla(var(--bw-0), 1);
--woly-canvas-text-active: hsla(var(--bw-0), 1);
}

[data-priority='white'] {
--woly-shape-default: hsla(var(--bw-1000), 1);
--woly-shape-default: hsla(var(--bw-0), 1);
--woly-shape-disabled: hsla(var(--bw-200), 1);
--woly-shape-hover: hsla(var(--bw-400), 1);
--woly-shape-active: hsla(var(--bw-600), 1);

--woly-shape-text-default: hsla(var(--bw-0), 1);
--woly-shape-text-default: hsla(var(--bw-1000), 1);
--woly-shape-text-disabled: hsla(var(--bw-300), 1);
--woly-shape-text-hover: hsla(var(--bw-0), 1);
--woly-shape-text-active: hsla(var(--bw-0), 1);
--woly-shape-text-hover: hsla(var(--bw-1000), 1);
--woly-shape-text-active: hsla(var(--bw-1000), 1);

--woly-canvas-default: transparent;
--woly-canvas-disabled: hsla(var(--bw-200), 1);
--woly-canvas-hover: transparent;
--woly-canvas-active: transparent;

--woly-canvas-text-default: hsla(var(--bw-0), 1);
--woly-canvas-text-default: hsla(var(--bw-1000), 1);
--woly-canvas-text-disabled: hsla(var(--bw-300), 1);
--woly-canvas-text-hover: hsla(var(--bw-600), 1);
--woly-canvas-text-active: hsla(var(--bw-700), 1);
}

[data-priority='danger'] {
--woly-shape-default: hsla(var(--danger-500), 1);
--woly-shape-disabled: hsla(var(--danger-200), 1);
--woly-shape-hover: hsla(var(--danger-600), 1);
--woly-shape-active: hsla(var(--danger-700), 1);

--woly-shape-text-default: hsla(var(--bw-1000), 1);
--woly-shape-text-disabled: hsla(var(--bw-300), 1);
--woly-shape-text-hover: hsla(var(--bw-1000), 1);
--woly-shape-text-active: hsla(var(--bw-1000), 1);

--woly-canvas-default: transparent;
--woly-canvas-disabled: hsla(var(--danger-200), 1);
--woly-canvas-hover: hsla(var(--danger-600), 1);
--woly-canvas-active: hsla(var(--danger-700), 1);

--woly-canvas-text-default: hsla(var(--danger-500), 1);
--woly-canvas-text-disabled: hsla(var(--danger-300), 1);
--woly-canvas-text-hover: hsla(var(--danger-600), 1);
--woly-canvas-text-active: hsla(var(--danger-700), 1);
}
${createPriority({
priorityName: 'default',
paletteName: 'bw',
bwPaletteName: 'bw',
})}

${createPriority({
priorityName: 'primary',
paletteName: 'primary',
bwPaletteName: 'bw',
})}

${createPriority({
priorityName: 'secondary',
paletteName: 'secondary',
bwPaletteName: 'bw',
})}

${createPriority({
priorityName: 'danger',
paletteName: 'danger',
bwPaletteName: 'bw',
})}

${createPriority({
priorityName: 'success',
paletteName: 'success',
bwPaletteName: 'bw',
})}
`;
35 changes: 35 additions & 0 deletions src/dev/maps/common/combination.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
type VaritationsMap = Record<string, readonly unknown[]>;

export function createCombinations(obj: VaritationsMap) {
const fieldNames = Object.keys(obj);

if (fieldNames.length === 0) return [{}];

function _combinations<Combination extends string[]>(
[key, ...restKeys]: Combination,
combinations: Record<string, unknown[]>,
): Record<string, unknown>[] {
const possibleValues = obj[key];

if (!Array.isArray(possibleValues) || possibleValues.length === 0) {
throw new Error(`Please provide a non-empty array of possible values for prop ${key}`);
}

const variation = possibleValues.map((fieldValue) => ({
...combinations,
[key]: fieldValue,
}));

if (restKeys.length === 0) {
return variation;
}

return flatMap(variation, (newAcc) => _combinations(restKeys, newAcc));
}

return _combinations(fieldNames, {});
}

function flatMap<T>(arr: Array<T>, fn: (value: T, index: number, array: Array<T>) => Array<T>) {
return arr.map(fn).reduce((a, b) => a.concat(b));
}
16 changes: 16 additions & 0 deletions src/dev/maps/common/group-by-key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export function groupByKey<Variants extends Record<string, unknown>, Key extends keyof Variants>(
arr: Variants[],
key: Key,
keyMapper?: (fn: Variants[Key]) => string,
) {
return arr.reduce<Record<string, Variants[]>>((all, current) => {
const valueAsKey = keyMapper ? keyMapper(current[key]) : `${current[key]}`;

// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (all[valueAsKey] === undefined) {
all[valueAsKey] = [];
}
all[valueAsKey].push(current);
return all;
}, {});
}
111 changes: 111 additions & 0 deletions src/dev/maps/priority-weight-map.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import React from 'react';
import styled from 'styled-components';
import { Global } from 'dev/global';
import { Grid, Heading } from 'ui';

import { createCombinations } from './common/combination';
import { groupByKey } from './common/group-by-key';

export const priorities = ['default', 'primary', 'secondary', 'white', 'danger', 'success'];

interface ThemeProps {
weight: string;
priority: string;
disabled: boolean;
}

interface PriorityWeightMapProps {
weights: ('fill' | 'outline' | 'goast' | 'transparent')[];
render: (props: ThemeProps) => React.ReactElement;
}

export const PriorityWeightMap = ({ weights, render }: PriorityWeightMapProps) => {
const allCombinations = createCombinations({
weight: weights,
priority: priorities,
disabled: [true, false],
});

if (Object.keys(allCombinations).length === 0) return null;

return (
<Wrapper>
Copy link

Choose a reason for hiding this comment

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

suggestion: очень сложный jsx, может стоит декомпозировать?

{Object.entries(groupByKey(allCombinations, 'priority')).map(
([priority, combinations], index) => {
return (
// eslint-disable-next-line react/no-array-index-key
<PriorityGroup key={index}>
<Header>{priority}</Header>
<GridTemplate columns={weights.length + 1}>
<div /> {/* plug to make empty space at top left corner */}
{weights.map((weight, index) => (
<Centered key={index}>
<b>{weight}</b>
</Centered>
))}
{Object.entries(
groupByKey(combinations, 'disabled', (key) => (key ? 'normal' : 'disable')),
).map(([state, variations], index) => {
return (
<React.Fragment key={index}>
<Centered>
<b>{state}</b>
</Centered>
{variations.map((variation, index) => {
const { disabled, ...props } = variation as ThemeProps;

return (
<VariantCell key={index}>
{render({ ...props, disabled: state === 'disable' })}
</VariantCell>
);
})}
</React.Fragment>
);
})}
</GridTemplate>
</PriorityGroup>
);
},
)}
</Wrapper>
);
};

const Wrapper = styled(Global)`
display: flex;
flex-direction: row;
overflow-y: auto;
`;

const PriorityGroup = styled.div`
display: flex;
flex-direction: column;
padding: 20px;
`;

const VariantCell = styled.div`
display: flex;
align-items: center;
justify-content: center;
min-width: 100px;
padding: 20px;
`;

const Header = styled(Heading)`
padding-bottom: 15px;
padding-left: 5px;
`;

const GridTemplate = styled(Grid)`
gap: 10px;

color: #c4c4c4;
white-space: pre-line;
`;

const Centered = styled.div`
display: flex;
align-items: center;
justify-content: center;
`;
6 changes: 3 additions & 3 deletions src/dev/playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import { block } from './block';
export { block };

interface Props {
size: keyof typeof block;
direction: 'vertical' | 'horizontal';
configurators: ConfiguratorName[];
size?: keyof typeof block;
direction?: 'vertical' | 'horizontal';
configurators?: ConfiguratorName[];
}

export const Playground: React.FC<Props> = ({
Expand Down
2 changes: 1 addition & 1 deletion src/lib/palette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const saturationFn = (number: number, saturation: number) => {
return saturation - 10;
};

const COLOR_NUMBERS = [100, 200, 300, 400, 500, 600, 700, 800];
const COLOR_NUMBERS = [100, 200, 300, 400, 500, 600, 700, 800, 900];

export const createPalette = (color: string, name: string) => {
const hsl = getHsl(color);
Expand Down
39 changes: 39 additions & 0 deletions src/lib/priority.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { css } from 'styled-components';

interface PriorityType {
bwPaletteName: string;
paletteName: string;
priorityName: string;
}

export const createPriority = ({ bwPaletteName, paletteName, priorityName }: PriorityType) => {
const colors: Record<string, string> = {
'shape-default': `hsla(var(--${paletteName}-500), 1)`,
'shape-disabled': `hsla(var(--${paletteName}-200), 1)`,
'shape-hover': `hsla(var(--${paletteName}-600), 1)`,
'shape-active': `hsla(var(--${paletteName}-700), 1)`,

'shape-text-default': `hsla(var(--${bwPaletteName}-0), 1)`,
'shape-text-disabled': `hsla(var(--${paletteName}-300), 1)`,
'shape-text-hover': `hsla(var(--${bwPaletteName}-0), 1)`,
'shape-text-active': `hsla(var(--${bwPaletteName}-0), 1)`,

'canvas-default': `transparent`,
'canvas-disabled': `hsla(var(--${bwPaletteName}-200), 1)`,
'canvas-hover': `hsla(var(--${paletteName}-600), 1)`,
'canvas-active': `hsla(var(--${paletteName}-700), 1)`,

'canvas-text-default': `hsla(var(--${bwPaletteName}-1000), 1)`,
'canvas-text-disabled': `hsla(var(--${bwPaletteName}-300), 1)`,
'canvas-text-hover': `hsla(var(--${bwPaletteName}-1000), 1)`,
'canvas-text-active': `hsla(var(--${bwPaletteName}-1000), 1)`,
};

const priorityPalette = Object.keys(colors).map((key) => `--woly-${key}: ${colors[key]};`);

return css`
[data-priority='${priorityName}'] {
${priorityPalette.join('\n')}
}
`;
};
Loading