From 086a0aedf072896c17b449a7231424e7261fb485 Mon Sep 17 00:00:00 2001 From: Brian Heston Date: Tue, 7 Jan 2020 13:43:00 -0800 Subject: [PATCH 1/2] Initial idea for converting recipe parameters into a style provider module. --- .../src/design-system/index.ts | 14 +++++ .../src/outline-button/index.ts | 15 ++--- .../src/utilities/color/common.ts | 22 +++++++ .../src/utilities/color/neutral-outline.ts | 48 +++++++------- .../src/utilities/color/offsets-algorithm.ts | 62 +++++++++++++++++++ 5 files changed, 125 insertions(+), 36 deletions(-) create mode 100644 packages/fast-components-styles-msft/src/utilities/color/offsets-algorithm.ts diff --git a/packages/fast-components-styles-msft/src/design-system/index.ts b/packages/fast-components-styles-msft/src/design-system/index.ts index 7e13489d6cc..730b944e351 100644 --- a/packages/fast-components-styles-msft/src/design-system/index.ts +++ b/packages/fast-components-styles-msft/src/design-system/index.ts @@ -11,6 +11,8 @@ import { FontWeight } from "../utilities/fonts"; import designSystemSchema from "./design-system.schema"; import { accentPalette, neutralPalette } from "../default-palette"; import { isFunction } from "lodash-es"; +import { ColorRecipe, colorRecipeFactory, SwatchFamily } from "../utilities/color/common"; +import { offsetsAlgorithm } from "../utilities/color/offsets-algorithm"; export const defaultFontWeights: FontWeight = { light: 100, @@ -202,6 +204,8 @@ export interface DesignSystem { neutralOutlineHoverDelta: number; neutralOutlineActiveDelta: number; neutralOutlineFocusDelta: number; + + neutralOutline: ColorRecipe; } const designSystemDefaults: DesignSystem = { @@ -270,10 +274,20 @@ const designSystemDefaults: DesignSystem = { neutralDividerRestDelta: 8, + /** + * These would be deprecated / removed + */ neutralOutlineRestDelta: 25, neutralOutlineHoverDelta: 40, neutralOutlineActiveDelta: 16, neutralOutlineFocusDelta: 25, + + /** + * Recipes would be configured more like this. Is there a pattern we've used + * to define interface types like this in the schema instead of the properties + * that go into it? + */ + neutralOutline: colorRecipeFactory(offsetsAlgorithm(neutralPalette, 25, 40, 16, 25)), }; /** diff --git a/packages/fast-components-styles-msft/src/outline-button/index.ts b/packages/fast-components-styles-msft/src/outline-button/index.ts index 52f773ba513..c684fd14bb2 100644 --- a/packages/fast-components-styles-msft/src/outline-button/index.ts +++ b/packages/fast-components-styles-msft/src/outline-button/index.ts @@ -3,13 +3,7 @@ import { ComponentStyles } from "@microsoft/fast-jss-manager"; import { applyFocusVisible, format, subtract, toPx } from "@microsoft/fast-jss-utilities"; import { DesignSystem } from "../design-system"; import { baseButton, buttonStyles } from "../patterns/button"; -import { - neutralFocus, - neutralForegroundRest, - neutralOutlineActive, - neutralOutlineHover, - neutralOutlineRest, -} from "../utilities/color"; +import { neutralFocus, neutralForegroundRest, neutralOutline } from "../utilities/color"; import { horizontalSpacing } from "../utilities/density"; import { focusOutlineWidth, outlineWidth } from "../utilities/design-system"; import { @@ -21,6 +15,7 @@ import { highContrastSelected, highContrastSelector, } from "../utilities/high-contrast"; +import { active, hover, rest } from "../utilities/color/common"; const styles: ComponentStyles = { ...baseButton, @@ -32,7 +27,7 @@ const styles: ComponentStyles border: format( "{0} solid {1}", toPx(outlineWidth), - neutralOutlineRest + rest(neutralOutline) ), padding: format("0 {0}", horizontalSpacing(outlineWidth)), "&:hover:enabled": { @@ -40,7 +35,7 @@ const styles: ComponentStyles border: format( "{0} solid {1}", toPx(outlineWidth), - neutralOutlineHover + hover(neutralOutline) ), ...highContrastSelected, }, @@ -49,7 +44,7 @@ const styles: ComponentStyles border: format( "{0} solid {1}", toPx(outlineWidth), - neutralOutlineActive + active(neutralOutline) ), }, ...applyFocusVisible({ diff --git a/packages/fast-components-styles-msft/src/utilities/color/common.ts b/packages/fast-components-styles-msft/src/utilities/color/common.ts index 3dfd82b4918..7742b669aaa 100644 --- a/packages/fast-components-styles-msft/src/utilities/color/common.ts +++ b/packages/fast-components-styles-msft/src/utilities/color/common.ts @@ -143,6 +143,28 @@ export function swatchFamilyToSwatchRecipeFactory( }; } +export function rest(swatchFamilyResolver: SwatchFamilyResolver): SwatchRecipe { + return swatchFamilyToSwatchRecipeFactory(SwatchFamilyType.rest, swatchFamilyResolver); +} +export function hover(swatchFamilyResolver: SwatchFamilyResolver): SwatchRecipe { + return swatchFamilyToSwatchRecipeFactory( + SwatchFamilyType.hover, + swatchFamilyResolver + ); +} +export function active(swatchFamilyResolver: SwatchFamilyResolver): SwatchRecipe { + return swatchFamilyToSwatchRecipeFactory( + SwatchFamilyType.active, + swatchFamilyResolver + ); +} +export function focus(swatchFamilyResolver: SwatchFamilyResolver): SwatchRecipe { + return swatchFamilyToSwatchRecipeFactory( + SwatchFamilyType.focus, + swatchFamilyResolver + ); +} + /** * Converts a color string into a ColorRGBA64 instance. * Supports #RRGGBB and rgb(r, g, b) formats diff --git a/packages/fast-components-styles-msft/src/utilities/color/neutral-outline.ts b/packages/fast-components-styles-msft/src/utilities/color/neutral-outline.ts index 0d94b80900c..0496c6a5924 100644 --- a/packages/fast-components-styles-msft/src/utilities/color/neutral-outline.ts +++ b/packages/fast-components-styles-msft/src/utilities/color/neutral-outline.ts @@ -1,5 +1,3 @@ -import { DesignSystem } from "../../design-system"; -import { findClosestBackgroundIndex, getSwatch, isDarkMode } from "./palette"; import { ColorRecipe, colorRecipeFactory, @@ -9,53 +7,51 @@ import { SwatchFamilyType, SwatchRecipe, } from "./common"; +import { offsetsAlgorithm } from "./offsets-algorithm"; +import { neutralPalette } from "../../default-palette"; import { neutralOutlineActiveDelta, neutralOutlineFocusDelta, neutralOutlineHoverDelta, neutralOutlineRestDelta, - neutralPalette, } from "../design-system"; -const neutralOutlineAlgorithm: SwatchFamilyResolver = ( - designSystem: DesignSystem -): SwatchFamily => { - const palette: string[] = neutralPalette(designSystem); - const backgroundIndex: number = findClosestBackgroundIndex(designSystem); - const direction: 1 | -1 = isDarkMode(designSystem) ? -1 : 1; - - const restDelta: number = neutralOutlineRestDelta(designSystem); - const restIndex: number = backgroundIndex + direction * restDelta; - const hoverDelta: number = neutralOutlineHoverDelta(designSystem); - const hoverIndex: number = restIndex + direction * (hoverDelta - restDelta); - const activeDelta: number = neutralOutlineActiveDelta(designSystem); - const activeIndex: number = restIndex + direction * (activeDelta - restDelta); - const focusDelta: number = neutralOutlineFocusDelta(designSystem); - const focusIndex: number = restIndex + direction * (focusDelta - restDelta); - - return { - rest: getSwatch(restIndex, palette), - hover: getSwatch(hoverIndex, palette), - active: getSwatch(activeIndex, palette), - focus: getSwatch(focusIndex, palette), - }; -}; +const neutralOutlineAlgorithm: SwatchFamilyResolver = offsetsAlgorithm( + neutralPalette, + neutralOutlineRestDelta, + neutralOutlineHoverDelta, + neutralOutlineActiveDelta, + neutralOutlineFocusDelta +); export const neutralOutline: ColorRecipe = colorRecipeFactory( neutralOutlineAlgorithm ); + +/** + * @deprecated + */ export const neutralOutlineRest: SwatchRecipe = swatchFamilyToSwatchRecipeFactory( SwatchFamilyType.rest, neutralOutline ); +/** + * @deprecated + */ export const neutralOutlineHover: SwatchRecipe = swatchFamilyToSwatchRecipeFactory( SwatchFamilyType.hover, neutralOutline ); +/** + * @deprecated + */ export const neutralOutlineActive: SwatchRecipe = swatchFamilyToSwatchRecipeFactory( SwatchFamilyType.active, neutralOutline ); +/** + * @deprecated + */ export const neutralOutlineFocus: SwatchRecipe = swatchFamilyToSwatchRecipeFactory( SwatchFamilyType.focus, neutralOutline diff --git a/packages/fast-components-styles-msft/src/utilities/color/offsets-algorithm.ts b/packages/fast-components-styles-msft/src/utilities/color/offsets-algorithm.ts new file mode 100644 index 00000000000..4ef8cf9921d --- /dev/null +++ b/packages/fast-components-styles-msft/src/utilities/color/offsets-algorithm.ts @@ -0,0 +1,62 @@ +import { + checkDesignSystemResolver, + DesignSystem, + DesignSystemResolver, +} from "../../design-system"; +import { SwatchFamily, SwatchFamilyResolver } from "./common"; +import { findClosestBackgroundIndex, getSwatch, isDarkMode, Palette } from "./palette"; + +/** + * Function to derive colors from offset configuration. + */ +export function offsetsAlgorithm( + palette: Palette | DesignSystemResolver, + restDelta: number | DesignSystemResolver, + hoverDelta: number | DesignSystemResolver, + activeDelta: number | DesignSystemResolver, + focusDelta: number | DesignSystemResolver +): SwatchFamilyResolver { + return (designSystem: DesignSystem): SwatchFamily => { + const resolvedPalette: Palette = checkDesignSystemResolver(palette, designSystem); + + const backgroundIndex: number = findClosestBackgroundIndex(designSystem); + + const direction: 1 | -1 = isDarkMode(designSystem) ? -1 : 1; + + const resolvedRestDelta: number = checkDesignSystemResolver( + restDelta, + designSystem + ); + const resolvedHoverDelta: number = checkDesignSystemResolver( + hoverDelta, + designSystem + ); + const resolvedActiveDelta: number = checkDesignSystemResolver( + activeDelta, + designSystem + ); + const resolvedFocusDelta: number = checkDesignSystemResolver( + focusDelta, + designSystem + ); + + return { + rest: getSwatch( + backgroundIndex + direction * resolvedRestDelta, + resolvedPalette + ), + hover: getSwatch( + backgroundIndex + direction * resolvedHoverDelta, + resolvedPalette + ), + active: getSwatch( + backgroundIndex + direction * resolvedActiveDelta, + resolvedPalette + ), + focus: getSwatch( + backgroundIndex + direction * resolvedFocusDelta, + resolvedPalette + ), + }; + }; +} From c5a5dd92dc47b939c4e982098015873fe2af37b0 Mon Sep 17 00:00:00 2001 From: Brian Heston Date: Tue, 14 Jan 2020 17:09:09 -0800 Subject: [PATCH 2/2] Added illustration of recipe customization. Does not work though. --- .../outline-button/outline-button.stories.tsx | 24 +++++++++- .../src/design-system/index.ts | 6 +-- .../src/outline-button/index.ts | 14 ++++-- .../src/utilities/color/common.ts | 47 +++++++++++++++---- .../src/utilities/color/index.ts | 1 + .../src/utilities/color/neutral-outline.ts | 11 +++-- .../src/utilities/design-system.ts | 5 ++ 7 files changed, 87 insertions(+), 21 deletions(-) diff --git a/packages/fast-components-react-msft/src/outline-button/outline-button.stories.tsx b/packages/fast-components-react-msft/src/outline-button/outline-button.stories.tsx index 226d7287004..e14fd706d39 100644 --- a/packages/fast-components-react-msft/src/outline-button/outline-button.stories.tsx +++ b/packages/fast-components-react-msft/src/outline-button/outline-button.stories.tsx @@ -2,6 +2,14 @@ import { storiesOf } from "@storybook/react"; import React from "react"; import { OutlineButton } from "./"; import { glyphFactory, SVGGlyph } from "../../assets/svg-element"; +import { DesignSystemProvider } from "@microsoft/fast-jss-manager-react"; +import { + accentPalette, + DesignSystem, + DesignSystemDefaults, + offsetsAlgorithm, +} from "@microsoft/fast-components-styles-msft"; +import { colorRecipeFactory } from "@microsoft/fast-components-styles-msft/dist/utilities/color/common"; storiesOf("Outline button", module) .add("Default", () => Outline button) @@ -48,4 +56,18 @@ storiesOf("Outline button", module) > Disabled outline anchor button - )); + )) + .add("Alternate style", () => { + const alternateDesignSystem: DesignSystem = Object.assign( + {}, + DesignSystemDefaults, + { + neutralOutline: offsetsAlgorithm(accentPalette, 10, 40, 16, 50), + } + ); + return ( + + Alternate style outline button + + ); + }); diff --git a/packages/fast-components-styles-msft/src/design-system/index.ts b/packages/fast-components-styles-msft/src/design-system/index.ts index 730b944e351..4516130abbc 100644 --- a/packages/fast-components-styles-msft/src/design-system/index.ts +++ b/packages/fast-components-styles-msft/src/design-system/index.ts @@ -11,7 +11,7 @@ import { FontWeight } from "../utilities/fonts"; import designSystemSchema from "./design-system.schema"; import { accentPalette, neutralPalette } from "../default-palette"; import { isFunction } from "lodash-es"; -import { ColorRecipe, colorRecipeFactory, SwatchFamily } from "../utilities/color/common"; +import { SwatchFamilyResolver } from "../utilities/color/common"; import { offsetsAlgorithm } from "../utilities/color/offsets-algorithm"; export const defaultFontWeights: FontWeight = { @@ -205,7 +205,7 @@ export interface DesignSystem { neutralOutlineActiveDelta: number; neutralOutlineFocusDelta: number; - neutralOutline: ColorRecipe; + neutralOutline: SwatchFamilyResolver; } const designSystemDefaults: DesignSystem = { @@ -287,7 +287,7 @@ const designSystemDefaults: DesignSystem = { * to define interface types like this in the schema instead of the properties * that go into it? */ - neutralOutline: colorRecipeFactory(offsetsAlgorithm(neutralPalette, 25, 40, 16, 25)), + neutralOutline: offsetsAlgorithm(neutralPalette, 25, 40, 16, 25), }; /** diff --git a/packages/fast-components-styles-msft/src/outline-button/index.ts b/packages/fast-components-styles-msft/src/outline-button/index.ts index c684fd14bb2..8e36c795032 100644 --- a/packages/fast-components-styles-msft/src/outline-button/index.ts +++ b/packages/fast-components-styles-msft/src/outline-button/index.ts @@ -3,9 +3,13 @@ import { ComponentStyles } from "@microsoft/fast-jss-manager"; import { applyFocusVisible, format, subtract, toPx } from "@microsoft/fast-jss-utilities"; import { DesignSystem } from "../design-system"; import { baseButton, buttonStyles } from "../patterns/button"; -import { neutralFocus, neutralForegroundRest, neutralOutline } from "../utilities/color"; +import { neutralFocus, neutralForegroundRest } from "../utilities/color"; import { horizontalSpacing } from "../utilities/density"; -import { focusOutlineWidth, outlineWidth } from "../utilities/design-system"; +import { + focusOutlineWidth, + neutralOutlineRecipe, + outlineWidth, +} from "../utilities/design-system"; import { highContrastDisabledBorder, highContrastLinkBorder, @@ -27,7 +31,7 @@ const styles: ComponentStyles border: format( "{0} solid {1}", toPx(outlineWidth), - rest(neutralOutline) + rest(neutralOutlineRecipe) ), padding: format("0 {0}", horizontalSpacing(outlineWidth)), "&:hover:enabled": { @@ -35,7 +39,7 @@ const styles: ComponentStyles border: format( "{0} solid {1}", toPx(outlineWidth), - hover(neutralOutline) + hover(neutralOutlineRecipe) ), ...highContrastSelected, }, @@ -44,7 +48,7 @@ const styles: ComponentStyles border: format( "{0} solid {1}", toPx(outlineWidth), - active(neutralOutline) + active(neutralOutlineRecipe) ), }, ...applyFocusVisible({ diff --git a/packages/fast-components-styles-msft/src/utilities/color/common.ts b/packages/fast-components-styles-msft/src/utilities/color/common.ts index 7742b669aaa..8b98da817e5 100644 --- a/packages/fast-components-styles-msft/src/utilities/color/common.ts +++ b/packages/fast-components-styles-msft/src/utilities/color/common.ts @@ -143,23 +143,54 @@ export function swatchFamilyToSwatchRecipeFactory( }; } -export function rest(swatchFamilyResolver: SwatchFamilyResolver): SwatchRecipe { - return swatchFamilyToSwatchRecipeFactory(SwatchFamilyType.rest, swatchFamilyResolver); +function swatchFamilyResolverToSwatchRecipeFactory( + type: keyof T, + callback: DesignSystemResolver> +): SwatchRecipe { + const memoizedRecipe: typeof callback = memoize(callback); + return (arg: DesignSystem | SwatchResolver): any => { + if (typeof arg === "function") { + return (designSystem: DesignSystem): Swatch => { + return memoizedRecipe( + Object.assign({}, designSystem, { + backgroundColor: arg(designSystem), + }) + )(designSystem)[type as string]; + }; + } else { + return memoizedRecipe(arg)(arg)[type]; + } + }; } -export function hover(swatchFamilyResolver: SwatchFamilyResolver): SwatchRecipe { - return swatchFamilyToSwatchRecipeFactory( + +export function rest( + swatchFamilyResolver: DesignSystemResolver +): SwatchRecipe { + return swatchFamilyResolverToSwatchRecipeFactory( + SwatchFamilyType.rest, + swatchFamilyResolver + ); +} +export function hover( + swatchFamilyResolver: DesignSystemResolver +): SwatchRecipe { + return swatchFamilyResolverToSwatchRecipeFactory( SwatchFamilyType.hover, swatchFamilyResolver ); } -export function active(swatchFamilyResolver: SwatchFamilyResolver): SwatchRecipe { - return swatchFamilyToSwatchRecipeFactory( +export function active( + swatchFamilyResolver: DesignSystemResolver +): SwatchRecipe { + return swatchFamilyResolverToSwatchRecipeFactory( SwatchFamilyType.active, swatchFamilyResolver ); } -export function focus(swatchFamilyResolver: SwatchFamilyResolver): SwatchRecipe { - return swatchFamilyToSwatchRecipeFactory( +export function focus( + swatchFamilyResolver: DesignSystemResolver +): SwatchRecipe { + return swatchFamilyResolverToSwatchRecipeFactory( SwatchFamilyType.focus, swatchFamilyResolver ); diff --git a/packages/fast-components-styles-msft/src/utilities/color/index.ts b/packages/fast-components-styles-msft/src/utilities/color/index.ts index 85421a7804f..70c268824c8 100644 --- a/packages/fast-components-styles-msft/src/utilities/color/index.ts +++ b/packages/fast-components-styles-msft/src/utilities/color/index.ts @@ -120,3 +120,4 @@ export { neutralFocus, neutralFocusInnerAccent } from "./neutral-focus"; export { neutralPaletteConfig, accentPaletteConfig } from "./color-constants"; export { isDarkMode, palette, PaletteType, Palette } from "./palette"; export { createColorPalette } from "./create-color-palette"; +export { offsetsAlgorithm } from "./offsets-algorithm"; diff --git a/packages/fast-components-styles-msft/src/utilities/color/neutral-outline.ts b/packages/fast-components-styles-msft/src/utilities/color/neutral-outline.ts index 0496c6a5924..e6deb37a3b4 100644 --- a/packages/fast-components-styles-msft/src/utilities/color/neutral-outline.ts +++ b/packages/fast-components-styles-msft/src/utilities/color/neutral-outline.ts @@ -24,6 +24,9 @@ const neutralOutlineAlgorithm: SwatchFamilyResolver = offsetsAlgorithm( neutralOutlineFocusDelta ); +/** + * @deprecated + */ export const neutralOutline: ColorRecipe = colorRecipeFactory( neutralOutlineAlgorithm ); @@ -33,26 +36,26 @@ export const neutralOutline: ColorRecipe = colorRecipeFactory( */ export const neutralOutlineRest: SwatchRecipe = swatchFamilyToSwatchRecipeFactory( SwatchFamilyType.rest, - neutralOutline + neutralOutlineAlgorithm ); /** * @deprecated */ export const neutralOutlineHover: SwatchRecipe = swatchFamilyToSwatchRecipeFactory( SwatchFamilyType.hover, - neutralOutline + neutralOutlineAlgorithm ); /** * @deprecated */ export const neutralOutlineActive: SwatchRecipe = swatchFamilyToSwatchRecipeFactory( SwatchFamilyType.active, - neutralOutline + neutralOutlineAlgorithm ); /** * @deprecated */ export const neutralOutlineFocus: SwatchRecipe = swatchFamilyToSwatchRecipeFactory( SwatchFamilyType.focus, - neutralOutline + neutralOutlineAlgorithm ); diff --git a/packages/fast-components-styles-msft/src/utilities/design-system.ts b/packages/fast-components-styles-msft/src/utilities/design-system.ts index f011b1e2aa3..bea6027cae7 100644 --- a/packages/fast-components-styles-msft/src/utilities/design-system.ts +++ b/packages/fast-components-styles-msft/src/utilities/design-system.ts @@ -5,6 +5,7 @@ import designSystemDefaults, { import { Palette } from "../utilities/color/palette"; import { Direction } from "@microsoft/fast-web-utilities"; import { FontWeight } from "./fonts"; +import { SwatchFamilyResolver } from "./color/common"; /** * Safely retrieves the value from a key of the DesignSystem. @@ -250,3 +251,7 @@ export const getFontWeight: DesignSystemResolver = getDesignSystemVa export const neutralOutlineFocusDelta: DesignSystemResolver< number > = getDesignSystemValue("neutralOutlineFocusDelta"); + +export const neutralOutlineRecipe: DesignSystemResolver< + SwatchFamilyResolver +> = getDesignSystemValue("neutralOutline");