diff --git a/src/dev/global.ts b/src/dev/global.ts index 192e85b7..7b2a75c2 100644 --- a/src/dev/global.ts +++ b/src/dev/global.ts @@ -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'; @@ -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')} @@ -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', + })} `; diff --git a/src/dev/maps/common/combination.ts b/src/dev/maps/common/combination.ts new file mode 100644 index 00000000..a57488b1 --- /dev/null +++ b/src/dev/maps/common/combination.ts @@ -0,0 +1,35 @@ +type VaritationsMap = Record; + +export function createCombinations(obj: VaritationsMap) { + const fieldNames = Object.keys(obj); + + if (fieldNames.length === 0) return [{}]; + + function _combinations( + [key, ...restKeys]: Combination, + combinations: Record, + ): Record[] { + 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(arr: Array, fn: (value: T, index: number, array: Array) => Array) { + return arr.map(fn).reduce((a, b) => a.concat(b)); +} diff --git a/src/dev/maps/common/group-by-key.ts b/src/dev/maps/common/group-by-key.ts new file mode 100644 index 00000000..3c90486e --- /dev/null +++ b/src/dev/maps/common/group-by-key.ts @@ -0,0 +1,16 @@ +export function groupByKey, Key extends keyof Variants>( + arr: Variants[], + key: Key, + keyMapper?: (fn: Variants[Key]) => string, +) { + return arr.reduce>((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; + }, {}); +} diff --git a/src/dev/maps/priority-weight-map.tsx b/src/dev/maps/priority-weight-map.tsx new file mode 100644 index 00000000..dfba0bb6 --- /dev/null +++ b/src/dev/maps/priority-weight-map.tsx @@ -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 ( + + {Object.entries(groupByKey(allCombinations, 'priority')).map( + ([priority, combinations], index) => { + return ( + // eslint-disable-next-line react/no-array-index-key + +
{priority}
+ +
{/* plug to make empty space at top left corner */} + {weights.map((weight, index) => ( + + {weight} + + ))} + {Object.entries( + groupByKey(combinations, 'disabled', (key) => (key ? 'normal' : 'disable')), + ).map(([state, variations], index) => { + return ( + + + {state} + + {variations.map((variation, index) => { + const { disabled, ...props } = variation as ThemeProps; + + return ( + + {render({ ...props, disabled: state === 'disable' })} + + ); + })} + + ); + })} + + + ); + }, + )} + + ); +}; + +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; +`; diff --git a/src/dev/playground.tsx b/src/dev/playground.tsx index 12c24f8f..e4f323ff 100644 --- a/src/dev/playground.tsx +++ b/src/dev/playground.tsx @@ -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 = ({ diff --git a/src/lib/palette.tsx b/src/lib/palette.tsx index ac804c01..8e1e4be1 100644 --- a/src/lib/palette.tsx +++ b/src/lib/palette.tsx @@ -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); diff --git a/src/lib/priority.tsx b/src/lib/priority.tsx new file mode 100644 index 00000000..a6871643 --- /dev/null +++ b/src/lib/priority.tsx @@ -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 = { + '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')} + } + `; +}; diff --git a/src/woly/atoms/button-icon/usage.mdx b/src/woly/atoms/button-icon/usage.mdx index 5a5cddd2..394de25c 100644 --- a/src/woly/atoms/button-icon/usage.mdx +++ b/src/woly/atoms/button-icon/usage.mdx @@ -74,6 +74,7 @@ Button-icon's size can controlled by block-container and it`s width is equal to ### Weight and priority Button-icon can be represented in primary, secondary or default priorities and can be styled by changing icon`s weight: fill, outline, transparent. + In case of choosing button-icon in black-and-white priority with outline styles use the opposite background color to the text color of button-icon. diff --git a/src/woly/atoms/button/priorities.mdx b/src/woly/atoms/button/priorities.mdx new file mode 100644 index 00000000..01e9bceb --- /dev/null +++ b/src/woly/atoms/button/priorities.mdx @@ -0,0 +1,174 @@ +import {Button, Input, Table, Tbody, Td, Th, Thead, Tr} from 'ui' +import {Playground} from 'dev/playground' + +### Priorities + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Colors/WeightPrimarySecondaryDefault
Filled +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Outlined +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
None +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/woly/atoms/button/state-props.tsx b/src/woly/atoms/button/state-props.tsx index 002ced97..42940981 100644 --- a/src/woly/atoms/button/state-props.tsx +++ b/src/woly/atoms/button/state-props.tsx @@ -20,7 +20,7 @@ interface ComponentButtonProps { export const variants: ComponentProps = { name: 'variants', - values: ['primary', 'secondary'], + values: ['primary', 'secondary', 'danger', 'goast', 'default'], }; export const sizes: ComponentProps = { @@ -41,7 +41,7 @@ export const ComponentButton: React.FC<{ prop: ComponentButtonProps }> = ({ prop onClick={() => console.log('Hi!')} outlined={prop.outlined} text="Button" - variant={prop.variants} + priority={prop.variants} /> ); diff --git a/src/woly/atoms/text/index.tsx b/src/woly/atoms/text/index.tsx index 84aec42c..6f42aec8 100644 --- a/src/woly/atoms/text/index.tsx +++ b/src/woly/atoms/text/index.tsx @@ -15,7 +15,7 @@ const map = (properties: TextProps & Priority) => ({ }); export const Text = styled.p.attrs(map)` - --local-color: var(--woly-shape-text-default); + --local-color: var(--woly-canvas-text-default); margin: 0; diff --git a/src/woly/organisms/palette-example/index.tsx b/src/woly/organisms/palette-example/index.tsx new file mode 100644 index 00000000..096dfb78 --- /dev/null +++ b/src/woly/organisms/palette-example/index.tsx @@ -0,0 +1,130 @@ +/* eslint-disable prettier/prettier */ +import React from 'react'; +import styled from 'styled-components'; +import { ButtonIcon } from 'ui'; +import { IconSearch } from 'static/icons'; +import { Playground } from 'dev/playground'; +import { PriorityWeightMap } from 'dev/maps/priority-weight-map'; + +export const Palettes = () => { + return ( + + + + + + + + + + + + + + + + + + + + + +
+ 01002003004005006007008009001000
+
+ ); +}; + +export const PriorityVariables = () => { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Shape DefaultShape DisabledShape HoverShape ActiveShape Text DefaultShape Text DisabledShape Text HoverShape Text ActiveCanvas DefaultCanvas DisabledCanvas HoverCanvas ActiveCanvas Text DefaultCanvas Text DisabledCanvas Text HoverCanvas Text Active
+
+ ); +}; + +const PaletteRow = ({ name }: { name: string }) => ( + + {name.charAt(0).toLowerCase() + name.slice(1)} + {Array.from({ length: 11 }).map((value, index) => { + return ( + + ); + })} + +); + +const PriorityRow = ({ name }: { name: string }) => ( + + {name.charAt(0).toLowerCase() + name.slice(1)} + + + + + + + + + + + + + + + + + +); + +const Table = styled.table` + position: relative; + + background-color: #dfdbe5; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 8 8'%3E%3Cg fill='%239C92AC' fill-opacity='0.4'%3E%3Cpath fill-rule='evenodd' d='M0 0h4v4H0V0zm4 4h4v4H4V4z'/%3E%3C/g%3E%3C/svg%3E"); + + td { + width: 200px; + height: 50px; + } +`; + +export const ButtonIconWeightPriorityWeight = () => ( + ( + } + onClick={() => console.info('ButtonIcon clicked')} + weight={weight} + priority={priority} + disabled={disabled} + /> + )} + /> +); diff --git a/src/woly/organisms/palette-example/usage.mdx b/src/woly/organisms/palette-example/usage.mdx new file mode 100644 index 00000000..e4671879 --- /dev/null +++ b/src/woly/organisms/palette-example/usage.mdx @@ -0,0 +1,13 @@ +import { Palettes, PriorityVariables, ButtonIconWeightPriorityWeight } from './index' + +## Palettes + + + +## Priority Variables + + + +## Button Icon Priority Weight Matrix + +