From 5304d1149247595dba5c991fe62d8dc500ac8002 Mon Sep 17 00:00:00 2001 From: Brian Heston <47367562+bheston@users.noreply.github.com> Date: Thu, 20 Oct 2022 15:38:03 -0700 Subject: [PATCH] (web-components) Cleaned up shared styles for button and input for improved reuse and color updates (#24929) * Cleaned up shared styles for button and input for improved reuse and color updates * Change file * Remove underscore update on internals. * Fix lint issues --- ...-4bde24b4-312c-47f7-bbd5-003938181433.json | 7 + packages/web-components/docs/api-report.md | 137 ++----- .../src/anchor/anchor.styles.ts | 24 +- .../src/button/button.styles.ts | 89 +---- .../src/combobox/combobox.stories.ts | 9 +- .../src/combobox/combobox.styles.ts | 60 ++- .../src/number-field/number-field.styles.ts | 39 +- .../src/search/search.styles.ts | 41 +- .../src/select/select.stories.ts | 4 +- .../src/select/select.styles.ts | 185 +++------ .../src/styles/patterns/button.styles.ts | 358 ++++++++++-------- .../src/styles/patterns/input.styles.ts | 232 +++++++----- .../src/text-area/text-area.styles.ts | 34 +- .../src/text-field/text-field.styles.ts | 34 +- 14 files changed, 545 insertions(+), 708 deletions(-) create mode 100644 change/@fluentui-web-components-4bde24b4-312c-47f7-bbd5-003938181433.json diff --git a/change/@fluentui-web-components-4bde24b4-312c-47f7-bbd5-003938181433.json b/change/@fluentui-web-components-4bde24b4-312c-47f7-bbd5-003938181433.json new file mode 100644 index 00000000000000..762ae0755b6db2 --- /dev/null +++ b/change/@fluentui-web-components-4bde24b4-312c-47f7-bbd5-003938181433.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Cleaned up shared styles for button and input for improved reuse and color updates", + "packageName": "@fluentui/web-components", + "email": "47367562+bheston@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/web-components/docs/api-report.md b/packages/web-components/docs/api-report.md index 17cf813173b604..f549fa209800bc 100644 --- a/packages/web-components/docs/api-report.md +++ b/packages/web-components/docs/api-report.md @@ -41,7 +41,6 @@ import { FlipperOptions } from '@microsoft/fast-foundation'; import { FoundationElement } from '@microsoft/fast-foundation'; import { FoundationElementDefinition } from '@microsoft/fast-foundation'; import { FoundationElementRegistry } from '@microsoft/fast-foundation'; -import { FoundationElementTemplate } from '@microsoft/fast-foundation'; import { HorizontalScroll as HorizontalScroll_2 } from '@microsoft/fast-foundation'; import { HorizontalScrollOptions } from '@microsoft/fast-foundation'; import { Listbox as Listbox_2 } from '@microsoft/fast-foundation'; @@ -72,7 +71,6 @@ import { TabPanel } from '@microsoft/fast-foundation'; import { Tabs } from '@microsoft/fast-foundation'; import { TextArea as TextArea_2 } from '@microsoft/fast-foundation'; import { TextField as TextField_2 } from '@microsoft/fast-foundation'; -import { TextFieldOptions } from '@microsoft/fast-foundation'; import { Toolbar as Toolbar_2 } from '@microsoft/fast-foundation'; import { Tooltip as Tooltip_2 } from '@microsoft/fast-foundation'; import { TreeItem } from '@microsoft/fast-foundation'; @@ -86,7 +84,7 @@ export const accentBaseColor: CSSDesignToken; // Warning: (ae-internal-missing-underscore) The name "AccentButtonStyles" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) -export const AccentButtonStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, interactivitySelector?: string, nonInteractivitySelector?: string) => ElementStyles; +export const AccentButtonStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, interactivitySelector: string, nonInteractivitySelector?: string) => ElementStyles; // @public (undocumented) export const accentFillActive: CSSDesignToken; @@ -224,40 +222,8 @@ export const allComponents: { fluentTabs: (overrideDefinition?: OverrideFoundationElementDefinition | undefined) => FoundationElementRegistry; fluentTab: (overrideDefinition?: OverrideFoundationElementDefinition | undefined) => FoundationElementRegistry; fluentTabPanel: (overrideDefinition?: OverrideFoundationElementDefinition | undefined) => FoundationElementRegistry; - fluentTextArea: (overrideDefinition?: OverrideFoundationElementDefinition< { - baseName: string; - baseClass: typeof TextArea_2; - template: FoundationElementTemplate, FoundationElementDefinition>; - styles: (context: any, definition: any) => ElementStyles; - shadowOptions: { - delegatesFocus: true; - }; - }> | undefined) => FoundationElementRegistry< { - baseName: string; - baseClass: typeof TextArea_2; - template: FoundationElementTemplate, FoundationElementDefinition>; - styles: (context: any, definition: any) => ElementStyles; - shadowOptions: { - delegatesFocus: true; - }; - }, TextArea>; - fluentTextField: (overrideDefinition?: OverrideFoundationElementDefinition< { - baseName: string; - baseClass: typeof TextField_2; - template: FoundationElementTemplate, TextFieldOptions>; - styles: (context: any, definition: any) => ElementStyles; - shadowOptions: { - delegatesFocus: true; - }; - }> | undefined) => FoundationElementRegistry< { - baseName: string; - baseClass: typeof TextField_2; - template: FoundationElementTemplate, TextFieldOptions>; - styles: (context: any, definition: any) => ElementStyles; - shadowOptions: { - delegatesFocus: true; - }; - }, TextField>; + fluentTextArea: (overrideDefinition?: OverrideFoundationElementDefinition | undefined) => FoundationElementRegistry; + fluentTextField: (overrideDefinition?: OverrideFoundationElementDefinition | undefined) => FoundationElementRegistry; fluentToolbar: (overrideDefinition?: OverrideFoundationElementDefinition | undefined) => FoundationElementRegistry; fluentTooltip: (overrideDefinition?: OverrideFoundationElementDefinition | undefined) => FoundationElementRegistry; fluentTreeView: (overrideDefinition?: OverrideFoundationElementDefinition | undefined) => FoundationElementRegistry; @@ -310,8 +276,8 @@ export const badgeStyles: (context: ElementDefinitionContext, definition: Founda // Warning: (ae-internal-missing-underscore) The name "baseButtonStyles" should be prefixed with an underscore because the declaration is marked as @internal // -// @internal (undocumented) -export const baseButtonStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, interactivitySelector?: string, nonInteractivitySelector?: string) => ElementStyles; +// @internal +export const baseButtonStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, interactivitySelector: string, nonInteractivitySelector?: string) => ElementStyles; // @public (undocumented) export const baseHeightMultiplier: CSSDesignToken; @@ -319,6 +285,11 @@ export const baseHeightMultiplier: CSSDesignToken; // @public (undocumented) export const baseHorizontalSpacingMultiplier: CSSDesignToken; +// Warning: (ae-internal-missing-underscore) The name "baseInputStyles" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export const baseInputStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, logicalControlSelector: string) => ElementStyles; + // @public (undocumented) export const baseLayerLuminance: CSSDesignToken; @@ -716,44 +687,12 @@ export const fluentTabs: (overrideDefinition?: OverrideFoundationElementDefiniti // Warning: (ae-incompatible-release-tags) The symbol "fluentTextArea" is marked as @public, but its signature references "TextArea" which is marked as @internal // // @public -export const fluentTextArea: (overrideDefinition?: OverrideFoundationElementDefinition< { -baseName: string; -baseClass: typeof TextArea_2; -template: FoundationElementTemplate, FoundationElementDefinition>; -styles: (context: any, definition: any) => ElementStyles; -shadowOptions: { -delegatesFocus: true; -}; -}> | undefined) => FoundationElementRegistry< { -baseName: string; -baseClass: typeof TextArea_2; -template: FoundationElementTemplate, FoundationElementDefinition>; -styles: (context: any, definition: any) => ElementStyles; -shadowOptions: { -delegatesFocus: true; -}; -}, typeof TextArea>; +export const fluentTextArea: (overrideDefinition?: OverrideFoundationElementDefinition | undefined) => FoundationElementRegistry; // Warning: (ae-incompatible-release-tags) The symbol "fluentTextField" is marked as @public, but its signature references "TextField" which is marked as @internal // // @public -export const fluentTextField: (overrideDefinition?: OverrideFoundationElementDefinition< { -baseName: string; -baseClass: typeof TextField_2; -template: FoundationElementTemplate, TextFieldOptions>; -styles: (context: any, definition: any) => ElementStyles; -shadowOptions: { -delegatesFocus: true; -}; -}> | undefined) => FoundationElementRegistry< { -baseName: string; -baseClass: typeof TextField_2; -template: FoundationElementTemplate, TextFieldOptions>; -styles: (context: any, definition: any) => ElementStyles; -shadowOptions: { -delegatesFocus: true; -}; -}, typeof TextField>; +export const fluentTextField: (overrideDefinition?: OverrideFoundationElementDefinition | undefined) => FoundationElementRegistry; // Warning: (ae-incompatible-release-tags) The symbol "fluentToolbar" is marked as @public, but its signature references "Toolbar" which is marked as @internal // @@ -845,32 +784,27 @@ export const horizontalScrollStyles: (context: ElementDefinitionContext, definit // Warning: (ae-internal-missing-underscore) The name "HypertextStyles" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) -export const HypertextStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, interactivitySelector?: string, nonInteractivitySelector?: string) => ElementStyles; - -// Warning: (ae-internal-missing-underscore) The name "inputFilledForcedColorStyles" should be prefixed with an underscore because the declaration is marked as @internal -// -// @internal (undocumented) -export const inputFilledForcedColorStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, rootSelector: string) => ElementStyles; +export const HypertextStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, interactivitySelector: string, nonInteractivitySelector?: string) => ElementStyles; // Warning: (ae-internal-missing-underscore) The name "inputFilledStyles" should be prefixed with an underscore because the declaration is marked as @internal // -// @internal (undocumented) -export const inputFilledStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, rootSelector: string) => ElementStyles; +// @internal +export const inputFilledStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, logicalControlSelector: string, interactivitySelector?: string) => ElementStyles; // Warning: (ae-internal-missing-underscore) The name "inputForcedColorStyles" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) -export const inputForcedColorStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, rootSelector: string) => ElementStyles; +export const inputForcedColorStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, logicalControlSelector: string, interactivitySelector?: string) => ElementStyles; -// Warning: (ae-internal-missing-underscore) The name "inputStateStyles" should be prefixed with an underscore because the declaration is marked as @internal +// Warning: (ae-internal-missing-underscore) The name "inputOutlineStyles" should be prefixed with an underscore because the declaration is marked as @internal // -// @internal (undocumented) -export const inputStateStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, rootSelector: string) => ElementStyles; +// @internal +export const inputOutlineStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, logicalControlSelector: string, interactivitySelector?: string) => ElementStyles; -// Warning: (ae-internal-missing-underscore) The name "inputStyles" should be prefixed with an underscore because the declaration is marked as @internal +// Warning: (ae-internal-missing-underscore) The name "inputStateStyles" should be prefixed with an underscore because the declaration is marked as @internal // -// @internal (undocumented) -export const inputStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, rootSelector: string) => ElementStyles; +// @internal +export const inputStateStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, logicalControlSelector: string) => ElementStyles; // @public (undocumented) export interface InteractiveColorRecipe { @@ -897,7 +831,7 @@ export const layerCornerRadius: CSSDesignToken; // Warning: (ae-internal-missing-underscore) The name "LightweightButtonStyles" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) -export const LightweightButtonStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, interactivitySelector?: string, nonInteractivitySelector?: string) => ElementStyles; +export const LightweightButtonStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, interactivitySelector: string, nonInteractivitySelector?: string) => ElementStyles; // @public (undocumented) export class Listbox extends Listbox_2 { @@ -923,6 +857,11 @@ export const menuStyles: (context: ElementDefinitionContext, definition: Foundat // @public (undocumented) export const neutralBaseColor: CSSDesignToken; +// Warning: (ae-internal-missing-underscore) The name "NeutralButtonStyles" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal (undocumented) +export const NeutralButtonStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, interactivitySelector: string, nonInteractivitySelector?: string) => ElementStyles; + // @public @deprecated (undocumented) export const neutralContrastFillActive: CSSDesignToken; @@ -1429,7 +1368,7 @@ export class NumberField extends NumberField_2 { export type NumberFieldAppearance = 'filled' | 'outline'; // @public -export const numberFieldStyles: (context: any, definition: any) => ElementStyles; +export const numberFieldStyles: (context: ElementDefinitionContext, definition: NumberFieldOptions) => ElementStyles; // @public export const OptionStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition) => ElementStyles; @@ -1437,7 +1376,7 @@ export const OptionStyles: (context: ElementDefinitionContext, definition: Found // Warning: (ae-internal-missing-underscore) The name "OutlineButtonStyles" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) -export const OutlineButtonStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, interactivitySelector?: string, nonInteractivitySelector?: string) => ElementStyles; +export const OutlineButtonStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, interactivitySelector: string, nonInteractivitySelector?: string) => ElementStyles; // @public @deprecated (undocumented) export const outlineWidth: CSSDesignToken; @@ -1508,7 +1447,7 @@ export class Search extends Search_2 { export type SearchAppearance = 'filled' | 'outline'; // @public -export const searchStyles: (context: any, definition: any) => ElementStyles; +export const searchStyles: (context: ElementDefinitionContext, definition: SearchOptions) => ElementStyles; // @public (undocumented) export const searchTemplate: (context: ElementDefinitionContext, definition: SearchOptions) => ViewTemplate; @@ -1529,7 +1468,7 @@ export class Select extends Select_2 { export type SelectAppearance = 'filled' | 'outline' | 'stealth'; // @public -export const selectStyles: (context: any, definition: any) => ElementStyles; +export const selectStyles: (context: ElementDefinitionContext, definition: SelectOptions) => ElementStyles; export { Skeleton } @@ -1557,7 +1496,7 @@ export enum StandardLuminance { // Warning: (ae-internal-missing-underscore) The name "StealthButtonStyles" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) -export const StealthButtonStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, interactivitySelector?: string, nonInteractivitySelector?: string) => ElementStyles; +export const StealthButtonStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition, interactivitySelector: string, nonInteractivitySelector?: string) => ElementStyles; // @public (undocumented) export const strokeWidth: CSSDesignToken; @@ -1626,7 +1565,7 @@ export class TextArea extends TextArea_2 { export type TextAreaAppearance = 'filled' | 'outline'; // @public -export const textAreaStyles: (context: any, definition: any) => ElementStyles; +export const textAreaStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition) => ElementStyles; // Warning: (ae-internal-missing-underscore) The name "TextField" should be prefixed with an underscore because the declaration is marked as @internal // @@ -1644,7 +1583,7 @@ export class TextField extends TextField_2 { export type TextFieldAppearance = 'filled' | 'outline'; // @public -export const textFieldStyles: (context: any, definition: any) => ElementStyles; +export const textFieldStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition) => ElementStyles; // Warning: (ae-internal-missing-underscore) The name "Toolbar" should be prefixed with an underscore because the declaration is marked as @internal // @@ -1786,9 +1725,9 @@ export const typeRampPlus6LineHeight: CSSDesignToken; // dist/dts/custom-elements.d.ts:54:5 - (ae-incompatible-release-tags) The symbol "fluentBadge" is marked as @public, but its signature references "Badge" which is marked as @internal // dist/dts/custom-elements.d.ts:57:5 - (ae-incompatible-release-tags) The symbol "fluentButton" is marked as @public, but its signature references "Button" which is marked as @internal // dist/dts/custom-elements.d.ts:96:5 - (ae-incompatible-release-tags) The symbol "fluentTextArea" is marked as @public, but its signature references "TextArea" which is marked as @internal -// dist/dts/custom-elements.d.ts:113:5 - (ae-incompatible-release-tags) The symbol "fluentTextField" is marked as @public, but its signature references "TextField" which is marked as @internal -// dist/dts/custom-elements.d.ts:130:5 - (ae-incompatible-release-tags) The symbol "fluentToolbar" is marked as @public, but its signature references "Toolbar" which is marked as @internal -// dist/dts/custom-elements.d.ts:131:5 - (ae-incompatible-release-tags) The symbol "fluentTooltip" is marked as @public, but its signature references "Tooltip" which is marked as @internal +// dist/dts/custom-elements.d.ts:97:5 - (ae-incompatible-release-tags) The symbol "fluentTextField" is marked as @public, but its signature references "TextField" which is marked as @internal +// dist/dts/custom-elements.d.ts:98:5 - (ae-incompatible-release-tags) The symbol "fluentToolbar" is marked as @public, but its signature references "Toolbar" which is marked as @internal +// dist/dts/custom-elements.d.ts:99:5 - (ae-incompatible-release-tags) The symbol "fluentTooltip" is marked as @public, but its signature references "Tooltip" which is marked as @internal // (No @packageDocumentation comment for this package) diff --git a/packages/web-components/src/anchor/anchor.styles.ts b/packages/web-components/src/anchor/anchor.styles.ts index 1936112ce86c35..d076bfda6ad5a2 100644 --- a/packages/web-components/src/anchor/anchor.styles.ts +++ b/packages/web-components/src/anchor/anchor.styles.ts @@ -1,32 +1,28 @@ -import { css, ElementStyles } from '@microsoft/fast-element'; +import { ElementStyles } from '@microsoft/fast-element'; import { ElementDefinitionContext, FoundationElementDefinition } from '@microsoft/fast-foundation'; import { AccentButtonStyles, baseButtonStyles, HypertextStyles, LightweightButtonStyles, + NeutralButtonStyles, OutlineButtonStyles, StealthButtonStyles, } from '../styles/'; import { appearanceBehavior } from '../utilities/behaviors'; const interactivitySelector: string = '[href]'; -const nonInteractivitySelector: string = ':not([href])'; export const anchorStyles: ( context: ElementDefinitionContext, definition: FoundationElementDefinition, ) => ElementStyles = (context: ElementDefinitionContext, definition: FoundationElementDefinition) => - css` - :host .control:not([href]) { - cursor: default; - } - - ${baseButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)} - `.withBehaviors( - appearanceBehavior('accent', AccentButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)), - appearanceBehavior('hypertext', HypertextStyles(context, definition, interactivitySelector, nonInteractivitySelector)), - appearanceBehavior('lightweight', LightweightButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)), - appearanceBehavior('outline', OutlineButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)), - appearanceBehavior('stealth', StealthButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)), + baseButtonStyles(context, definition, interactivitySelector) + .withBehaviors( + appearanceBehavior('neutral', NeutralButtonStyles(context, definition, interactivitySelector)), + appearanceBehavior('accent', AccentButtonStyles(context, definition, interactivitySelector)), + appearanceBehavior('hypertext', HypertextStyles(context, definition, interactivitySelector)), + appearanceBehavior('lightweight', LightweightButtonStyles(context, definition, interactivitySelector)), + appearanceBehavior('outline', OutlineButtonStyles(context, definition, interactivitySelector)), + appearanceBehavior('stealth', StealthButtonStyles(context, definition, interactivitySelector)), ); diff --git a/packages/web-components/src/button/button.styles.ts b/packages/web-components/src/button/button.styles.ts index c184ef5943ed7b..58fe6ae60e28f9 100644 --- a/packages/web-components/src/button/button.styles.ts +++ b/packages/web-components/src/button/button.styles.ts @@ -2,14 +2,13 @@ import { css, ElementStyles } from '@microsoft/fast-element'; import { disabledCursor, ElementDefinitionContext, - forcedColorsStylesheetBehavior, FoundationElementDefinition, } from '@microsoft/fast-foundation'; -import { SystemColors } from "@microsoft/fast-web-utilities"; import { AccentButtonStyles, baseButtonStyles, LightweightButtonStyles, + NeutralButtonStyles, OutlineButtonStyles, StealthButtonStyles, } from '../styles/'; @@ -24,79 +23,25 @@ export const buttonStyles: ( definition: FoundationElementDefinition, ) => ElementStyles = (context: ElementDefinitionContext, definition: FoundationElementDefinition) => css` - :host([disabled]) { - opacity: ${disabledOpacity}; + :host(${interactivitySelector}) .control { + cursor: pointer; + } + + :host(${nonInteractivitySelector}) .control { cursor: ${disabledCursor}; } + @media (forced-colors: none) { + :host(${nonInteractivitySelector}) .control { + opacity: ${disabledOpacity}; + } + } + ${baseButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)} `.withBehaviors( - forcedColorsStylesheetBehavior( - css` - :host([disabled]) { - opacity: 1; - } - :host([disabled]) .control { - border-color: ${SystemColors.GrayText}; - color: ${SystemColors.GrayText}; - fill: currentcolor; - } - `, - ), - appearanceBehavior( - 'accent', - css` - ${AccentButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)}, - `.withBehaviors( - forcedColorsStylesheetBehavior( - css` - :host([disabled]) .control { - background: ${SystemColors.ButtonFace}; - } - `, - ), - ) - ), - appearanceBehavior( - 'lightweight', - css` - ${LightweightButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)}, - `.withBehaviors( - forcedColorsStylesheetBehavior( - css` - :host([disabled]) .control { - border-color: ${SystemColors.ButtonFace}; - } - `, - ), - ) - ), - appearanceBehavior( - 'outline', - css` - ${OutlineButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)} - `.withBehaviors( - forcedColorsStylesheetBehavior( - css` - :host([disabled]) .control { - border-color: ${SystemColors.GrayText}; - } - `, - ), - ) - ), - appearanceBehavior( - 'stealth', - css` - ${StealthButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)} - `.withBehaviors( - forcedColorsStylesheetBehavior( - css` - :host([disabled]) .control { - border-color: ${SystemColors.ButtonFace}; - } - `, - ), - ) - ) + appearanceBehavior('neutral', NeutralButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)), + appearanceBehavior('accent', AccentButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)), + appearanceBehavior('lightweight', LightweightButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)), + appearanceBehavior('outline', OutlineButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)), + appearanceBehavior('stealth', StealthButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)), ); diff --git a/packages/web-components/src/combobox/combobox.stories.ts b/packages/web-components/src/combobox/combobox.stories.ts index f5f8aeb5dc3ebe..54288198241a55 100644 --- a/packages/web-components/src/combobox/combobox.stories.ts +++ b/packages/web-components/src/combobox/combobox.stories.ts @@ -8,6 +8,9 @@ export default { options: ['filled', 'outline'], control: { type: 'radio' }, }, + disabled: { + control: { type: 'boolean' }, + }, autocomplete: { options: ['inline', 'list', 'none', 'both'], control: { type: 'radio' }, @@ -22,7 +25,7 @@ export default { }, }; -const ComboboxTemplate = ({ appearance, autocomplete, position, required }) => ` +const ComboboxTemplate = ({ appearance, disabled, autocomplete, position, required }) => ` ElementStyles = ( context: ElementDefinitionContext, definition: ComboboxOptions, ) => css` - ${selectStyles(context, definition)} - - :host { - background: padding-box linear-gradient(${neutralFillInputRest}, ${neutralFillInputRest}), - border-box ${neutralStrokeInputRest}; - } + ${baseSelectStyles(context, definition)} - :host(:not([disabled]):not([open]):hover) { - background: padding-box linear-gradient(${neutralFillInputHover}, ${neutralFillInputHover}), - border-box ${neutralStrokeInputHover}; - } - - :host(:not([disabled]):not([open]):active) { - background: padding-box linear-gradient(${neutralFillInputActive}, ${neutralFillInputActive}), - border-box ${neutralStrokeInputActive}; - } + ${inputStateStyles(context, definition, logicalControlSelector)} :host(:empty) .listbox { - display: none; + display: none; } :host([disabled]) *, :host([disabled]) { - cursor: ${disabledCursor}; - user-select: none; + cursor: ${disabledCursor}; + user-select: none; } :host(:active) .selected-value { - user-select: none; + user-select: none; } .selected-value { - -webkit-appearance: none; - background: transparent; - border: none; - color: inherit; - ${typeRampBase} - height: calc(100% - ${strokeWidth} * 1px)); - margin: auto 0; - width: 100%; - outline: none; + -webkit-appearance: none; + background: transparent; + border: none; + color: inherit; + ${typeRampBase} + height: calc(100% - ${strokeWidth} * 1px)); + margin: auto 0; + width: 100%; + outline: none; } -`.withBehaviors( - appearanceBehavior('filled', selectFilledStyles(context, definition))); + `.withBehaviors( + appearanceBehavior('outline', inputOutlineStyles(context, definition, logicalControlSelector, interactivitySelector)), + appearanceBehavior('filled', inputFilledStyles(context, definition, logicalControlSelector, interactivitySelector)), + forcedColorsStylesheetBehavior(inputForcedColorStyles(context, definition, logicalControlSelector, interactivitySelector)), + ); diff --git a/packages/web-components/src/number-field/number-field.styles.ts b/packages/web-components/src/number-field/number-field.styles.ts index 38c0369d5be825..7428062cc31476 100644 --- a/packages/web-components/src/number-field/number-field.styles.ts +++ b/packages/web-components/src/number-field/number-field.styles.ts @@ -5,38 +5,28 @@ import { forcedColorsStylesheetBehavior, NumberFieldOptions, } from '@microsoft/fast-foundation'; -import { SystemColors } from "@microsoft/fast-web-utilities"; import { - inputFilledForcedColorStyles, + baseInputStyles, inputFilledStyles, inputForcedColorStyles, + inputOutlineStyles, inputStateStyles, - inputStyles, } from '../styles/index'; import { appearanceBehavior } from '../utilities/behaviors'; import { designUnit } from '../design-tokens'; -export const numberFieldFilledStyles: ( +const logicalControlSelector: string = '.root'; + +export const numberFieldStyles: (context: ElementDefinitionContext, definition: NumberFieldOptions) => ElementStyles = ( context: ElementDefinitionContext, definition: NumberFieldOptions, -) => ElementStyles = (context: ElementDefinitionContext, definition: NumberFieldOptions) => - css` - ${inputFilledStyles(context, definition, '.root')} - `.withBehaviors( - forcedColorsStylesheetBehavior( - css` - ${inputFilledForcedColorStyles(context, definition, '.root')} - `, - ), - ); - -export const numberFieldStyles = (context, definition) => +) => css` ${display('inline-block')} - ${inputStyles(context, definition, '.root')} + ${baseInputStyles(context, definition, logicalControlSelector)} - ${inputStateStyles(context, definition, '.root')} + ${inputStateStyles(context, definition, logicalControlSelector)} .root { display: flex; @@ -96,14 +86,7 @@ export const numberFieldStyles = (context, definition) => padding-top: 3px; } `.withBehaviors( - appearanceBehavior('filled', numberFieldFilledStyles(context, definition)), - forcedColorsStylesheetBehavior( - css` - ${inputForcedColorStyles(context, definition, '.root')} - .step-up, - .step-down { - fill: ${SystemColors.FieldText}; - } - `, - ), + appearanceBehavior('outline', inputOutlineStyles(context, definition, logicalControlSelector)), + appearanceBehavior('filled', inputFilledStyles(context, definition, logicalControlSelector)), + forcedColorsStylesheetBehavior(inputForcedColorStyles(context, definition, logicalControlSelector)), ); diff --git a/packages/web-components/src/search/search.styles.ts b/packages/web-components/src/search/search.styles.ts index b120abddee0ac2..cc20bdd6e5967e 100644 --- a/packages/web-components/src/search/search.styles.ts +++ b/packages/web-components/src/search/search.styles.ts @@ -5,21 +5,22 @@ import { display, ElementDefinitionContext, forcedColorsStylesheetBehavior, - FoundationElementDefinition, + SearchOptions, } from '@microsoft/fast-foundation'; import { + baseInputStyles, heightNumber, - inputFilledForcedColorStyles, inputFilledStyles, inputForcedColorStyles, + inputOutlineStyles, inputStateStyles, - inputStyles, } from '../styles'; import { appearanceBehavior } from '../utilities/behaviors'; import { controlCornerRadius, density, designUnit, neutralFillInputRecipe, neutralFillStealthRecipe, neutralForegroundRest } from '../design-tokens'; import { typeRampBase } from '../styles/patterns/type-ramp'; import { Swatch } from '../color/swatch'; +const logicalControlSelector: string = '.root'; const clearButtonHover = DesignToken.create("clear-button-hover").withDefault( (target: HTMLElement) => { @@ -37,26 +38,17 @@ const clearButtonActive = DesignToken.create("clear-button-active").with } ); - -export const searchFilledStyles: ( +export const searchStyles: (context: ElementDefinitionContext, definition: SearchOptions) => ElementStyles = ( context: ElementDefinitionContext, - definition: FoundationElementDefinition, -) => ElementStyles = (context: ElementDefinitionContext, definition: FoundationElementDefinition) => - css` - ${inputFilledStyles(context, definition, '.root')} - `.withBehaviors( - forcedColorsStylesheetBehavior( - css` - ${inputFilledForcedColorStyles(context, definition, '.root')} - `, - ), - ); - -export const searchStyles = (context, definition) => + definition: SearchOptions, +) => css` ${display('inline-block')} - ${inputStyles(context, definition, '.root')} - ${inputStateStyles(context, definition, '.root')} + + ${baseInputStyles(context, definition, logicalControlSelector)} + + ${inputStateStyles(context, definition, logicalControlSelector)} + .root { display: flex; flex-direction: row; @@ -137,10 +129,7 @@ export const searchStyles = (context, definition) => margin-inline-end: 1px; } `.withBehaviors( - appearanceBehavior('filled', searchFilledStyles(context, definition)), - forcedColorsStylesheetBehavior( - css` - ${inputForcedColorStyles(context, definition, '.root')} - `, - ) + appearanceBehavior('outline', inputOutlineStyles(context, definition, logicalControlSelector)), + appearanceBehavior('filled', inputFilledStyles(context, definition, logicalControlSelector)), + forcedColorsStylesheetBehavior(inputForcedColorStyles(context, definition, logicalControlSelector)), ); diff --git a/packages/web-components/src/select/select.stories.ts b/packages/web-components/src/select/select.stories.ts index 2a0818f9065255..2f4f670dffd0c2 100644 --- a/packages/web-components/src/select/select.stories.ts +++ b/packages/web-components/src/select/select.stories.ts @@ -6,9 +6,9 @@ export default { component: fluentSelect, argTypes: { appearance: { - options: ['filled', 'outlined', 'stealth'], + options: ['filled', 'outline', 'stealth'], control: { type: 'radio' }, - defaultValue: 'outlined', + defaultValue: 'outline', }, disabled: { control: { type: 'boolean' }, diff --git a/packages/web-components/src/select/select.styles.ts b/packages/web-components/src/select/select.styles.ts index 3580a6dcb318d3..4a0dd537f65c0a 100644 --- a/packages/web-components/src/select/select.styles.ts +++ b/packages/web-components/src/select/select.styles.ts @@ -18,95 +18,42 @@ import { disabledOpacity, fillColor, layerCornerRadius, - neutralFillActive, - neutralFillHover, - neutralFillRest, - neutralFillSecondaryActive, - neutralFillSecondaryHover, - neutralFillSecondaryRest, - neutralFillStealthActive, - neutralFillStealthHover, - neutralFillStealthRest, neutralForegroundRest, - neutralStrokeControlActive, - neutralStrokeControlHover, - neutralStrokeControlRest, strokeWidth, } from '../design-tokens'; import { typeRampBase } from '../styles/patterns/type-ramp'; import { focusTreatmentBase } from '../styles/focus'; - -export const selectFilledStyles: (context: ElementDefinitionContext, definition: SelectOptions) => ElementStyles = ( - context: ElementDefinitionContext, - definition: SelectOptions, -) => css` - :host { - background: ${neutralFillSecondaryRest}; - border-color: transparent; - } - - :host(:not([disabled]):not([open]):hover) { - background: ${neutralFillSecondaryHover}; - border-color: transparent; - } - - :host(:not([disabled]):not([open]):active) { - background: ${neutralFillSecondaryActive}; - border-color: transparent; - } -`.withBehaviors( - forcedColorsStylesheetBehavior( - css` - :host(:not([disabled]):not([open]):hover) { - background: transparent; - } - :host(:not([disabled]):not([open]):hover), - :host(:not([disabled]):not([open]):active) { - border-color: ${SystemColors.Highlight}; - } - `, - ) -); - -export const selectStealthStyles: (context: ElementDefinitionContext, definition: SelectOptions) => ElementStyles = ( +import { inputFilledStyles, inputForcedColorStyles, NeutralButtonStyles, StealthButtonStyles } from '../styles'; + +const logicalControlSelector: string = '.control'; +const interactivitySelector: string = ':not([disabled]):not([open])'; +const nonInteractivitySelector: string = '[disabled]'; + +/** + * The base styles for a select and combobox, without `appearance` visual differences. + * + * @internal + */ +export const baseSelectStyles: (context: ElementDefinitionContext, definition: SelectOptions) => ElementStyles = ( context: ElementDefinitionContext, definition: SelectOptions, -) => css` - :host { - background: ${neutralFillStealthRest}; - border-color: transparent; - } - - :host(:not([disabled]):not([open]):hover) { - background: ${neutralFillStealthHover}; - border-color: transparent; - } - - :host(:not([disabled]):not([open]):active) { - background: ${neutralFillStealthActive}; - border-color: transparent; - } -`; - -export const selectStyles = (context, definition) => +) => css` - ${display('inline-flex')} :host { - background: padding-box linear-gradient(${neutralFillRest}, ${neutralFillRest}), - border-box ${neutralStrokeControlRest}; - border: calc(${strokeWidth} * 1px) solid transparent; + ${display('inline-flex')} + + :host { border-radius: calc(${controlCornerRadius} * 1px); box-sizing: border-box; color: ${neutralForegroundRest}; fill: currentcolor; font-family: ${bodyFont}; - height: calc(${heightNumber} * 1px); position: relative; user-select: none; min-width: 250px; vertical-align: top; } - :host .listbox { + .listbox { box-shadow: ${elevationShadowFlyout}; background: ${fillColor}; border-radius: calc(${layerCornerRadius} * 1px); @@ -115,7 +62,7 @@ export const selectStyles = (context, definition) => flex-direction: column; left: 0; max-height: calc(var(--max-height) - (${heightNumber} * 1px)); - padding: calc((${designUnit} - ${strokeWidth} ) * 1px) 0; + padding: calc((${designUnit} - ${strokeWidth} ) * 1px); overflow-y: auto; position: absolute; width: 100%; @@ -124,11 +71,14 @@ export const selectStyles = (context, definition) => border: calc(${strokeWidth} * 1px) solid transparent; } - :host .listbox[hidden] { + .listbox[hidden] { display: none; } - :host .control { + .control { + border: calc(${strokeWidth} * 1px) solid transparent; + border-radius: calc(${controlCornerRadius} * 1px); + height: calc(${heightNumber} * 1px); align-items: center; box-sizing: border-box; cursor: pointer; @@ -139,27 +89,13 @@ export const selectStyles = (context, definition) => width: 100%; } - :host(:not([disabled]):not([open]):hover) { - background: padding-box linear-gradient(${neutralFillHover}, ${neutralFillHover}), - border-box ${neutralStrokeControlHover}; - } - - :host(:not([disabled]):not([open]):active) { - background: padding-box linear-gradient(${neutralFillActive}, ${neutralFillActive}), - border-box ${neutralStrokeControlActive}; - } - :host(:${focusVisible}) { ${focusTreatmentBase} } - :host([disabled]) { - cursor: ${disabledCursor}; - opacity: ${disabledOpacity}; - } - :host([disabled]) .control { cursor: ${disabledCursor}; + opacity: ${disabledOpacity}; user-select: none; } @@ -210,43 +146,36 @@ export const selectStyles = (context, definition) => ::slotted([role='option']) { flex: 0 0 auto; } - `.withBehaviors( - appearanceBehavior('filled', selectFilledStyles(context, definition)), - appearanceBehavior('stealth', selectStealthStyles(context, definition)), - forcedColorsStylesheetBehavior( - css` - :host { - background: ${SystemColors.ButtonFace}; - color: ${SystemColors.ButtonText}; - } - :host(:not([disabled]):not([open]):hover) { - background: transparent; - } - :host(:not([disabled]):hover) { - border-color: ${SystemColors.Highlight}; - } - :host(:${focusVisible}) { - forced-color-adjust: none; - outline-color: ${SystemColors.Highlight}; - } - :host([open]) .listbox { - background: ${SystemColors.ButtonFace}; - border-color: ${SystemColors.CanvasText}; - } - .start, .end, .indicator, ::slotted(svg) { - fill: ${SystemColors.FieldText}; - } - :host([disabled]) { - border-color: ${SystemColors.GrayText}; - color: ${SystemColors.GrayText}; - opacity: 1; - } - :host([disabled]) .start, - :host([disabled]) .end, - :host([disabled]) .indicator, - :host([disabled]) ::slotted(svg) { - fill: ${SystemColors.GrayText}; - } - `, - ) -); + `; + +/** + * @internal + */ +export const baseSelectForcedColorStyles: ( + context: ElementDefinitionContext, + definition: SelectOptions +) => ElementStyles = ( + context: ElementDefinitionContext, + definition: SelectOptions, +) => + css` + :host([open]) .listbox { + background: ${SystemColors.ButtonFace}; + border-color: ${SystemColors.CanvasText}; + } + `; + +export const selectStyles: (context: ElementDefinitionContext, definition: SelectOptions) => ElementStyles = ( + context: ElementDefinitionContext, + definition: SelectOptions, +) => + baseSelectStyles(context, definition) + .withBehaviors( + appearanceBehavior('outline', NeutralButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)), + appearanceBehavior('filled', + inputFilledStyles(context, definition, logicalControlSelector, interactivitySelector) + .withBehaviors(forcedColorsStylesheetBehavior(inputForcedColorStyles(context, definition, logicalControlSelector, interactivitySelector))) + ), + appearanceBehavior('stealth', StealthButtonStyles(context, definition, interactivitySelector, nonInteractivitySelector)), + forcedColorsStylesheetBehavior(baseSelectForcedColorStyles(context, definition)) + ); diff --git a/packages/web-components/src/styles/patterns/button.styles.ts b/packages/web-components/src/styles/patterns/button.styles.ts index de364724422e81..b64d5fa6a05704 100644 --- a/packages/web-components/src/styles/patterns/button.styles.ts +++ b/packages/web-components/src/styles/patterns/button.styles.ts @@ -45,16 +45,20 @@ import { typeRampBase } from '../../styles/patterns/type-ramp'; import { focusTreatmentBase, focusTreatmentTight } from '../focus'; /** + * The base styles for button controls, without `appearance` visual differences. + * * @internal */ export const baseButtonStyles = ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - interactivitySelector: string = '', - nonInteractivitySelector: string = '', + interactivitySelector: string, + nonInteractivitySelector: string = '[disabled]', ) => css` - ${display('inline-flex')} :host { + ${display('inline-flex')} + + :host { position: relative; box-sizing: border-box; ${typeRampBase} @@ -63,12 +67,9 @@ export const baseButtonStyles = ( color: ${neutralForegroundRest}; border-radius: calc(${controlCornerRadius} * 1px); fill: currentcolor; - cursor: pointer; } - :host .control { - background: padding-box linear-gradient(${neutralFillRest}, ${neutralFillRest}), - border-box ${neutralStrokeControlRest}; + .control { border: calc(${strokeWidth} * 1px) solid transparent; flex-grow: 1; box-sizing: border-box; @@ -82,7 +83,6 @@ export const baseButtonStyles = ( color: inherit; border-radius: inherit; fill: inherit; - cursor: inherit; font-family: inherit; } @@ -97,24 +97,10 @@ export const baseButtonStyles = ( line-height: 0; } - :host .control${interactivitySelector}:hover { - background: padding-box linear-gradient(${neutralFillHover}, ${neutralFillHover}), - border-box ${neutralStrokeControlHover}; - } - - :host .control${interactivitySelector}:active { - background: padding-box linear-gradient(${neutralFillActive}, ${neutralFillActive}), - border-box ${neutralStrokeControlActive}; - } - - :host .control:${focusVisible} { + .control:${focusVisible} { ${focusTreatmentBase} } - :host .control${nonInteractivitySelector} { - background: padding-box linear-gradient(${neutralFillRest}, ${neutralFillRest}), border-box ${neutralStrokeRest}; - } - .control::-moz-focus-inner { border: 0; } @@ -136,45 +122,75 @@ export const baseButtonStyles = ( .end { margin-inline-start: 11px; } + `; + +/** + * @internal + */ +export const NeutralButtonStyles = ( + context: ElementDefinitionContext, + definition: FoundationElementDefinition, + interactivitySelector: string, + nonInteractivitySelector: string = '[disabled]', +) => + css` + .control { + background: padding-box linear-gradient(${neutralFillRest}, ${neutralFillRest}), + border-box ${neutralStrokeControlRest}; + } + + :host(${interactivitySelector}:hover) .control { + background: padding-box linear-gradient(${neutralFillHover}, ${neutralFillHover}), + border-box ${neutralStrokeControlHover}; + } + + :host(${interactivitySelector}:active) .control { + background: padding-box linear-gradient(${neutralFillActive}, ${neutralFillActive}), + border-box ${neutralStrokeControlActive}; + } + + :host(${nonInteractivitySelector}) .control { + background: padding-box linear-gradient(${neutralFillRest}, ${neutralFillRest}), + border-box ${neutralStrokeRest}; + } `.withBehaviors( forcedColorsStylesheetBehavior( css` - :host .control { + .control { background: ${SystemColors.ButtonFace}; border-color: ${SystemColors.ButtonText}; color: ${SystemColors.ButtonText}; - fill: currentcolor; } - :host(:not([disabled])) .control:hover, - :host .control${interactivitySelector}:hover, - .control${interactivitySelector}:hover { + + :host(${interactivitySelector}:hover) .control, + :host(${interactivitySelector}:active) .control { forced-color-adjust: none; - background: ${SystemColors.Highlight}; - color: ${SystemColors.HighlightText}; + background: ${SystemColors.HighlightText}; + border-color: ${SystemColors.Highlight}; + color: ${SystemColors.Highlight}; } - .control:${focusVisible}, - :host .control:${focusVisible}, - :host(:${focusVisible}) .control { - forced-color-adjust: none; - background: ${SystemColors.ButtonFace}; - outline-color: ${SystemColors.Highlight}; + + :host(${nonInteractivitySelector}) .control { + background: transparent; + border-color: ${SystemColors.GrayText}; + color: ${SystemColors.GrayText}; } + + .control:${focusVisible} { + outline-color: ${SystemColors.CanvasText}; + } + :host([href]) .control { - background: ${SystemColors.ButtonFace}; + background: transparent; border-color: ${SystemColors.LinkText}; color: ${SystemColors.LinkText}; - fill: currentcolor; } - :host([href]) .control:hover, - :host(.neutral[href]) .control:hover { - background: ${SystemColors.LinkText}; - border-color: ${SystemColors.LinkText} !important; - color: ${SystemColors.HighlightText}; - fill: currentcolor; - } - :host([href]) .control:${focusVisible}{ - forced-color-adjust: none; - outline-color: ${SystemColors.LinkText}; + + :host([href]:hover) .control, + :host([href]:active) .control { + background: transparent; + border-color: ${SystemColors.CanvasText}; + color: ${SystemColors.CanvasText}; } `, ), @@ -186,71 +202,72 @@ export const baseButtonStyles = ( export const AccentButtonStyles = ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - interactivitySelector: string = '', - nonInteractivitySelector: string = '', + interactivitySelector: string, + nonInteractivitySelector: string = '[disabled]', ) => css` - :host .control { + .control { background: padding-box linear-gradient(${accentFillRest}, ${accentFillRest}), border-box ${accentStrokeControlRest}; color: ${foregroundOnAccentRest}; } - :host .control${interactivitySelector}:hover { + :host(${interactivitySelector}:hover) .control { background: padding-box linear-gradient(${accentFillHover}, ${accentFillHover}), border-box ${accentStrokeControlHover}; color: ${foregroundOnAccentHover}; } - :host .control${interactivitySelector}:active { + :host(${interactivitySelector}:active) .control { background: padding-box linear-gradient(${accentFillActive}, ${accentFillActive}), border-box ${accentStrokeControlActive}; color: ${foregroundOnAccentActive}; } - :host .control:${focusVisible} { - ${focusTreatmentBase} - box-shadow: 0 0 0 calc(((${focusStrokeWidth} + ${strokeWidth}) - ${strokeWidth}) * 1px) ${focusStrokeInner} inset !important; + :host(${nonInteractivitySelector}) .control { + background: ${accentFillRest}; } - :host .control${nonInteractivitySelector} { - background: ${accentFillRest}; + .control:${focusVisible} { + box-shadow: 0 0 0 calc(${focusStrokeWidth} * 1px) ${focusStrokeInner} inset !important; } `.withBehaviors( forcedColorsStylesheetBehavior( css` - :host .control { + .control { forced-color-adjust: none; background: ${SystemColors.Highlight}; color: ${SystemColors.HighlightText}; } - :host .control${interactivitySelector}:hover, - :host .control${interactivitySelector}:active { + + :host(${interactivitySelector}:hover) .control, + :host(${interactivitySelector}:active) .control { background: ${SystemColors.HighlightText}; border-color: ${SystemColors.Highlight}; color: ${SystemColors.Highlight}; } - :host .control:${focusVisible} { - background: ${SystemColors.Highlight}; - outline-color: ${SystemColors.Highlight}; - box-shadow: 0 0 0 calc(((${focusStrokeWidth} + ${strokeWidth}) - ${strokeWidth}) * 1px) ${SystemColors.HighlightText} inset !important; + + :host(${nonInteractivitySelector}) .control { + background: transparent; + border-color: ${SystemColors.GrayText}; + color: ${SystemColors.GrayText}; } + + .control:${focusVisible} { + outline-color: ${SystemColors.CanvasText}; + box-shadow: 0 0 0 calc(${focusStrokeWidth} * 1px) ${SystemColors.HighlightText} inset !important; + } + :host([href]) .control { background: ${SystemColors.LinkText}; color: ${SystemColors.HighlightText}; } - :host([href]) .control:hover { + + :host([href]:hover) .control, + :host([href]:active) .control { background: ${SystemColors.ButtonFace}; border-color: ${SystemColors.LinkText}; color: ${SystemColors.LinkText}; - fill: currentcolor; - } - :host([href]) .control:${focusVisible} { - background: ${SystemColors.LinkText}; - outline-color: ${SystemColors.LinkText}; - box-shadow: 0 0 0 calc(((${focusStrokeWidth} + ${strokeWidth}) - ${strokeWidth}) * 1px) ${SystemColors.HighlightText} inset !important; - color: ${SystemColors.HighlightText}; - fill: currentcolor; } `, ), @@ -262,8 +279,8 @@ export const AccentButtonStyles = ( export const HypertextStyles = ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - interactivitySelector: string = '', - nonInteractivitySelector: string = '', + interactivitySelector: string, + nonInteractivitySelector: string = '[disabled]', ) => css` :host { @@ -274,54 +291,47 @@ export const HypertextStyles = ( min-width: 0; } - :host .control { + .control { display: inline; padding: 0; - background: transparent; border: none; box-shadow: none; line-height: 1; - text-decoration: underline 1px; } - :host .control:not([href]) { - background: transparent; - } - - :host .control${interactivitySelector} { - background: transparent; + :host(${interactivitySelector}) .control { color: ${accentForegroundRest}; + text-decoration: underline 1px; } - :host .control${interactivitySelector}:hover { - background: transparent; + :host(${interactivitySelector}:hover) .control { color: ${accentForegroundHover}; text-decoration: none; } - :host .control${interactivitySelector}:active { - background: transparent; + :host(${interactivitySelector}:active) .control { color: ${accentForegroundActive}; text-decoration: none; } - :host .control:${focusVisible} { + .control:${focusVisible} { ${focusTreatmentTight} } - - :host .control${nonInteractivitySelector} { - background: transparent; - } `.withBehaviors( forcedColorsStylesheetBehavior( css` - :host .control${interactivitySelector}:hover { - color: ${SystemColors.Highlight}; - fill: currentcolor; - } - :host .control:${focusVisible} { - color: ${SystemColors.LinkText}; - } + :host(${interactivitySelector}) .control { + color: ${SystemColors.LinkText}; + } + + :host(${interactivitySelector}:hover) .control, + :host(${interactivitySelector}:active) .control { + color: ${SystemColors.CanvasText}; + } + + .control:${focusVisible} { + outline-color: ${SystemColors.CanvasText}; + } `, ), ); @@ -332,52 +342,66 @@ export const HypertextStyles = ( export const LightweightButtonStyles = ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - interactivitySelector: string = '', - nonInteractivitySelector: string = '', + interactivitySelector: string, + nonInteractivitySelector: string = '[disabled]', ) => css` :host { color: ${accentForegroundRest}; } - :host .control { + .control { background: ${neutralFillStealthRest}; } - :host .control${interactivitySelector}:hover { + :host(${interactivitySelector}:hover) .control { background: ${neutralFillStealthHover}; color: ${accentForegroundHover}; } - :host .control${interactivitySelector}:active { + :host(${interactivitySelector}:active) .control { background: ${neutralFillStealthActive}; color: ${accentForegroundActive}; } - :host .control${nonInteractivitySelector} { + :host(${nonInteractivitySelector}) .control { background: ${neutralFillStealthRest}; } `.withBehaviors( forcedColorsStylesheetBehavior( css` - :host .control { - border-color: ${SystemColors.ButtonFace}; + :host { color: ${SystemColors.ButtonText}; } - :host .control${interactivitySelector}:hover, - :host .control${interactivitySelector}:active, - :host .control:${focusVisible} { - border-color: ${SystemColors.Highlight}; - background: ${SystemColors.Highlight}; - color: ${SystemColors.HighlightText}; + + .control { + forced-color-adjust: none; + background: transparent; + } + + :host(${interactivitySelector}:hover) .control, + :host(${interactivitySelector}:active) .control { + background: transparent; + border-color: ${SystemColors.ButtonText}; + color: ${SystemColors.ButtonText}; } + + :host(${nonInteractivitySelector}) .control { + background: transparent; + color: ${SystemColors.GrayText}; + } + + .control:${focusVisible} { + outline-color: ${SystemColors.CanvasText}; + } + :host([href]) .control { - border-color: ${SystemColors.ButtonFace}; color: ${SystemColors.LinkText}; } - :host([href]) .control:hover, - :host([href]) .control:${focusVisible} { - background: ${SystemColors.ButtonFace}; + + :host([href]:hover) .control, + :host([href]:active) .control { + border-color: ${SystemColors.LinkText}; color: ${SystemColors.LinkText}; } `, @@ -390,44 +414,61 @@ export const LightweightButtonStyles = ( export const OutlineButtonStyles = ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - interactivitySelector: string = '', - nonInteractivitySelector: string = '', + interactivitySelector: string, + nonInteractivitySelector: string = '[disabled]', ) => css` - :host .control { + .control { background: transparent !important; border-color: ${neutralStrokeRest}; } - :host .control${interactivitySelector}:hover { + :host(${interactivitySelector}:hover) .control { border-color: ${neutralStrokeHover}; } - :host .control${interactivitySelector}:active { + :host(${interactivitySelector}:active) .control { border-color: ${neutralStrokeActive}; } - :host .control${nonInteractivitySelector} { + :host(${nonInteractivitySelector}) .control { background: transparent !important; border-color: ${neutralStrokeRest}; } `.withBehaviors( forcedColorsStylesheetBehavior( css` - :host .control${nonInteractivitySelector} { + .control { border-color: ${SystemColors.ButtonText}; + color: ${SystemColors.ButtonText}; } - :host .control${interactivitySelector}:hover { + + :host(${interactivitySelector}:hover) .control, + :host(${interactivitySelector}:active) .control { + background: ${SystemColors.HighlightText}; border-color: ${SystemColors.Highlight}; - color: ${SystemColors.ButtonText}; + color: ${SystemColors.Highlight}; } - :host([href]) { - border-color: ${SystemColors.LinkText}; + + :host(${nonInteractivitySelector}) .control { + border-color: ${SystemColors.GrayText}; + color: ${SystemColors.GrayText}; } - :host([href]) .control:hover { - outline-color: ${SystemColors.LinkText}; + + .control:${focusVisible} { + outline-color: ${SystemColors.CanvasText}; + } + + :host([href]) .control { + border-color: ${SystemColors.LinkText}; color: ${SystemColors.LinkText}; } + + :host([href]:hover) .control, + :host([href]:active) .control { + border-color: ${SystemColors.CanvasText}; + color: ${SystemColors.CanvasText}; + } `, ), ); @@ -438,52 +479,59 @@ export const OutlineButtonStyles = ( export const StealthButtonStyles = ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - interactivitySelector: string = '', - nonInteractivitySelector: string = '', + interactivitySelector: string, + nonInteractivitySelector: string = '[disabled]', ) => css` - :host .control { + .control { background: ${neutralFillStealthRest}; } - :host .control${interactivitySelector}:hover { + :host(${interactivitySelector}:hover) .control { background: ${neutralFillStealthHover}; } - :host .control${interactivitySelector}:active { + :host(${interactivitySelector}:active) .control { background: ${neutralFillStealthActive}; } - :host .control${nonInteractivitySelector} { + :host(${nonInteractivitySelector}) .control { background: ${neutralFillStealthRest}; } `.withBehaviors( forcedColorsStylesheetBehavior( css` - :host .control { - background: ${SystemColors.ButtonFace}; - border-color: ${SystemColors.ButtonFace}; + .control { + forced-color-adjust: none; + background: transparent; color: ${SystemColors.ButtonText}; - fill: currentcolor; } - :host .control${interactivitySelector}:hover, - :host .control${interactivitySelector}:active, - :host .control:${focusVisible} { - background: ${SystemColors.Highlight}; - border-color: ${SystemColors.Highlight}; - color: ${SystemColors.HighlightText}; - fill: currentcolor; + + :host(${interactivitySelector}:hover) .control, + :host(${interactivitySelector}:active) .control { + background: transparent; + border-color: ${SystemColors.ButtonText}; + color: ${SystemColors.ButtonText}; } + + :host(${nonInteractivitySelector}) .control { + background: transparent; + color: ${SystemColors.GrayText}; + } + + .control:${focusVisible} { + outline-color: ${SystemColors.CanvasText}; + } + :host([href]) .control { - border-color: ${SystemColors.ButtonFace}; color: ${SystemColors.LinkText}; } - :host([href]) .control:hover, - :host([href]) .control:${focusVisible} { - background: ${SystemColors.LinkText}; + + :host([href]:hover) .control, + :host([href]:active) .control { + background: transparent; border-color: ${SystemColors.LinkText}; - color: ${SystemColors.HighlightText}; - fill: currentcolor; + color: ${SystemColors.LinkText}; } `, ), diff --git a/packages/web-components/src/styles/patterns/input.styles.ts b/packages/web-components/src/styles/patterns/input.styles.ts index fdb8c5cb54d683..ed90312029c312 100644 --- a/packages/web-components/src/styles/patterns/input.styles.ts +++ b/packages/web-components/src/styles/patterns/input.styles.ts @@ -16,6 +16,7 @@ import { neutralFillInputHover, neutralFillInputRecipe, neutralFillInputRest, + neutralFillSecondaryFocus, neutralFillSecondaryHover, neutralFillSecondaryRecipe, neutralFillSecondaryRest, @@ -28,6 +29,7 @@ import { } from '../../design-tokens'; import { typeRampBase } from '../patterns/type-ramp'; import { heightNumber } from '../size'; +import { focusTreatmentBase } from '../focus'; const placeholderRest = DesignToken.create('input-placeholder-rest').withDefault((target: HTMLElement) => { const baseRecipe = neutralFillInputRecipe.getValueFor(target); @@ -58,16 +60,18 @@ const filledPlaceholderHover = DesignToken.create('input-filled-placehol ); /** + * The base styles for input controls, without `appearance` visual differences. + * * @internal */ -export const inputStyles: ( +export const baseInputStyles: ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - rootSelector: string, + logicalControlSelector: string, ) => ElementStyles = ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - rootSelector: string, + logicalControlSelector: string, ) => css` :host { ${typeRampBase} @@ -77,12 +81,10 @@ export const inputStyles: ( position: relative; } - ${rootSelector} { + ${logicalControlSelector} { box-sizing: border-box; position: relative; color: inherit; - background: padding-box linear-gradient(${neutralFillInputRest}, ${neutralFillInputRest}), - border-box ${neutralStrokeInputRest}; border: calc(${strokeWidth} * 1px) solid transparent; border-radius: calc(${controlCornerRadius} * 1px); height: calc(${heightNumber} * 1px); @@ -109,25 +111,9 @@ export const inputStyles: ( visibility: hidden; } - :host(:hover:not([disabled]):not(:focus-within)) ${rootSelector} { - background: padding-box linear-gradient(${neutralFillInputHover}, ${neutralFillInputHover}), - border-box ${neutralStrokeInputHover}; - } - - :host(:not([disabled]):focus-within) ${rootSelector} { - background: padding-box linear-gradient(${neutralFillInputFocus}, ${neutralFillInputFocus}), - border-box ${neutralStrokeInputRest}; - } - - .control::placeholder { - color: ${placeholderRest}; - } - - :host(:hover:not([disabled]):not(:focus-within)) .control::placeholder { - color: ${placeholderHover}; - } - - :host([disabled]) ${rootSelector}, :host([readonly]) ${rootSelector}, :host([disabled]) .label, + :host([disabled]) ${logicalControlSelector}, + :host([readonly]) ${logicalControlSelector}, + :host([disabled]) .label, :host([readonly]) .label, :host([disabled]) .control, :host([readonly]) .control { @@ -137,149 +123,189 @@ export const inputStyles: ( :host([disabled]) { opacity: ${disabledOpacity}; } - - :host([disabled]) ${rootSelector} { - background: padding-box linear-gradient(${neutralFillInputRest}, ${neutralFillInputRest}), - border-box ${neutralStrokeRest}; - } `; /** + * The styles for active and focus interactions for input controls. + * * @internal */ export const inputStateStyles: ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - rootSelector: string, + logicalControlSelector: string, ) => ElementStyles = ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - rootSelector: string, + logicalControlSelector: string, ) => css` - :host(:not([disabled]):active)::after { - left: 50%; - width: 40%; - transform: translateX(-50%); - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - } + @media (forced-colors: none) { + :host(:not([disabled]):active)::after { + left: 50%; + width: 40%; + transform: translateX(-50%); + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } - :host(:not([disabled]):focus-within)::after { - left: 0; - width: 100%; - transform: none; - } + :host(:not([disabled]):focus-within)::after { + left: 0; + width: 100%; + transform: none; + } - :host(:not([disabled]):active)::after, - :host(:not([disabled]):focus-within:not(:active))::after { - content: ''; - position: absolute; - height: calc(${focusStrokeWidth} * 1px); - bottom: 0; - border-bottom: calc(${focusStrokeWidth} * 1px) solid ${accentFillRest}; - border-bottom-left-radius: calc(${controlCornerRadius} * 1px); - border-bottom-right-radius: calc(${controlCornerRadius} * 1px); - z-index: 2; - transition: all 300ms cubic-bezier(0.1, 0.9, 0.2, 1); + :host(:not([disabled]):active)::after, + :host(:not([disabled]):focus-within:not(:active))::after { + content: ''; + position: absolute; + height: calc(${focusStrokeWidth} * 1px); + bottom: 0; + border-bottom: calc(${focusStrokeWidth} * 1px) solid ${accentFillRest}; + border-bottom-left-radius: calc(${controlCornerRadius} * 1px); + border-bottom-right-radius: calc(${controlCornerRadius} * 1px); + z-index: 2; + transition: all 300ms cubic-bezier(0.1, 0.9, 0.2, 1); + } } `; /** + * The visual styles for inputs with `appearance='outline'`. + * * @internal */ -export const inputFilledStyles: ( + export const inputOutlineStyles: ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - rootSelector: string, + logicalControlSelector: string, + interactivitySelector?: string, ) => ElementStyles = ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - rootSelector: string, + logicalControlSelector: string, + interactivitySelector: string = ':not([disabled]):not(:focus-within)', ) => css` - :host ${rootSelector} { - background: ${neutralFillSecondaryRest}; - border-color: transparent; + ${logicalControlSelector} { + background: padding-box linear-gradient(${neutralFillInputRest}, ${neutralFillInputRest}), + border-box ${neutralStrokeInputRest}; } - :host(:hover:not([disabled]):not(:focus-within)) ${rootSelector} { - background: ${neutralFillSecondaryHover}; - border-color: transparent; + :host(${interactivitySelector}:hover) ${logicalControlSelector} { + background: padding-box linear-gradient(${neutralFillInputHover}, ${neutralFillInputHover}), + border-box ${neutralStrokeInputHover}; } - .control::placeholder { - color: ${filledPlaceholderRest}; + :host(:not([disabled]):focus-within) ${logicalControlSelector} { + background: padding-box linear-gradient(${neutralFillInputFocus}, ${neutralFillInputFocus}), + border-box ${neutralStrokeInputRest}; + } + + :host([disabled]) ${logicalControlSelector} { + background: padding-box linear-gradient(${neutralFillInputRest}, ${neutralFillInputRest}), + border-box ${neutralStrokeRest}; } - :host(:hover:not([disabled]):not(:focus-within)) .control::placeholder { - color: ${filledPlaceholderHover}; + .control::placeholder { + color: ${placeholderRest}; } - :host(:focus-within:not([disabled])) ${rootSelector} { - border-color: transparent; + :host(${interactivitySelector}:hover) .control::placeholder { + color: ${placeholderHover}; } `; /** + * The visual styles for inputs with `appearance='filled'`. + * * @internal */ -export const inputForcedColorStyles: ( +export const inputFilledStyles: ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - rootSelector: string, + logicalControlSelector: string, + interactivitySelector?: string, ) => ElementStyles = ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - rootSelector: string, + logicalControlSelector: string, + interactivitySelector: string = ':not([disabled]):not(:focus-within)', ) => css` - :host ${rootSelector} { - background: ${SystemColors.Field}; - border-color: ${SystemColors.FieldText}; + ${logicalControlSelector} { + background: ${neutralFillSecondaryRest}; } - :host(:hover:not([disabled]):not(:focus-within)) ${rootSelector} { - border-color: ${SystemColors.Highlight}; + + :host(${interactivitySelector}:hover) ${logicalControlSelector} { + background: ${neutralFillSecondaryHover}; } - :host(:not([disabled]):active)::after, - :host(:not([disabled]):focus-within:not(:active))::after { - border-bottom-color: ${SystemColors.Highlight}; + + :host(:not([disabled]):focus-within) ${logicalControlSelector} { + background: ${neutralFillSecondaryFocus}; } - :host([disabled]) { - opacity: 1; + + :host([disabled]) ${logicalControlSelector} { + background: ${neutralFillSecondaryRest}; } - :host([disabled]) ${rootSelector} { - border-color: ${SystemColors.GrayText}; + + .control::placeholder { + color: ${filledPlaceholderRest}; } - :host([disabled]) ::placeholder, - :host([disabled]) ::-webkit-input-placeholder, - :host([disabled]) .label { - color: ${SystemColors.GrayText}; - fill: currentcolor; + + :host(${interactivitySelector}:hover) .control::placeholder { + color: ${filledPlaceholderHover}; } `; /** * @internal */ -export const inputFilledForcedColorStyles: ( +export const inputForcedColorStyles: ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - rootSelector: string, + logicalControlSelector: string, + interactivitySelector?: string, ) => ElementStyles = ( context: ElementDefinitionContext, definition: FoundationElementDefinition, - rootSelector: string, + logicalControlSelector: string, + interactivitySelector: string = ':not([disabled]):not(:focus-within)', ) => css` - :host ${rootSelector}, - :host(:hover:not([disabled])) ${rootSelector}, - :host(:active:not([disabled])) ${rootSelector}, - :host(:focus-within:not([disabled])) ${rootSelector} { - background: ${SystemColors.Field}; - border-color: ${SystemColors.FieldText}; + :host { + color: ${SystemColors.ButtonText}; + } + + ${logicalControlSelector} { + background: ${SystemColors.ButtonFace}; + border-color: ${SystemColors.ButtonText}; } - :host(:not([disabled]):active)::after, - :host(:not([disabled]):focus-within:not(:active))::after { - border-bottom-color: ${SystemColors.Highlight}; + + :host(${interactivitySelector}:hover) ${logicalControlSelector}, + :host(:not([disabled]):focus-within) ${logicalControlSelector} { + border-color: ${SystemColors.Highlight}; } - :host([disabled]) ${rootSelector} { + + :host([disabled]) ${logicalControlSelector} { + opacity: 1; + background: ${SystemColors.ButtonFace}; border-color: ${SystemColors.GrayText}; } + + .control::placeholder, + :host(${interactivitySelector}:hover) .control::placeholder { + color: ${SystemColors.CanvasText}; + } + + :host(:not([disabled]):focus) ${logicalControlSelector} { + ${focusTreatmentBase} + outline-color: ${SystemColors.Highlight}; + } + + :host([disabled]) { + opacity: 1; + color: ${SystemColors.GrayText}; + } + + :host([disabled]) ::placeholder, + :host([disabled]) ::-webkit-input-placeholder { + color: ${SystemColors.GrayText}; + } `; diff --git a/packages/web-components/src/text-area/text-area.styles.ts b/packages/web-components/src/text-area/text-area.styles.ts index 506a31489f91c4..5846a28de18bc6 100644 --- a/packages/web-components/src/text-area/text-area.styles.ts +++ b/packages/web-components/src/text-area/text-area.styles.ts @@ -6,37 +6,28 @@ import { FoundationElementDefinition, } from '@microsoft/fast-foundation'; import { + baseInputStyles, heightNumber, - inputFilledForcedColorStyles, inputFilledStyles, inputForcedColorStyles, + inputOutlineStyles, inputStateStyles, - inputStyles, } from '../styles'; import { appearanceBehavior } from '../utilities/behaviors'; import { designUnit } from '../design-tokens'; -export const textAreaFilledStyles: ( +const logicalControlSelector: string = '.control'; + +export const textAreaStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition) => ElementStyles = ( context: ElementDefinitionContext, definition: FoundationElementDefinition, -) => ElementStyles = (context: ElementDefinitionContext, definition: FoundationElementDefinition) => - css` - ${inputFilledStyles(context, definition, '.control')} - `.withBehaviors( - forcedColorsStylesheetBehavior( - css` - ${inputFilledForcedColorStyles(context, definition, '.control')} - `, - ), - ); - -export const textAreaStyles = (context, definition) => +) => css` ${display('inline-flex')} - ${inputStyles(context, definition, '.control')} + ${baseInputStyles(context, definition, logicalControlSelector)} - ${inputStateStyles(context, definition, '.control')} + ${inputStateStyles(context, definition, logicalControlSelector)} :host { flex-direction: column; @@ -64,10 +55,7 @@ export const textAreaStyles = (context, definition) => resize: vertical; } `.withBehaviors( - appearanceBehavior('filled', textAreaFilledStyles(context, definition)), - forcedColorsStylesheetBehavior( - css` - ${inputForcedColorStyles(context, definition, '.control')} - `, - ), + appearanceBehavior('outline', inputOutlineStyles(context, definition, logicalControlSelector)), + appearanceBehavior('filled', inputFilledStyles(context, definition, logicalControlSelector)), + forcedColorsStylesheetBehavior(inputForcedColorStyles(context, definition, logicalControlSelector)), ); diff --git a/packages/web-components/src/text-field/text-field.styles.ts b/packages/web-components/src/text-field/text-field.styles.ts index 1846202e938e91..110607e7c3a4b0 100644 --- a/packages/web-components/src/text-field/text-field.styles.ts +++ b/packages/web-components/src/text-field/text-field.styles.ts @@ -6,36 +6,27 @@ import { FoundationElementDefinition, } from '@microsoft/fast-foundation'; import { - inputFilledForcedColorStyles, + baseInputStyles, inputFilledStyles, inputForcedColorStyles, + inputOutlineStyles, inputStateStyles, - inputStyles, } from '../styles'; import { appearanceBehavior } from '../utilities/behaviors'; import { designUnit } from '../design-tokens'; -export const textFieldFilledStyles: ( +const logicalControlSelector: string = '.root'; + +export const textFieldStyles: (context: ElementDefinitionContext, definition: FoundationElementDefinition) => ElementStyles = ( context: ElementDefinitionContext, definition: FoundationElementDefinition, -) => ElementStyles = (context: ElementDefinitionContext, definition: FoundationElementDefinition) => - css` - ${inputFilledStyles(context, definition, '.root')} - `.withBehaviors( - forcedColorsStylesheetBehavior( - css` - ${inputFilledForcedColorStyles(context, definition, '.root')} - `, - ), - ); - -export const textFieldStyles = (context, definition) => +) => css` ${display('inline-block')} - ${inputStyles(context, definition, '.root')} + ${baseInputStyles(context, definition, logicalControlSelector)} - ${inputStateStyles(context, definition, '.root')} + ${inputStateStyles(context, definition, logicalControlSelector)} .root { display: flex; @@ -72,10 +63,7 @@ export const textFieldStyles = (context, definition) => margin-inline-end: 11px; } `.withBehaviors( - appearanceBehavior('filled', textFieldFilledStyles(context, definition)), - forcedColorsStylesheetBehavior( - css` - ${inputForcedColorStyles(context, definition, '.root')} - `, - ), + appearanceBehavior('outline', inputOutlineStyles(context, definition, logicalControlSelector)), + appearanceBehavior('filled', inputFilledStyles(context, definition, logicalControlSelector)), + forcedColorsStylesheetBehavior(inputForcedColorStyles(context, definition, logicalControlSelector)), );