From f00595492e43bd9d98727266d7b5ba3c62615198 Mon Sep 17 00:00:00 2001 From: Levi Thomason Date: Tue, 7 May 2019 22:01:51 -0700 Subject: [PATCH 01/28] introduce selector/style tuple style files --- .../react/src/components/Avatar/Avatar.tsx | 4 - .../react/src/lib/resolveComponentRules.ts | 81 +++++++++++ .../teams/components/Avatar/avatarStyles.ts | 5 +- .../teams/components/Status/statusStyles.ts | 129 ++++++++---------- .../components/Status/statusVariables.ts | 41 +++++- packages/react/src/themes/types.ts | 6 +- 6 files changed, 181 insertions(+), 85 deletions(-) create mode 100644 packages/react/src/lib/resolveComponentRules.ts diff --git a/packages/react/src/components/Avatar/Avatar.tsx b/packages/react/src/components/Avatar/Avatar.tsx index a27bf4375d..8e75fa6d41 100644 --- a/packages/react/src/components/Avatar/Avatar.tsx +++ b/packages/react/src/components/Avatar/Avatar.tsx @@ -113,10 +113,6 @@ class Avatar extends UIComponent, any> { defaultProps: { size, styles: styles.status, - variables: { - borderColor: variables.statusBorderColor, - borderWidth: variables.statusBorderWidth, - }, }, })} diff --git a/packages/react/src/lib/resolveComponentRules.ts b/packages/react/src/lib/resolveComponentRules.ts new file mode 100644 index 0000000000..e3d53ac4ff --- /dev/null +++ b/packages/react/src/lib/resolveComponentRules.ts @@ -0,0 +1,81 @@ +import { ComponentSlotStylesInput, ICSSInJSStyle, SiteVariablesInput } from 'src/themes/types' + +export function isObject(item): boolean { + return typeof item === 'object' && !Array.isArray(item) && item !== null +} + +// fast object merge with assumptions +export function deepMergeObjects(target: object, source: object): object { + Object.keys(source).forEach(key => { + const value = source[key] + + if (isObject(value)) { + if (!target[key]) target[key] = {} + deepMergeObjects(target[key], value) + } else { + target[key] = value + } + }) + + return target +} + +const isMatch = (props, selector): boolean => { + if (selector === null) return true + + return Object.keys(selector).every(k => props[k] === selector[k]) +} + +const reduceSelectorStyleTuples = (props, tuples: [object, ICSSInJSStyle][]): ICSSInJSStyle => { + return tuples.reduce((acc, [selector, style]) => { + return isMatch(props, selector) ? deepMergeObjects(acc, style) : acc + }, {}) +} + +// Map reduces object values (array of tuples [selector, style]) +const resolveComponentRules = (rules, props = {}): ICSSInJSStyle => { + return Object.keys(rules).reduce((acc, next) => { + acc[next] = reduceSelectorStyleTuples(props, rules[next]) + return acc + }, {}) +} + +// TODO: temporary during migration to selector/style tuple styles +// Backports selector/style tuple styles to previous signature +export const backportComponentStyle = (selectorStyleFunc): ComponentSlotStylesInput => { + if (typeof selectorStyleFunc !== 'function') { + return selectorStyleFunc + } + + const withoutVariables = selectorStyleFunc({ + colors: { + white: {}, + green: {}, + yellow: {}, + orange: {}, + purple: {}, + grey: {}, + blue: {}, + black: {}, + danger: {}, + info: {}, + pink: {}, + primary: {}, + red: {}, + secondary: {}, + success: {}, + teal: {}, + text: {}, + warning: {}, + }, + } as SiteVariablesInput) + + return Object.keys(withoutVariables).reduce((acc, part) => { + acc[part] = ({ props, variables }) => { + return resolveComponentRules(selectorStyleFunc(variables), props)[part] + } + return acc + }, {}) +} + +export default resolveComponentRules diff --git a/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts b/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts index d64e1c8ba7..0c4307fcb6 100644 --- a/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts +++ b/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts @@ -50,8 +50,9 @@ const avatarStyles: ComponentSlotStylesInput = { }, status: ({ variables: v }): ICSSInJSStyle => ({ position: 'absolute', - bottom: `-${v.statusBorderWidth}px`, - right: `-${v.statusBorderWidth}px`, + bottom: 0, + right: 0, + boxShadow: `0 0 0 ${pxToRem(v.statusBorderWidth)} ${v.statusBorderColor}`, }), } diff --git a/packages/react/src/themes/teams/components/Status/statusStyles.ts b/packages/react/src/themes/teams/components/Status/statusStyles.ts index 87e05838ef..45be45a655 100644 --- a/packages/react/src/themes/teams/components/Status/statusStyles.ts +++ b/packages/react/src/themes/teams/components/Status/statusStyles.ts @@ -1,81 +1,64 @@ -import { pxToRem, SizeValue } from '../../../../lib' -import { ComponentSlotStylesInput, ICSSInJSStyle } from '../../../types' import { StatusProps } from '../../../../components/Status/Status' import { StatusVariables } from './statusVariables' +import { ComponentSelectorsAndStyles } from 'src/themes/types' +import { backportComponentStyle } from 'src/lib/resolveComponentRules' -const getBackgroundColor = (state: string, variables: StatusVariables) => { - switch (state) { - case 'success': - return variables.successBackgroundColor - case 'info': - return variables.infoBackgroundColor - case 'warning': - return variables.warningBackgroundColor - case 'error': - return variables.errorBackgroundColor - case 'unknown': - default: - return variables.defaultBackgroundColor - } -} +const statusStyles: ComponentSelectorsAndStyles = v => ({ + root: [ + [ + null, + { + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + verticalAlign: 'middle', + width: v.medium, + height: v.medium, + color: v.defaultTextColor, + backgroundColor: v.defaultBackgroundColor, + borderRadius: '9999px', + }, + ], -const getTextColor = (state: string, variables: StatusVariables) => { - switch (state) { - case 'success': - return variables.successTextColor - case 'info': - return variables.infoTextColor - case 'warning': - return variables.warningTextColor - case 'error': - return variables.errorTextColor - case 'unknown': - default: - return variables.defaultTextColor - } -} + // + // Colors + // + [{ color: 'red' }, { backgroundColor: 'red' }], + [{ color: 'orange' }, { backgroundColor: 'orange' }], + [{ color: 'yellow' }, { backgroundColor: 'yellow' }], + [{ color: 'green' }, { backgroundColor: 'green' }], + [{ color: 'blue' }, { backgroundColor: 'blue' }], + [{ color: 'violet' }, { backgroundColor: 'violet' }], -const sizeToPxValue: Record = { - smallest: 8, - smaller: 8, - small: 8, - medium: 10, - large: 12, - larger: 14, - largest: 16, -} + // + // States + // + [{ state: 'success' }, { backgroundColor: v.successBackgroundColor }], + [{ state: 'info' }, { backgroundColor: v.infoBackgroundColor }], + [{ state: 'warning' }, { backgroundColor: v.warningBackgroundColor }], + [{ state: 'error' }, { backgroundColor: v.errorBackgroundColor }], -export const getSizeStyles = (sizeInPx: number, variables: StatusVariables) => { - const borderWidth = (variables.borderColor && variables.borderWidth) || 0 - const sizeInRem = pxToRem(sizeInPx + 2 * borderWidth) + // + // Sizes + // + [{ size: 'smallest' }, { width: v.smallest, height: v.smallest }], + [{ size: 'smaller' }, { width: v.smaller, height: v.smaller }], + [{ size: 'small' }, { width: v.small, height: v.small }], + [{ size: 'medium' }, { width: v.medium, height: v.medium }], + [{ size: 'large' }, { width: v.large, height: v.large }], + [{ size: 'larger' }, { width: v.larger, height: v.larger }], + [{ size: 'largest' }, { width: v.largest, height: v.largest }], + ], - return { - height: sizeInRem, - width: sizeInRem, - } -} + // ---------------------------------------- + // Icon + // ---------------------------------------- + icon: [ + [{ state: 'success' }, { color: v.successTextColor }], + [{ state: 'info' }, { color: v.infoTextColor }], + [{ state: 'warning' }, { color: v.warningTextColor }], + [{ state: 'error' }, { color: v.errorTextColor }], + ], +}) -const statusStyles: ComponentSlotStylesInput = { - root: ({ props: { color, size, state }, variables }): ICSSInJSStyle => { - return { - display: 'inline-flex', - alignItems: 'center', - justifyContent: 'center', - ...getSizeStyles(sizeToPxValue[size], variables), - verticalAlign: 'middle', - borderRadius: '9999px', - ...(variables.borderColor && { - borderColor: variables.borderColor, - borderWidth: pxToRem(variables.borderWidth), - borderStyle: 'solid', - }), - backgroundColor: color || getBackgroundColor(state, variables), - } - }, - - icon: ({ props: { state }, variables }): ICSSInJSStyle => ({ - color: getTextColor(state, variables), - }), -} - -export default statusStyles +export default backportComponentStyle(statusStyles) diff --git a/packages/react/src/themes/teams/components/Status/statusVariables.ts b/packages/react/src/themes/teams/components/Status/statusVariables.ts index 9abb603dfe..e447f710b6 100644 --- a/packages/react/src/themes/teams/components/Status/statusVariables.ts +++ b/packages/react/src/themes/teams/components/Status/statusVariables.ts @@ -1,6 +1,7 @@ +import { pxToRem } from '../../../../lib' +import { SiteVariablesInput } from 'src/themes/types' + export interface StatusVariables { - borderColor: string - borderWidth: number successBackgroundColor: string successTextColor: string infoBackgroundColor: string @@ -11,11 +12,24 @@ export interface StatusVariables { errorTextColor: string defaultBackgroundColor: string defaultTextColor: string + + backgroundRed: string + backgroundOrange: string + backgroundYellow: string + backgroundGreen: string + backgroundBlue: string + backgroundViolet: string + + smallest: string + smaller: string + small: string + medium: string + large: string + larger: string + largest: string } -export default siteVariables => ({ - borderColor: undefined, - borderWidth: 2, +export default (siteVariables: SiteVariablesInput): StatusVariables => ({ successBackgroundColor: siteVariables.colors.green[200], successTextColor: siteVariables.colors.white, infoBackgroundColor: siteVariables.colors.brand[500], @@ -26,4 +40,21 @@ export default siteVariables => ({ errorTextColor: siteVariables.colors.white, defaultBackgroundColor: siteVariables.colors.grey[350], defaultTextColor: siteVariables.colors.white, + + backgroundRed: siteVariables.errorStatusBackgroundColor, + backgroundOrange: siteVariables.warningStatusBackgroundColor, + // TODO: support real site variables colors here + backgroundYellow: 'yellow', + backgroundGreen: siteVariables.successStatusBackgroundColor, + backgroundBlue: siteVariables.infoStatusBackgroundColor, + // TODO: support real site variables colors here + backgroundViolet: 'violet', + + smallest: pxToRem(8), + smaller: pxToRem(8), + small: pxToRem(8), + medium: pxToRem(10), + large: pxToRem(12), + larger: pxToRem(14), + largest: pxToRem(16), }) diff --git a/packages/react/src/themes/types.ts b/packages/react/src/themes/types.ts index daa7cddea5..050f1936c2 100644 --- a/packages/react/src/themes/types.ts +++ b/packages/react/src/themes/types.ts @@ -1,7 +1,7 @@ import * as CSSType from 'csstype' import { IRenderer as FelaRenderer } from 'fela' import * as React from 'react' -import { Extendable, ObjectOf, ObjectOrFunc, Omit } from '../types' +import { Extendable, Nullable, ObjectOf, ObjectOrFunc, Omit } from '../types' // Themes go through 3 phases. // 1. Input - (from the user), variable and style objects/functions, some values optional @@ -272,6 +272,10 @@ export type ComponentSlotStyle = export interface ComponentSlotStylesInput extends ObjectOf> {} +export type ComponentSelectorsAndStyles = ( + vars: TVars, +) => { [key in keyof TProps]: [Nullable>, ICSSInJSStyle][] } + export interface ComponentSlotStylesPrepared extends ObjectOf> {} From 34ef2787b2ed7a050ef07a3088f8022508beab30 Mon Sep 17 00:00:00 2001 From: Levi Thomason Date: Tue, 7 May 2019 22:29:35 -0700 Subject: [PATCH 02/28] cleanup status styles and variables --- .../react/src/lib/resolveComponentRules.ts | 25 ++----------------- .../teams/components/Status/statusStyles.ts | 12 ++++----- 2 files changed, 8 insertions(+), 29 deletions(-) diff --git a/packages/react/src/lib/resolveComponentRules.ts b/packages/react/src/lib/resolveComponentRules.ts index e3d53ac4ff..651180430a 100644 --- a/packages/react/src/lib/resolveComponentRules.ts +++ b/packages/react/src/lib/resolveComponentRules.ts @@ -1,4 +1,4 @@ -import { ComponentSlotStylesInput, ICSSInJSStyle, SiteVariablesInput } from 'src/themes/types' +import { ComponentSlotStylesInput, ICSSInJSStyle } from 'src/themes/types' export function isObject(item): boolean { return typeof item === 'object' && !Array.isArray(item) && item !== null @@ -47,28 +47,7 @@ export const backportComponentStyle = (selectorStyleFunc): ComponentSlotStylesIn return selectorStyleFunc } - const withoutVariables = selectorStyleFunc({ - colors: { - white: {}, - green: {}, - yellow: {}, - orange: {}, - purple: {}, - grey: {}, - blue: {}, - black: {}, - danger: {}, - info: {}, - pink: {}, - primary: {}, - red: {}, - secondary: {}, - success: {}, - teal: {}, - text: {}, - warning: {}, - }, - } as SiteVariablesInput) + const withoutVariables = selectorStyleFunc({}) return Object.keys(withoutVariables).reduce((acc, part) => { acc[part] = ({ props, variables }) => { diff --git a/packages/react/src/themes/teams/components/Status/statusStyles.ts b/packages/react/src/themes/teams/components/Status/statusStyles.ts index 45be45a655..faf795d6d5 100644 --- a/packages/react/src/themes/teams/components/Status/statusStyles.ts +++ b/packages/react/src/themes/teams/components/Status/statusStyles.ts @@ -23,12 +23,12 @@ const statusStyles: ComponentSelectorsAndStyles = // // Colors // - [{ color: 'red' }, { backgroundColor: 'red' }], - [{ color: 'orange' }, { backgroundColor: 'orange' }], - [{ color: 'yellow' }, { backgroundColor: 'yellow' }], - [{ color: 'green' }, { backgroundColor: 'green' }], - [{ color: 'blue' }, { backgroundColor: 'blue' }], - [{ color: 'violet' }, { backgroundColor: 'violet' }], + [{ color: 'red' }, { backgroundColor: v.backgroundRed }], + [{ color: 'orange' }, { backgroundColor: v.backgroundOrange }], + [{ color: 'yellow' }, { backgroundColor: v.backgroundYellow }], + [{ color: 'green' }, { backgroundColor: v.backgroundGreen }], + [{ color: 'blue' }, { backgroundColor: v.backgroundBlue }], + [{ color: 'violet' }, { backgroundColor: v.backgroundViolet }], // // States From 276a88b6da5de7c47d8a49ca7d3ed665bf8b2337 Mon Sep 17 00:00:00 2001 From: Levi Thomason Date: Wed, 8 May 2019 11:45:32 -0700 Subject: [PATCH 03/28] refactor: avatarStyles to tuple syntax --- .../teams/components/Avatar/avatarStyles.ts | 143 +++++++++++------- .../components/Avatar/avatarVariables.ts | 26 +++- 2 files changed, 112 insertions(+), 57 deletions(-) diff --git a/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts b/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts index 0c4307fcb6..10e9716e45 100644 --- a/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts +++ b/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts @@ -1,59 +1,96 @@ -import { pxToRem } from '../../../../lib' -import { ComponentSlotStylesInput, ICSSInJSStyle } from '../../../types' +import { ComponentSelectorsAndStyles } from '../../../types' import { AvatarProps } from '../../../../components/Avatar/Avatar' +import { AvatarVariables } from 'src/themes/teams/components/Avatar/avatarVariables' +import { backportComponentStyle } from 'src/lib/resolveComponentRules' -const sizeToPxValue = { - smallest: 24, - smaller: 24, - small: 24, - medium: 32, - large: 36, - larger: 42, - largest: 48, -} +const avatarStyles: ComponentSelectorsAndStyles = v => ({ + root: [ + [ + null, + { + position: 'relative', + backgroundColor: 'inherit', + display: 'inline-block', + verticalAlign: 'middle', + height: v.medium, + width: v.medium, + }, + ], -const avatarStyles: ComponentSlotStylesInput = { - root: ({ props: { size } }): ICSSInJSStyle => { - const sizeInRem = pxToRem(sizeToPxValue[size]) + // + // Sizes + // + [{ size: 'smallest' }, { width: v.smallest, height: v.smallest }], + [{ size: 'smaller' }, { width: v.smaller, height: v.smaller }], + [{ size: 'small' }, { width: v.small, height: v.small }], + [{ size: 'medium' }, { width: v.medium, height: v.medium }], + [{ size: 'large' }, { width: v.large, height: v.large }], + [{ size: 'larger' }, { width: v.larger, height: v.larger }], + [{ size: 'largest' }, { width: v.largest, height: v.largest }], + ], - return { - position: 'relative', - backgroundColor: 'inherit', - display: 'inline-block', - verticalAlign: 'middle', - height: sizeInRem, - width: sizeInRem, - } - }, - image: ({ variables: v }): ICSSInJSStyle => ({ - borderColor: v.avatarBorderColor, - borderStyle: 'solid', - borderWidth: `${v.avatarBorderWidth}px`, + // ---------------------------------------- + // Image + // ---------------------------------------- + image: [ + [ + null, + { + borderColor: v.avatarBorderColor, + borderStyle: 'solid', + borderWidth: v.avatarBorderWidth, - height: '100%', - objectFit: 'cover', - verticalAlign: 'top', - width: '100%', - }), - label: ({ props: { size } }): ICSSInJSStyle => { - const sizeInRem = pxToRem(sizeToPxValue[size]) - return { - display: 'inline-block', - width: sizeInRem, - height: sizeInRem, - lineHeight: sizeInRem, - fontSize: pxToRem(sizeToPxValue[size] / 2.333), - verticalAlign: 'top', - textAlign: 'center', - padding: '0px', - } - }, - status: ({ variables: v }): ICSSInJSStyle => ({ - position: 'absolute', - bottom: 0, - right: 0, - boxShadow: `0 0 0 ${pxToRem(v.statusBorderWidth)} ${v.statusBorderColor}`, - }), -} + height: '100%', + objectFit: 'cover', + verticalAlign: 'top', + width: '100%', + }, + ], + ], -export default avatarStyles + // ---------------------------------------- + // Label + // ---------------------------------------- + label: [ + [ + null, + { + display: 'inline-block', + width: v.medium, + height: v.medium, + lineHeight: v.medium, + fontSize: `calc(${v.medium} / 2.333)`, + verticalAlign: 'top', + textAlign: 'center', + padding: '0px', + }, + ], + + // + // Sizes + // + [{ size: 'smallest' }, { width: v.smallest, height: v.smallest, lineHeight: v.smallest }], + [{ size: 'smaller' }, { width: v.smaller, height: v.smaller, lineHeight: v.smaller }], + [{ size: 'small' }, { width: v.small, height: v.small, lineHeight: v.small }], + [{ size: 'medium' }, { width: v.medium, height: v.medium, lineHeight: v.medium }], + [{ size: 'large' }, { width: v.large, height: v.large, lineHeight: v.large }], + [{ size: 'larger' }, { width: v.larger, height: v.larger, lineHeight: v.larger }], + [{ size: 'largest' }, { width: v.largest, height: v.largest, lineHeight: v.largest }], + ], + + // ---------------------------------------- + // Status + // ---------------------------------------- + status: [ + [ + null, + { + position: 'absolute', + bottom: 0, + right: 0, + boxShadow: `0 0 0 ${v.statusBorderWidth} ${v.statusBorderColor}`, + }, + ], + ], +}) +export default backportComponentStyle(avatarStyles) diff --git a/packages/react/src/themes/teams/components/Avatar/avatarVariables.ts b/packages/react/src/themes/teams/components/Avatar/avatarVariables.ts index f952d65e12..57f0dd9c83 100644 --- a/packages/react/src/themes/teams/components/Avatar/avatarVariables.ts +++ b/packages/react/src/themes/teams/components/Avatar/avatarVariables.ts @@ -1,13 +1,31 @@ +import { pxToRem } from 'src/lib' + export interface AvatarVariables { avatarBorderColor: string - avatarBorderWidth: number + avatarBorderWidth: string statusBorderColor: string - statusBorderWidth: number + statusBorderWidth: string + + smallest: string + smaller: string + small: string + medium: string + large: string + larger: string + largest: string } export default (siteVariables): AvatarVariables => ({ avatarBorderColor: '', - avatarBorderWidth: 0, + avatarBorderWidth: '0', statusBorderColor: siteVariables.bodyBackground, - statusBorderWidth: 2, + statusBorderWidth: '2px', + + smallest: pxToRem(24), + smaller: pxToRem(24), + small: pxToRem(24), + medium: pxToRem(32), + large: pxToRem(36), + larger: pxToRem(42), + largest: pxToRem(48), }) From eb15a886e2df4e7f9d3627e39e6ce14cd3e846dd Mon Sep 17 00:00:00 2001 From: Levi Thomason Date: Wed, 8 May 2019 11:50:33 -0700 Subject: [PATCH 04/28] fix: use relative imports --- .../react/src/themes/teams/components/Avatar/avatarStyles.ts | 4 ++-- .../src/themes/teams/components/Avatar/avatarVariables.ts | 2 +- .../react/src/themes/teams/components/Status/statusStyles.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts b/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts index 10e9716e45..3b4a2d1012 100644 --- a/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts +++ b/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts @@ -1,7 +1,7 @@ import { ComponentSelectorsAndStyles } from '../../../types' import { AvatarProps } from '../../../../components/Avatar/Avatar' -import { AvatarVariables } from 'src/themes/teams/components/Avatar/avatarVariables' -import { backportComponentStyle } from 'src/lib/resolveComponentRules' +import { AvatarVariables } from './avatarVariables' +import { backportComponentStyle } from '../../../../lib/resolveComponentRules' const avatarStyles: ComponentSelectorsAndStyles = v => ({ root: [ diff --git a/packages/react/src/themes/teams/components/Avatar/avatarVariables.ts b/packages/react/src/themes/teams/components/Avatar/avatarVariables.ts index 57f0dd9c83..e8215bcc21 100644 --- a/packages/react/src/themes/teams/components/Avatar/avatarVariables.ts +++ b/packages/react/src/themes/teams/components/Avatar/avatarVariables.ts @@ -1,4 +1,4 @@ -import { pxToRem } from 'src/lib' +import { pxToRem } from '../../../../lib' export interface AvatarVariables { avatarBorderColor: string diff --git a/packages/react/src/themes/teams/components/Status/statusStyles.ts b/packages/react/src/themes/teams/components/Status/statusStyles.ts index faf795d6d5..6ee27215f5 100644 --- a/packages/react/src/themes/teams/components/Status/statusStyles.ts +++ b/packages/react/src/themes/teams/components/Status/statusStyles.ts @@ -1,7 +1,7 @@ import { StatusProps } from '../../../../components/Status/Status' import { StatusVariables } from './statusVariables' -import { ComponentSelectorsAndStyles } from 'src/themes/types' -import { backportComponentStyle } from 'src/lib/resolveComponentRules' +import { ComponentSelectorsAndStyles } from '../../../types' +import { backportComponentStyle } from '../../../../lib/resolveComponentRules' const statusStyles: ComponentSelectorsAndStyles = v => ({ root: [ From fb864a97089a7c22c639d3635ce36931bbbb5223 Mon Sep 17 00:00:00 2001 From: Levi Thomason Date: Tue, 18 Jun 2019 09:03:27 -0700 Subject: [PATCH 05/28] wip --- .../react/src/lib/resolveComponentRules.ts | 2 +- .../components/Avatar/avatarVariables.ts | 2 +- .../components/Status/statusVariables.ts | 2 +- packages/react/src/themes/types.ts | 4 +- packages/style/compile.ts | 357 ++++++++++++++++++ packages/style/index.ts | 39 ++ packages/style/package.json | 8 + packages/style/tsconfig.json | 4 + 8 files changed, 413 insertions(+), 5 deletions(-) create mode 100644 packages/style/compile.ts create mode 100644 packages/style/index.ts create mode 100644 packages/style/package.json create mode 100644 packages/style/tsconfig.json diff --git a/packages/react/src/lib/resolveComponentRules.ts b/packages/react/src/lib/resolveComponentRules.ts index 651180430a..920a40d834 100644 --- a/packages/react/src/lib/resolveComponentRules.ts +++ b/packages/react/src/lib/resolveComponentRules.ts @@ -1,4 +1,4 @@ -import { ComponentSlotStylesInput, ICSSInJSStyle } from 'src/themes/types' +import { ComponentSlotStylesInput, ICSSInJSStyle } from '../themes/types' export function isObject(item): boolean { return typeof item === 'object' && !Array.isArray(item) && item !== null diff --git a/packages/react/src/themes/teams-high-contrast/components/Avatar/avatarVariables.ts b/packages/react/src/themes/teams-high-contrast/components/Avatar/avatarVariables.ts index 08cf6cc6b9..047326ca10 100644 --- a/packages/react/src/themes/teams-high-contrast/components/Avatar/avatarVariables.ts +++ b/packages/react/src/themes/teams-high-contrast/components/Avatar/avatarVariables.ts @@ -2,6 +2,6 @@ import { AvatarVariables } from '../../../teams/components/Avatar/avatarVariable export default (siteVariables: any): Partial => ({ avatarBorderColor: siteVariables.colors.white, - avatarBorderWidth: 2, + avatarBorderWidth: '2px', statusBorderColor: siteVariables.colors.black, }) diff --git a/packages/react/src/themes/teams/components/Status/statusVariables.ts b/packages/react/src/themes/teams/components/Status/statusVariables.ts index e447f710b6..3bc1dde4b6 100644 --- a/packages/react/src/themes/teams/components/Status/statusVariables.ts +++ b/packages/react/src/themes/teams/components/Status/statusVariables.ts @@ -1,5 +1,5 @@ import { pxToRem } from '../../../../lib' -import { SiteVariablesInput } from 'src/themes/types' +import { SiteVariablesInput } from '../../../types' export interface StatusVariables { successBackgroundColor: string diff --git a/packages/react/src/themes/types.ts b/packages/react/src/themes/types.ts index 050f1936c2..479ab948e4 100644 --- a/packages/react/src/themes/types.ts +++ b/packages/react/src/themes/types.ts @@ -1,7 +1,7 @@ import * as CSSType from 'csstype' import { IRenderer as FelaRenderer } from 'fela' import * as React from 'react' -import { Extendable, Nullable, ObjectOf, ObjectOrFunc, Omit } from '../types' +import { Extendable, ObjectOf, ObjectOrFunc, Omit } from '../types' // Themes go through 3 phases. // 1. Input - (from the user), variable and style objects/functions, some values optional @@ -274,7 +274,7 @@ export interface ComponentSlotStylesInput export type ComponentSelectorsAndStyles = ( vars: TVars, -) => { [key in keyof TProps]: [Nullable>, ICSSInJSStyle][] } +) => { [key in keyof TProps]: [Partial, ICSSInJSStyle][] } export interface ComponentSlotStylesPrepared extends ObjectOf> {} diff --git a/packages/style/compile.ts b/packages/style/compile.ts new file mode 100644 index 0000000000..4444a99be4 --- /dev/null +++ b/packages/style/compile.ts @@ -0,0 +1,357 @@ +/** + * To run: + * nodemon --watch 'src/themes/toCSS.ts' --exec 'ts-node src/themes/toCSS.ts' + */ +// import { cssifyObject } from 'css-in-js-utils' +import * as _ from 'lodash' +import { ThemePrepared } from '@stardust-ui/react/src' + +export const fs = require('fs') +export const pkg = require('../../package.json') + +// ============================================================ +// Utilities +// ============================================================ + +// For a given base style and override style, returns only those +// properties in the override which update the base style. +// Duplicate or unnecessary properties are removed. +export const getOverrideStyles = (base = {}, override = {}) => { + return Object.keys(base).reduce((acc, next) => { + if (base[next] !== override[next]) { + acc[next] = _.isPlainObject(base[next]) ? getOverrideStyles(base[next]) : base[next] + } + + return acc + }, {}) +} + +export const sortObject = unsorted => { + return Object.keys(unsorted) + .sort() + .reduce((sorted, key) => { + const value = unsorted[key] + sorted[key] = _.isPlainObject(value) ? sortObject(value) : value + return sorted + }, {}) +} + +// ============================================================ +// Selectors +// ============================================================ +export const nameToSelector = (name: string) => `.ui-${_.kebabCase(name)}` + +export const slotToSelector = (slot: string) => `__${_.kebabCase(slot)}` + +export const propsToSelector = (props: object) => { + return Object.keys(props).reduce((acc, key) => { + const value = props[key] + const kebabKey = _.kebabCase(key) + + const className = value === true ? kebabKey : `${kebabKey}-${_.kebabCase(value)}` + + return `.${className}` + }, '') +} +export const makeSelector = (name: string, slot: string, props: object) => { + return slot === 'root' + ? nameToSelector(name) + propsToSelector(props) + : nameToSelector(name) + slotToSelector(slot) + propsToSelector(props) +} + +// ============================================================ +// JS Style Objects +// ============================================================ + +export const jsStyleToCSSObject = (styleObject = {}) => { + return Object.keys(styleObject).reduce((acc, key) => { + const value = styleObject[key] + const cssKey = /[A-Z]/.test(key) ? _.kebabCase(key) : key + + acc[cssKey] = _.isPlainObject(value) ? jsStyleToCSSObject(value) : value + + return acc + }, {}) +} +/** + * IN { + * '.button': { + * color: 'blue', + * '&:hover': { color: 'red' } + * '.icon': { color: 'inherit' } + * } + * } + * OUT { + * '.button': { color: 'blue' } + * '.button:hover': { color: 'red' } + * '.button .icon': { color: 'inherit' } + * } + */ +// const flattenJSStyleSheet = styleSheet => { +// const flattened = {} +// const selectors = [] +// +// // TODO: naive, doesn't handle element selectors +// const isSelector = str => /^[^a-zA-Z]/.test(str.trim()) +// +// // ensures proper spacing between selectors +// // supports '&' for root selector +// const joinSelectors = selectors => { +// return selectors +// .reduce((acc, next, i) => { +// const maybeSpace = i > 0 && /^[^&]/.test(next) ? ' ' : '' +// acc += maybeSpace + next +// return acc +// }, '') +// .replace(/&/g, '') +// } +// +// const flattenStyle = style => { +// Object.keys(style).forEach(key => { +// if (isSelector(key)) { +// selectors.push(key) +// flattenStyle(_.get(styleSheet, selectors)) +// } else { +// _.set(flattened, [joinSelectors(selectors), key], style[key]) +// } +// }) +// // once we've finished iterating this style object +// // we're no longer under the current selector +// selectors.pop() +// } +// +// flattenStyle(styleSheet) +// +// return flattened +// } + +// ============================================================ +// CSS String +// ============================================================ + +export const cssObjectToString = (cssObject = {}) => { + return ( + JSON.stringify(cssObject, null, 2) + // remove double quotes + .replace(/"/gm, '') + // quote content properties + .replace(/ content: (.*),/gm, ' content: "$1",') + // remove colon before curly braces + .replace(/: \{/gm, ' {') + // remove commas + .replace(/,$/gm, '') + // add semis + .replace(/([^{}])$/gm, '$1;') + // remove empty rules + .replace(/^.*\{\}\n/gm, '') + ) +} + +export const jsStyleSheetToCSSString = (jsStyleObject = {}) => { + return Object.keys(jsStyleObject) + .reduce((cssFile, selector) => { + const style = cssObjectToString(jsStyleToCSSObject(jsStyleObject[selector])) + return [...cssFile, `${selector} ${style}`] + }, []) + .join('\n\n') +} + +// ============================================================ +// Stardust Theme Utils +// ============================================================ + +export const makeStyleArg = (name: string, props: object, theme: ThemePrepared) => { + const SEE_FINDINGS_RADIO_GROUP_ITEM = {} + + return { + rtl: false, + disableAnimations: false, + props: { + isFromKeyboard: false, // see FINDINGS 3 + // ..._.get(stardust, `${name}.defaultProps`, {}), // see FINDINGS 1 + ...props, + }, + variables: theme.componentVariables[name] + ? theme.componentVariables[name](theme.siteVariables, SEE_FINDINGS_RADIO_GROUP_ITEM) + : {}, + colors: {}, + theme, + } +} + +// const spec = { +// name: COMPONENT_NAME, +// definition: [ +// // ---------------------------------------- +// // Base +// // ---------------------------------------- +// {}, +// +// // ---------------------------------------- +// // Types +// // ---------------------------------------- +// { primary: true }, +// { secondary: true }, +// +// // icon +// // { iconOnly: true }, +// // { iconPosition: 'before' }, +// // { iconPosition: 'after' }, +// +// // ---------------------------------------- +// // States +// // ---------------------------------------- +// // { active: true }, +// { disabled: true }, +// // { focus: true }, +// +// // ---------------------------------------- +// // Variations +// // ---------------------------------------- +// // { circular: true }, +// // { fluid: true }, +// { text: true }, +// ], +// } + +// ====================================================================== +// USAGE +// ====================================================================== + +export function toSCSS(theme = {}, opts = {}) { + // TODO: we should have a function to prepare an input theme + const { componentStyles = {}, componentVariables = {}, siteVariables = {} } = theme as any + const { name = '', version = '', gitHubURL = '', npmURL = '', docsURL = '' } = opts as any + + let result = [ + `/*`, + ` * Name : ${name}`, + ` * Version : ${version}`, + ` * GitHub : ${gitHubURL}`, + ` * NPM : ${npmURL}`, + ` * Docs : ${docsURL}`, + ` */`, + '', + ].join('\n') + + const componentNames = Object.keys(componentStyles) + console.log('componentNames', componentNames) + + componentNames.forEach(name => { + if (typeof componentStyles[name] !== 'function') { + return console.log('Skipping old style signature:', name) + } + + const headerLength = 40 + const paddingLength = Math.floor((headerLength - name.length) / 2) + const padding = ' '.repeat(paddingLength) + + result += `\n/${'*'.repeat(headerLength - 1)}\n` + result += `${padding}${name}${padding}\n` + result += `${'*'.repeat(headerLength - 1)}/\n\n` + + const variables = componentVariables[name] ? componentVariables[name](siteVariables) : {} + const styles = componentStyles[name](variables) + const anatomy = Object.keys(styles) + + anatomy.forEach(slot => { + styles[slot].forEach(([propsMatcher, styleObject]) => { + const slotSelector = makeSelector(name, slot, propsMatcher) + const slotStyle = cssObjectToString(jsStyleToCSSObject(styleObject)) + result += `${slotSelector}${slotStyle}\n` + }) + }) + }) + + return result +} + +// const makeStyleSheet = spec => { +// const [baseProps, ...restProps] = spec.definition +// +// // TODO: make styles for all anatomy parts +// // const anatomy = Object.keys(buttonStyles) +// +// const baseStyle = themes.teams.componentStyles[COMPONENT_NAME].root(makeStyleArg(spec.name, { props: baseProps })) +// const baseSelector = nameToSelector(spec.name) + propsToSelector(baseProps) +// +// const styleSheet = { [baseSelector]: baseStyle } +// +// return restProps.reduce((acc, props) => { +// const style = themes.teams.componentStyles[COMPONENT_NAME].root(makeStyleArg(spec.name, { props })) +// const selector = nameToSelector(spec.name) + propsToSelector(props) +// +// acc[selector] = getOverrideStyles(style, baseStyle) +// +// return acc +// }, styleSheet) +// } +// +// const jsStyleSheet = makeStyleSheet(spec) +// +// console.log(_.mapValues(jsStyleSheet, (val, key) => cssifyObject(val))) + +/* +============================================================ + + FINDINGS + +============================================================ + +TODO + - [ ] stardust.scss .ui-icon style is missing font-family value + - [ ] stardust.scss .ui-layout style is missing grid-template-columns value + +# 1. defaultProps +Many styles are dependant on defaultProp values. Some styles break (statusStyles) when the default +props are not present. + +Aside from breaking, there are some components where a default prop value is going to make sense. In +those cases, the default "style props" should likely be part of the base theme. This way, when +calling the style functions, the correct "base" style is produced for the component. + +If we leave defaultProps in each component, then styles have a hard dependency on components. + +# 2. Prop Permutations +In order to generate styles for each type, state, and variation we need to have props objects +that describe each of these. In order to invoke a style object code path, we need to pass the +correct props to the style function. + +This has consequences and benefits. It means we need to produce a _definition_ of each component. +This definition should codify the design terms available to a component. + +In order to produce a stylesheet with the proper flow and optimizations, we need to know which order +these design terms are applied. This way the base style is defined at the top of the sheet and more +detailed definitions are at the bottom. This order also has to be shared and adopted, else, we +won't be able to reliably produce styles. + +# 3. isFromKeyboard +https://github.com/stardust-ui/react/issues/749 + +There is no way to encode this in a flat stylesheet. Even if we produce two flat styles, one with +keyboard focus and one without, we will have to decide on a selector to use in the stylesheet. This +means consumers will also have to use a similar utility and creating matching elements in order to +apply the style. + +# 4. RadioGroupItem + +The variables for this file require props to be provided. This is the only file doing so. +Only styles should be dependant on runtime values, such as props. Variables should be static. + +# 5. dropdownSearchInputStyles +https://github.com/stardust-ui/react/issues/753 + +This style file has no root key. + +# 6. inputStyles + +The `root` key is applied to the `wrapper` slot in the render function. + +# 7. attachmentStyles + +Does not gracefully handle undefined props.progress in the "progress" slot styles for width. + +# 8. Missing variables for menuDividerStyles and menuItemStyles + +There are variables for the Menu itself, but not for the divider or item subcomponents. +*/ diff --git a/packages/style/index.ts b/packages/style/index.ts new file mode 100644 index 0000000000..966e515f2d --- /dev/null +++ b/packages/style/index.ts @@ -0,0 +1,39 @@ +import { toSCSS } from './compile' +// import { ThemeInput } from '@stardust-ui/react/src' +// import resolveComponentRules from '@stardust-ui/react/src/lib/resolveComponentRules' +import * as stardust from '../react' + +console.clear() + +console.log('='.repeat(80)) +console.time('compile theme:') + +const theme = { + siteVariables: { + brandColor: 'cornflowerblue', + ...stardust.themes.base.siteVariables, + }, + + componentVariables: { + Button: () => ({}), + ...stardust.themes.base.componentVariables, + }, + + componentStyles: { + Button: props => ({ + root: [[{}, { display: 'inline-block' }]], + }), + ...stardust.themes.base.componentStyles, + }, +} + +const scss = toSCSS(theme, { + name: 'Stardust UI', + version: '1.0.0', + gitHubURL: 'https://github.com/stardust-ui', + npmURL: 'https://npmjs.com/@stardust-ui', + docsURL: 'https://stardust-ui.github.io', +}) + +console.log(scss) +console.timeEnd('compile theme:') diff --git a/packages/style/package.json b/packages/style/package.json new file mode 100644 index 0000000000..0511576f5f --- /dev/null +++ b/packages/style/package.json @@ -0,0 +1,8 @@ +{ + "name": "@stardust-ui/style", + "version": "1.0.0", + "description": "Tools for creating and building framework agnostic themes.", + "main": "index.js", + "repository": "https://github.com/stardust-ui/react", + "license": "MIT" +} diff --git a/packages/style/tsconfig.json b/packages/style/tsconfig.json new file mode 100644 index 0000000000..f94e22b1aa --- /dev/null +++ b/packages/style/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../build/tsconfig.common", + "include": ["src"] +} From e5ab3a5ee74f18e2b0f7766e74f89d1ee396a5e6 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Tue, 29 Oct 2019 20:18:32 +0100 Subject: [PATCH 06/28] Converted menu styles --- .../react/src/lib/resolveComponentRules.ts | 7 +- .../teams/components/Menu/menuStyles.ts | 150 +++++++++++------- .../teams/components/Menu/menuVariables.ts | 8 + packages/react/src/themes/types.ts | 8 +- 4 files changed, 113 insertions(+), 60 deletions(-) diff --git a/packages/react/src/lib/resolveComponentRules.ts b/packages/react/src/lib/resolveComponentRules.ts index 920a40d834..cbaa30a38d 100644 --- a/packages/react/src/lib/resolveComponentRules.ts +++ b/packages/react/src/lib/resolveComponentRules.ts @@ -28,7 +28,12 @@ const isMatch = (props, selector): boolean => { const reduceSelectorStyleTuples = (props, tuples: [object, ICSSInJSStyle][]): ICSSInJSStyle => { return tuples.reduce((acc, [selector, style]) => { - return isMatch(props, selector) ? deepMergeObjects(acc, style) : acc + if (Array.isArray(selector)) { + selector.forEach(sel => (isMatch(props, sel) ? deepMergeObjects(acc, style) : acc)) + return acc + } + return isMatch(props, selector) ? deepMergeObjects(acc, style) : acc + }, {}) } diff --git a/packages/react/src/themes/teams/components/Menu/menuStyles.ts b/packages/react/src/themes/teams/components/Menu/menuStyles.ts index 3e3a0e0ce1..37f8ecb635 100644 --- a/packages/react/src/themes/teams/components/Menu/menuStyles.ts +++ b/packages/react/src/themes/teams/components/Menu/menuStyles.ts @@ -1,67 +1,101 @@ import { pxToRem } from '../../../../lib' -import { ComponentSlotStylesPrepared, ICSSInJSStyle } from '../../../types' +import { ComponentSelectorsAndStyles } from '../../../types' import { MenuProps, MenuState } from '../../../../components/Menu/Menu' import { MenuVariables } from './menuVariables' -import { - verticalPillsBottomMargin, - horizontalPillsRightMargin, - verticalPointingBottomMargin, -} from './menuItemStyles' -import { getColorScheme } from '../../colors' +import { backportComponentStyle } from '../../../../lib/resolveComponentRules' -type MenuPropsAndState = MenuProps & MenuState +type MenuPropsAndState = MenuProps & MenuState & { root?: any; divider?: any } -export default { - root: ({ props: p, variables: v }): ICSSInJSStyle => { - const { iconOnly, fluid, pointing, pills, primary, underlined, vertical, submenu } = p - const colors = getColorScheme(v.colorScheme, null, primary) - - return { - display: 'flex', - minHeight: pxToRem(24), - margin: 0, - padding: 0, - color: v.color, - backgroundColor: v.backgroundColor || 'inherit', - listStyleType: 'none', - ...(iconOnly && { alignItems: 'center' }), - ...(vertical && { - flexDirection: 'column', - backgroundColor: v.verticalBackgroundColor, - padding: `${pxToRem(8)} 0`, - ...(submenu && { +const menuStyles: ComponentSelectorsAndStyles = v => { + return { + root: [ + [ + null, + { + // TODO: add for different colors - primary or not primary... + // const colors = getColorScheme(v.colorScheme, null, primary) + display: 'flex', + minHeight: pxToRem(24), + margin: 0, + padding: 0, + color: v.color, + backgroundColor: v.backgroundColor || 'inherit', + listStyleType: 'none', + }, + ], + [{ iconOnly: true }, { alignItems: 'center' }], + [ + { vertical: true }, + { + flexDirection: 'column', + backgroundColor: v.verticalBackgroundColor, + padding: `${pxToRem(8)} 0`, + }, + ], + [ + { vertical: true, submenu: true }, + { boxShadow: v.verticalBoxShadow, - }), - ...(!fluid && !submenu && { width: 'fit-content' }), - ...(iconOnly && { + }, + ], + [ + { vertical: true, iconOnly: true }, + { display: 'inline-block', width: 'auto', - }), - }), - ...(!pills && - !iconOnly && - !(pointing && vertical) && - !underlined && { - // primary has hardcoded grey border color - border: `${v.borderWidth} solid ${ - primary ? v.primaryBorderColor : v.borderColor || colors.border - }`, + }, + ], + [{ vertical: true, fluid: false, submenu: false }, { width: 'fit-content' }], + [ + [ + { pills: false, iconOnly: false, underlined: false, pointing: false, primary: true }, + { pills: false, iconOnly: false, underlined: false, vertical: false, primary: true }, + ], + { + border: `${v.borderWidth} solid ${v.primaryBorderColor /* || colors.border */}`, + borderRadius: pxToRem(4), + }, + ], + [ + [ + { pills: false, iconOnly: false, underlined: false, pointing: false, primary: true }, + { pills: false, iconOnly: false, underlined: false, vertical: false, primary: true }, + ], + { + // colors.border ?! + border: `${v.borderWidth} solid ${v.primaryBorderColor /* || colors.border */}`, borderRadius: pxToRem(4), - }), - ...(underlined && { - borderBottom: `${v.underlinedBottomBorderWidth} solid ${v.underlinedBorderColor}`, - }), - } - }, - divider: ({ props: { pointing, vertical, pills } }) => ({ - ...(pointing && - vertical && { - marginBottom: verticalPointingBottomMargin, - }), - ...(pills && { - ...(vertical - ? { margin: `0 0 ${verticalPillsBottomMargin} 0` } - : { margin: `0 ${horizontalPillsRightMargin} 0 0` }), - }), - }), -} as ComponentSlotStylesPrepared + }, + ], + [ + [ + { pills: false, iconOnly: false, underlined: false, pointing: false, primary: false }, + { pills: false, iconOnly: false, underlined: false, vertical: false, primary: false }, + ], + { + // colors.border ?! + border: `${v.borderWidth} solid ${v.borderColor /* || colors.border */}`, + borderRadius: pxToRem(4), + }, + ], + [ + { underlined: true }, + { + borderBottom: `${v.underlinedBottomBorderWidth} solid ${v.underlinedBorderColor}`, + }, + ], + ], + divider: [ + [ + { pointing: true, vertical: true }, + { + marginBottom: v.verticalPointingBottomMargin, + }, + ], + [{ pills: true, vertical: true }, { margin: `0 0 ${v.verticalPillsBottomMargin} 0` }], + [{ pills: true, vertical: false }, { margin: `0 ${v.horizontalPillsRightMargin} 0 0` }], + ], + } +} + +export default backportComponentStyle(menuStyles) diff --git a/packages/react/src/themes/teams/components/Menu/menuVariables.ts b/packages/react/src/themes/teams/components/Menu/menuVariables.ts index 0ddfa87f1f..cd439929b8 100644 --- a/packages/react/src/themes/teams/components/Menu/menuVariables.ts +++ b/packages/react/src/themes/teams/components/Menu/menuVariables.ts @@ -57,6 +57,10 @@ export interface MenuVariables { dividerHeight: string borderWidth: string + + verticalPillsBottomMargin: string + horizontalPillsRightMargin: string + verticalPointingBottomMargin: string } export default (siteVars: any): MenuVariables => { @@ -122,5 +126,9 @@ export default (siteVars: any): MenuVariables => { dividerHeight: pxToRem(1), borderWidth: pxToRem(1), + + verticalPillsBottomMargin: pxToRem(5), + horizontalPillsRightMargin: pxToRem(8), + verticalPointingBottomMargin: pxToRem(12), } } diff --git a/packages/react/src/themes/types.ts b/packages/react/src/themes/types.ts index d5f9d584b1..ef9600c196 100644 --- a/packages/react/src/themes/types.ts +++ b/packages/react/src/themes/types.ts @@ -370,9 +370,15 @@ export type ComponentSlotStyle = export interface ComponentSlotStylesInput extends ObjectOf> {} +export type ComponentStyleSelector = + | { [key in keyof TProps]: any } + | { [key in keyof TProps]: any }[] + export type ComponentSelectorsAndStyles = ( vars: TVars, -) => { [key in keyof TProps]: [Partial, ICSSInJSStyle][] } +) => { + [key: string]: [ComponentStyleSelector, ICSSInJSStyle][] +} export interface ComponentSlotStylesPrepared extends ObjectOf> {} From 6675f1407b39d332e12c37de332da917b9bfaf5d Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Wed, 30 Oct 2019 10:13:06 +0100 Subject: [PATCH 07/28] Fixed ts errors --- packages/react/src/lib/resolveComponentRules.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/react/src/lib/resolveComponentRules.ts b/packages/react/src/lib/resolveComponentRules.ts index cbaa30a38d..20c3746985 100644 --- a/packages/react/src/lib/resolveComponentRules.ts +++ b/packages/react/src/lib/resolveComponentRules.ts @@ -1,4 +1,4 @@ -import { ComponentSlotStylesInput, ICSSInJSStyle } from '../themes/types' +import { ComponentSlotStylesPrepared, ICSSInJSStyle } from '../themes/types' export function isObject(item): boolean { return typeof item === 'object' && !Array.isArray(item) && item !== null @@ -31,9 +31,8 @@ const reduceSelectorStyleTuples = (props, tuples: [object, ICSSInJSStyle][]): IC if (Array.isArray(selector)) { selector.forEach(sel => (isMatch(props, sel) ? deepMergeObjects(acc, style) : acc)) return acc - } - return isMatch(props, selector) ? deepMergeObjects(acc, style) : acc - + } + return isMatch(props, selector) ? deepMergeObjects(acc, style) : acc }, {}) } @@ -47,7 +46,7 @@ const resolveComponentRules = (rules, props = {}): ICSSInJSStyle => { // TODO: temporary during migration to selector/style tuple styles // Backports selector/style tuple styles to previous signature -export const backportComponentStyle = (selectorStyleFunc): ComponentSlotStylesInput => { +export const backportComponentStyle = (selectorStyleFunc): ComponentSlotStylesPrepared => { if (typeof selectorStyleFunc !== 'function') { return selectorStyleFunc } From a72e636e8536a40883a5201990d45856dab3bd9e Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Wed, 30 Oct 2019 10:25:42 +0100 Subject: [PATCH 08/28] Remove unnecessery typings --- packages/react/src/themes/teams/components/Menu/menuStyles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/themes/teams/components/Menu/menuStyles.ts b/packages/react/src/themes/teams/components/Menu/menuStyles.ts index 37f8ecb635..1a08c63b01 100644 --- a/packages/react/src/themes/teams/components/Menu/menuStyles.ts +++ b/packages/react/src/themes/teams/components/Menu/menuStyles.ts @@ -4,7 +4,7 @@ import { MenuProps, MenuState } from '../../../../components/Menu/Menu' import { MenuVariables } from './menuVariables' import { backportComponentStyle } from '../../../../lib/resolveComponentRules' -type MenuPropsAndState = MenuProps & MenuState & { root?: any; divider?: any } +type MenuPropsAndState = MenuProps & MenuState const menuStyles: ComponentSelectorsAndStyles = v => { return { From 1f0f68abd488eed18eaf95b711e6575e805134d6 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Mon, 4 Nov 2019 13:20:11 +0100 Subject: [PATCH 09/28] fixed issues --- packages/react/src/lib/resolveComponentRules.ts | 11 ++++++++--- .../src/themes/teams/components/Menu/menuStyles.ts | 13 ++++++------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/react/src/lib/resolveComponentRules.ts b/packages/react/src/lib/resolveComponentRules.ts index 20c3746985..93a9d76215 100644 --- a/packages/react/src/lib/resolveComponentRules.ts +++ b/packages/react/src/lib/resolveComponentRules.ts @@ -22,14 +22,19 @@ export function deepMergeObjects(target: object, source: object): object { const isMatch = (props, selector): boolean => { if (selector === null) return true - - return Object.keys(selector).every(k => props[k] === selector[k]) + return Object.keys(selector).every( + k => props[k] === selector[k] || (props[k] === undefined && !!props[k] === !!selector[k]), + ) } const reduceSelectorStyleTuples = (props, tuples: [object, ICSSInJSStyle][]): ICSSInJSStyle => { return tuples.reduce((acc, [selector, style]) => { if (Array.isArray(selector)) { - selector.forEach(sel => (isMatch(props, sel) ? deepMergeObjects(acc, style) : acc)) + for (let i = 0; i < selector.length; i++) { + if (isMatch(props, selector[i])) { + return deepMergeObjects(acc, style) + } + } return acc } return isMatch(props, selector) ? deepMergeObjects(acc, style) : acc diff --git a/packages/react/src/themes/teams/components/Menu/menuStyles.ts b/packages/react/src/themes/teams/components/Menu/menuStyles.ts index 1a08c63b01..395594d946 100644 --- a/packages/react/src/themes/teams/components/Menu/menuStyles.ts +++ b/packages/react/src/themes/teams/components/Menu/menuStyles.ts @@ -12,8 +12,6 @@ const menuStyles: ComponentSelectorsAndStyles [ null, { - // TODO: add for different colors - primary or not primary... - // const colors = getColorScheme(v.colorScheme, null, primary) display: 'flex', minHeight: pxToRem(24), margin: 0, @@ -52,7 +50,8 @@ const menuStyles: ComponentSelectorsAndStyles { pills: false, iconOnly: false, underlined: false, vertical: false, primary: true }, ], { - border: `${v.borderWidth} solid ${v.primaryBorderColor /* || colors.border */}`, + border: `${v.borderWidth} solid ${v.primaryBorderColor || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.border)}`, borderRadius: pxToRem(4), }, ], @@ -62,8 +61,8 @@ const menuStyles: ComponentSelectorsAndStyles { pills: false, iconOnly: false, underlined: false, vertical: false, primary: true }, ], { - // colors.border ?! - border: `${v.borderWidth} solid ${v.primaryBorderColor /* || colors.border */}`, + border: `${v.borderWidth} solid ${v.primaryBorderColor || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.border)}`, borderRadius: pxToRem(4), }, ], @@ -73,8 +72,8 @@ const menuStyles: ComponentSelectorsAndStyles { pills: false, iconOnly: false, underlined: false, vertical: false, primary: false }, ], { - // colors.border ?! - border: `${v.borderWidth} solid ${v.borderColor /* || colors.border */}`, + border: `${v.borderWidth} solid ${v.borderColor || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)}`, borderRadius: pxToRem(4), }, ], From 1dacee681a0191760f48c326208272a0efecdfc9 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Mon, 4 Nov 2019 17:36:26 +0100 Subject: [PATCH 10/28] converted menu item styles --- .../Types/MenuExamplePointing.shorthand.tsx | 2 +- .../teams/components/Menu/menuItemStyles.ts | 976 ++++++++++-------- 2 files changed, 559 insertions(+), 419 deletions(-) diff --git a/docs/src/examples/components/Menu/Types/MenuExamplePointing.shorthand.tsx b/docs/src/examples/components/Menu/Types/MenuExamplePointing.shorthand.tsx index 162f46a62f..58739052b3 100644 --- a/docs/src/examples/components/Menu/Types/MenuExamplePointing.shorthand.tsx +++ b/docs/src/examples/components/Menu/Types/MenuExamplePointing.shorthand.tsx @@ -9,7 +9,7 @@ const items = [ const MenuExamplePointing = () => (
- +
diff --git a/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts b/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts index 6e822e09b3..949fee51fd 100644 --- a/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts +++ b/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts @@ -1,16 +1,9 @@ import { pxToRem } from '../../../../lib' -import { - ComponentSlotStylesPrepared, - ICSSInJSStyle, - StrictColorScheme, - ItemType, -} from '../../../types' -import { MenuVariables, menuColorAreas } from './menuVariables' -import { MenuItemProps, MenuItemState } from '../../../../components/Menu/MenuItem' -import { getColorScheme } from '../../colors' +import { ICSSInJSStyle, ComponentSelectorsAndStyles } from '../../../types' +import { MenuVariables } from './menuVariables' +import { MenuItemProps } from '../../../../components/Menu/MenuItem' import getIconFillOrOutlineStyles from '../../getIconFillOrOutlineStyles' - -type MenuItemPropsAndState = MenuItemProps & MenuItemState +import { backportComponentStyle } from '../../../../lib/resolveComponentRules' export const verticalPillsBottomMargin = pxToRem(5) export const horizontalPillsRightMargin = pxToRem(8) @@ -22,429 +15,576 @@ export const underlinedItem = (color: string): ICSSInJSStyle => ({ transition: 'color .1s ease', }) -const getActionStyles = ({ - props: { primary, underlined, iconOnly }, - variables: v, - colors, -}: { - props: MenuItemPropsAndState - variables: MenuVariables - colors: StrictColorScheme> -}): ICSSInJSStyle => - underlined || iconOnly - ? { - color: v.color, - } - : primary - ? { - color: colors.foregroundActive, - background: v.backgroundColorActive || colors.backgroundActive, - } - : { - color: v.color, - background: v.backgroundColorActive || colors.backgroundActive, - } - -const getFocusedStyles = ({ - props, - variables: v, - colors, -}: { - props: MenuItemPropsAndState - variables: MenuVariables - colors: StrictColorScheme> -}): ICSSInJSStyle => { - const { primary, underlined, isFromKeyboard, active, vertical } = props - if (active && !underlined && !vertical) return {} +const updatedMenuItemStyles: ComponentSelectorsAndStyles = v => { return { - color: primary ? colors.foregroundFocus : v.colorActive, - background: v.backgroundColorFocus || colors.backgroundFocus, - ...(vertical && isFromKeyboard && !primary - ? { + wrapper: [ + [ + null, + { + color: 'inherit', + lineHeight: 1, + position: 'relative', + verticalAlign: 'middle', + display: 'block', + }, + ], + [{ secondary: true }, { background: 'salmon' }], + [ + { vertical: true }, + { + border: `solid ${v.verticalItemBorderWidth} ${v.verticalItemBorderColor}`, + }, + ], + [{ pills: true }, { borderRadius: pxToRem(5) }], + [{ pills: true, vertical: true }, { margin: `0 0 ${verticalPillsBottomMargin} 0` }], + [{ pills: true, vertical: false }, { margin: `0 ${horizontalPillsRightMargin} 0 0` }], + [ + { underlined: true }, + { + display: 'flex', + alignItems: 'center', + height: pxToRem(29), + lineHeight: v.lineHeightBase, + padding: `0 ${pxToRem(4)}`, + margin: `0 ${pxToRem(4)} 0 0`, + ':nth-child(n+2)': { + marginLeft: `${pxToRem(4)}`, + }, + boxShadow: 'none', + }, + ], + [ + { vertical: false, pills: false, underlined: false, iconOnly: false, primary: true }, + { + boxShadow: `-1px 0 0 0 ${v.primaryBorderColor || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.border)} inset`, + }, + ], + [ + { vertical: false, pills: false, underlined: false, iconOnly: false, primary: false }, + { + boxShadow: `-1px 0 0 0 ${v.borderColor || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)} inset`, + }, + ], + [ + [{ active: true, underlined: true }, { active: true, iconOnly: true }], + { + color: v.color, + }, + ], + [ + { active: true, underlined: false, iconOnly: false, primary: true }, + { + color: v.colorScheme && v.colorScheme.default && v.colorScheme.brand.foregroundActive, + background: + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), + }, + ], + [ + { active: true, underlined: false, iconOnly: false, primary: false }, + { + color: v.color, + background: + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), + }, + ], + [ + [ + { active: true, pointing: 'start', vertical: true, isFromKeyboard: false }, + { active: true, pointing: 'end', vertical: true, isFromKeyboard: false }, + { active: true, pointing: true, vertical: true, isFromKeyboard: false }, + ], + { + '::before': { + content: `''`, + position: 'absolute', + width: pxToRem(3), + height: `calc(100% + ${pxToRem(4)})`, + top: pxToRem(-2), + backgroundColor: v.pointingIndicatorBackgroundColor, + }, + }, + ], + [ + { active: true, vertical: true, isFromKeyboard: false, pointing: 'end' }, + { + '::before': { + right: pxToRem(-2), + }, + }, + ], + [ + [ + { active: true, vertical: true, isFromKeyboard: false, pointing: 'start' }, + { active: true, vertical: true, isFromKeyboard: false, pointing: true }, + ], + { + '::before': { + left: pxToRem(-2), + }, + }, + ], + [ + [ + { active: true, pointing: 'start', vertical: false }, + { active: true, pointing: 'end', vertical: false }, + { active: true, pointing: true, vertical: false }, + ], + { + '::after': { + visibility: 'visible', + position: 'absolute', + content: '""', + left: '50%', + transform: 'translateX(-50%) translateY(-50%) rotate(45deg)', + margin: '.5px 0 0', + width: pxToRem(10), + height: pxToRem(10), + border: 'none', + zIndex: 2, + transition: 'background .1s ease', + }, + }, + ], + [ + [ + { active: true, pointing: 'start', vertical: false, primary: true }, + { active: true, pointing: true, vertical: false, primary: true }, + ], + { + '::after': { + top: '-1px', + background: + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), + borderTop: `1px solid ${v.borderColor || v.primaryBorderColor}`, + borderLeft: `1px solid ${v.borderColor || v.primaryBorderColor}`, + }, + }, + ], + [ + [ + { active: true, pointing: 'start', vertical: false, primary: false }, + { active: true, pointing: true, vertical: false, primary: false }, + ], + { + '::after': { + top: '-1px', + background: + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), + borderTop: `1px solid ${v.borderColor || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)}`, + borderLeft: `1px solid ${v.borderColor || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)}`, + }, + }, + ], + [ + { active: true, pointing: 'end', vertical: false, primary: true }, + { + '::after': { + top: '100%', + background: + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), + borderBottom: `1px solid ${v.borderColor || v.primaryBorderColor}`, + borderRight: `1px solid ${v.borderColor || v.primaryBorderColor}`, + }, + }, + ], + [ + { active: true, pointing: 'end', vertical: false, primary: false }, + { + '::after': { + top: '100%', + background: + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), + borderBottom: `1px solid ${v.borderColor || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)}`, + borderRight: `1px solid ${v.borderColor || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)}`, + }, + }, + ], + [ + { iconOnly: true }, + { + display: 'flex', + ':hover': { + color: v.iconOnlyColorActive, + }, + }, + ], + [ + { iconOnly: true, isFromKeyboard: true }, + { + color: v.iconOnlyColorActive, + }, + ], + [ + { iconOnly: false, isFromKeyboard: true, vertical: true, primary: false }, + { border: `solid 1px ${v.borderColorFocus}`, outline: `solid 1px ${v.outlineColorFocus}`, margin: pxToRem(1), - background: v.verticalBackgroundColorFocus || colors.backgroundFocus, - } - : {}), - } -} - -const getHoverStyles = ({ - props, - variables: v, - colors, -}: { - props: MenuItemPropsAndState - variables: MenuVariables - colors: StrictColorScheme> -}): ICSSInJSStyle => { - const { underlined, active, vertical } = props - if (active && !underlined && !vertical) return {} - return { - ...(underlined - ? { + background: + v.verticalBackgroundColorFocus || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundFocus), + }, + ], + [ + { iconOnly: false, isFromKeyboard: true, primary: true }, + { + color: v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.foregroundFocus, + background: + v.backgroundColorFocus || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundFocus), + }, + ], + [ + { iconOnly: false, isFromKeyboard: true, primary: false }, + { color: v.colorActive, - } - : { - color: colors.foregroundHover, - background: v.backgroundColorHover || colors.backgroundHover, - }), - } -} - -const pointingBeak = ({ - props, - variables: v, - colors, -}: { - props: MenuItemProps - variables: MenuVariables - colors: StrictColorScheme> -}): ICSSInJSStyle => { - const { pointing, primary } = props - - let top: string - let borders: ICSSInJSStyle - - const backgroundColor = v.backgroundColorActive || colors.backgroundActive - const borderColor = v.borderColor || primary ? v.primaryBorderColor : colors.border - - if (pointing === 'start') { - borders = { - borderTop: `1px solid ${borderColor}`, - borderLeft: `1px solid ${borderColor}`, - } - top = '-1px' // 1px for the border - } else { - borders = { - borderBottom: `1px solid ${borderColor}`, - borderRight: `1px solid ${borderColor}`, - } - top = '100%' - } - - return { - '::after': { - visibility: 'visible', - background: backgroundColor, - position: 'absolute', - content: '""', - top, - left: '50%', - transform: 'translateX(-50%) translateY(-50%) rotate(45deg)', - margin: '.5px 0 0', - width: pxToRem(10), - height: pxToRem(10), - border: 'none', - ...borders, - zIndex: 2, - transition: 'background .1s ease', - }, - } -} - -const menuItemStyles: ComponentSlotStylesPrepared = { - wrapper: ({ props, variables: v, theme }): ICSSInJSStyle => { - const { - active, - disabled, - iconOnly, - isFromKeyboard, - pills, - pointing, - secondary, - underlined, - vertical, - primary, - } = props - - const colors = getColorScheme(v.colorScheme, null, primary) - - return { - color: 'inherit', - lineHeight: 1, - position: 'relative', - verticalAlign: 'middle', - display: 'block', - - ...(secondary && { - background: 'salmon', - }), - - ...(vertical && { - border: `solid ${v.verticalItemBorderWidth} ${v.verticalItemBorderColor}`, - }), - - ...(pills && { - ...(vertical - ? { margin: `0 0 ${verticalPillsBottomMargin} 0` } - : { margin: `0 ${horizontalPillsRightMargin} 0 0` }), - borderRadius: pxToRem(5), - }), - - ...(underlined && { - display: 'flex', - alignItems: 'center', - height: pxToRem(29), - lineHeight: v.lineHeightBase, - padding: `0 ${pxToRem(4)}`, - margin: `0 ${pxToRem(4)} 0 0`, - ':nth-child(n+2)': { - marginLeft: `${pxToRem(4)}`, - }, - boxShadow: 'none', - }), - - // item separator - ...(!vertical && - !pills && - !underlined && - !iconOnly && { - boxShadow: `-1px 0 0 0 ${ - primary ? v.primaryBorderColor : v.borderColor || colors.border - } inset`, - }), - - // active styles - ...(active && { - ...getActionStyles({ props, variables: v, colors }), + background: + v.backgroundColorFocus || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundFocus), + }, + ], - ...(pointing && - vertical && - !isFromKeyboard && { + [ + { iconOnly: false, isFromKeyboard: true, active: true, underlined: false, vertical: false }, + { + color: 'inherit', + backgroundColor: 'inherit', + }, + ], + [ + { iconOnly: false, underlined: true }, + { + ':hover': { + color: v.colorActive, + }, + }, + ], + [ + { iconOnly: false, underlined: false, primary: true }, + { + ':hover': { + color: v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.foregroundHover, + background: + v.backgroundColorHover || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundHover), + }, + }, + ], + [ + { iconOnly: false, underlined: false, primary: false }, + { + ':hover': { + color: v.colorScheme && v.colorScheme.default && v.colorScheme.default.foregroundHover, + background: + v.backgroundColorHover || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundHover), + }, + }, + ], + [ + { iconOnly: false, active: true, underlined: false, vertical: false }, + { + // ':hover': { + // if (active && !underlined && !vertical) return {} //:( + // }, + ':hover': { + color: 'inherit', + backgroundColor: 'inherit', + }, + }, + ], + [ + { pills: false, iconOnly: false, underlined: false, pointing: false, vertical: true }, + { + ':first-child': { '::before': { - content: `''`, - position: 'absolute', - width: pxToRem(3), - height: `calc(100% + ${pxToRem(4)})`, - top: pxToRem(-2), - backgroundColor: v.pointingIndicatorBackgroundColor, - ...(pointing === 'end' ? { right: pxToRem(-2) } : { left: pxToRem(-2) }), + display: 'none', }, - }), - - ...(pointing && - !vertical && { - ...pointingBeak({ props, variables: v, colors }), - }), - }), - - ...(iconOnly && { - display: 'flex', - - // focus styles - ...(isFromKeyboard && { - color: v.iconOnlyColorActive, - }), - - // hover styles - ':hover': { - color: v.iconOnlyColorActive, + }, }, - }), - - ...(!iconOnly && { - // focus styles - ...(isFromKeyboard && getFocusedStyles({ props, variables: v, colors })), - - // hover styles - ':hover': getHoverStyles({ props, variables: v, colors }), - }), - - ':first-child': { - ...(!pills && - !iconOnly && - !(pointing && vertical) && - !underlined && { - ...(vertical && { - '::before': { - display: 'none', - }, - }), - ...(!vertical && { - borderBottomLeftRadius: pxToRem(3), - borderTopLeftRadius: pxToRem(3), - }), - }), - }, - - ...(disabled && { - color: v.colorDisabled || colors.foregroundDisabled, - ':hover': { - // empty - overwrite all existing hover styles - }, - }), - } - }, - - root: ({ props: p, variables: v }): ICSSInJSStyle => { - const { - active, - iconOnly, - isFromKeyboard, - pointing, - primary, - underlined, - vertical, - disabled, - } = p - - const colors = getColorScheme(v.colorScheme, null, primary) - - return { - color: 'inherit', - display: 'block', - cursor: 'pointer', - whiteSpace: 'nowrap', - - ...(pointing && - vertical && { + ], + [ + { pills: false, iconOnly: false, underlined: false, pointing: false, vertical: false }, + { + ':first-child': { + borderBottomLeftRadius: pxToRem(3), + borderTopLeftRadius: pxToRem(3), + }, + }, + ], + [ + { disabled: true, primary: false }, + { + color: + v.colorDisabled || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.foregroundDisabled), + }, + ], + [ + { disabled: true, primary: true }, + { + color: + v.colorDisabled || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.foregroundDisabled), + }, + ], + ], + root: [ + [ + null, + { + color: 'inherit', + display: 'block', + cursor: 'pointer', + whiteSpace: 'nowrap', + ':focus': { + outline: 0, + }, + ':hover': { + color: 'inherit', + }, + }, + ], + [ + [ + { pointing: 'start', vertical: true }, + { pointing: 'end', vertical: true }, + { pointing: true, vertical: true }, + ], + { border: '1px solid transparent', - }), - - ...(iconOnly && { - border: `${pxToRem(2)} solid transparent`, - }), - - ...(underlined - ? { padding: `${pxToRem(4)} 0` } - : pointing && vertical - ? { padding: `${pxToRem(8)} ${pxToRem(18)}` } - : vertical - ? { padding: v.verticalItemPadding } - : { - padding: v.horizontalPadding, - }), - - ...(iconOnly && { - margin: pxToRem(1), - padding: pxToRem(5), // padding works this way to get the border to only be 30x30px on focus which is the current design - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - }), - - // active styles - ...(active && { - ...(iconOnly && { + }, + ], + // TODO: this was spread on different placed across the file :\ + [ + { iconOnly: true }, + { + border: `${pxToRem(2)} solid transparent`, + margin: pxToRem(1), + padding: pxToRem(5), // padding works this way to get the border to only be 30x30px on focus which is the current design + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + ':hover': { + ...getIconFillOrOutlineStyles({ outline: false }), + }, + }, + ], + [ + { underlined: true }, + { + padding: `${pxToRem(4)} 0`, + }, + ], + [ + [ + { underlined: false, pointing: 'start', vertical: true }, + { underlined: false, pointing: 'end', vertical: true }, + { underlined: false, pointing: true, vertical: true }, + ], + { + padding: `${pxToRem(8)} ${pxToRem(18)}`, + }, + ], + [ + { underlined: false, pointing: false, vertical: true }, + { + padding: v.verticalItemPadding, + }, + ], + [ + { underlined: false, vertical: false }, + { + padding: v.horizontalPadding, + }, + ], + [ + { active: true, iconOnly: true }, + { color: v.iconOnlyColorActive, ...getIconFillOrOutlineStyles({ outline: false }), - }), - - ...(primary - ? { - ...(underlined && { - color: colors.borderActive, - ...underlinedItem(v.borderColorActive || colors.borderActive), - }), - } - : underlined && { - fontWeight: 700, - ...underlinedItem(v.colorActive), - }), - }), - - // focus styles - ...(isFromKeyboard && { - ...(iconOnly && { + }, + ], + [ + { active: true, primary: true, underlined: true }, + { + color: v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.borderActive, + ...underlinedItem( + v.borderColorActive || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.borderActive), + ), + }, + ], + [ + { active: true, primary: false, underlined: true }, + { + fontWeight: 700, + ...underlinedItem(v.colorActive), + }, + ], + [ + { primary: true, active: false, underlined: true }, + { + ...underlinedItem( + v.underlinedBorderColor || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), + ), + }, + ], + [ + { primary: false, active: false, underlined: true }, + { + ...underlinedItem( + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), + ), + }, + ], + [ + { isFromKeyboard: true, iconOnly: true }, + { borderRadius: '50%', borderColor: v.iconOnlyColorActive, ...getIconFillOrOutlineStyles({ outline: false }), - }), - - ...(primary - ? { - ...(iconOnly && { - color: 'inherit', - borderColor: v.borderColorActive || colors.borderActive, - }), - - ...(underlined && { color: 'inherit' }), - - ...(underlined && active && underlinedItem(colors.foregroundActive)), - } - : { - ...(underlined && { fontWeight: 700 }), - - ...(underlined && active && underlinedItem(v.colorActive)), - }), - }), - - ':focus': { - outline: 0, - }, - - // hover styles - ':hover': { - color: 'inherit', - - ...(iconOnly && getIconFillOrOutlineStyles({ outline: false })), - - ...(primary - ? { - ...(iconOnly && { color: 'inherit' }), - ...(!active && - underlined && - underlinedItem(v.underlinedBorderColor || colors.backgroundActive)), - } - : !active && - underlined && - underlinedItem(v.backgroundColorActive || colors.backgroundActive)), - }, - - ...(disabled && { - cursor: 'default', - ':hover': { - // reset all existing hover styles + }, + ], + [ + { isFromKeyboard: true, primary: true, iconOnly: true }, + { color: 'inherit', + borderColor: + v.borderColorActive || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.borderActive), }, - }), - } - }, - - content: ({ props: p }): ICSSInJSStyle => { - const widthAdjust = (p.icon ? 26 : 0) + (p.menu ? 16 : 0) - return { - whiteSpace: 'normal', - lineHeight: 1.5, - marginTop: pxToRem(-4), - marginBottom: pxToRem(-4), - display: 'inline-block', - ...((p.inSubmenu || p.vertical) && { - width: 'max-content', - minWidth: pxToRem(46 - widthAdjust), - maxWidth: pxToRem(262 - widthAdjust), - marginRight: pxToRem(16), - }), - } - }, - - icon: ({ props: p }): ICSSInJSStyle => ({ - ...(!p.iconOnly && { - // reduce margins so text has the dominant influence on the vertical height - marginTop: 0, - marginBottom: pxToRem(-8), - verticalAlign: 'top', - }), - }), - - menu: () => ({ zIndex: 1000 }), - - indicator: ({ props: p }) => ({ - position: 'relative', - float: 'right', - left: pxToRem(12), - userSelect: 'none', - marginRight: pxToRem(4), - - ...(p.inSubmenu && { - position: 'absolute', - top: pxToRem(6), - right: pxToRem(2), - left: 'unset', - }), - }), + ], + [ + { isFromKeyboard: true, primary: true, underlined: true }, + { + color: 'inherit', + }, + ], + [ + { isFromKeyboard: true, primary: true, underlined: true, active: true }, + { + ...underlinedItem( + v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.foregroundActive, + ), + }, + ], + [ + { isFromKeyboard: true, primary: false, underlined: true }, + { + fontWeight: 700, + }, + ], + [ + { isFromKeyboard: true, primary: false, underlined: true, active: true }, + { + ...underlinedItem(v.colorActive), + }, + ], + [ + { primary: true, active: false, underlined: true }, + { + ':hover': { + ...underlinedItem( + v.underlinedBorderColor || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), + ), + }, + }, + ], + [ + { primary: false, active: false, underlined: true }, + { + ':hover': { + ...underlinedItem( + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), + ), + }, + }, + ], + [ + { disabled: true }, + { + cursor: 'default', + ':hover': { + // reset all existing hover styles + color: 'inherit', // :/ + }, + }, + ], + ], + content: [ + [ + null, + { + whiteSpace: 'normal', + lineHeight: 1.5, + marginTop: pxToRem(-4), + marginBottom: pxToRem(-4), + display: 'inline-block', + }, + ], + [ + [{ inSubmenu: true }, { vertical: true }], + { + width: 'max-content', + // TODO: check if is defined + // const widthAdjust = (p.icon ? 26 : 0) + (p.menu ? 16 : 0) + // minWidth: pxToRem(46 - widthAdjust), + // maxWidth: pxToRem(262 - widthAdjust), + marginRight: pxToRem(16), + }, + ], + ], + icon: [ + [ + { iconOnly: false }, + { + // reduce margins so text has the dominant influence on the vertical height + marginTop: 0, + marginBottom: pxToRem(-8), + verticalAlign: 'top', + }, + ], + ], + menu: [[null, { zIndex: 1000 }]], + indicator: [ + [ + null, + { + position: 'relative', + float: 'right', + left: pxToRem(12), + userSelect: 'none', + marginRight: pxToRem(4), + }, + ], + [ + { inSubmenu: true }, + { + position: 'absolute', + top: pxToRem(6), + right: pxToRem(2), + left: 'unset', + }, + ], + ], + } } -export default menuItemStyles +export default backportComponentStyle(updatedMenuItemStyles) From 036ea7ae7752b641f1fe4ae1dba96e96492bd727 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Tue, 5 Nov 2019 11:02:27 +0100 Subject: [PATCH 11/28] -fixed regressions --- .../react/src/lib/resolveComponentRules.ts | 5 +- .../teams/components/Menu/menuItemStyles.ts | 119 ++++++++++-------- 2 files changed, 73 insertions(+), 51 deletions(-) diff --git a/packages/react/src/lib/resolveComponentRules.ts b/packages/react/src/lib/resolveComponentRules.ts index 93a9d76215..1762c02059 100644 --- a/packages/react/src/lib/resolveComponentRules.ts +++ b/packages/react/src/lib/resolveComponentRules.ts @@ -23,7 +23,10 @@ export function deepMergeObjects(target: object, source: object): object { const isMatch = (props, selector): boolean => { if (selector === null) return true return Object.keys(selector).every( - k => props[k] === selector[k] || (props[k] === undefined && !!props[k] === !!selector[k]), + k => + props[k] === selector[k] || + ((typeof selector[k] === 'boolean' || props[k] === undefined) && + !!props[k] === !!selector[k]), ) } diff --git a/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts b/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts index 949fee51fd..220be8920a 100644 --- a/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts +++ b/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts @@ -152,7 +152,7 @@ const updatedMenuItemStyles: ComponentSelectorsAndStyles Date: Tue, 5 Nov 2019 11:06:16 +0100 Subject: [PATCH 12/28] -removed comments --- .../react/src/themes/teams/components/Menu/menuItemStyles.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts b/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts index 220be8920a..ae4a213b15 100644 --- a/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts +++ b/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts @@ -150,10 +150,7 @@ const updatedMenuItemStyles: ComponentSelectorsAndStyles Date: Tue, 5 Nov 2019 11:37:38 +0100 Subject: [PATCH 13/28] -converted menu divider styles --- .../components/Menu/menuDividerStyles.ts | 46 +- .../teams/components/Menu/menuItemStyles.ts | 1077 ++++++++--------- 2 files changed, 557 insertions(+), 566 deletions(-) diff --git a/packages/react/src/themes/teams/components/Menu/menuDividerStyles.ts b/packages/react/src/themes/teams/components/Menu/menuDividerStyles.ts index 14dc8f37fe..4da2713c84 100644 --- a/packages/react/src/themes/teams/components/Menu/menuDividerStyles.ts +++ b/packages/react/src/themes/teams/components/Menu/menuDividerStyles.ts @@ -1,32 +1,32 @@ -import { ComponentSlotStylesPrepared, ICSSInJSStyle } from '../../../types' +import { ComponentSelectorsAndStyles } from '../../../types' import { MenuDividerProps } from '../../../../components/Menu/MenuDivider' import { MenuVariables } from './menuVariables' -import { getColorScheme } from '../../colors' +import { backportComponentStyle } from '../../../../lib/resolveComponentRules' -const menuDividerStyles: ComponentSlotStylesPrepared = { - root: ({ props: p, variables: v }): ICSSInJSStyle => { - const colors = getColorScheme(v.colorScheme, null, p.primary) - const borderColor = p.primary ? v.primaryBorderColor : v.borderColor || colors.border - const borderType = p.vertical ? 'borderTop' : 'borderLeft' - - return p.content - ? { +const menuDividerStyles: ComponentSelectorsAndStyles = v => { + const primaryBorderColor = + v.primaryBorderColor || (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.border) + const defaultBorderColor = + v.borderColor || (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border) + return { + root: [ + [ + { content: true }, + { display: 'flex', justifyContent: 'center', flexDirection: 'column', textAlign: 'center', - } - : { - [borderType]: `1px solid ${borderColor}`, - ...(!p.vertical && { - alignSelf: 'stretch', - }), - ...(p.vertical && - p.inSubmenu && { - margin: '8px 0', - }), - } - }, + }, + ], + [{ content: false, vertical: true, primary: true }, { borderTop: primaryBorderColor }], + [{ content: false, vertical: true, primary: false }, { borderTop: defaultBorderColor }], + [{ content: false, vertical: false }, { alignSelf: 'stretch' }], + [{ content: false, vertical: true, inSubmenu: true }, { margin: '8px 0' }], + [{ content: false, vertical: false, primary: true }, { borderLeft: primaryBorderColor }], + [{ content: false, vertical: false, primary: false }, { borderLeft: defaultBorderColor }], + ], + } } -export default menuDividerStyles +export default backportComponentStyle(menuDividerStyles) diff --git a/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts b/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts index ae4a213b15..6d848f56b4 100644 --- a/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts +++ b/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts @@ -5,602 +5,593 @@ import { MenuItemProps } from '../../../../components/Menu/MenuItem' import getIconFillOrOutlineStyles from '../../getIconFillOrOutlineStyles' import { backportComponentStyle } from '../../../../lib/resolveComponentRules' -export const verticalPillsBottomMargin = pxToRem(5) -export const horizontalPillsRightMargin = pxToRem(8) -export const verticalPointingBottomMargin = pxToRem(12) - export const underlinedItem = (color: string): ICSSInJSStyle => ({ paddingBottom: 0, borderBottom: `solid ${pxToRem(4)} ${color}`, transition: 'color .1s ease', }) -const updatedMenuItemStyles: ComponentSelectorsAndStyles = v => { - return { - wrapper: [ +const menuItemStyles: ComponentSelectorsAndStyles = v => ({ + wrapper: [ + [ + null, + { + color: 'inherit', + lineHeight: 1, + position: 'relative', + verticalAlign: 'middle', + display: 'block', + }, + ], + [{ secondary: true }, { background: 'salmon' }], + [ + { vertical: true }, + { + border: `solid ${v.verticalItemBorderWidth} ${v.verticalItemBorderColor}`, + }, + ], + [{ pills: true }, { borderRadius: pxToRem(5) }], + [{ pills: true, vertical: true }, { margin: `0 0 ${v.verticalPillsBottomMargin} 0` }], + [{ pills: true, vertical: false }, { margin: `0 ${v.horizontalPillsRightMargin} 0 0` }], + [ + { underlined: true }, + { + display: 'flex', + alignItems: 'center', + height: pxToRem(29), + lineHeight: v.lineHeightBase, + padding: `0 ${pxToRem(4)}`, + margin: `0 ${pxToRem(4)} 0 0`, + ':nth-child(n+2)': { + marginLeft: `${pxToRem(4)}`, + }, + boxShadow: 'none', + }, + ], + [ + { vertical: false, pills: false, underlined: false, iconOnly: false, primary: true }, + { + boxShadow: `-1px 0 0 0 ${v.primaryBorderColor || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.border)} inset`, + }, + ], + [ + { vertical: false, pills: false, underlined: false, iconOnly: false, primary: false }, + { + boxShadow: `-1px 0 0 0 ${v.borderColor || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)} inset`, + }, + ], + [ + [{ active: true, underlined: true }, { active: true, iconOnly: true }], + { + color: v.color, + }, + ], + [ + { active: true, underlined: false, iconOnly: false, primary: true }, + { + color: v.colorScheme && v.colorScheme.default && v.colorScheme.brand.foregroundActive, + background: + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), + }, + ], + [ + { active: true, underlined: false, iconOnly: false, primary: false }, + { + color: v.color, + background: + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), + }, + ], + [ [ - null, - { - color: 'inherit', - lineHeight: 1, - position: 'relative', - verticalAlign: 'middle', - display: 'block', - }, + { active: true, pointing: 'start', vertical: true, isFromKeyboard: false }, + { active: true, pointing: 'end', vertical: true, isFromKeyboard: false }, + { active: true, pointing: true, vertical: true, isFromKeyboard: false }, ], - [{ secondary: true }, { background: 'salmon' }], - [ - { vertical: true }, - { - border: `solid ${v.verticalItemBorderWidth} ${v.verticalItemBorderColor}`, + { + '::before': { + content: `''`, + position: 'absolute', + width: pxToRem(3), + height: `calc(100% + ${pxToRem(4)})`, + top: pxToRem(-2), + backgroundColor: v.pointingIndicatorBackgroundColor, }, - ], - [{ pills: true }, { borderRadius: pxToRem(5) }], - [{ pills: true, vertical: true }, { margin: `0 0 ${verticalPillsBottomMargin} 0` }], - [{ pills: true, vertical: false }, { margin: `0 ${horizontalPillsRightMargin} 0 0` }], - [ - { underlined: true }, - { - display: 'flex', - alignItems: 'center', - height: pxToRem(29), - lineHeight: v.lineHeightBase, - padding: `0 ${pxToRem(4)}`, - margin: `0 ${pxToRem(4)} 0 0`, - ':nth-child(n+2)': { - marginLeft: `${pxToRem(4)}`, - }, - boxShadow: 'none', + }, + ], + [ + { active: true, vertical: true, isFromKeyboard: false, pointing: 'end' }, + { + '::before': { + right: pxToRem(-2), }, - ], + }, + ], + [ [ - { vertical: false, pills: false, underlined: false, iconOnly: false, primary: true }, - { - boxShadow: `-1px 0 0 0 ${v.primaryBorderColor || - (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.border)} inset`, - }, + { active: true, vertical: true, isFromKeyboard: false, pointing: 'start' }, + { active: true, vertical: true, isFromKeyboard: false, pointing: true }, ], - [ - { vertical: false, pills: false, underlined: false, iconOnly: false, primary: false }, - { - boxShadow: `-1px 0 0 0 ${v.borderColor || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)} inset`, + { + '::before': { + left: pxToRem(-2), }, - ], + }, + ], + [ [ - [{ active: true, underlined: true }, { active: true, iconOnly: true }], - { - color: v.color, - }, + { active: true, pointing: 'start', vertical: false }, + { active: true, pointing: 'end', vertical: false }, + { active: true, pointing: true, vertical: false }, ], - [ - { active: true, underlined: false, iconOnly: false, primary: true }, - { - color: v.colorScheme && v.colorScheme.default && v.colorScheme.brand.foregroundActive, + { + '::after': { + visibility: 'visible', + position: 'absolute', + content: '""', + left: '50%', + transform: 'translateX(-50%) translateY(-50%) rotate(45deg)', + margin: '.5px 0 0', + width: pxToRem(10), + height: pxToRem(10), + border: 'none', + zIndex: 2, + transition: 'background .1s ease', + }, + }, + ], + [ + [{ active: true, pointing: 'start', vertical: false, primary: true }], + { + '::after': { + top: '-1px', background: v.backgroundColorActive || (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), + borderTop: `1px solid ${v.borderColor || v.primaryBorderColor}`, + borderLeft: `1px solid ${v.borderColor || v.primaryBorderColor}`, }, - ], + }, + ], + [ [ - { active: true, underlined: false, iconOnly: false, primary: false }, - { - color: v.color, + { active: true, pointing: 'start', vertical: false, primary: false }, + { active: true, pointing: true, vertical: false, primary: false }, + ], + { + '::after': { + top: '-1px', background: v.backgroundColorActive || (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), + borderTop: `1px solid ${v.borderColor || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)}`, + borderLeft: `1px solid ${v.borderColor || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)}`, }, - ], - [ - [ - { active: true, pointing: 'start', vertical: true, isFromKeyboard: false }, - { active: true, pointing: 'end', vertical: true, isFromKeyboard: false }, - { active: true, pointing: true, vertical: true, isFromKeyboard: false }, - ], - { - '::before': { - content: `''`, - position: 'absolute', - width: pxToRem(3), - height: `calc(100% + ${pxToRem(4)})`, - top: pxToRem(-2), - backgroundColor: v.pointingIndicatorBackgroundColor, - }, - }, - ], - [ - { active: true, vertical: true, isFromKeyboard: false, pointing: 'end' }, - { - '::before': { - right: pxToRem(-2), - }, - }, - ], - [ - [ - { active: true, vertical: true, isFromKeyboard: false, pointing: 'start' }, - { active: true, vertical: true, isFromKeyboard: false, pointing: true }, - ], - { - '::before': { - left: pxToRem(-2), - }, - }, - ], - [ - [ - { active: true, pointing: 'start', vertical: false }, - { active: true, pointing: 'end', vertical: false }, - { active: true, pointing: true, vertical: false }, - ], - { - '::after': { - visibility: 'visible', - position: 'absolute', - content: '""', - left: '50%', - transform: 'translateX(-50%) translateY(-50%) rotate(45deg)', - margin: '.5px 0 0', - width: pxToRem(10), - height: pxToRem(10), - border: 'none', - zIndex: 2, - transition: 'background .1s ease', - }, - }, - ], - [ - [{ active: true, pointing: 'start', vertical: false, primary: true }], - { - '::after': { - top: '-1px', - background: - v.backgroundColorActive || - (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), - borderTop: `1px solid ${v.borderColor || v.primaryBorderColor}`, - borderLeft: `1px solid ${v.borderColor || v.primaryBorderColor}`, - }, - }, - ], - [ - [ - { active: true, pointing: 'start', vertical: false, primary: false }, - { active: true, pointing: true, vertical: false, primary: false }, - ], - { - '::after': { - top: '-1px', - background: - v.backgroundColorActive || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), - borderTop: `1px solid ${v.borderColor || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)}`, - borderLeft: `1px solid ${v.borderColor || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)}`, - }, - }, - ], - [ - { active: true, pointing: 'end', vertical: false, primary: true }, - { - '::after': { - top: '100%', - background: - v.backgroundColorActive || - (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), - borderBottom: `1px solid ${v.borderColor || v.primaryBorderColor}`, - borderRight: `1px solid ${v.borderColor || v.primaryBorderColor}`, - }, - }, - ], - [ - { active: true, pointing: 'end', vertical: false, primary: false }, - { - '::after': { - top: '100%', - background: - v.backgroundColorActive || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), - borderBottom: `1px solid ${v.borderColor || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)}`, - borderRight: `1px solid ${v.borderColor || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)}`, - }, + }, + ], + [ + { active: true, pointing: 'end', vertical: false, primary: true }, + { + '::after': { + top: '100%', + background: + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), + borderBottom: `1px solid ${v.borderColor || v.primaryBorderColor}`, + borderRight: `1px solid ${v.borderColor || v.primaryBorderColor}`, }, - ], - [ - { iconOnly: true, disabled: false }, - { - display: 'flex', - ':hover': { - color: v.iconOnlyColorActive, - }, + }, + ], + [ + { active: true, pointing: 'end', vertical: false, primary: false }, + { + '::after': { + top: '100%', + background: + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), + borderBottom: `1px solid ${v.borderColor || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)}`, + borderRight: `1px solid ${v.borderColor || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.border)}`, }, - ], - [ - { iconOnly: true, isFromKeyboard: true }, - { + }, + ], + [ + { iconOnly: true, disabled: false }, + { + display: 'flex', + ':hover': { color: v.iconOnlyColorActive, }, - ], - [ - { iconOnly: false, isFromKeyboard: true, vertical: true, primary: false }, - { - border: `solid 1px ${v.borderColorFocus}`, - outline: `solid 1px ${v.outlineColorFocus}`, - margin: pxToRem(1), - background: - v.verticalBackgroundColorFocus || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundFocus), + }, + ], + [ + { iconOnly: true, isFromKeyboard: true }, + { + color: v.iconOnlyColorActive, + }, + ], + [ + { iconOnly: false, isFromKeyboard: true, vertical: true, primary: false }, + { + border: `solid 1px ${v.borderColorFocus}`, + outline: `solid 1px ${v.outlineColorFocus}`, + margin: pxToRem(1), + background: + v.verticalBackgroundColorFocus || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundFocus), + }, + ], + [ + [ + { iconOnly: false, isFromKeyboard: true, primary: true, active: false }, + { iconOnly: false, isFromKeyboard: true, primary: true, underlined: true }, + { iconOnly: false, isFromKeyboard: true, primary: true, vertical: true }, + ], + { + color: v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.foregroundFocus, + background: + v.backgroundColorFocus || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundFocus), + }, + ], + [ + [ + { iconOnly: false, isFromKeyboard: true, primary: false, active: false }, + { iconOnly: false, isFromKeyboard: true, primary: false, underlined: true }, + { iconOnly: false, isFromKeyboard: true, primary: false, vertical: true }, + ], + { + color: v.colorActive, + background: + v.backgroundColorFocus || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundFocus), + }, + ], + [ + { iconOnly: false, underlined: true, disabled: false }, + { + ':hover': { + color: v.colorActive, }, - ], - [ - [ - { iconOnly: false, isFromKeyboard: true, primary: true, active: false }, - { iconOnly: false, isFromKeyboard: true, primary: true, underlined: true }, - { iconOnly: false, isFromKeyboard: true, primary: true, vertical: true }, - ], - { - color: v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.foregroundFocus, + }, + ], + [ + { iconOnly: false, underlined: false, primary: true, active: false, disabled: false }, + { + ':hover': { + color: v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.foregroundHover, background: - v.backgroundColorFocus || - (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundFocus), + v.backgroundColorHover || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundHover), }, - ], - [ - [ - { iconOnly: false, isFromKeyboard: true, primary: false, active: false }, - { iconOnly: false, isFromKeyboard: true, primary: false, underlined: true }, - { iconOnly: false, isFromKeyboard: true, primary: false, vertical: true }, - ], - { - color: v.colorActive, + }, + ], + [ + { iconOnly: false, underlined: false, primary: false, active: false, disabled: false }, + { + ':hover': { + color: v.colorScheme && v.colorScheme.default && v.colorScheme.default.foregroundHover, background: - v.backgroundColorFocus || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundFocus), - }, - ], - [ - { iconOnly: false, underlined: true, disabled: false }, - { - ':hover': { - color: v.colorActive, - }, + v.backgroundColorHover || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundHover), }, - ], - [ - { iconOnly: false, underlined: false, primary: true, active: false, disabled: false }, - { - ':hover': { - color: v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.foregroundHover, - background: - v.backgroundColorHover || - (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundHover), - }, - }, - ], - [ - { iconOnly: false, underlined: false, primary: false, active: false, disabled: false }, - { - ':hover': { - color: v.colorScheme && v.colorScheme.default && v.colorScheme.default.foregroundHover, - background: - v.backgroundColorHover || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundHover), - }, - }, - ], - [ - { pills: false, iconOnly: false, underlined: false, pointing: false, vertical: true }, - { - ':first-child': { - '::before': { - display: 'none', - }, - }, - }, - ], - [ - { pills: false, iconOnly: false, underlined: false, pointing: false, vertical: false }, - { - ':first-child': { - borderBottomLeftRadius: pxToRem(3), - borderTopLeftRadius: pxToRem(3), + }, + ], + [ + { pills: false, iconOnly: false, underlined: false, pointing: false, vertical: true }, + { + ':first-child': { + '::before': { + display: 'none', }, }, - ], - [ - { disabled: true, primary: false }, - { - color: - v.colorDisabled || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.foregroundDisabled), - }, - ], - [ - { disabled: true, primary: true }, - { - color: - v.colorDisabled || - (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.foregroundDisabled), - }, - ], + }, ], - root: [ - [ - null, - { + [ + { pills: false, iconOnly: false, underlined: false, pointing: false, vertical: false }, + { + ':first-child': { + borderBottomLeftRadius: pxToRem(3), + borderTopLeftRadius: pxToRem(3), + }, + }, + ], + [ + { disabled: true, primary: false }, + { + color: + v.colorDisabled || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.foregroundDisabled), + }, + ], + [ + { disabled: true, primary: true }, + { + color: + v.colorDisabled || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.foregroundDisabled), + }, + ], + ], + root: [ + [ + null, + { + color: 'inherit', + display: 'block', + cursor: 'pointer', + whiteSpace: 'nowrap', + ':focus': { + outline: 0, + }, + ':hover': { color: 'inherit', - display: 'block', - cursor: 'pointer', - whiteSpace: 'nowrap', - ':focus': { - outline: 0, - }, - ':hover': { - color: 'inherit', - }, }, - ], - [ - [ - { pointing: 'start', vertical: true }, - { pointing: 'end', vertical: true }, - { pointing: true, vertical: true }, - ], - { - border: '1px solid transparent', - }, - ], - [ - { iconOnly: true }, - { - border: `${pxToRem(2)} solid transparent`, - margin: pxToRem(1), - padding: pxToRem(5), // padding works this way to get the border to only be 30x30px on focus which is the current design - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - }, - ], - [ - { iconOnly: true, disabled: false }, - { - ':hover': { - ...getIconFillOrOutlineStyles({ outline: false }), - }, - }, - ], - [ - { underlined: true }, - { - padding: `${pxToRem(4)} 0`, - }, - ], - [ - [ - { underlined: false, pointing: 'start', vertical: true }, - { underlined: false, pointing: 'end', vertical: true }, - { underlined: false, pointing: true, vertical: true }, - ], - { - padding: `${pxToRem(8)} ${pxToRem(18)}`, - }, - ], - [ - { underlined: false, pointing: false, vertical: true, iconOnly: false }, - { - padding: v.verticalItemPadding, - }, - ], + }, + ], + [ [ - { underlined: false, vertical: false, iconOnly: false }, - { - padding: v.horizontalPadding, - }, + { pointing: 'start', vertical: true }, + { pointing: 'end', vertical: true }, + { pointing: true, vertical: true }, ], - [ - { active: true, iconOnly: true }, - { - color: v.iconOnlyColorActive, + { + border: '1px solid transparent', + }, + ], + [ + { iconOnly: true }, + { + border: `${pxToRem(2)} solid transparent`, + margin: pxToRem(1), + padding: pxToRem(5), // padding works this way to get the border to only be 30x30px on focus which is the current design + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + }, + ], + [ + { iconOnly: true, disabled: false }, + { + ':hover': { ...getIconFillOrOutlineStyles({ outline: false }), }, - ], - [ - { active: true, primary: true, underlined: true }, - { - color: v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.borderActive, - ...underlinedItem( - v.borderColorActive || - (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.borderActive), - ), - }, - ], - [ - { active: true, primary: false, underlined: true }, - { - fontWeight: 700, - ...underlinedItem(v.colorActive), - }, - ], - [ - { primary: true, active: false, underlined: true, disabled: false }, - { - ':hover': { - ...underlinedItem( - v.underlinedBorderColor || - (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), - ), - }, - }, - ], - [ - { primary: false, active: false, underlined: true, disabled: false }, - { - ':hover': { - ...underlinedItem( - v.backgroundColorActive || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), - ), - }, - }, - ], + }, + ], + [ + { underlined: true }, + { + padding: `${pxToRem(4)} 0`, + }, + ], + [ [ - { isFromKeyboard: true, iconOnly: true }, - { - borderRadius: '50%', - borderColor: v.iconOnlyColorActive, - ...getIconFillOrOutlineStyles({ outline: false }), - }, + { underlined: false, pointing: 'start', vertical: true }, + { underlined: false, pointing: 'end', vertical: true }, + { underlined: false, pointing: true, vertical: true }, ], - [ - { isFromKeyboard: true, primary: true, iconOnly: true }, - { - color: 'inherit', - borderColor: - v.borderColorActive || + { + padding: `${pxToRem(8)} ${pxToRem(18)}`, + }, + ], + [ + { underlined: false, pointing: false, vertical: true, iconOnly: false }, + { + padding: v.verticalItemPadding, + }, + ], + [ + { underlined: false, vertical: false, iconOnly: false }, + { + padding: v.horizontalPadding, + }, + ], + [ + { active: true, iconOnly: true }, + { + color: v.iconOnlyColorActive, + ...getIconFillOrOutlineStyles({ outline: false }), + }, + ], + [ + { active: true, primary: true, underlined: true }, + { + color: v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.borderActive, + ...underlinedItem( + v.borderColorActive || (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.borderActive), - }, - ], - [ - { isFromKeyboard: true, primary: true, underlined: true }, - { - color: 'inherit', - }, - ], - [ - { isFromKeyboard: true, primary: true, underlined: true, active: true }, - { + ), + }, + ], + [ + { active: true, primary: false, underlined: true }, + { + fontWeight: 700, + ...underlinedItem(v.colorActive), + }, + ], + [ + { primary: true, active: false, underlined: true, disabled: false }, + { + ':hover': { ...underlinedItem( - v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.foregroundActive, + v.underlinedBorderColor || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), ), }, - ], - [ - { isFromKeyboard: true, primary: false, underlined: true }, - { - fontWeight: 700, - }, - ], - [ - { isFromKeyboard: true, primary: false, underlined: true, active: true }, - { - ...underlinedItem(v.colorActive), - }, - ], - [ - { primary: true, active: false, underlined: true, disabled: false }, - { - ':hover': { - ...underlinedItem( - v.underlinedBorderColor || - (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), - ), - }, - }, - ], - [ - { primary: false, active: false, underlined: true, disabled: false }, - { - ':hover': { - ...underlinedItem( - v.backgroundColorActive || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), - ), - }, - }, - ], - [ - { disabled: true }, - { - cursor: 'default', - }, - ], + }, ], - content: [ - [ - null, - { - whiteSpace: 'normal', - lineHeight: 1.5, - marginTop: pxToRem(-4), - marginBottom: pxToRem(-4), - display: 'inline-block', - }, - ], - [ - [{ inSubmenu: true }, { vertical: true }], - { - width: 'max-content', - marginRight: pxToRem(16), - }, - ], - [ - [{ inSubmenu: true, icon: true, menu: true }, { vertical: true, icon: true, menu: true }], - { - minWidth: pxToRem(46 - 26 - 16), - maxWidth: pxToRem(262 - 26 - 16), - }, - ], - [ - [{ inSubmenu: true, icon: true, menu: false }, { vertical: true, icon: true, menu: false }], - { - minWidth: pxToRem(46 - 26), - maxWidth: pxToRem(262 - 26), - }, - ], - [ - [{ inSubmenu: true, icon: false, menu: true }, { vertical: true, icon: false, menu: true }], - { - minWidth: pxToRem(46 - 16), - maxWidth: pxToRem(262 - 16), - }, - ], - [ - [ - { inSubmenu: true, icon: false, menu: false }, - { vertical: true, icon: false, menu: false }, - ], - { - minWidth: pxToRem(46), - maxWidth: pxToRem(262), + [ + { primary: false, active: false, underlined: true, disabled: false }, + { + ':hover': { + ...underlinedItem( + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), + ), }, - ], + }, ], - icon: [ - [ - { iconOnly: false }, - { - // reduce margins so text has the dominant influence on the vertical height - marginTop: 0, - marginBottom: pxToRem(-8), - verticalAlign: 'top', - }, - ], + [ + { isFromKeyboard: true, iconOnly: true }, + { + borderRadius: '50%', + borderColor: v.iconOnlyColorActive, + ...getIconFillOrOutlineStyles({ outline: false }), + }, ], - menu: [[null, { zIndex: 1000 }]], - indicator: [ - [ - null, - { - position: 'relative', - float: 'right', - left: pxToRem(12), - userSelect: 'none', - marginRight: pxToRem(4), + [ + { isFromKeyboard: true, primary: true, iconOnly: true }, + { + color: 'inherit', + borderColor: + v.borderColorActive || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.borderActive), + }, + ], + [ + { isFromKeyboard: true, primary: true, underlined: true }, + { + color: 'inherit', + }, + ], + [ + { isFromKeyboard: true, primary: true, underlined: true, active: true }, + { + ...underlinedItem( + v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.foregroundActive, + ), + }, + ], + [ + { isFromKeyboard: true, primary: false, underlined: true }, + { + fontWeight: 700, + }, + ], + [ + { isFromKeyboard: true, primary: false, underlined: true, active: true }, + { + ...underlinedItem(v.colorActive), + }, + ], + [ + { primary: true, active: false, underlined: true, disabled: false }, + { + ':hover': { + ...underlinedItem( + v.underlinedBorderColor || + (v.colorScheme && v.colorScheme.brand && v.colorScheme.brand.backgroundActive), + ), }, - ], - [ - { inSubmenu: true }, - { - position: 'absolute', - top: pxToRem(6), - right: pxToRem(2), - left: 'unset', + }, + ], + [ + { primary: false, active: false, underlined: true, disabled: false }, + { + ':hover': { + ...underlinedItem( + v.backgroundColorActive || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundActive), + ), }, - ], + }, + ], + [ + { disabled: true }, + { + cursor: 'default', + }, + ], + ], + content: [ + [ + null, + { + whiteSpace: 'normal', + lineHeight: 1.5, + marginTop: pxToRem(-4), + marginBottom: pxToRem(-4), + display: 'inline-block', + }, + ], + [ + [{ inSubmenu: true }, { vertical: true }], + { + width: 'max-content', + marginRight: pxToRem(16), + }, ], - } -} + [ + [{ inSubmenu: true, icon: true, menu: true }, { vertical: true, icon: true, menu: true }], + { + minWidth: pxToRem(46 - 26 - 16), + maxWidth: pxToRem(262 - 26 - 16), + }, + ], + [ + [{ inSubmenu: true, icon: true, menu: false }, { vertical: true, icon: true, menu: false }], + { + minWidth: pxToRem(46 - 26), + maxWidth: pxToRem(262 - 26), + }, + ], + [ + [{ inSubmenu: true, icon: false, menu: true }, { vertical: true, icon: false, menu: true }], + { + minWidth: pxToRem(46 - 16), + maxWidth: pxToRem(262 - 16), + }, + ], + [ + [{ inSubmenu: true, icon: false, menu: false }, { vertical: true, icon: false, menu: false }], + { + minWidth: pxToRem(46), + maxWidth: pxToRem(262), + }, + ], + ], + icon: [ + [ + { iconOnly: false }, + { + // reduce margins so text has the dominant influence on the vertical height + marginTop: 0, + marginBottom: pxToRem(-8), + verticalAlign: 'top', + }, + ], + ], + menu: [[null, { zIndex: 1000 }]], + indicator: [ + [ + null, + { + position: 'relative', + float: 'right', + left: pxToRem(12), + userSelect: 'none', + marginRight: pxToRem(4), + }, + ], + [ + { inSubmenu: true }, + { + position: 'absolute', + top: pxToRem(6), + right: pxToRem(2), + left: 'unset', + }, + ], + ], +}) -export default backportComponentStyle(updatedMenuItemStyles) +export default backportComponentStyle(menuItemStyles) From d4277947189d08c5cd67069f02e9ca38655aea35 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Tue, 5 Nov 2019 11:50:58 +0100 Subject: [PATCH 14/28] -fixed menu divider styles --- .../components/Menu/menuDividerStyles.ts | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/react/src/themes/teams/components/Menu/menuDividerStyles.ts b/packages/react/src/themes/teams/components/Menu/menuDividerStyles.ts index 4da2713c84..b75f79badb 100644 --- a/packages/react/src/themes/teams/components/Menu/menuDividerStyles.ts +++ b/packages/react/src/themes/teams/components/Menu/menuDividerStyles.ts @@ -19,12 +19,24 @@ const menuDividerStyles: ComponentSelectorsAndStyles Date: Tue, 5 Nov 2019 12:34:09 +0100 Subject: [PATCH 15/28] -converted slider styles --- .../teams/components/Slider/sliderStyles.ts | 239 ++++++++++-------- .../components/Slider/sliderVariables.ts | 10 + .../src/themes/teams/getBorderFocusStyles.ts | 4 +- 3 files changed, 144 insertions(+), 109 deletions(-) diff --git a/packages/react/src/themes/teams/components/Slider/sliderStyles.ts b/packages/react/src/themes/teams/components/Slider/sliderStyles.ts index d9637d0db7..58a9b12e1c 100644 --- a/packages/react/src/themes/teams/components/Slider/sliderStyles.ts +++ b/packages/react/src/themes/teams/components/Slider/sliderStyles.ts @@ -1,8 +1,9 @@ import * as React from 'react' import { SliderVariables } from './sliderVariables' -import Slider, { SliderProps, SliderState } from '../../../../components/Slider/Slider' -import { ComponentSlotStylesPrepared, ICSSInJSStyle } from '../../../types' +import Slider, { SliderProps } from '../../../../components/Slider/Slider' +import { ComponentSelectorsAndStyles, ICSSInJSStyle } from '../../../types' import getBorderFocusStyles from '../../getBorderFocusStyles' +import { backportComponentStyle } from '../../../../lib/resolveComponentRules' const selectors = { WEBKIT_THUMB: '::-webkit-slider-thumb', @@ -12,7 +13,7 @@ const selectors = { MS_THUMB: '::-ms-thumb', } -const getCommonSlotStyles = (p: SliderProps, v: SliderVariables): ICSSInJSStyle => ({ +const getCommonSlotStyles = (v: SliderVariables): ICSSInJSStyle => ({ cursor: 'pointer', pointerEvents: 'none', position: 'absolute', @@ -24,110 +25,134 @@ const getCommonSlotStyles = (p: SliderProps, v: SliderVariables): ICSSInJSStyle // this selector is used to identify the thumb slot from a previous sibling const thumbFromPreviousSiblingSelector = `&+ .${Slider.slotClassNames.thumb}` -const getFluidStyles = (p: SliderProps) => p.fluid && !p.vertical && { width: '100%' } - -const sliderStyles: ComponentSlotStylesPrepared = { - root: ({ props: p, variables: v }): ICSSInJSStyle => ({ - height: v.height, - - ...(p.disabled && { pointerEvents: 'none' }), - ...(p.vertical && { height: v.length, width: v.height }), - ...getFluidStyles(p), - }), - - input: ({ props: p, variables: v, theme: { siteVariables } }): ICSSInJSStyle => { - const activeThumbStyles: React.CSSProperties = { - height: v.activeThumbHeight, - width: v.activeThumbWidth, - background: v.activeThumbColor, - marginTop: `calc(${v.height} / 2 - ${v.activeThumbHeight} / 2)`, - marginLeft: `calc(-${v.activeThumbWidth} / 2)`, - } - const borderFocusStyles = getBorderFocusStyles({ - siteVariables, - borderPadding: v.thumbBorderPadding, - }) - const thumbStyles = { border: 0, width: '1px' } - - return { - '-webkit-appearance': 'none', - cursor: 'pointer', - height: '100%', - width: '100%', - margin: 0, - padding: 0, - opacity: 0, - - [selectors.WEBKIT_THUMB]: { ...thumbStyles, '-webkit-appearance': 'none' }, - [selectors.MOZ_THUMB]: thumbStyles, - [selectors.MS_THUMB]: { ...thumbStyles, marginTop: `calc(-${v.thumbHeight} / 2)` }, - - [selectors.MS_FILL_LOWER]: { display: 'none' }, - [selectors.MS_FILL_UPPER]: { display: 'none' }, - - ...getFluidStyles(p), - - ':active': { [thumbFromPreviousSiblingSelector]: activeThumbStyles }, - - ':focus': { - outline: 0, // TODO: check if this is correct - [thumbFromPreviousSiblingSelector]: borderFocusStyles[':focus'], - }, - ':focus-visible': { - [thumbFromPreviousSiblingSelector]: { - ...borderFocusStyles[':focus-visible'], - ...activeThumbStyles, +const sliderStyles: ComponentSelectorsAndStyles = v => { + const thumbStyles = { border: 0, width: '1px' } + + const activeThumbStyles: React.CSSProperties = { + height: v.activeThumbHeight, + width: v.activeThumbWidth, + background: v.activeThumbColor, + marginTop: `calc(${v.height} / 2 - ${v.activeThumbHeight} / 2)`, + marginLeft: `calc(-${v.activeThumbWidth} / 2)`, + } + + const transformOriginValue = `calc(${v.length} / 2)` + + const borderFocusStyles = getBorderFocusStyles({ + siteVariables: { + borderWidth: v.focusBorderWidth, + borderRadius: v.focusBorderRadius, + focusInnerBorderColor: v.focusInnerBorderColor, + focusOuterBorderColor: v.focusOuterBorderColor, + }, + borderPadding: v.thumbBorderPadding, + }) + + return { + root: [ + [null, { height: v.height }], + [{ disabled: true }, { pointerEvents: 'none' }], + [{ vertical: true }, { height: v.length, width: v.height }], + [{ fluid: true, vertical: false }, { width: '100%' }], + ], + + input: [ + [ + null, + { + '-webkit-appearance': 'none', + cursor: 'pointer', + height: '100%', + width: '100%', + margin: 0, + padding: 0, + opacity: 0, + + [selectors.WEBKIT_THUMB]: { ...thumbStyles, '-webkit-appearance': 'none' }, + [selectors.MOZ_THUMB]: thumbStyles, + [selectors.MS_THUMB]: { ...thumbStyles, marginTop: `calc(-${v.thumbHeight} / 2)` }, + + [selectors.MS_FILL_LOWER]: { display: 'none' }, + [selectors.MS_FILL_UPPER]: { display: 'none' }, + ':active': { [thumbFromPreviousSiblingSelector]: activeThumbStyles }, + ':focus': { + outline: 0, + [thumbFromPreviousSiblingSelector]: borderFocusStyles[':focus'], + }, + ':focus-visible': { + [thumbFromPreviousSiblingSelector]: { + ...borderFocusStyles[':focus-visible'], + ...activeThumbStyles, + }, + }, }, - }, - } - }, - - inputWrapper: ({ props: p, variables: v }) => { - const transformOriginValue = `calc(${v.length} / 2)` - - return { - position: 'relative', - display: 'inline-block', - height: v.height, - width: v.length, - ...(p.vertical && { - transform: 'rotate(-90deg)', - transformOrigin: `${transformOriginValue} ${transformOriginValue}`, - }), - ...getFluidStyles(p), - } - }, - - rail: ({ props: p, variables: v }) => ({ - width: '100%', - background: v.railColor, - - ...getCommonSlotStyles(p, v), - ...(p.disabled && { background: v.disabledRailColor }), - }), - - track: ({ props: p, variables: v }) => ({ - background: v.trackColor, - - ...getCommonSlotStyles(p, v), - ...(p.disabled && { background: v.disabledTrackColor }), - }), - - thumb: ({ props: p, variables: v }) => ({ - border: 0, - borderRadius: '100%', - cursor: 'pointer', - pointerEvents: 'none', - position: 'absolute', - - background: v.thumbColor, - height: v.thumbHeight, - width: v.thumbWidth, - marginTop: `calc(${v.height} / 2 - ${v.thumbHeight} / 2)`, - marginLeft: `calc(-${v.thumbWidth} / 2)`, - - ...(p.disabled && { background: v.disabledThumbColor }), - }), + ], + [{ fluid: true, vertical: false }, { width: '100%' }], + ], + + inputWrapper: [ + [ + null, + { + position: 'relative', + display: 'inline-block', + height: v.height, + width: v.length, + }, + ], + [ + { vertical: true }, + { + transform: 'rotate(-90deg)', + transformOrigin: `${transformOriginValue} ${transformOriginValue}`, + }, + ], + [{ fluid: true, vertical: false }, { width: '100%' }], + ], + + rail: [ + [ + null, + { + width: '100%', + background: v.railColor, + ...getCommonSlotStyles(v), + }, + ], + [{ disabled: true }, { background: v.disabledRailColor }], + ], + + track: [ + [ + null, + { + background: v.trackColor, + ...getCommonSlotStyles(v), + }, + ], + [{ disabled: true }, { background: v.disabledTrackColor }], + ], + + thumb: [ + [ + null, + { + border: 0, + borderRadius: '100%', + cursor: 'pointer', + pointerEvents: 'none', + position: 'absolute', + + background: v.thumbColor, + height: v.thumbHeight, + width: v.thumbWidth, + marginTop: `calc(${v.height} / 2 - ${v.thumbHeight} / 2)`, + marginLeft: `calc(-${v.thumbWidth} / 2)`, + }, + ], + [{ disabled: true }, { background: v.disabledThumbColor }], + ], + } } -export default sliderStyles +export default backportComponentStyle(sliderStyles) diff --git a/packages/react/src/themes/teams/components/Slider/sliderVariables.ts b/packages/react/src/themes/teams/components/Slider/sliderVariables.ts index 43d880df98..22d61848b8 100644 --- a/packages/react/src/themes/teams/components/Slider/sliderVariables.ts +++ b/packages/react/src/themes/teams/components/Slider/sliderVariables.ts @@ -20,6 +20,11 @@ export interface SliderVariables { trackColor: string disabledTrackColor: string + + focusBorderWidth: string + focusBorderRadius: string + focusInnerBorderColor: string + focusOuterBorderColor: string } export default (siteVars: SiteVariablesPrepared): SliderVariables => { const { colorScheme } = siteVars @@ -43,5 +48,10 @@ export default (siteVars: SiteVariablesPrepared): SliderVariables => { trackColor: colorScheme.brand.foregroundActive, disabledTrackColor: colorScheme.default.foregroundDisabled1, + + focusBorderWidth: siteVars.borderWidth, + focusBorderRadius: siteVars.borderRadius, + focusInnerBorderColor: siteVars.focusInnerBorderColor, + focusOuterBorderColor: siteVars.focusOuterBorderColor, } } diff --git a/packages/react/src/themes/teams/getBorderFocusStyles.ts b/packages/react/src/themes/teams/getBorderFocusStyles.ts index 4fa8e8472e..a37cbe868d 100644 --- a/packages/react/src/themes/teams/getBorderFocusStyles.ts +++ b/packages/react/src/themes/teams/getBorderFocusStyles.ts @@ -1,11 +1,11 @@ import * as React from 'react' -import { ICSSInJSStyle, SiteVariablesPrepared } from '../types' +import { ICSSInJSStyle } from '../types' type CSSBorderStyles = Pick type BorderFocusStyles = CSSBorderStyles & { - siteVariables?: SiteVariablesPrepared + siteVariables?: object focusInnerBorderColor?: string focusOuterBorderColor?: string borderPadding?: React.CSSProperties['padding'] From 755295623d25da9567df234fd923b5bffeef94fc Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Tue, 5 Nov 2019 12:46:09 +0100 Subject: [PATCH 16/28] -fixed menu regressions --- .../teams/components/Menu/menuItemStyles.ts | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts b/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts index 6d848f56b4..4eff5627d4 100644 --- a/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts +++ b/packages/react/src/themes/teams/components/Menu/menuItemStyles.ts @@ -218,17 +218,6 @@ const menuItemStyles: ComponentSelectorsAndStyles color: v.iconOnlyColorActive, }, ], - [ - { iconOnly: false, isFromKeyboard: true, vertical: true, primary: false }, - { - border: `solid 1px ${v.borderColorFocus}`, - outline: `solid 1px ${v.outlineColorFocus}`, - margin: pxToRem(1), - background: - v.verticalBackgroundColorFocus || - (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundFocus), - }, - ], [ [ { iconOnly: false, isFromKeyboard: true, primary: true, active: false }, @@ -255,6 +244,17 @@ const menuItemStyles: ComponentSelectorsAndStyles (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundFocus), }, ], + [ + { iconOnly: false, isFromKeyboard: true, vertical: true, primary: false }, + { + border: `solid 1px ${v.borderColorFocus}`, + outline: `solid 1px ${v.outlineColorFocus}`, + margin: pxToRem(1), + background: + v.verticalBackgroundColorFocus || + (v.colorScheme && v.colorScheme.default && v.colorScheme.default.backgroundFocus), + }, + ], [ { iconOnly: false, underlined: true, disabled: false }, { From 756442ec4669b31030d3eb045bed0aea5e59af9e Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Tue, 5 Nov 2019 14:02:07 +0100 Subject: [PATCH 17/28] -fixed status differences in chat examples --- docs/src/examples/components/Chat/Rtl/ChatExample.rtl.tsx | 2 +- .../examples/components/Chat/Types/ChatExample.shorthand.tsx | 2 +- .../Chat/Types/ChatExampleContentPosition.shorthand.tsx | 2 +- .../components/Chat/Types/ChatMessageExampleBadge.shorthand.tsx | 2 +- .../Chat/Types/ChatMessageExampleStyled.shorthand.tsx | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/src/examples/components/Chat/Rtl/ChatExample.rtl.tsx b/docs/src/examples/components/Chat/Rtl/ChatExample.rtl.tsx index 113f6c801d..601001957d 100644 --- a/docs/src/examples/components/Chat/Rtl/ChatExample.rtl.tsx +++ b/docs/src/examples/components/Chat/Rtl/ChatExample.rtl.tsx @@ -18,7 +18,7 @@ const items: ShorthandCollection = [ gutter: ( ), message: ( diff --git a/docs/src/examples/components/Chat/Types/ChatExample.shorthand.tsx b/docs/src/examples/components/Chat/Types/ChatExample.shorthand.tsx index ea34b578d4..f437132548 100644 --- a/docs/src/examples/components/Chat/Types/ChatExample.shorthand.tsx +++ b/docs/src/examples/components/Chat/Types/ChatExample.shorthand.tsx @@ -3,7 +3,7 @@ import { Avatar, Chat, ChatItemProps, Divider, ShorthandCollection } from '@star const janeAvatar = { image: 'public/images/avatar/small/ade.jpg', - status: { color: 'green', icon: 'stardust-checkmark' }, + status: { styles: { backgroundColor: 'green' }, icon: 'stardust-checkmark' }, } const items: ShorthandCollection = [ diff --git a/docs/src/examples/components/Chat/Types/ChatExampleContentPosition.shorthand.tsx b/docs/src/examples/components/Chat/Types/ChatExampleContentPosition.shorthand.tsx index 6f24597424..bb1a9f076c 100644 --- a/docs/src/examples/components/Chat/Types/ChatExampleContentPosition.shorthand.tsx +++ b/docs/src/examples/components/Chat/Types/ChatExampleContentPosition.shorthand.tsx @@ -6,7 +6,7 @@ const [janeAvatar, johnAvatar] = [ 'public/images/avatar/small/joe.jpg', ].map(src => ({ image: src, - status: { color: 'green', icon: 'stardust-checkmark' }, + status: { styles: { backgroundColor: 'green' }, icon: 'stardust-checkmark' }, })) const items: ShorthandCollection = [ diff --git a/docs/src/examples/components/Chat/Types/ChatMessageExampleBadge.shorthand.tsx b/docs/src/examples/components/Chat/Types/ChatMessageExampleBadge.shorthand.tsx index b805aa30e8..81b8982231 100644 --- a/docs/src/examples/components/Chat/Types/ChatMessageExampleBadge.shorthand.tsx +++ b/docs/src/examples/components/Chat/Types/ChatMessageExampleBadge.shorthand.tsx @@ -3,7 +3,7 @@ import { Avatar, Chat, ChatItemProps, ShorthandCollection } from '@stardust-ui/r const janeAvatar = { image: 'public/images/avatar/small/ade.jpg', - status: { color: 'green', icon: 'stardust-checkmark' }, + status: { styles: { backgroundColor: 'green' }, icon: 'stardust-checkmark' }, } const items: ShorthandCollection = [ diff --git a/docs/src/examples/components/Chat/Types/ChatMessageExampleStyled.shorthand.tsx b/docs/src/examples/components/Chat/Types/ChatMessageExampleStyled.shorthand.tsx index f3863f0719..08f6b3fd8f 100644 --- a/docs/src/examples/components/Chat/Types/ChatMessageExampleStyled.shorthand.tsx +++ b/docs/src/examples/components/Chat/Types/ChatMessageExampleStyled.shorthand.tsx @@ -15,7 +15,7 @@ const reactions: ShorthandCollection = [ const janeAvatar: AvatarProps = { image: 'public/images/avatar/small/ade.jpg', - status: { color: 'green', icon: 'stardust-checkmark' }, + status: { styles: { backgroundColor: 'green' }, icon: 'stardust-checkmark' }, } const content = ( From da11f81c7721a913cac19db91777c33aafcaaa16 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Tue, 5 Nov 2019 14:39:07 +0100 Subject: [PATCH 18/28] fixed ts issues --- packages/react/src/themes/teams/getBorderFocusStyles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/themes/teams/getBorderFocusStyles.ts b/packages/react/src/themes/teams/getBorderFocusStyles.ts index a37cbe868d..6303ffab44 100644 --- a/packages/react/src/themes/teams/getBorderFocusStyles.ts +++ b/packages/react/src/themes/teams/getBorderFocusStyles.ts @@ -5,7 +5,7 @@ import { ICSSInJSStyle } from '../types' type CSSBorderStyles = Pick type BorderFocusStyles = CSSBorderStyles & { - siteVariables?: object + siteVariables?: { [key: string]: any } focusInnerBorderColor?: string focusOuterBorderColor?: string borderPadding?: React.CSSProperties['padding'] From cb4ec1164855d63ac8ce1c758caca2c31fca6cf5 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Tue, 5 Nov 2019 15:29:47 +0100 Subject: [PATCH 19/28] -fixed status regressions in the Avatar component --- .../Avatar/Rtl/AvatarExample.rtl.tsx | 2 +- .../Usage/AvatarUsageExample.shorthand.tsx | 6 +++++- ...AvatarExampleExcludedInitials.shorthand.tsx | 6 +++++- .../AvatarExampleGetInitials.shorthand.tsx | 6 +++++- ...atarExampleImageCustomization.shorthand.tsx | 18 +++++++++++++++--- .../Variations/AvatarExampleName.shorthand.tsx | 2 +- .../Variations/AvatarExampleSize.shorthand.tsx | 2 +- .../AvatarExampleStatus.shorthand.tsx | 13 ++++++++++--- ...tarExampleStatusCustomization.shorthand.tsx | 10 +++++----- .../components/Chat/Performance/Chat.perf.tsx | 2 +- .../Chat/Performance/ChatWithPopover.perf.tsx | 2 +- 11 files changed, 50 insertions(+), 19 deletions(-) diff --git a/docs/src/examples/components/Avatar/Rtl/AvatarExample.rtl.tsx b/docs/src/examples/components/Avatar/Rtl/AvatarExample.rtl.tsx index 286430c532..a3fc35767c 100644 --- a/docs/src/examples/components/Avatar/Rtl/AvatarExample.rtl.tsx +++ b/docs/src/examples/components/Avatar/Rtl/AvatarExample.rtl.tsx @@ -5,7 +5,7 @@ const AvatarExampleRtl = () => ( diff --git a/docs/src/examples/components/Avatar/Usage/AvatarUsageExample.shorthand.tsx b/docs/src/examples/components/Avatar/Usage/AvatarUsageExample.shorthand.tsx index 61e477af92..c1fa9c8d6d 100644 --- a/docs/src/examples/components/Avatar/Usage/AvatarUsageExample.shorthand.tsx +++ b/docs/src/examples/components/Avatar/Usage/AvatarUsageExample.shorthand.tsx @@ -1,7 +1,11 @@ import * as React from 'react' import { Avatar } from '@stardust-ui/react' -const status = { color: 'green', icon: 'stardust-checkmark', title: 'Available' } +const status = { + styles: { backgroundColor: 'green' }, + icon: 'stardust-checkmark', + title: 'Available', +} const AvatarUsageExampleShorthand = () => (
diff --git a/docs/src/examples/components/Avatar/Variations/AvatarExampleExcludedInitials.shorthand.tsx b/docs/src/examples/components/Avatar/Variations/AvatarExampleExcludedInitials.shorthand.tsx index 4725e8ac32..a6fd5f80f8 100644 --- a/docs/src/examples/components/Avatar/Variations/AvatarExampleExcludedInitials.shorthand.tsx +++ b/docs/src/examples/components/Avatar/Variations/AvatarExampleExcludedInitials.shorthand.tsx @@ -1,7 +1,11 @@ import * as React from 'react' import { Avatar } from '@stardust-ui/react' -const status = { color: 'green', icon: 'stardust-checkmark', title: 'Available' } +const status = { + styles: { backgroundColor: 'green' }, + icon: 'stardust-checkmark', + title: 'Available', +} const AvatarExampleExcludedInitialsShorthand = () => (
diff --git a/docs/src/examples/components/Avatar/Variations/AvatarExampleGetInitials.shorthand.tsx b/docs/src/examples/components/Avatar/Variations/AvatarExampleGetInitials.shorthand.tsx index acdf9169b0..8809ae769d 100644 --- a/docs/src/examples/components/Avatar/Variations/AvatarExampleGetInitials.shorthand.tsx +++ b/docs/src/examples/components/Avatar/Variations/AvatarExampleGetInitials.shorthand.tsx @@ -7,7 +7,11 @@ const AvatarExampleGetInitialsShorthand = () => ( ) diff --git a/docs/src/examples/components/Avatar/Variations/AvatarExampleImageCustomization.shorthand.tsx b/docs/src/examples/components/Avatar/Variations/AvatarExampleImageCustomization.shorthand.tsx index adf8fa9f30..b6976d27a1 100644 --- a/docs/src/examples/components/Avatar/Variations/AvatarExampleImageCustomization.shorthand.tsx +++ b/docs/src/examples/components/Avatar/Variations/AvatarExampleImageCustomization.shorthand.tsx @@ -5,12 +5,20 @@ const AvatarExampleImageCustomizationShorthand = () => ( <> ( /> )) } - status={{ color: 'green', icon: 'stardust-checkmark', title: 'Available' }} + status={{ + styles: { backgroundColor: 'green' }, + icon: 'stardust-checkmark', + title: 'Available', + }} /> ) diff --git a/docs/src/examples/components/Avatar/Variations/AvatarExampleName.shorthand.tsx b/docs/src/examples/components/Avatar/Variations/AvatarExampleName.shorthand.tsx index f576f17ba0..e980efb51d 100644 --- a/docs/src/examples/components/Avatar/Variations/AvatarExampleName.shorthand.tsx +++ b/docs/src/examples/components/Avatar/Variations/AvatarExampleName.shorthand.tsx @@ -5,7 +5,7 @@ const AvatarExampleNameShorthand = () => ( (
  - +
diff --git a/docs/src/examples/components/Avatar/Variations/AvatarExampleStatusCustomization.shorthand.tsx b/docs/src/examples/components/Avatar/Variations/AvatarExampleStatusCustomization.shorthand.tsx index e9b1a537ef..08a92a0b66 100644 --- a/docs/src/examples/components/Avatar/Variations/AvatarExampleStatusCustomization.shorthand.tsx +++ b/docs/src/examples/components/Avatar/Variations/AvatarExampleStatusCustomization.shorthand.tsx @@ -5,7 +5,7 @@ const defaultAvatar = ( ( ( image={{ src: 'public/images/avatar/small/matt.jpg', alt: 'Profile picture of Matt' }} size="larger" status={{ - color: 'green', + styles: { backgroundColor: 'green' }, icon: 'stardust-checkmark', title: 'Available', }} @@ -44,7 +44,7 @@ const AvatarExampleStatusCustomizationShorthand = () => ( ( image={{ src: 'public/images/avatar/small/matt.jpg', alt: 'Profile picture of Matt' }} size="larger" status={{ - color: 'green', + styles: { backgroundColor: 'green' }, icon: 'stardust-checkmark', title: 'Available', size: 'medium', diff --git a/docs/src/examples/components/Chat/Performance/Chat.perf.tsx b/docs/src/examples/components/Chat/Performance/Chat.perf.tsx index 444354ab77..eb5d099a83 100644 --- a/docs/src/examples/components/Chat/Performance/Chat.perf.tsx +++ b/docs/src/examples/components/Chat/Performance/Chat.perf.tsx @@ -9,7 +9,7 @@ const avatars = { const janeAvatar = { image: `data:image/jpeg;base64,${avatars.ade}`, - status: { color: 'green', icon: 'stardust-checkmark' }, + status: { styles: { backgroundColor: 'green' }, icon: 'stardust-checkmark' }, } const ChatExample = () => { diff --git a/docs/src/examples/components/Chat/Performance/ChatWithPopover.perf.tsx b/docs/src/examples/components/Chat/Performance/ChatWithPopover.perf.tsx index dd5bc529e3..4799d30faf 100644 --- a/docs/src/examples/components/Chat/Performance/ChatWithPopover.perf.tsx +++ b/docs/src/examples/components/Chat/Performance/ChatWithPopover.perf.tsx @@ -17,7 +17,7 @@ const avatars = { const janeAvatar = { image: `data:image/jpeg;base64,${avatars.ade}`, - status: { color: 'green', icon: 'stardust-checkmark' }, + status: { styles: { backgroundColor: 'green' }, icon: 'stardust-checkmark' }, } export interface PopoverProps { From 4a8726024ae25227d5f2ce74d0c91590c4638bb9 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Tue, 5 Nov 2019 17:03:01 +0100 Subject: [PATCH 20/28] fixed avatar regressions, converted menu item styles in hc theme --- .../components/Menu/menuItemStyles.ts | 192 +++++++++--------- .../teams/components/Avatar/avatarStyles.ts | 70 ++++++- 2 files changed, 162 insertions(+), 100 deletions(-) diff --git a/packages/react/src/themes/teams-high-contrast/components/Menu/menuItemStyles.ts b/packages/react/src/themes/teams-high-contrast/components/Menu/menuItemStyles.ts index b4d8cfde7b..2d461b5fe4 100644 --- a/packages/react/src/themes/teams-high-contrast/components/Menu/menuItemStyles.ts +++ b/packages/react/src/themes/teams-high-contrast/components/Menu/menuItemStyles.ts @@ -1,109 +1,115 @@ -import { ComponentSlotStylesPrepared, ICSSInJSStyle } from '../../../types' +import { ComponentSelectorsAndStyles } from '../../../types' import { MenuVariables } from '../../../teams/components/Menu/menuVariables' -import { MenuItemProps, MenuItemState } from '../../../../components/Menu/MenuItem' +import { MenuItemProps } from '../../../../components/Menu/MenuItem' import { underlinedItem } from '../../../teams/components/Menu/menuItemStyles' +import { backportComponentStyle } from '../../../../lib/resolveComponentRules' -type MenuItemPropsAndState = MenuItemProps & MenuItemState - -const menuItemStyles: ComponentSlotStylesPrepared = { - wrapper: ({ props: p, variables: v }): ICSSInJSStyle => { - const { - iconOnly, - isFromKeyboard, - vertical, - active, - underlined, - primary, - pointing, - disabled, - } = p - - return { - ':hover': { - color: v.colorActive, - ...(!active && { - ...(primary && !underlined && { color: v.colorActive }), - background: v.backgroundColorFocus, - }), - }, - - ...(active && - !underlined && { - background: v.backgroundColorActive, - color: v.colorActive, - }), - - ...((iconOnly || vertical) && { - ...(isFromKeyboard && { +const menuItemStyles: ComponentSelectorsAndStyles = v => ({ + wrapper: [ + [ + { disabled: false }, + { + ':hover': { color: v.colorActive, + }, + }, + ], + [ + { disabled: false, active: false, underlined: false }, + { + ':hover': { background: v.backgroundColorFocus, - }), - - ...(active && { - color: v.colorActive, - background: v.backgroundColorActive, - }), - + }, + }, + ], + [ + { active: true, underlined: false }, + { + color: v.colorActive, + background: v.backgroundColorActive, + }, + ], + [ + [{ iconOnly: true, disabled: false }, { vertical: true, disabled: false }], + { ':hover': { - color: v.colorActive, background: v.backgroundColorFocus, }, - }), - - ...(underlined && { - ...(active && { - color: v.color, - }), + }, + ], + [ + [{ iconOnly: true, isFromKeyboard: true }, { vertical: true, isFromKeyboard: true }], + { + color: v.colorActive, + background: v.backgroundColorFocus, + }, + ], + [ + [{ iconOnly: true, active: true }, { vertical: true, active: true }], + { + color: v.colorActive, + background: v.backgroundColorActive, + }, + ], + [ + { underlined: true, disabled: false }, + { ':hover': { color: v.color, }, - ...(isFromKeyboard && { - color: v.colorActive, - }), - }), - - ...(pointing && - vertical && { - '::before': { - display: 'none', - }, - }), - - ...(disabled && { - cursor: 'default', - ':hover': { - // reset all existing hover styles + }, + ], + [{ underlined: true, active: true }, { color: v.color }], + [ + { underlined: true, isFromKeyboard: true }, + { + color: v.colorActive, + }, + ], + [ + { pointing: true, vertical: true }, + { + '::before': { + display: 'none', }, - }), - } - }, - - root: ({ props, variables: v }): ICSSInJSStyle => { - const { iconOnly, isFromKeyboard, underlined, primary, color, active } = props - - return { - ...(underlined && { - ...(active && { - color: v.color, - ...(!primary && - !color && { - ...underlinedItem(v.color), - }), - }), + }, + ], + [{ disabled: true }, { cursor: 'default' }], + ], + root: [ + [ + { underlined: true }, + { ':hover': { color: v.color, }, - ...(isFromKeyboard && { - color: v.colorActive, - }), - }), - // focus styles - ...(isFromKeyboard && - iconOnly && { - borderColor: 'transparent', - }), - } - }, -} + }, + ], + [ + { underlined: true, active: true }, + { + color: v.color, + }, + ], + [ + { underlined: true, active: true, primary: false }, + { + ...underlinedItem(v.color), + }, + ], + [ + { underlined: true, isFromKeyboard: true }, + { + color: v.colorActive, + }, + ], + [ + { isFromKeyboard: true, iconOnly: true }, + { + borderColor: 'transparent', + }, + ], + ], +}) -export default menuItemStyles +export default backportComponentStyle(menuItemStyles) diff --git a/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts b/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts index 3b4a2d1012..402cc0f812 100644 --- a/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts +++ b/packages/react/src/themes/teams/components/Avatar/avatarStyles.ts @@ -69,13 +69,69 @@ const avatarStyles: ComponentSelectorsAndStyles = // // Sizes // - [{ size: 'smallest' }, { width: v.smallest, height: v.smallest, lineHeight: v.smallest }], - [{ size: 'smaller' }, { width: v.smaller, height: v.smaller, lineHeight: v.smaller }], - [{ size: 'small' }, { width: v.small, height: v.small, lineHeight: v.small }], - [{ size: 'medium' }, { width: v.medium, height: v.medium, lineHeight: v.medium }], - [{ size: 'large' }, { width: v.large, height: v.large, lineHeight: v.large }], - [{ size: 'larger' }, { width: v.larger, height: v.larger, lineHeight: v.larger }], - [{ size: 'largest' }, { width: v.largest, height: v.largest, lineHeight: v.largest }], + [ + { size: 'smallest' }, + { + fontSize: `calc(${v.smallest} / 2.333)`, + width: v.smallest, + height: v.smallest, + lineHeight: v.smallest, + }, + ], + [ + { size: 'smaller' }, + { + fontSize: `calc(${v.smaller} / 2.333)`, + width: v.smaller, + height: v.smaller, + lineHeight: v.smaller, + }, + ], + [ + { size: 'small' }, + { + fontSize: `calc(${v.small} / 2.333)`, + width: v.small, + height: v.small, + lineHeight: v.small, + }, + ], + [ + { size: 'medium' }, + { + fontSize: `calc(${v.medium} / 2.333)`, + width: v.medium, + height: v.medium, + lineHeight: v.medium, + }, + ], + [ + { size: 'large' }, + { + fontSize: `calc(${v.large} / 2.333)`, + width: v.large, + height: v.large, + lineHeight: v.large, + }, + ], + [ + { size: 'larger' }, + { + fontSize: `calc(${v.larger} / 2.333)`, + width: v.larger, + height: v.larger, + lineHeight: v.larger, + }, + ], + [ + { size: 'largest' }, + { + fontSize: `calc(${v.largest} / 2.333)`, + width: v.largest, + height: v.largest, + lineHeight: v.largest, + }, + ], ], // ---------------------------------------- From 1b9045cd1256b1b1fbb27d2027d5de478e74116a Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Tue, 12 Nov 2019 11:01:42 +0100 Subject: [PATCH 21/28] menuColorAreas --- packages/react/package.json | 1 + packages/react/src/components/Menu/Menu.tsx | 29 +++++-- .../react/src/components/Menu/MenuDivider.tsx | 14 +++- .../react/src/components/Menu/MenuItem.tsx | 50 +++++++++--- packages/react/src/lib/classNameBuilders.ts | 21 +++++ packages/react/src/lib/felaRenderer.tsx | 3 +- packages/react/src/lib/renderComponent.tsx | 73 +++++++++++++++++ .../react/src/themes/teams/componentStyles.ts | 6 +- .../components/Menu/menuDividerStyles.ts | 4 +- .../teams/components/Menu/menuItemStyles.ts | 8 +- .../teams/components/Menu/menuStyles.ts | 5 +- packages/react/src/themes/teams/index.tsx | 78 +++++++++++++++++++ yarn.lock | 24 ++++++ 13 files changed, 284 insertions(+), 32 deletions(-) create mode 100644 packages/react/src/lib/classNameBuilders.ts diff --git a/packages/react/package.json b/packages/react/package.json index cb9e4a7da1..682ea8b336 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -16,6 +16,7 @@ "downshift": "3.2.14", "fast-memoize": "^2.5.1", "fela": "^10.6.1", + "fela-monolithic": "^10.8.2", "fela-plugin-embedded": "^10.6.1", "fela-plugin-fallback-value": "^10.6.1", "fela-plugin-placeholder-prefixer": "^10.6.1", diff --git a/packages/react/src/components/Menu/Menu.tsx b/packages/react/src/components/Menu/Menu.tsx index aecaae9ec5..7286495f40 100644 --- a/packages/react/src/components/Menu/Menu.tsx +++ b/packages/react/src/components/Menu/Menu.tsx @@ -3,6 +3,8 @@ import * as customPropTypes from '@stardust-ui/react-proptypes' import * as _ from 'lodash' import * as PropTypes from 'prop-types' import * as React from 'react' +import { useValueAndKey, useKeyOnly } from '../../lib/classNameBuilders' +import cx from 'classnames' import { AutoControlledComponent, @@ -19,7 +21,7 @@ import { mergeComponentVariables } from '../../lib/mergeThemes' import MenuItem, { MenuItemProps } from './MenuItem' import { ReactAccessibilityBehavior } from '../../lib/accessibility/reactTypes' -import { ComponentVariablesObject, ComponentSlotStylesPrepared } from '../../themes/types' +import { ComponentVariablesObject } from '../../themes/types' import { WithAsProp, ShorthandCollection, @@ -167,7 +169,7 @@ class Menu extends AutoControlledComponent, MenuState> { }) renderItems = ( - styles: ComponentSlotStylesPrepared, + propsClasses: string, variables: ComponentVariablesObject, accessibility: ReactAccessibilityBehavior, ) => { @@ -198,11 +200,10 @@ class Menu extends AutoControlledComponent, MenuState> { if (kind === 'divider') { return MenuDivider.create(item, { defaultProps: { - className: Menu.slotClassNames.divider, + className: cx(Menu.slotClassNames.divider, propsClasses), primary, secondary, vertical, - styles: styles.divider, inSubmenu: submenu, accessibility: accessibility.childBehaviors ? accessibility.childBehaviors.divider @@ -216,7 +217,7 @@ class Menu extends AutoControlledComponent, MenuState> { return MenuItem.create(item, { defaultProps: { - className: Menu.slotClassNames.item, + className: cx(Menu.slotClassNames.item, propsClasses), iconOnly, pills, pointing, @@ -240,15 +241,27 @@ class Menu extends AutoControlledComponent, MenuState> { } renderComponent({ ElementType, classes, accessibility, styles, variables, unhandledProps }) { - const { children } = this.props + const { children, primary, iconOnly, vertical, pills, pointing, underlined } = this.props + + const propClasses = cx( + useKeyOnly(primary, 'primary'), + useKeyOnly(iconOnly, 'iconOnly'), + useKeyOnly(vertical, 'vertical'), + useKeyOnly(pills, 'pills'), + useKeyOnly(underlined, 'underlined'), + useValueAndKey(pointing, 'pointing'), + ) + return ( - {childrenExist(children) ? children : this.renderItems(styles, variables, accessibility)} + {childrenExist(children) + ? children + : this.renderItems(propClasses, variables, accessibility)} ) } diff --git a/packages/react/src/components/Menu/MenuDivider.tsx b/packages/react/src/components/Menu/MenuDivider.tsx index dc689a0332..aa0a79f416 100644 --- a/packages/react/src/components/Menu/MenuDivider.tsx +++ b/packages/react/src/components/Menu/MenuDivider.tsx @@ -1,6 +1,8 @@ import { Accessibility, menuDividerBehavior } from '@stardust-ui/accessibility' import * as React from 'react' import * as PropTypes from 'prop-types' +import cx from 'classnames' +import { useKeyOnly } from '../../lib/classNameBuilders' import { createShorthandFactory, @@ -49,14 +51,22 @@ class MenuDivider extends UIComponent> { } renderComponent({ ElementType, classes, unhandledProps, accessibility }) { - const { children, content } = this.props + const { children, content, primary, secondary, vertical, inSubmenu } = this.props + + const propClasses = cx( + useKeyOnly(primary, 'primary'), + useKeyOnly(secondary, 'secondary'), + useKeyOnly(vertical, 'vertical'), + useKeyOnly(inSubmenu, 'inSubmenu'), + useKeyOnly(content, 'content'), + ) return ( {childrenExist(children) ? children : content} diff --git a/packages/react/src/components/Menu/MenuItem.tsx b/packages/react/src/components/Menu/MenuItem.tsx index 1b4c9425ad..9ed767a014 100644 --- a/packages/react/src/components/Menu/MenuItem.tsx +++ b/packages/react/src/components/Menu/MenuItem.tsx @@ -7,6 +7,7 @@ import * as _ from 'lodash' import cx from 'classnames' import * as PropTypes from 'prop-types' import * as React from 'react' +import { useValueAndKey, useKeyOnly } from '../../lib/classNameBuilders' import { AutoControlledComponent, @@ -36,6 +37,9 @@ import { Popper } from '../../lib/positioner' export interface MenuItemSlotClassNames { wrapper: string submenu: string + indicator: string + icon: string + content: string } export interface MenuItemProps @@ -154,6 +158,9 @@ class MenuItem extends AutoControlledComponent, MenuIt static slotClassNames: MenuItemSlotClassNames = { submenu: `${MenuItem.className}__submenu`, wrapper: `${MenuItem.className}__wrapper`, + indicator: `${MenuItem.className}__indicator`, + icon: `${MenuItem.className}__icon`, + content: `${MenuItem.className}__content`, } static create: ShorthandFactory @@ -201,15 +208,20 @@ class MenuItem extends AutoControlledComponent, MenuIt const { children, content, - icon, + icon, // wrapper, menu, - primary, + primary, // secondary, - active, - vertical, + active, // + vertical, // indicator, - disabled, + disabled, // + iconOnly, // + pointing, + pills, + underlined, + inSubmenu, } = this.props const { menuOpen } = this.state @@ -217,12 +229,24 @@ class MenuItem extends AutoControlledComponent, MenuIt const indicatorWithDefaults = indicator === undefined ? defaultIndicator : indicator const targetRef = toRefObject(this.context.target) + const propClasses = cx( + useKeyOnly(primary, 'primary'), + useKeyOnly(iconOnly, 'iconOnly'), + useKeyOnly(disabled, 'disabled'), + useKeyOnly(vertical, 'vertical'), + useKeyOnly(active, 'active'), + useKeyOnly(pills, 'pills'), + useKeyOnly(underlined, 'underlined'), + useKeyOnly(inSubmenu, 'inSubmenu'), + useValueAndKey(pointing, 'pointing'), + ) + const menuItemInner = childrenExist(children) ? ( children ) : ( , MenuIt Icon.create(this.props.icon, { defaultProps: { xSpacing: !!content ? 'after' : 'none', - styles: styles.icon, + className: cx(MenuItem.slotClassNames.icon, propClasses), }, })} {Box.create(content, { - defaultProps: { as: 'span', styles: styles.content }, + defaultProps: { + as: 'span', + className: cx(MenuItem.slotClassNames.content, propClasses), + }, })} {menu && Icon.create(indicatorWithDefaults, { defaultProps: { + className: cx(MenuItem.slotClassNames.indicator, propClasses), name: vertical ? 'stardust-menu-arrow-end' : 'stardust-menu-arrow-down', - styles: styles.indicator, + // styles: styles.indicator, }, })} @@ -264,7 +292,7 @@ class MenuItem extends AutoControlledComponent, MenuIt {Menu.create(menu, { defaultProps: { accessibility: submenuBehavior, - className: MenuItem.slotClassNames.submenu, + className: cx(MenuItem.slotClassNames.submenu, propClasses), vertical: true, primary, secondary, @@ -282,7 +310,7 @@ class MenuItem extends AutoControlledComponent, MenuIt if (wrapper) { return Box.create(wrapper, { defaultProps: { - className: cx(MenuItem.slotClassNames.wrapper, classes.wrapper), + className: cx(MenuItem.slotClassNames.wrapper, propClasses), ...accessibility.attributes.wrapper, ...applyAccessibilityKeyHandlers(accessibility.keyHandlers.wrapper, wrapper), }, diff --git a/packages/react/src/lib/classNameBuilders.ts b/packages/react/src/lib/classNameBuilders.ts new file mode 100644 index 0000000000..5bf36c1f32 --- /dev/null +++ b/packages/react/src/lib/classNameBuilders.ts @@ -0,0 +1,21 @@ +/** + * Props where only the prop key is used in the className. + * @param {*} val A props value + * @param {string} key A props key + * + * @example + *