Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed foregroundOnAccent recipe to work in all states #18765

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Fixed foregroundOnAccent recipe to work in all states",
"packageName": "@fluentui/web-components",
"email": "[email protected]",
"dependentChangeType": "patch"
}
18 changes: 18 additions & 0 deletions packages/web-components/docs/api-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,24 @@ export const focusStrokeOuterRecipe: DesignToken<ColorRecipe>;
// @public (undocumented)
export const focusStrokeWidth: import("@microsoft/fast-foundation").CSSDesignToken<number>;

// @public (undocumented)
export const foregroundOnAccentActive: import("@microsoft/fast-foundation").CSSDesignToken<Swatch>;

// @public (undocumented)
export const foregroundOnAccentActiveLarge: import("@microsoft/fast-foundation").CSSDesignToken<Swatch>;

// @public (undocumented)
export const foregroundOnAccentFocus: import("@microsoft/fast-foundation").CSSDesignToken<Swatch>;

// @public (undocumented)
export const foregroundOnAccentFocusLarge: import("@microsoft/fast-foundation").CSSDesignToken<Swatch>;

// @public (undocumented)
export const foregroundOnAccentHover: import("@microsoft/fast-foundation").CSSDesignToken<Swatch>;

// @public (undocumented)
export const foregroundOnAccentHoverLarge: import("@microsoft/fast-foundation").CSSDesignToken<Swatch>;

// @public (undocumented)
export const foregroundOnAccentLargeRecipe: DesignToken<ColorRecipe>;

Expand Down
59 changes: 0 additions & 59 deletions packages/web-components/src/color/recipes/accent-fill.spec.ts

This file was deleted.

