diff --git a/change/@fluentui-react-theme-146a4801-8176-4b81-ac38-9046973ce1a4.json b/change/@fluentui-react-theme-146a4801-8176-4b81-ac38-9046973ce1a4.json new file mode 100644 index 00000000000000..d7ed7c4d9607e4 --- /dev/null +++ b/change/@fluentui-react-theme-146a4801-8176-4b81-ac38-9046973ce1a4.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "chore(react-theme): Migrate to new DX", + "packageName": "@fluentui/react-theme", + "email": "miroslav.stastny@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/jest.config.js b/jest.config.js index 3b4f37d886127e..50decdebaea497 100644 --- a/jest.config.js +++ b/jest.config.js @@ -21,6 +21,7 @@ module.exports = { '/packages/jest-serializer-make-styles', '/packages/react-context-selector', '/packages/babel-make-styles', + '/packages/react-theme', '/packages/react-badge', ], }; diff --git a/nx.json b/nx.json index f9c0da1a2df98f..e7801050e6e0fa 100644 --- a/nx.json +++ b/nx.json @@ -113,7 +113,7 @@ "@fluentui/react-tabs": { "implicitDependencies": [] }, "@fluentui/react-tabster": { "tags": ["vNext", "platform:web"], "implicitDependencies": [] }, "@fluentui/react-text": { "tags": ["vNext", "platform:web"], "implicitDependencies": [] }, - "@fluentui/react-theme": { "implicitDependencies": [] }, + "@fluentui/react-theme": { "tags": ["vNext", "platform:web"], "implicitDependencies": [] }, "@fluentui/react-toggle": { "implicitDependencies": [] }, "@fluentui/react-tooltip": { "implicitDependencies": [] }, "@fluentui/react-utilities": { "implicitDependencies": [] }, diff --git a/packages/react-theme/config/api-extractor.json b/packages/react-theme/config/api-extractor.json new file mode 100644 index 00000000000000..f890ae360b7f7f --- /dev/null +++ b/packages/react-theme/config/api-extractor.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "extends": "@fluentui/scripts/api-extractor/api-extractor.common.json" +} diff --git a/packages/react-theme/config/api-extractor.local.json b/packages/react-theme/config/api-extractor.local.json new file mode 100644 index 00000000000000..c2ea401c1c3685 --- /dev/null +++ b/packages/react-theme/config/api-extractor.local.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "extends": "./api-extractor.json", + "mainEntryPointFilePath": "/dist//src/index.d.ts" +} diff --git a/packages/react-theme/config/tests.js b/packages/react-theme/config/tests.js new file mode 100644 index 00000000000000..3882d3702ddc99 --- /dev/null +++ b/packages/react-theme/config/tests.js @@ -0,0 +1,7 @@ +/** Jest test setup file. */ + +const { configure } = require('enzyme'); +const Adapter = require('enzyme-adapter-react-16'); + +// Configure enzyme. +configure({ adapter: new Adapter() }); diff --git a/packages/react-theme/etc/react-theme.api.md b/packages/react-theme/etc/react-theme.api.md new file mode 100644 index 00000000000000..98bf65332cb1f0 --- /dev/null +++ b/packages/react-theme/etc/react-theme.api.md @@ -0,0 +1,506 @@ +## API Report File for "@fluentui/react-theme" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +// @public (undocumented) +export type BackgroundColorTokens = { + background: string; + backgroundHover: string; + backgroundPressed: string; + backgroundSelected: string; +}; + +// @public (undocumented) +export const black = "#000000"; + +// @public (undocumented) +export type BorderRadius = { + none: string; + small: string; + medium: string; + large: string; + xLarge: string; + circular: string; +}; + +// @public (undocumented) +export const borderRadius: BorderRadius; + +// @public (undocumented) +export type BrandColorTokens = { + brandBackground: string; + brandBackgroundHover: string; + brandBackgroundPressed: string; + brandBackgroundSelected: string; + brandBackgroundStatic: string; +}; + +// @public (undocumented) +export type BrandVariants = ColorVariants & { + shade60: string; +}; + +// @public +export type ColorVariants = { + shade50: string; + shade40: string; + shade30: string; + shade20: string; + shade10: string; + primary: string; + tint10: string; + tint20: string; + tint30: string; + tint40: string; + tint50: string; + tint60: string; +}; + +// @public (undocumented) +export const createDarkTheme: (brand: BrandVariants) => Theme; + +// @public (undocumented) +export const createGlobalTheme: (brand: BrandVariants) => Theme['global']; + +// @public (undocumented) +export const createHighContrastTheme: (brand: BrandVariants) => Theme; + +// @public (undocumented) +export const createLightTheme: (brand: BrandVariants) => Theme; + +// @public (undocumented) +export const createTeamsDarkTheme: (brand: BrandVariants) => Theme; + +// @public (undocumented) +export type FontFamilies = { + base: string; + monospace: string; + numeric: string; +}; + +// @public (undocumented) +export const fontFamilies: FontFamilies; + +// @public (undocumented) +export type FontSizes = { + base: { + 100: string; + 200: string; + 300: string; + 400: string; + 500: string; + 600: string; + }; + hero: { + 700: string; + 800: string; + 900: string; + 1000: string; + }; +}; + +// @public (undocumented) +export const fontSizes: FontSizes; + +// @public (undocumented) +export type FontWeights = { + regular: number; + medium: number; + semibold: number; +}; + +// @public (undocumented) +export const fontWeights: FontWeights; + +// @public (undocumented) +export type GhostColorTokens = { + ghostBackground: string; + ghostBackgroundHover: string; + ghostBackgroundPressed: string; + ghostBackgroundSelected: string; +}; + +// @public +export type GlobalSharedColors = { + darkRed: ColorVariants; + burgundy: ColorVariants; + cranberry: ColorVariants; + red: ColorVariants; + darkOrange: ColorVariants; + bronze: ColorVariants; + pumpkin: ColorVariants; + orange: ColorVariants; + peach: ColorVariants; + marigold: ColorVariants; + yellow: ColorVariants; + gold: ColorVariants; + brass: ColorVariants; + brown: ColorVariants; + darkBrown: ColorVariants; + lime: ColorVariants; + forest: ColorVariants; + seafoam: ColorVariants; + lightGreen: ColorVariants; + green: ColorVariants; + darkGreen: ColorVariants; + lightTeal: ColorVariants; + teal: ColorVariants; + darkTeal: ColorVariants; + cyan: ColorVariants; + steel: ColorVariants; + lightBlue: ColorVariants; + blue: ColorVariants; + royalBlue: ColorVariants; + darkBlue: ColorVariants; + cornflower: ColorVariants; + navy: ColorVariants; + lavender: ColorVariants; + purple: ColorVariants; + darkPurple: ColorVariants; + orchid: ColorVariants; + grape: ColorVariants; + berry: ColorVariants; + lilac: ColorVariants; + pink: ColorVariants; + hotPink: ColorVariants; + magenta: ColorVariants; + plum: ColorVariants; + beige: ColorVariants; + mink: ColorVariants; + silver: ColorVariants; + platinum: ColorVariants; + anchor: ColorVariants; + charcoal: ColorVariants; +}; + +// @public (undocumented) +export const grey: { + '0': string; + '2': string; + '4': string; + '6': string; + '8': string; + '10': string; + '12': string; + '14': string; + '16': string; + '18': string; + '20': string; + '22': string; + '24': string; + '26': string; + '28': string; + '30': string; + '32': string; + '34': string; + '36': string; + '38': string; + '40': string; + '42': string; + '44': string; + '46': string; + '48': string; + '50': string; + '52': string; + '54': string; + '56': string; + '58': string; + '60': string; + '62': string; + '64': string; + '66': string; + '68': string; + '70': string; + '72': string; + '74': string; + '76': string; + '78': string; + '80': string; + '82': string; + '84': string; + '86': string; + '88': string; + '90': string; + '92': string; + '94': string; + '96': string; + '98': string; + '100': string; +}; + +// @public (undocumented) +export type Greys = 0 | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 60 | 62 | 64 | 66 | 68 | 70 | 72 | 74 | 76 | 78 | 80 | 82 | 84 | 86 | 88 | 90 | 92 | 94 | 96 | 98 | 100; + +// @public (undocumented) +export const hcButtonFace = "#ffffff"; + +// @public (undocumented) +export const hcButtonText = "#000000"; + +// @public (undocumented) +export const hcCanvas = "#000000"; + +// @public (undocumented) +export const hcCanvasText = "#ffffff"; + +// @public (undocumented) +export const hcDisabled = "#3ff23f"; + +// @public (undocumented) +export const hcHighlight = "#1aebff"; + +// @public (undocumented) +export const hcHighlightText = "#000000"; + +// @public (undocumented) +export const hcHyperlink = "#ffff00"; + +// @public (undocumented) +export type LineHeights = FontSizes; + +// @public (undocumented) +export const lineHeights: LineHeights; + +// @public (undocumented) +export function mergeThemes(a: Theme | undefined, b: PartialTheme | Theme | undefined): Theme; + +// @public +export type NeutralColorTokens = { + neutralForeground1: string; + neutralForeground2: string; + neutralForeground2Hover: string; + neutralForeground2Pressed: string; + neutralForeground2Selected: string; + neutralForeground2BrandHover: string; + neutralForeground2BrandPressed: string; + neutralForeground2BrandSelected: string; + neutralForeground3: string; + neutralForeground3Hover: string; + neutralForeground3Pressed: string; + neutralForeground3Selected: string; + neutralForeground3BrandHover: string; + neutralForeground3BrandPressed: string; + neutralForeground3BrandSelected: string; + neutralForeground4: string; + neutralForegroundDisabled: string; + brandForegroundLink: string; + brandForegroundLinkHover: string; + brandForegroundLinkPressed: string; + brandForegroundLinkSelected: string; + compoundBrandForeground1: string; + compoundBrandForeground1Hover: string; + compoundBrandForeground1Pressed: string; + brandForeground1: string; + brandForeground2: string; + neutralForegroundInverted: string; + neutralForegroundInvertedAccessible: string; + neutralForegroundInvertedLink: string; + neutralForegroundInvertedLinkHover: string; + neutralForegroundInvertedLinkPressed: string; + neutralForegroundInvertedLinkSelected: string; + neutralBackground1: string; + neutralBackground1Hover: string; + neutralBackground1Pressed: string; + neutralBackground1Selected: string; + neutralBackground2: string; + neutralBackground2Hover: string; + neutralBackground2Pressed: string; + neutralBackground2Selected: string; + neutralBackground3: string; + neutralBackground3Hover: string; + neutralBackground3Pressed: string; + neutralBackground3Selected: string; + neutralBackground4: string; + neutralBackground4Hover: string; + neutralBackground4Pressed: string; + neutralBackground4Selected: string; + neutralBackground5: string; + neutralBackground5Hover: string; + neutralBackground5Pressed: string; + neutralBackground5Selected: string; + neutralBackground6: string; + subtleBackground: string; + subtleBackgroundHover: string; + subtleBackgroundPressed: string; + subtleBackgroundSelected: string; + transparentBackground: string; + transparentBackgroundHover: string; + transparentBackgroundPressed: string; + transparentBackgroundSelected: string; + neutralBackgroundDisabled: string; + brandBackground: string; + brandBackgroundHover: string; + brandBackgroundPressed: string; + brandBackgroundSelected: string; + compoundBrandBackground: string; + compoundBrandBackgroundHover: string; + compoundBrandBackgroundPressed: string; + brandBackgroundStatic: string; + brandBackground2: string; + neutralStrokeAccessible: string; + neutralStrokeAccessibleHover: string; + neutralStrokeAccessiblePressed: string; + neutralStrokeAccessibleSelected: string; + neutralStroke1: string; + neutralStroke1Hover: string; + neutralStroke1Pressed: string; + neutralStroke1Selected: string; + neutralStroke2: string; + neutralStroke3: string; + brandStroke1: string; + brandStroke2: string; + compoundBrandStroke: string; + compoundBrandStrokeHover: string; + compoundBrandStrokePressed: string; + neutralStrokeDisabled: string; + strokeAccessible: string; + strokeAccessibleInteractive: string; + strokeAccessibleDisabled: string; + strokeFocus1: string; + strokeFocus2: string; + neutralShadowAmbient: string; + neutralShadowKey: string; + neutralShadowAmbientLighter: string; + neutralShadowKeyLighter: string; + neutralShadowAmbientDarker: string; + neutralShadowKeyDarker: string; + brandShadowAmbient: string; + brandShadowKey: string; +}; + +// Warning: (ae-forgotten-export) The symbol "RecursivePartial" needs to be exported by the entry point index.d.ts +// +// @public (undocumented) +export type PartialTheme = RecursivePartial; + +// @public +export type ProductBrandColors = { + teams: BrandVariants; + web: BrandVariants; +}; + +// @public +export type ShadowLevelTokens = { + shadow2: string; + shadow4: string; + shadow8: string; + shadow16: string; + shadow28: string; + shadow64: string; +}; + +// @public (undocumented) +export const sharedColors: GlobalSharedColors; + +// @public +export type SharedColorTokens = { + background1: string; + background2: string; + background3: string; + foreground1: string; + foreground2: string; + foreground3: string; + borderActive: string; + border2: string; +}; + +// @public (undocumented) +export type StrokeWidths = { + thin: string; + thick: string; + thicker: string; + thickest: string; +}; + +// @public (undocumented) +export const strokeWidths: StrokeWidths; + +// @public (undocumented) +export const teamsDarkTheme: Theme; + +// @public (undocumented) +export const teamsHighContrastTheme: Theme; + +// @public (undocumented) +export const teamsLightTheme: Theme; + +// @public (undocumented) +export type TextAlignment = 'inherit' | 'initial' | 'revert' | 'unset' | 'center' | 'end' | 'start' | 'justify' | 'left' | 'match-parent' | 'right'; + +// @public (undocumented) +export type TextAlignments = { + start: TextAlignment; + center: TextAlignment; + end: TextAlignment; + justify: TextAlignment; +}; + +// @public (undocumented) +export const textAlignments: TextAlignments; + +// @public (undocumented) +export type Theme = { + global: { + color: { + black: string; + white: string; + hcHyperlink: string; + hcHighlight: string; + hcDisabled: string; + hcCanvas: string; + hcCanvasText: string; + hcHighlightText: string; + hcButtonText: string; + hcButtonFace: string; + }; + palette: GlobalSharedColors & { + brand: BrandVariants; + grey: Record; + }; + type: { + fontSizes: FontSizes; + fontWeights: FontWeights; + fontFamilies: FontFamilies; + lineHeights: LineHeights; + alignment: TextAlignments; + }; + borderRadius: BorderRadius; + strokeWidth: StrokeWidths; + }; + alias: { + color: Record & { + neutral: NeutralColorTokens; + }; + shadow: ShadowLevelTokens; + }; +}; + +// @public (undocumented) +export function themeToCSSVariables(theme: Theme): Record; + +// @public (undocumented) +export type TransparentColorTokens = { + transparentBackground: string; + transparentBackgroundHover: string; + transparentBackgroundPressed: string; + transparentBackgroundSelected: string; +}; + +// @public (undocumented) +export const webDarkTheme: Theme; + +// @public (undocumented) +export const webHighContrastTheme: Theme; + +// @public (undocumented) +export const webLightTheme: Theme; + +// @public (undocumented) +export const white = "#ffffff"; + + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/react-theme/jest.config.js b/packages/react-theme/jest.config.js index f95d6c5bb5c1ba..73c7cb184bf1bd 100644 --- a/packages/react-theme/jest.config.js +++ b/packages/react-theme/jest.config.js @@ -1,5 +1,20 @@ -let { createConfig } = require('@fluentui/scripts/jest/jest-resources'); +// @ts-check -const config = createConfig(); - -module.exports = config; +/** + * @type {jest.InitialOptions} + */ +module.exports = { + displayName: 'react-theme', + preset: '../../jest.preset.js', + globals: { + 'ts-jest': { + tsConfig: '/tsconfig.json', + diagnostics: false, + }, + }, + transform: { + '^.+\\.tsx?$': 'ts-jest', + }, + coverageDirectory: './coverage', + setupFilesAfterEnv: ['./config/tests.js'], +}; diff --git a/packages/react-theme/package.json b/packages/react-theme/package.json index 4d8b96f3fc0957..535876067f89dc 100644 --- a/packages/react-theme/package.json +++ b/packages/react-theme/package.json @@ -18,11 +18,11 @@ "code-style": "just-scripts code-style", "just": "just-scripts", "lint": "just-scripts lint", - "start": "echo \"This is DEPRECATED, use 'storybook' instead\" && just-scripts dev:storybook", + "start": "storybook", "storybook": "start-storybook", - "start-test": "just-scripts jest-watch", - "test": "just-scripts test", - "update-snapshots": "just-scripts jest -u" + "test": "jest", + "docs": "api-extractor run --config=config/api-extractor.local.json --local", + "build:local": "tsc -p . --module esnext --emitDeclarationOnly && node ../../scripts/typescript/normalize-import --output dist/react-theme/src && yarn docs" }, "devDependencies": { "@fluentui/eslint-plugin": "^1.3.1", diff --git a/packages/react-theme/src/themes/teams/darkTheme.ts b/packages/react-theme/src/themes/teams/darkTheme.ts index 26b32252382f5e..2fc8c9efcfb059 100644 --- a/packages/react-theme/src/themes/teams/darkTheme.ts +++ b/packages/react-theme/src/themes/teams/darkTheme.ts @@ -1,4 +1,5 @@ import { createTeamsDarkTheme } from '../../utils/createTeamsDarkTheme'; import { brandTeams } from '../../global/brandColors'; +import { Theme } from '../../types'; -export const teamsDarkTheme = createTeamsDarkTheme(brandTeams); +export const teamsDarkTheme: Theme = createTeamsDarkTheme(brandTeams); diff --git a/packages/react-theme/src/themes/teams/highContrastTheme.ts b/packages/react-theme/src/themes/teams/highContrastTheme.ts index e75eb4450e5945..45b635e2ba78d6 100644 --- a/packages/react-theme/src/themes/teams/highContrastTheme.ts +++ b/packages/react-theme/src/themes/teams/highContrastTheme.ts @@ -1,4 +1,5 @@ import { createHighContrastTheme } from '../../utils/createHighContrastTheme'; import { brandTeams } from '../../global/brandColors'; +import { Theme } from '../../types'; -export const teamsHighContrastTheme = createHighContrastTheme(brandTeams); +export const teamsHighContrastTheme: Theme = createHighContrastTheme(brandTeams); diff --git a/packages/react-theme/src/themes/teams/lightTheme.ts b/packages/react-theme/src/themes/teams/lightTheme.ts index 932cac3cdee86f..ae9a86bdb730c8 100644 --- a/packages/react-theme/src/themes/teams/lightTheme.ts +++ b/packages/react-theme/src/themes/teams/lightTheme.ts @@ -1,4 +1,5 @@ import { createLightTheme } from '../../utils/createLightTheme'; import { brandTeams } from '../../global/brandColors'; +import { Theme } from '../../types'; -export const teamsLightTheme = createLightTheme(brandTeams); +export const teamsLightTheme: Theme = createLightTheme(brandTeams); diff --git a/packages/react-theme/src/themes/web/darkTheme.ts b/packages/react-theme/src/themes/web/darkTheme.ts index 8ed4fe286a4b4e..9bb685b9775c28 100644 --- a/packages/react-theme/src/themes/web/darkTheme.ts +++ b/packages/react-theme/src/themes/web/darkTheme.ts @@ -1,4 +1,5 @@ import { createDarkTheme } from '../../utils/createDarkTheme'; import { brandWeb } from '../../global/brandColors'; +import { Theme } from '../../types'; -export const webDarkTheme = createDarkTheme(brandWeb); +export const webDarkTheme: Theme = createDarkTheme(brandWeb); diff --git a/packages/react-theme/src/themes/web/highContrastTheme.ts b/packages/react-theme/src/themes/web/highContrastTheme.ts index b9817495ce3d03..92955fdd60f2a1 100644 --- a/packages/react-theme/src/themes/web/highContrastTheme.ts +++ b/packages/react-theme/src/themes/web/highContrastTheme.ts @@ -1,4 +1,5 @@ import { createHighContrastTheme } from '../../utils/createHighContrastTheme'; import { brandWeb } from '../../global/brandColors'; +import { Theme } from '../../types'; -export const webHighContrastTheme = createHighContrastTheme(brandWeb); +export const webHighContrastTheme: Theme = createHighContrastTheme(brandWeb); diff --git a/packages/react-theme/src/themes/web/lightTheme.ts b/packages/react-theme/src/themes/web/lightTheme.ts index 1d074d3016843b..d983b0074af42b 100644 --- a/packages/react-theme/src/themes/web/lightTheme.ts +++ b/packages/react-theme/src/themes/web/lightTheme.ts @@ -1,4 +1,5 @@ import { createLightTheme } from '../../utils/createLightTheme'; import { brandWeb } from '../../global/brandColors'; +import { Theme } from '../../types'; -export const webLightTheme = createLightTheme(brandWeb); +export const webLightTheme: Theme = createLightTheme(brandWeb); diff --git a/packages/react-theme/tsconfig.json b/packages/react-theme/tsconfig.json index a3ff72129341c5..1259d048631bd2 100644 --- a/packages/react-theme/tsconfig.json +++ b/packages/react-theme/tsconfig.json @@ -1,22 +1,17 @@ { + "extends": "../../tsconfig.base.json", + "include": ["src"], "compilerOptions": { - "baseUrl": ".", + "target": "ES5", + "module": "CommonJS", + "lib": ["es5", "dom"], "outDir": "dist", - "target": "es5", - "module": "commonjs", "jsx": "react", "declaration": true, - "sourceMap": true, "experimentalDecorators": true, "importHelpers": true, "noUnusedLocals": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "moduleResolution": "node", "preserveConstEnums": true, - "lib": ["es5", "dom"], - "typeRoots": ["../../node_modules/@types", "../../typings"], - "types": ["custom-global", "jest"] - }, - "include": ["src"] + "types": ["jest", "custom-global", "inline-style-expand-shorthand"] + } } diff --git a/workspace.json b/workspace.json index 67898eea77fb43..32b260b2adeff6 100644 --- a/workspace.json +++ b/workspace.json @@ -193,7 +193,11 @@ "projectType": "library", "sourceRoot": "packages/react-text/src" }, - "@fluentui/react-theme": { "root": "packages/react-theme", "projectType": "library" }, + "@fluentui/react-theme": { + "root": "packages/react-theme", + "projectType": "library", + "sourceRoot": "packages/react-theme/src" + }, "@fluentui/react-toggle": { "root": "packages/react-toggle", "projectType": "library" }, "@fluentui/react-tooltip": { "root": "packages/react-tooltip", "projectType": "library" }, "@fluentui/react-utilities": { "root": "packages/react-utilities", "projectType": "library" },