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 7e13489d6cc..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,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 { SwatchFamilyResolver } 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: SwatchFamilyResolver;
}
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: 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..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,15 +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,
- neutralOutlineActive,
- neutralOutlineHover,
- neutralOutlineRest,
-} 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,
@@ -21,6 +19,7 @@ import {
highContrastSelected,
highContrastSelector,
} from "../utilities/high-contrast";
+import { active, hover, rest } from "../utilities/color/common";
const styles: ComponentStyles = {
...baseButton,
@@ -32,7 +31,7 @@ const styles: ComponentStyles
border: format(
"{0} solid {1}",
toPx(outlineWidth),
- neutralOutlineRest
+ rest(neutralOutlineRecipe)
),
padding: format("0 {0}", horizontalSpacing(outlineWidth)),
"&:hover:enabled": {
@@ -40,7 +39,7 @@ const styles: ComponentStyles
border: format(
"{0} solid {1}",
toPx(outlineWidth),
- neutralOutlineHover
+ hover(neutralOutlineRecipe)
),
...highContrastSelected,
},
@@ -49,7 +48,7 @@ const styles: ComponentStyles
border: format(
"{0} solid {1}",
toPx(outlineWidth),
- neutralOutlineActive
+ 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 3dfd82b4918..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,6 +143,59 @@ export function swatchFamilyToSwatchRecipeFactory(
};
}
+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 rest(
+ swatchFamilyResolver: DesignSystemResolver
+): SwatchRecipe {
+ return swatchFamilyResolverToSwatchRecipeFactory(
+ SwatchFamilyType.rest,
+ swatchFamilyResolver
+ );
+}
+export function hover(
+ swatchFamilyResolver: DesignSystemResolver
+): SwatchRecipe {
+ return swatchFamilyResolverToSwatchRecipeFactory(
+ SwatchFamilyType.hover,
+ swatchFamilyResolver
+ );
+}
+export function active(
+ swatchFamilyResolver: DesignSystemResolver
+): SwatchRecipe {
+ return swatchFamilyResolverToSwatchRecipeFactory(
+ SwatchFamilyType.active,
+ swatchFamilyResolver
+ );
+}
+export function focus(
+ swatchFamilyResolver: DesignSystemResolver
+): SwatchRecipe {
+ return swatchFamilyResolverToSwatchRecipeFactory(
+ 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/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 0d94b80900c..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
@@ -1,5 +1,3 @@
-import { DesignSystem } from "../../design-system";
-import { findClosestBackgroundIndex, getSwatch, isDarkMode } from "./palette";
import {
ColorRecipe,
colorRecipeFactory,
@@ -9,54 +7,55 @@ 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
+);
+/**
+ * @deprecated
+ */
export const neutralOutline: ColorRecipe = colorRecipeFactory(
neutralOutlineAlgorithm
);
+
+/**
+ * @deprecated
+ */
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/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
+ ),
+ };
+ };
+}
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");