17 changes: 1 addition & 16 deletions packages/web-components/src/color/recipes/accent-fill.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { inRange } from 'lodash-es';
import { Palette } from '../palette';
import { InteractiveSwatchSet } from '../recipe';
import { Swatch } from '../swatch';
Expand All @@ -10,8 +9,6 @@ export function accentFill(
palette: Palette,
neutralPalette: Palette,
reference: Swatch,
textColor: Swatch,
contrastTarget: number,
hoverDelta: number,
activeDelta: number,
focusDelta: number,
Expand All @@ -23,21 +20,9 @@ export function accentFill(
const referenceIndex = neutralPalette.closestIndexOf(reference);
const swapThreshold = Math.max(neutralFillRestDelta, neutralFillHoverDelta, neutralFillActiveDelta);
const direction = referenceIndex >= swapThreshold ? -1 : 1;
const paletteLength = palette.swatches.length;
const maxIndex = paletteLength - 1;
const accentIndex = palette.closestIndexOf(accent);
let accessibleOffset = 0;

while (
accessibleOffset < direction * hoverDelta &&
inRange(accentIndex + accessibleOffset + direction, 0, paletteLength) &&
textColor.contrast(palette.get(accentIndex + accessibleOffset + direction)) >= contrastTarget &&
inRange(accentIndex + accessibleOffset + direction + direction, 0, maxIndex)
) {
accessibleOffset += direction;
}

const hoverIndex = accentIndex + accessibleOffset;
const hoverIndex = accentIndex;
const restIndex = hoverIndex + direction * -1 * hoverDelta;
const activeIndex = restIndex + direction * activeDelta;
const focusIndex = restIndex + direction * focusDelta;
Expand Down
104 changes: 69 additions & 35 deletions packages/web-components/src/design-tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,47 +231,12 @@ enum ContrastTarget {
large = 7,
}

// Foreground On Accent
const foregroundOnAccentByContrast = (contrast: number) => (element: HTMLElement, reference?: Swatch) =>
foregroundOnAccentAlgorithm(reference || fillColor.getValueFor(element), contrast);
/** @public */
export const foregroundOnAccentRecipe = create<ColorRecipe>({
name: 'foreground-on-accent-recipe',
cssCustomPropertyName: null,
}).withDefault({
evaluate: (element: HTMLElement, reference?: Swatch): Swatch =>
foregroundOnAccentByContrast(ContrastTarget.normal)(element, reference),
});
/** @public */
export const foregroundOnAccentLargeRecipe = create<ColorRecipe>({
name: 'foreground-on-accent-large-recipe',
cssCustomPropertyName: null,
}).withDefault({
evaluate: (element: HTMLElement, reference?: Swatch): Swatch =>
foregroundOnAccentByContrast(ContrastTarget.large)(element, reference),
});

/** @public */
export const foregroundOnAccentRest = create<Swatch>('foreground-on-accent-rest').withDefault((element: HTMLElement) =>
foregroundOnAccentRecipe.getValueFor(element).evaluate(element),
);
/** @public @deprecated Use foregroundOnAccentRest */
export const accentForegroundCut = foregroundOnAccentRest;
/** @public */
export const foregroundOnAccentRestLarge = create<Swatch>(
'foreground-on-accent-rest-large',
).withDefault((element: HTMLElement) => foregroundOnAccentLargeRecipe.getValueFor(element).evaluate(element));
/** @public @deprecated Use foregroundOnAccentRestLarge */
export const accentForegroundCutLarge = foregroundOnAccentRestLarge;

// Accent Fill
const accentFillByContrast = (contrast: number) => (element: HTMLElement, reference?: Swatch) =>
accentFillAlgorithm(
accentPalette.getValueFor(element),
neutralPalette.getValueFor(element),
reference || fillColor.getValueFor(element),
foregroundOnAccentRest.getValueFor(element),
contrast,
accentFillHoverDelta.getValueFor(element),
accentFillActiveDelta.getValueFor(element),
accentFillFocusDelta.getValueFor(element),
Expand Down Expand Up @@ -305,6 +270,75 @@ export const accentFillFocus = create<Swatch>('accent-fill-focus').withDefault((
return accentFillRecipe.getValueFor(element).evaluate(element).focus;
});

// Foreground On Accent
const foregroundOnAccentByContrast = (contrast: number) => (element: HTMLElement, reference?: Swatch) =>
foregroundOnAccentAlgorithm(reference || accentFillRest.getValueFor(element), contrast);
/** @public */
export const foregroundOnAccentRecipe = create<ColorRecipe>({
name: 'foreground-on-accent-recipe',
cssCustomPropertyName: null,
}).withDefault({
evaluate: (element: HTMLElement, reference?: Swatch): Swatch =>
foregroundOnAccentByContrast(ContrastTarget.normal)(element, reference),
});
/** @public */
export const foregroundOnAccentRest = create<Swatch>('foreground-on-accent-rest').withDefault((element: HTMLElement) =>
foregroundOnAccentRecipe.getValueFor(element).evaluate(element, accentFillRest.getValueFor(element)),
);
/** @public @deprecated Use foregroundOnAccentRest */
export const accentForegroundCut = foregroundOnAccentRest;
/** @public */
export const foregroundOnAccentHover = create<Swatch>(
'foreground-on-accent-hover',
).withDefault((element: HTMLElement) =>
foregroundOnAccentRecipe.getValueFor(element).evaluate(element, accentFillHover.getValueFor(element)),
);
/** @public */
export const foregroundOnAccentActive = create<Swatch>(
'foreground-on-accent-active',
).withDefault((element: HTMLElement) =>
foregroundOnAccentRecipe.getValueFor(element).evaluate(element, accentFillActive.getValueFor(element)),
);
/** @public */
export const foregroundOnAccentFocus = create<Swatch>(
'foreground-on-accent-focus',
).withDefault((element: HTMLElement) =>
foregroundOnAccentRecipe.getValueFor(element).evaluate(element, accentFillFocus.getValueFor(element)),
);

/** @public */
export const foregroundOnAccentLargeRecipe = create<ColorRecipe>({
name: 'foreground-on-accent-large-recipe',
cssCustomPropertyName: null,
}).withDefault({
evaluate: (element: HTMLElement, reference?: Swatch): Swatch =>
foregroundOnAccentByContrast(ContrastTarget.large)(element, reference),
});
/** @public */
export const foregroundOnAccentRestLarge = create<Swatch>(
'foreground-on-accent-rest-large',
).withDefault((element: HTMLElement) => foregroundOnAccentLargeRecipe.getValueFor(element).evaluate(element));
/** @public @deprecated Use foregroundOnAccentRestLarge */
export const accentForegroundCutLarge = foregroundOnAccentRestLarge;
/** @public */
export const foregroundOnAccentHoverLarge = create<Swatch>(
'foreground-on-accent-hover-large',
).withDefault((element: HTMLElement) =>
foregroundOnAccentLargeRecipe.getValueFor(element).evaluate(element, accentFillHover.getValueFor(element)),
);
/** @public */
export const foregroundOnAccentActiveLarge = create<Swatch>(
'foreground-on-accent-active-large',
).withDefault((element: HTMLElement) =>
foregroundOnAccentLargeRecipe.getValueFor(element).evaluate(element, accentFillActive.getValueFor(element)),
);
/** @public */
export const foregroundOnAccentFocusLarge = create<Swatch>(
'foreground-on-accent-focus-large',
).withDefault((element: HTMLElement) =>
foregroundOnAccentLargeRecipe.getValueFor(element).evaluate(element, accentFillFocus.getValueFor(element)),
);

// Accent Foreground
const accentForegroundByContrast = (contrast: number) => (element: HTMLElement, reference?: Swatch) =>
accentForegroundAlgorithm(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
import { css, ElementStyles } from '@microsoft/fast-element';
import { disabledCursor, display, ElementDefinitionContext, focusVisible, forcedColorsStylesheetBehavior, FoundationElementDefinition } from '@microsoft/fast-foundation';
import {
disabledCursor,
display,
ElementDefinitionContext,
focusVisible,
forcedColorsStylesheetBehavior,
FoundationElementDefinition,
} from '@microsoft/fast-foundation';
import { SystemColors } from '@microsoft/fast-web-utilities';
import { heightNumber } from '../styles/size';
import {
accentFillActive,
accentFillFocus,
accentFillHover,
accentFillRest,
bodyFont,
controlCornerRadius,
designUnit,
disabledOpacity,
focusStrokeInner,
focusStrokeOuter,
focusStrokeWidth,
foregroundOnAccentActive,
foregroundOnAccentFocus,
foregroundOnAccentHover,
foregroundOnAccentRest,
neutralFillActive,
neutralFillHover,
Expand All @@ -20,7 +32,10 @@ import {
typeRampBaseLineHeight,
} from '../design-tokens';

export const optionStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition) => ElementStyles = (context: ElementDefinitionContext, definition: FoundationElementDefinition) =>
export const optionStyles: (
context: ElementDefinitionContext,
definition: FoundationElementDefinition,
) => ElementStyles = (context: ElementDefinitionContext, definition: FoundationElementDefinition) =>
css`
${display('inline-flex')} :host {
font-family: ${bodyFont};
Expand All @@ -45,18 +60,23 @@ export const optionStyles: (context: ElementDefinitionContext, definition: Found
:host(:${focusVisible}) {
box-shadow: 0 0 0 calc(${focusStrokeWidth} * 1px) inset ${focusStrokeInner};
border-color: ${focusStrokeOuter};
background: ${accentFillHover};
color: ${foregroundOnAccentRest};
background: ${accentFillFocus};
color: ${foregroundOnAccentFocus};
}

:host([aria-selected="true"]) {
background: ${accentFillHover};
background: ${accentFillRest};
color: ${foregroundOnAccentRest};
}

:host(:hover) {
background: ${accentFillHover};
color: ${foregroundOnAccentHover};
}

:host(:active) {
background: ${accentFillActive};
color: ${foregroundOnAccentRest};
color: ${foregroundOnAccentActive};
}

:host(:not([aria-selected="true"]):hover) {
Expand Down
22 changes: 16 additions & 6 deletions packages/web-components/src/select/select.styles.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import { css, ElementStyles } from '@microsoft/fast-element';
import { disabledCursor, display, ElementDefinitionContext, focusVisible, forcedColorsStylesheetBehavior, SelectOptions } from '@microsoft/fast-foundation';
import {
disabledCursor,
display,
ElementDefinitionContext,
focusVisible,
forcedColorsStylesheetBehavior,
SelectOptions,
} from '@microsoft/fast-foundation';
import { SystemColors } from '@microsoft/fast-web-utilities';
import { elevation } from '../styles/elevation';
import { heightNumber } from '../styles/size';
import { appearanceBehavior } from '../utilities/behaviors';
import {
accentFillHover,
accentForegroundCut,
accentFillFocus,
bodyFont,
controlCornerRadius,
designUnit,
disabledOpacity,
focusStrokeInner,
focusStrokeOuter,
foregroundOnAccentFocus,
neutralFillHover,
neutralFillInputActive,
neutralFillInputHover,
Expand All @@ -29,7 +36,10 @@ import {
typeRampBaseLineHeight,
} from '../design-tokens';

export const selectFilledStyles: (context: ElementDefinitionContext, definition: SelectOptions) => ElementStyles = (context: ElementDefinitionContext, definition: SelectOptions) => css`
export const selectFilledStyles: (context: ElementDefinitionContext, definition: SelectOptions) => ElementStyles = (
context: ElementDefinitionContext,
definition: SelectOptions,
) => css`
:host([appearance="filled"]) {
background: ${neutralFillRest};
border-color: transparent;
Expand Down Expand Up @@ -121,8 +131,8 @@ export const selectStyles = (context, definition) =>
:host(:${focusVisible}) ::slotted([aria-selected="true"][role="option"]:not([disabled])) {
box-shadow: 0 0 0 calc(var(--focus-outline-width) * 1px) inset ${focusStrokeInner};
border-color: ${focusStrokeOuter};
background: ${accentFillHover};
color: ${accentForegroundCut};
background: ${accentFillFocus};
color: ${foregroundOnAccentFocus};
}

:host([disabled]) {
Expand Down
Loading