From 6e8904332dd4e24384772596bed67a34d3a49103 Mon Sep 17 00:00:00 2001 From: Oleksandr Fediashov Date: Thu, 13 Oct 2022 15:57:13 +0200 Subject: [PATCH 1/4] chore: refactor styles for Button --- ...-9d2cbb68-9215-4318-ad2a-99ab636a11cd.json | 7 + ...-b61e9cf0-13d7-4738-883a-48c34d57d26e.json | 7 + .../src/components/Button/useButtonStyles.ts | 213 +++++++++--------- .../etc/react-components.api.md | 6 + .../react-components/src/index.ts | 2 + 5 files changed, 128 insertions(+), 107 deletions(-) create mode 100644 change/@fluentui-react-button-9d2cbb68-9215-4318-ad2a-99ab636a11cd.json create mode 100644 change/@fluentui-react-components-b61e9cf0-13d7-4738-883a-48c34d57d26e.json diff --git a/change/@fluentui-react-button-9d2cbb68-9215-4318-ad2a-99ab636a11cd.json b/change/@fluentui-react-button-9d2cbb68-9215-4318-ad2a-99ab636a11cd.json new file mode 100644 index 0000000000000..b7e5109694631 --- /dev/null +++ b/change/@fluentui-react-button-9d2cbb68-9215-4318-ad2a-99ab636a11cd.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "chore: refactor to use makeResetStyles", + "packageName": "@fluentui/react-button", + "email": "olfedias@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@fluentui-react-components-b61e9cf0-13d7-4738-883a-48c34d57d26e.json b/change/@fluentui-react-components-b61e9cf0-13d7-4738-883a-48c34d57d26e.json new file mode 100644 index 0000000000000..438ab4abb3a0c --- /dev/null +++ b/change/@fluentui-react-components-b61e9cf0-13d7-4738-883a-48c34d57d26e.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "chore: add exports for CSS extraction in Griffel", + "packageName": "@fluentui/react-components", + "email": "olfedias@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-components/react-button/src/components/Button/useButtonStyles.ts b/packages/react-components/react-button/src/components/Button/useButtonStyles.ts index dfbdff1acc6fc..9033b41bdbde9 100644 --- a/packages/react-components/react-button/src/components/Button/useButtonStyles.ts +++ b/packages/react-components/react-button/src/components/Button/useButtonStyles.ts @@ -1,7 +1,7 @@ import { iconFilledClassName, iconRegularClassName } from '@fluentui/react-icons'; import { createCustomFocusIndicatorStyle } from '@fluentui/react-tabster'; import { tokens } from '@fluentui/react-theme'; -import { shorthands, makeStyles, mergeClasses } from '@griffel/react'; +import { shorthands, makeStyles, makeResetStyles, mergeClasses } from '@griffel/react'; import type { SlotClassNames } from '@fluentui/react-utilities'; import type { ButtonSlots, ButtonState } from './Button.types'; @@ -15,93 +15,123 @@ const iconSpacingVar = '--fui-Button__icon--spacing'; const buttonSpacingSmall = '3px'; const buttonSpacingMedium = '5px'; -const useRootStyles = makeStyles({ - // Base styles - base: { - alignItems: 'center', - boxSizing: 'border-box', - display: 'inline-flex', - justifyContent: 'center', - textDecorationLine: 'none', - verticalAlign: 'middle', +const useRootBaseClassName = makeResetStyles({ + alignItems: 'center', + boxSizing: 'border-box', + display: 'inline-flex', + justifyContent: 'center', + textDecorationLine: 'none', + verticalAlign: 'middle', - ...shorthands.margin(0), + margin: 0, + overflow: 'hidden', - ...shorthands.overflow('hidden'), + backgroundColor: tokens.colorNeutralBackground1, + color: tokens.colorNeutralForeground1, + border: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke1}`, - backgroundColor: tokens.colorNeutralBackground1, - color: tokens.colorNeutralForeground1, - ...shorthands.border(tokens.strokeWidthThin, 'solid', tokens.colorNeutralStroke1), - - fontFamily: tokens.fontFamilyBase, - - outlineStyle: 'none', + fontFamily: tokens.fontFamilyBase, + outlineStyle: 'none', - ':hover': { - backgroundColor: tokens.colorNeutralBackground1Hover, - ...shorthands.borderColor(tokens.colorNeutralStroke1Hover), - color: tokens.colorNeutralForeground1Hover, + ':hover': { + backgroundColor: tokens.colorNeutralBackground1Hover, + borderColor: tokens.colorNeutralStroke1Hover, + color: tokens.colorNeutralForeground1Hover, - cursor: 'pointer', + cursor: 'pointer', - [`& .${iconFilledClassName}`]: { - display: 'inline', - }, - [`& .${iconRegularClassName}`]: { - display: 'none', - }, + [`& .${iconFilledClassName}`]: { + display: 'inline', + }, + [`& .${iconRegularClassName}`]: { + display: 'none', }, + }, - ':hover:active': { - backgroundColor: tokens.colorNeutralBackground1Pressed, - ...shorthands.borderColor(tokens.colorNeutralStroke1Pressed), - color: tokens.colorNeutralForeground1Pressed, + ':hover:active': { + backgroundColor: tokens.colorNeutralBackground1Pressed, + borderColor: tokens.colorNeutralStroke1Pressed, + color: tokens.colorNeutralForeground1Pressed, - outlineStyle: 'none', + outlineStyle: 'none', - [`& .${iconFilledClassName}`]: { - display: 'inline', - }, - [`& .${iconRegularClassName}`]: { - display: 'none', - }, + [`& .${iconFilledClassName}`]: { + display: 'inline', + }, + [`& .${iconRegularClassName}`]: { + display: 'none', }, }, + padding: `${buttonSpacingMedium} ${tokens.spacingHorizontalM}`, + minWidth: '96px', + borderRadius: tokens.borderRadiusMedium, + + fontSize: tokens.fontSizeBase300, + fontWeight: tokens.fontWeightSemibold, + lineHeight: tokens.lineHeightBase300, + // Transition styles - transition: { - transitionDuration: tokens.durationFaster, - transitionProperty: 'background, border, color', - transitionTimingFunction: tokens.curveEasyEase, - '@media screen and (prefers-reduced-motion: reduce)': { - transitionDuration: '0.01ms', - }, + transitionDuration: tokens.durationFaster, + transitionProperty: 'background, border, color', + transitionTimingFunction: tokens.curveEasyEase, + + '@media screen and (prefers-reduced-motion: reduce)': { + transitionDuration: '0.01ms', }, // High contrast styles - highContrast: { - '@media (forced-colors: active)': { - ':focus': { - ...shorthands.borderColor('ButtonText'), - }, - ':hover': { - backgroundColor: 'HighlightText', - ...shorthands.borderColor('Highlight'), - color: 'Highlight', - forcedColorAdjust: 'none', - }, + '@media (forced-colors: active)': { + ':focus': { + borderColor: 'ButtonText', + }, - ':hover:active': { - backgroundColor: 'HighlightText', - ...shorthands.borderColor('Highlight'), - color: 'Highlight', - forcedColorAdjust: 'none', - }, + ':hover': { + backgroundColor: 'HighlightText', + borderColor: 'Highlight', + color: 'Highlight', + forcedColorAdjust: 'none', + }, + + ':hover:active': { + backgroundColor: 'HighlightText', + borderColor: 'Highlight', + color: 'Highlight', + forcedColorAdjust: 'none', }, }, + // Focus styles + + ...createCustomFocusIndicatorStyle({ + ...shorthands.borderColor(tokens.colorTransparentStroke), + ...shorthands.borderRadius(tokens.borderRadiusMedium), + outlineColor: tokens.colorTransparentStroke, + outlineWidth: tokens.strokeWidthThick, + outlineStyle: 'solid', + boxShadow: ` + ${tokens.shadow4}, + 0 0 0 2px ${tokens.colorStrokeFocus2} + `, + zIndex: 1, + }), +}); + +const useIconBaseClassName = makeResetStyles({ + alignItems: 'center', + display: 'inline-flex', + justifyContent: 'center', + + fontSize: '20px', + height: '20px', + width: '20px', + + [iconSpacingVar]: tokens.spacingHorizontalSNudge, +}); + +const useRootStyles = makeStyles({ // Appearance variations outline: { backgroundColor: tokens.colorTransparentBackground, @@ -201,15 +231,7 @@ const useRootStyles = makeStyles({ lineHeight: tokens.lineHeightBase200, }, medium: { - ...shorthands.padding(buttonSpacingMedium, tokens.spacingHorizontalM), - - minWidth: '96px', - - ...shorthands.borderRadius(tokens.borderRadiusMedium), - - fontSize: tokens.fontSizeBase300, - fontWeight: tokens.fontWeightSemibold, - lineHeight: tokens.lineHeightBase300, + /* defined in base styles */ }, large: { ...shorthands.padding(tokens.spacingVerticalS, tokens.spacingHorizontalL), @@ -343,18 +365,6 @@ const useRootDisabledStyles = makeStyles({ }); const useRootFocusStyles = makeStyles({ - base: createCustomFocusIndicatorStyle({ - ...shorthands.borderColor(tokens.colorTransparentStroke), - outlineColor: tokens.colorTransparentStroke, - outlineWidth: tokens.strokeWidthThick, - outlineStyle: 'solid', - boxShadow: ` - ${tokens.shadow4}, - 0 0 0 2px ${tokens.colorStrokeFocus2} - `, - zIndex: 1, - }), - // Shape variations circular: createCustomFocusIndicatorStyle({ ...shorthands.borderRadius(tokens.borderRadiusCircular), @@ -376,9 +386,9 @@ const useRootFocusStyles = makeStyles({ small: createCustomFocusIndicatorStyle({ ...shorthands.borderRadius(tokens.borderRadiusSmall), }), - medium: createCustomFocusIndicatorStyle({ - ...shorthands.borderRadius(tokens.borderRadiusMedium), - }), + medium: { + /* defined in base styles */ + }, large: createCustomFocusIndicatorStyle({ ...shorthands.borderRadius(tokens.borderRadiusLarge), }), @@ -407,13 +417,6 @@ const useRootIconOnlyStyles = makeStyles({ }); const useIconStyles = makeStyles({ - // Base styles - base: { - alignItems: 'center', - display: 'inline-flex', - justifyContent: 'center', - }, - // Size variations small: { fontSize: '20px', @@ -423,11 +426,7 @@ const useIconStyles = makeStyles({ [iconSpacingVar]: tokens.spacingHorizontalXS, }, medium: { - fontSize: '20px', - height: '20px', - width: '20px', - - [iconSpacingVar]: tokens.spacingHorizontalSNudge, + /* defined in base styles */ }, large: { fontSize: '24px', @@ -447,6 +446,9 @@ const useIconStyles = makeStyles({ }); export const useButtonStyles_unstable = (state: ButtonState): ButtonState => { + const rootBaseClassName = useRootBaseClassName(); + const iconBaseClassName = useIconBaseClassName(); + const rootStyles = useRootStyles(); const rootDisabledStyles = useRootDisabledStyles(); const rootFocusStyles = useRootFocusStyles(); @@ -457,12 +459,10 @@ export const useButtonStyles_unstable = (state: ButtonState): ButtonState => { state.root.className = mergeClasses( buttonClassNames.root, + rootBaseClassName, - // Root styles - rootStyles.base, - rootStyles.transition, - rootStyles.highContrast, appearance && rootStyles[appearance], + rootStyles[size], rootStyles[shape], @@ -472,7 +472,6 @@ export const useButtonStyles_unstable = (state: ButtonState): ButtonState => { appearance && (disabled || disabledFocusable) && rootDisabledStyles[appearance], // Focus styles - rootFocusStyles.base, appearance === 'primary' && rootFocusStyles.primary, rootFocusStyles[size], rootFocusStyles[shape], @@ -487,7 +486,7 @@ export const useButtonStyles_unstable = (state: ButtonState): ButtonState => { if (state.icon) { state.icon.className = mergeClasses( buttonClassNames.icon, - iconStyles.base, + iconBaseClassName, state.root.children !== undefined && state.root.children !== null && iconStyles[iconPosition], iconStyles[size], state.icon.className, diff --git a/packages/react-components/react-components/etc/react-components.api.md b/packages/react-components/react-components/etc/react-components.api.md index e1b79075c3bfb..8ee942a41bd03 100644 --- a/packages/react-components/react-components/etc/react-components.api.md +++ b/packages/react-components/react-components/etc/react-components.api.md @@ -5,6 +5,8 @@ ```ts import { __css } from '@griffel/react'; +import { __resetCSS } from '@griffel/react'; +import { __resetStyles } from '@griffel/react'; import { __styles } from '@griffel/react'; import { Accordion } from '@fluentui/react-accordion'; import { accordionClassNames } from '@fluentui/react-accordion'; @@ -632,6 +634,10 @@ import { webLightTheme } from '@fluentui/react-theme'; export { __css } +export { __resetCSS } + +export { __resetStyles } + export { __styles } export { Accordion } diff --git a/packages/react-components/react-components/src/index.ts b/packages/react-components/react-components/src/index.ts index 0461349fec16f..d9830f6428183 100644 --- a/packages/react-components/react-components/src/index.ts +++ b/packages/react-components/react-components/src/index.ts @@ -2,6 +2,8 @@ export { __css, __styles, + __resetStyles, + __resetCSS, createDOMRenderer, makeStaticStyles, makeStyles, From 444bef60f042307c498a4a33fa0691059e41c39b Mon Sep 17 00:00:00 2001 From: Oleksandr Fediashov Date: Wed, 23 Nov 2022 12:23:42 +0100 Subject: [PATCH 2/4] refactor createCustomFocusIndicatorStyle to allow CSS shorthands --- .../src/components/Button/useButtonStyles.ts | 8 ++-- .../react-tabster/etc/react-tabster.api.md | 3 +- .../focus/createCustomFocusIndicatorStyle.ts | 41 +++++++++++-------- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/packages/react-components/react-button/src/components/Button/useButtonStyles.ts b/packages/react-components/react-button/src/components/Button/useButtonStyles.ts index 9033b41bdbde9..6dc0b1cb21b2d 100644 --- a/packages/react-components/react-button/src/components/Button/useButtonStyles.ts +++ b/packages/react-components/react-button/src/components/Button/useButtonStyles.ts @@ -106,11 +106,9 @@ const useRootBaseClassName = makeResetStyles({ // Focus styles ...createCustomFocusIndicatorStyle({ - ...shorthands.borderColor(tokens.colorTransparentStroke), - ...shorthands.borderRadius(tokens.borderRadiusMedium), - outlineColor: tokens.colorTransparentStroke, - outlineWidth: tokens.strokeWidthThick, - outlineStyle: 'solid', + borderColor: tokens.colorTransparentStroke, + borderRadius: tokens.borderRadiusMedium, + outline: `${tokens.strokeWidthThick} solid ${tokens.colorTransparentStroke}`, boxShadow: ` ${tokens.shadow4}, 0 0 0 2px ${tokens.colorStrokeFocus2} diff --git a/packages/react-components/react-tabster/etc/react-tabster.api.md b/packages/react-components/react-tabster/etc/react-tabster.api.md index af80d9164e99d..a492d34543bc4 100644 --- a/packages/react-components/react-tabster/etc/react-tabster.api.md +++ b/packages/react-components/react-tabster/etc/react-tabster.api.md @@ -5,6 +5,7 @@ ```ts import type { GriffelStyle } from '@griffel/react'; +import { makeResetStyles } from '@griffel/react'; import * as React_2 from 'react'; import type { RefObject } from 'react'; import { Types } from 'tabster'; @@ -13,7 +14,7 @@ import { Types } from 'tabster'; export function applyFocusVisiblePolyfill(scope: HTMLElement, win: Window): () => void; // @public -export const createCustomFocusIndicatorStyle: (style: GriffelStyle, { selector, enableOutline, }?: CreateCustomFocusIndicatorStyleOptions) => GriffelStyle; +export function createCustomFocusIndicatorStyle(style: TStyle, { selector, enableOutline, }?: CreateCustomFocusIndicatorStyleOptions): TStyle extends GriffelStyle ? GriffelStyle : GriffelResetStyle; // @public (undocumented) export interface CreateCustomFocusIndicatorStyleOptions { diff --git a/packages/react-components/react-tabster/src/focus/createCustomFocusIndicatorStyle.ts b/packages/react-components/react-tabster/src/focus/createCustomFocusIndicatorStyle.ts index a338762ec2e81..5ad628256b336 100644 --- a/packages/react-components/react-tabster/src/focus/createCustomFocusIndicatorStyle.ts +++ b/packages/react-components/react-tabster/src/focus/createCustomFocusIndicatorStyle.ts @@ -1,6 +1,11 @@ import { defaultOptions, FOCUS_VISIBLE_ATTR, FOCUS_WITHIN_ATTR } from './constants'; +import { makeResetStyles } from '@griffel/react'; import type { GriffelStyle } from '@griffel/react'; +// TODO: Use the directly from @griffel/react +// https://github.com/microsoft/griffel/pull/278 +type GriffelResetStyle = Parameters[0]; + export interface CreateCustomFocusIndicatorStyleOptions { selector?: 'focus' | 'focus-within'; /** @@ -14,27 +19,29 @@ export interface CreateCustomFocusIndicatorStyleOptions { * Creates a style for @see makeStyles that includes the necessary selectors for focus. * Should be used only when @see createFocusOutlineStyle does not fit requirements * - * @param style - styling applied on focus, defaults to @see getDefaultFocusOutlineStyes + * @param style - styling applied on focus, defaults to @see getDefaultFocusOutlineStyles * @param options - Configure the style of the focus outline */ -export const createCustomFocusIndicatorStyle = ( - style: GriffelStyle, +export function createCustomFocusIndicatorStyle( + style: TStyle, { selector = defaultOptions.selector, enableOutline = false, }: CreateCustomFocusIndicatorStyleOptions = defaultOptions, -): GriffelStyle => ({ - ':focus': { - outlineStyle: enableOutline ? undefined : 'none', - }, - ':focus-visible': { - outlineStyle: enableOutline ? undefined : 'none', - }, +): TStyle extends GriffelStyle ? GriffelStyle : GriffelResetStyle { + return { + ':focus': { + outlineStyle: enableOutline ? undefined : 'none', + }, + ':focus-visible': { + outlineStyle: enableOutline ? undefined : 'none', + }, - ...(selector === 'focus' && { - [`&[${FOCUS_VISIBLE_ATTR}]`]: style, - }), - ...(selector === 'focus-within' && { - [`&[${FOCUS_WITHIN_ATTR}]:${selector}`]: style, - }), -}); + ...(selector === 'focus' && { + [`&[${FOCUS_VISIBLE_ATTR}]`]: style, + }), + ...(selector === 'focus-within' && { + [`&[${FOCUS_WITHIN_ATTR}]:${selector}`]: style, + }), + }; +} From 91d604f08a8acf01175bedbf8d923d480d19a261 Mon Sep 17 00:00:00 2001 From: Oleksandr Fediashov Date: Wed, 23 Nov 2022 13:07:02 +0100 Subject: [PATCH 3/4] change file --- ...react-tabster-d0eee5e7-8825-41d7-a50f-2737705f2e09.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@fluentui-react-tabster-d0eee5e7-8825-41d7-a50f-2737705f2e09.json diff --git a/change/@fluentui-react-tabster-d0eee5e7-8825-41d7-a50f-2737705f2e09.json b/change/@fluentui-react-tabster-d0eee5e7-8825-41d7-a50f-2737705f2e09.json new file mode 100644 index 0000000000000..35cb1f030d539 --- /dev/null +++ b/change/@fluentui-react-tabster-d0eee5e7-8825-41d7-a50f-2737705f2e09.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "fix: allow GriffelResetStyle to be passed to createCustomFocusIndicatorStyle", + "packageName": "@fluentui/react-tabster", + "email": "olfedias@microsoft.com", + "dependentChangeType": "patch" +} From acc75250eb6d54440a4205c966f66a92ebb0c1ef Mon Sep 17 00:00:00 2001 From: Oleksandr Fediashov Date: Wed, 30 Nov 2022 10:05:31 +0100 Subject: [PATCH 4/4] Apply suggestions from code review Co-authored-by: Makoto Morimoto --- packages/react-components/react-components/src/index.ts | 4 ++-- .../src/focus/createCustomFocusIndicatorStyle.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-components/react-components/src/index.ts b/packages/react-components/react-components/src/index.ts index d9830f6428183..396be72011b4b 100644 --- a/packages/react-components/react-components/src/index.ts +++ b/packages/react-components/react-components/src/index.ts @@ -1,9 +1,9 @@ // Utilities export { __css, - __styles, - __resetStyles, __resetCSS, + __resetStyles, + __styles, createDOMRenderer, makeStaticStyles, makeStyles, diff --git a/packages/react-components/react-tabster/src/focus/createCustomFocusIndicatorStyle.ts b/packages/react-components/react-tabster/src/focus/createCustomFocusIndicatorStyle.ts index 5ad628256b336..832e4ec3a2042 100644 --- a/packages/react-components/react-tabster/src/focus/createCustomFocusIndicatorStyle.ts +++ b/packages/react-components/react-tabster/src/focus/createCustomFocusIndicatorStyle.ts @@ -2,7 +2,7 @@ import { defaultOptions, FOCUS_VISIBLE_ATTR, FOCUS_WITHIN_ATTR } from './constan import { makeResetStyles } from '@griffel/react'; import type { GriffelStyle } from '@griffel/react'; -// TODO: Use the directly from @griffel/react +// TODO: Use the type directly from @griffel/react // https://github.com/microsoft/griffel/pull/278 type GriffelResetStyle = Parameters[0];